123 lines
2.9 KiB
TypeScript
123 lines
2.9 KiB
TypeScript
import React from "react";
|
|
|
|
// Components
|
|
|
|
// Stores
|
|
|
|
// Styles
|
|
import classes from "./classes.module.scss";
|
|
import Toasts, { IToast } from "@Front/Stores/Toasts";
|
|
import Typography, { ITypo, ITypoColor } from "@Front/Components/DesignSystem/Typography";
|
|
import CheckIcon from "@Assets/Icons/check.svg";
|
|
import Image from "next/image";
|
|
import { NextRouter, useRouter } from "next/router";
|
|
|
|
type IProps = {
|
|
toast: IToast;
|
|
};
|
|
|
|
type IPropsClass = IProps & {
|
|
router: NextRouter;
|
|
};
|
|
|
|
type IState = {
|
|
willClose: boolean;
|
|
};
|
|
|
|
class ToastElementClass extends React.Component<IPropsClass, IState> {
|
|
private closeTimeout = 0;
|
|
constructor(props: IPropsClass) {
|
|
super(props);
|
|
|
|
this.state = {
|
|
willClose: false,
|
|
};
|
|
|
|
this.onClose = this.onClose.bind(this);
|
|
this.handleClick = this.handleClick.bind(this);
|
|
}
|
|
|
|
public override render(): JSX.Element {
|
|
const toast = this.props.toast;
|
|
const style = {
|
|
"--data-duration": `${toast.time}ms`,
|
|
} as React.CSSProperties;
|
|
return (
|
|
<div
|
|
className={classes["root"]}
|
|
data-will-close={this.state.willClose}
|
|
data-clickable={toast.redirectUrl ? true : false}
|
|
onClick={this.handleClick}>
|
|
{toast.time !== 0 && <div className={classes["loadbar"]} style={style} />}
|
|
<div className={classes["header"]}>
|
|
<div className={classes["text-icon_row"]}>
|
|
{toast.icon && toast.icon}
|
|
<div className={classes["text-container"]}>
|
|
{this.getToastTitle(toast.title)}
|
|
{this.getToastText(toast.text)}
|
|
</div>
|
|
</div>
|
|
{toast.closable && <Image src={CheckIcon} alt="Document check" className={classes["cross"]} onClick={this.onClose} />}
|
|
</div>
|
|
{toast.button}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
public override componentDidMount() {
|
|
if (this.props.toast.time === 0) return;
|
|
|
|
this.closeTimeout = window.setTimeout(() => {
|
|
this.close();
|
|
}, this.props.toast.time);
|
|
}
|
|
|
|
private getToastTitle(title: string | React.ReactNode) {
|
|
if (typeof title === "string") {
|
|
return <Typography typo={ITypo.P_16}>{title}</Typography>;
|
|
}
|
|
return title;
|
|
}
|
|
|
|
private getToastText(text: React.ReactNode) {
|
|
if (typeof text === "string") {
|
|
return (
|
|
<div className={classes["text-container"]}>
|
|
<Typography typo={ITypo.CAPTION_14} color={ITypoColor.GREY}>
|
|
{text}
|
|
</Typography>
|
|
</div>
|
|
);
|
|
}
|
|
return text;
|
|
}
|
|
|
|
private onClose(e: React.MouseEvent) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
this.close();
|
|
}
|
|
|
|
private close() {
|
|
window.clearTimeout(this.closeTimeout);
|
|
this.setState({
|
|
willClose: true,
|
|
});
|
|
setTimeout(() => {
|
|
Toasts.getInstance().close(this.props.toast);
|
|
}, 200);
|
|
}
|
|
|
|
private handleClick(e: React.MouseEvent) {
|
|
if (this.props.toast.redirectUrl) {
|
|
this.props.router.push(this.props.toast.redirectUrl);
|
|
this.onClose(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
export default function ToastElement(props: IProps) {
|
|
const router = useRouter();
|
|
return <ToastElementClass {...props} router={router} />;
|
|
}
|