70 lines
2.2 KiB
JavaScript
70 lines
2.2 KiB
JavaScript
import { createContext, useState } from "react";
|
|
import { CircleAlert, X, CircleX, Check } from "lucide-react";
|
|
import { toTitleCase } from "../util/util";
|
|
|
|
import PropTypes from "prop-types";
|
|
|
|
export const ToastContext = createContext();
|
|
|
|
export const ToastProvider = ({ children }) => {
|
|
const [toast, setToast] = useState({ show: false, message: "", type: "" });
|
|
|
|
const playAudio = (type) => {
|
|
let audioSrc;
|
|
if(type === "warning") audioSrc = "/audio/warning.mp3";
|
|
else if (type === "error") audioSrc = "/audio/error.mp3";
|
|
|
|
if (audioSrc) {
|
|
const audio = new Audio(audioSrc);
|
|
audio.play().catch((error) => console.error("Error playing audio:", error));
|
|
}
|
|
};
|
|
|
|
const showToast = (message, type) => {
|
|
playAudio(type);
|
|
setToast({ show: true, message, type });
|
|
setTimeout(() => {
|
|
setToast({ show: false, message: "", type: "" });
|
|
}, 7000);
|
|
};
|
|
let toastIcon;
|
|
let surfaceColor;
|
|
let borderColor;
|
|
if(toast.type === "warning") {
|
|
toastIcon = <CircleAlert size={30} fill="#EA7000" stroke="#FDF1E5" />;
|
|
surfaceColor = "bg-warning-surface";
|
|
borderColor = "border-warning";
|
|
} else if(toast.type === "success") {
|
|
toastIcon = <Check size={30} color="green"/>;
|
|
surfaceColor = "bg-success-surface";
|
|
borderColor = "border-success";
|
|
} else if (toast.type === "error") {
|
|
toastIcon = <CircleX size={30} fill="#E5254B" stroke="#FCE9ED" />;
|
|
surfaceColor = "bg-error-surface";
|
|
borderColor = "border-error";
|
|
}
|
|
|
|
return (
|
|
<ToastContext.Provider value={ showToast }>
|
|
{children}
|
|
{toast.show && (
|
|
<div
|
|
className={`fixed bottom-10 right-5 px-5 py-2 ${surfaceColor} border-2 border-l-8 ${borderColor} rounded-xl font-medium text-onToast z-10 flex gap-5 items-center animate-[slideIn_0.5s]`}
|
|
role="alert"
|
|
>
|
|
{toastIcon}
|
|
<div>
|
|
<div className="text-lg text-onToast">{toTitleCase(toast.type)}</div>
|
|
<div className="text-sm font-body">{toast.message}</div>
|
|
</div>
|
|
<X onClick={() => setToast({ show: false, message: "", type: "" })}/>
|
|
</div>
|
|
)}
|
|
</ToastContext.Provider>
|
|
);
|
|
};
|
|
|
|
ToastProvider.propTypes = {
|
|
children: PropTypes.node.isRequired,
|
|
};
|