notifications container front

This commit is contained in:
Hugo Lextrait 2023-02-22 11:41:52 +01:00
parent 28e6ced198
commit fa7bc24fed
8 changed files with 61 additions and 38 deletions

View File

@ -23,7 +23,7 @@ export default class Toasts {
private toastList: IToast[] = []; private toastList: IToast[] = [];
private uid: number = 0; private uid: number = 0;
private defaultTime: IToast["time"] = 4000; private defaultTime: IToast["time"] = 40000;
private defaultClosable: IToast["closable"] = true; private defaultClosable: IToast["closable"] = true;
private defaultPriority: IToast["priority"] = EToastPriority.LOW; private defaultPriority: IToast["priority"] = EToastPriority.LOW;

View File

@ -1,13 +1,17 @@
@import "@Themes/constants.scss"; @import "@Themes/constants.scss";
.root { .root {
display: flex;
flex-direction: column;
width: 300px; width: 300px;
height: 500px; max-height: 80%;
background-color: $orange-flash; background-color: $white;
box-shadow: $shadow-nav;
padding: 24px; padding: 24px;
position: absolute; position: absolute;
top: 107px; top: 107px;
right:56px; right:56px;
.notification-header{ .notification-header{
width: 100%; width: 100%;
display: inline-flex; display: inline-flex;
@ -16,4 +20,9 @@
cursor: pointer; cursor: pointer;
} }
} }
.notification-body{
margin-top: 24px;
overflow: hidden;
overflow-y: auto;
}
} }

View File

@ -3,41 +3,64 @@ import classes from "./classes.module.scss";
import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography"; import Typography, { ITypo } from "@Front/Components/DesignSystem/Typography";
import CloseIcon from "@Assets/icons/cross.svg"; import CloseIcon from "@Assets/icons/cross.svg";
import Image from "next/image"; import Image from "next/image";
import ToastHandler from "@Front/Components/DesignSystem/Toasts/ToastsHandler";
import Toasts, { IToast } from "@Front/Stores/Toasts";
type IProps = { type IProps = {
openModal: () => void; isOpen: boolean;
closeModal: () => void;
}; };
type IState = { type IState = {
isModalOpen: boolean; toastList: IToast[] | null;
}; };
export default class NotificationModal extends React.Component<IProps, IState> { export default class NotificationModal extends React.Component<IProps, IState> {
private removeOnToastChange: () => void = () => { };
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
this.state = { this.state = {
isModalOpen: true, toastList: Toasts.getInstance().toasts,
}; };
this.closeModal = this.closeModal.bind(this); this.handleToastChange = this.handleToastChange.bind(this);
this.openModal = this.openModal.bind(this);
} }
public override render(): JSX.Element | null { public override render(): JSX.Element | null {
if (!this.state.isModalOpen) return null; if (!this.props.isOpen) return null;
return <div className={classes["root"]}> return <div className={classes["root"]}>
<div className={classes["notification-header"]}> <div className={classes["notification-header"]}>
<Typography typo={ITypo.P_16}> <Typography typo={ITypo.P_16}>
Notifications Notifications
</Typography> </Typography>
<div className={classes["close-icon"]} onClick={this.closeModal}> <div className={classes["close-icon"]} onClick={this.props.closeModal}>
<Image src={CloseIcon} alt="Close notification modal" className={classes["close-icon"]}></Image> <Image src={CloseIcon} alt="Close notification modal" className={classes["close-icon"]}></Image>
</div> </div>
</div>; </div>;
<div className={classes["notification-body"]}>
<>
{Toasts.getInstance().toasts.length === 0
?
<div>
<Typography typo={ITypo.P_16}>No notification yet</Typography>
</div>
: <ToastHandler />}
</>
</div>
</div> </div>
} }
private closeModal() {
this.setState({ isModalOpen: false }); public override componentDidMount() {
this.removeOnToastChange = Toasts.getInstance().onChange(this.handleToastChange);
} }
private openModal() {
this.setState({ isModalOpen: true }); public override componentWillUnmount() {
this.removeOnToastChange();
}
private handleToastChange(toastList: IToast[] | null) {
this.setState({
toastList,
});
} }
} }

View File

@ -18,21 +18,26 @@ export default class Notifications extends React.Component<IProps, IState> {
hasNotifications: true, hasNotifications: true,
isModalOpen: true, isModalOpen: true,
}; };
this.opeModal = this.opeModal.bind(this); this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
} }
public override render(): JSX.Element { public override render(): JSX.Element {
const hasNotifications = Toasts.getInstance().toasts.length; const hasNotifications = Toasts.getInstance().toasts.length;
console.log(hasNotifications) console.log(hasNotifications)
return <div className={classes["root"]}> return <div className={classes["root"]}>
<div className={classes["icon-container"]} onClick={this.opeModal}> <div className={classes["icon-container"]} onClick={this.openModal}>
<Image alt="notifications" src={NotificationIcon} className={classes["notification-icon"]} /> <Image alt="notifications" src={NotificationIcon} className={classes["notification-icon"]} />
{this.state.hasNotifications && <div className={classes["notification-dot"]}></div>} {this.state.hasNotifications && <div className={classes["notification-dot"]}></div>}
</div> </div>
{ this.state.isModalOpen && <NotificationModal isOpen={this.state.isModalOpen} />} {this.state.isModalOpen && <NotificationModal isOpen={this.state.isModalOpen} closeModal={this.closeModal} />}
</div>; </div>;
} }
private opeModal() { private openModal() {
this.setState({ isModalOpen: true }); this.setState({ isModalOpen: true });
}; };
private closeModal() {
this.setState({ isModalOpen: false });
};
} }

View File

@ -6,7 +6,7 @@
justify-content: space-between; justify-content: space-between;
height: 83px; height: 83px;
background-color: $white; background-color: $white;
box-shadow: $shadow-neutral; box-shadow: $shadow-nav;
padding: 0 48px; padding: 0 48px;
.logo-container { .logo-container {

View File

@ -3,22 +3,9 @@
.root { .root {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: fixed;
z-index: 10;
right: 0;
top: 0;
padding: 0px;
width: 0px;
max-height: calc(100vh - 80px);
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
&.open {
width: 341px;
top: 70px;
padding: 16px;
}
& > *:not(:first-child) { & > *:not(:first-child) {
margin-top: 16px; margin-top: 16px;
} }

View File

@ -1,7 +1,6 @@
import React, { ReactNode } from "react"; import React, { ReactNode } from "react";
import classes from "./classes.module.scss"; import classes from "./classes.module.scss";
import Header from "@Front/Components/DesignSystem/Header"; import Header from "@Front/Components/DesignSystem/Header";
import ToastHandler from "@Front/Components/DesignSystem/Toasts/ToastsHandler";
type IProps = { type IProps = {
title: string; title: string;
@ -23,7 +22,6 @@ export default class DefaultTemplate extends React.Component<IProps, IState> {
<> <>
<Header /> <Header />
<div className={classes["root"]}> <div className={classes["root"]}>
<ToastHandler />
<div className={classes["content"]}>{this.props.children}</div> <div className={classes["content"]}>{this.props.children}</div>
</div> </div>
</> </>

View File

@ -39,4 +39,5 @@ $grey-soft: #f9f9f9;
$modal-background: rgba(0, 0, 0, 0.44); $modal-background: rgba(0, 0, 0, 0.44);
$shadow-neutral: 0px 8px 10px 0px #00000012; $shadow-nav: 0px 8px 10px rgba(0, 0, 0, 0.07);
$shadow-tooltip: 0px 4px 24px rgba(0, 0, 0, 0.15);