diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 11abe31..a78248b 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -24,6 +24,10 @@ import { AuthContextProvider } from "./AuthContext";
// React router
import Router from "./Router";
+// Toasts
+import Toasts from "./components/Toasts";
+import { ToastContextProvider } from "./ToastContext";
+
const queryClient = new QueryClient();
const App = () => {
@@ -35,9 +39,12 @@ const App = () => {
Todo
-
-
-
+
+
+
+
+
+
diff --git a/frontend/src/ToastContext.tsx b/frontend/src/ToastContext.tsx
new file mode 100644
index 0000000..a764bd3
--- /dev/null
+++ b/frontend/src/ToastContext.tsx
@@ -0,0 +1,49 @@
+import { AlertColor } from "@mui/material/Alert";
+
+import React, { createContext, useState } from "react";
+
+export interface IToast {
+ category?: AlertColor;
+ key: number;
+ message: string;
+}
+
+interface IToastContext {
+ addToast: (message: string, category: AlertColor | undefined) => void;
+ setToasts: React.Dispatch>;
+ toasts: IToast[];
+}
+
+export const ToastContext = createContext({
+ addToast: () => {},
+ setToasts: () => {},
+ toasts: [],
+});
+
+interface IProps {
+ children?: React.ReactNode;
+}
+
+export const ToastContextProvider = ({ children }: IProps) => {
+ const [toasts, setToasts] = useState([]);
+
+ const addToast = (
+ message: string,
+ category: AlertColor | undefined = undefined,
+ ) => {
+ setToasts((prev) => [
+ ...prev,
+ {
+ category,
+ key: new Date().getTime(),
+ message,
+ },
+ ]);
+ };
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/frontend/src/components/Title.tsx b/frontend/src/components/Title.tsx
index cc5f2cc..9ac6d85 100644
--- a/frontend/src/components/Title.tsx
+++ b/frontend/src/components/Title.tsx
@@ -8,7 +8,7 @@ interface IProps {
const Title = ({ title }: IProps) => (
<>
- Tozo | {title}
+ Todo | {title}
{title}
diff --git a/frontend/src/components/Toasts.tsx b/frontend/src/components/Toasts.tsx
new file mode 100644
index 0000000..4c73fa5
--- /dev/null
+++ b/frontend/src/components/Toasts.tsx
@@ -0,0 +1,47 @@
+import Alert from "@mui/material/Alert";
+import Snackbar from "@mui/material/Snackbar";
+import React, { useContext, useEffect, useState } from "react";
+
+import { ToastContext, IToast } from "src/ToastContext";
+
+const Toasts = () => {
+ const { toasts, setToasts } = useContext(ToastContext);
+ const [open, setOpen] = useState(false);
+ const [currentToast, setCurrentToast] = useState();
+
+ useEffect(() => {
+ if (!open && toasts.length) {
+ setCurrentToast(toasts[0]);
+ setToasts((prev) => prev.slice(1));
+ setOpen(true);
+ }
+ }, [open, setCurrentToast, setOpen, setToasts, toasts]);
+
+ const onClose = (event?: React.SyntheticEvent | Event, reason?: string) => {
+ if (reason !== "clickaway") {
+ setOpen(false);
+ }
+ };
+
+ return (
+ setCurrentToast(undefined),
+ }}
+ >
+
+ {currentToast?.message}
+
+
+ );
+};
+
+export default Toasts;