forked from jamesp/sasa-membership
Add UTC datetime helpers to attempt to fix running issue
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import React, { createContext, useCallback, useContext, useMemo, useState } from 'react';
|
||||
|
||||
type ToastTone = 'success' | 'error' | 'info';
|
||||
|
||||
interface ToastItem {
|
||||
id: number;
|
||||
message: string;
|
||||
tone: ToastTone;
|
||||
}
|
||||
|
||||
interface ToastContextValue {
|
||||
showToast: (message: string, tone?: ToastTone) => void;
|
||||
success: (message: string) => void;
|
||||
error: (message: string) => void;
|
||||
info: (message: string) => void;
|
||||
}
|
||||
|
||||
const ToastContext = createContext<ToastContextValue | null>(null);
|
||||
|
||||
export const ToastProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const [toasts, setToasts] = useState<ToastItem[]>([]);
|
||||
|
||||
const dismissToast = useCallback((id: number) => {
|
||||
setToasts((prev) => prev.filter((toast) => toast.id !== id));
|
||||
}, []);
|
||||
|
||||
const showToast = useCallback((message: string, tone: ToastTone = 'info') => {
|
||||
const id = Date.now() + Math.floor(Math.random() * 1000);
|
||||
setToasts((prev) => [...prev, { id, message, tone }]);
|
||||
window.setTimeout(() => {
|
||||
setToasts((prev) => prev.filter((toast) => toast.id !== id));
|
||||
}, 5000);
|
||||
}, []);
|
||||
|
||||
const value = useMemo<ToastContextValue>(() => ({
|
||||
showToast,
|
||||
success: (message) => showToast(message, 'success'),
|
||||
error: (message) => showToast(message, 'error'),
|
||||
info: (message) => showToast(message, 'info')
|
||||
}), [showToast]);
|
||||
|
||||
return (
|
||||
<ToastContext.Provider value={value}>
|
||||
{children}
|
||||
<div className="toast-viewport" aria-live="polite" aria-atomic="true">
|
||||
{toasts.map((toast) => (
|
||||
<div key={toast.id} className={`toast toast-${toast.tone}`}>
|
||||
<div className="toast-message">{toast.message}</div>
|
||||
<button className="toast-close" type="button" onClick={() => dismissToast(toast.id)} aria-label="Dismiss notification">
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</ToastContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useToast = (): ToastContextValue => {
|
||||
const context = useContext(ToastContext);
|
||||
if (!context) {
|
||||
throw new Error('useToast must be used within a ToastProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
Reference in New Issue
Block a user