2022-11-19 14:21:26 +00:00
|
|
|
import React, { createContext, useCallback, useReducer } from "react";
|
|
|
|
// uuid
|
|
|
|
import { v4 as uuid } from "uuid";
|
|
|
|
// components
|
|
|
|
import ToastAlert from "components/toast-alert";
|
|
|
|
|
|
|
|
export const toastContext = createContext<ContextType>({} as ContextType);
|
|
|
|
|
|
|
|
// types
|
|
|
|
type ToastAlert = {
|
|
|
|
id: string;
|
|
|
|
title: string;
|
|
|
|
message?: string;
|
|
|
|
type: "success" | "error" | "warning" | "info";
|
|
|
|
};
|
|
|
|
|
|
|
|
type ReducerActionType = {
|
2023-01-26 18:12:20 +00:00
|
|
|
type: "SET_TOAST_ALERT" | "REMOVE_TOAST_ALERT";
|
2022-11-19 14:21:26 +00:00
|
|
|
payload: ToastAlert;
|
|
|
|
};
|
|
|
|
|
|
|
|
type ContextType = {
|
|
|
|
alerts?: ToastAlert[];
|
|
|
|
removeAlert: (id: string) => void;
|
|
|
|
setToastAlert: (data: {
|
|
|
|
title: string;
|
|
|
|
type?: "success" | "error" | "warning" | "info" | undefined;
|
|
|
|
message?: string | undefined;
|
|
|
|
}) => void;
|
|
|
|
};
|
|
|
|
|
|
|
|
type StateType = {
|
|
|
|
toastAlerts?: ToastAlert[];
|
|
|
|
};
|
|
|
|
|
|
|
|
type ReducerFunctionType = (state: StateType, action: ReducerActionType) => StateType;
|
|
|
|
|
|
|
|
export const initialState: StateType = {
|
|
|
|
toastAlerts: [],
|
|
|
|
};
|
|
|
|
|
|
|
|
export const reducer: ReducerFunctionType = (state, action) => {
|
|
|
|
const { type, payload } = action;
|
|
|
|
|
|
|
|
switch (type) {
|
2023-01-26 18:12:20 +00:00
|
|
|
case "SET_TOAST_ALERT":
|
2022-11-19 14:21:26 +00:00
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
toastAlerts: [...(state.toastAlerts ?? []), payload],
|
|
|
|
};
|
2023-01-26 18:12:20 +00:00
|
|
|
|
|
|
|
case "REMOVE_TOAST_ALERT":
|
2022-11-19 14:21:26 +00:00
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
toastAlerts: state.toastAlerts?.filter((toastAlert) => toastAlert.id !== payload.id),
|
|
|
|
};
|
2023-01-26 18:12:20 +00:00
|
|
|
|
2022-11-19 14:21:26 +00:00
|
|
|
default: {
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
export const ToastContextProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
|
|
const [state, dispatch] = useReducer(reducer, initialState);
|
|
|
|
|
|
|
|
const removeAlert = useCallback((id: string) => {
|
|
|
|
dispatch({
|
2023-01-26 18:12:20 +00:00
|
|
|
type: "REMOVE_TOAST_ALERT",
|
2022-11-19 14:21:26 +00:00
|
|
|
payload: { id, title: "", message: "", type: "success" },
|
|
|
|
});
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
const setToastAlert = useCallback(
|
|
|
|
(data: {
|
|
|
|
title: string;
|
|
|
|
type?: "success" | "error" | "warning" | "info";
|
|
|
|
message?: string;
|
|
|
|
}) => {
|
|
|
|
const id = uuid();
|
|
|
|
const { title, type, message } = data;
|
|
|
|
dispatch({
|
2023-01-26 18:12:20 +00:00
|
|
|
type: "SET_TOAST_ALERT",
|
2022-11-19 14:21:26 +00:00
|
|
|
payload: { id, title, message, type: type ?? "success" },
|
|
|
|
});
|
|
|
|
|
|
|
|
const timer = setTimeout(() => {
|
|
|
|
removeAlert(id);
|
|
|
|
clearTimeout(timer);
|
2022-12-06 14:38:28 +00:00
|
|
|
}, 3000);
|
2022-11-19 14:21:26 +00:00
|
|
|
},
|
|
|
|
[removeAlert]
|
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<toastContext.Provider value={{ setToastAlert, removeAlert, alerts: state.toastAlerts }}>
|
|
|
|
<ToastAlert />
|
|
|
|
{children}
|
|
|
|
</toastContext.Provider>
|
|
|
|
);
|
|
|
|
};
|