Add missing UserMenu component
This commit is contained in:
64
apps/web/src/components/ToastProvider.tsx
Normal file
64
apps/web/src/components/ToastProvider.tsx
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import React, { createContext, useContext, useState, useCallback } from 'react';
|
||||||
|
import Toast from './Toast';
|
||||||
|
|
||||||
|
export type ToastType = 'success' | 'error' | 'warning' | 'info';
|
||||||
|
|
||||||
|
export interface ToastMessage {
|
||||||
|
id: string;
|
||||||
|
type: ToastType;
|
||||||
|
message: string;
|
||||||
|
duration?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ToastContextType {
|
||||||
|
toasts: ToastMessage[];
|
||||||
|
showToast: (type: ToastType, message: string, duration?: number) => void;
|
||||||
|
removeToast: (id: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ToastContext = createContext<ToastContextType | undefined>(undefined);
|
||||||
|
|
||||||
|
export function ToastProvider({ children }: { children: React.ReactNode }) {
|
||||||
|
const [toasts, setToasts] = useState<ToastMessage[]>([]);
|
||||||
|
|
||||||
|
const showToast = useCallback((type: ToastType, message: string, duration = 5000) => {
|
||||||
|
const id = `toast-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||||
|
const toast: ToastMessage = { id, type, message, duration };
|
||||||
|
|
||||||
|
setToasts((prev) => [...prev, toast]);
|
||||||
|
|
||||||
|
if (duration > 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
removeToast(id);
|
||||||
|
}, duration);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const removeToast = useCallback((id: string) => {
|
||||||
|
setToasts((prev) => prev.filter((toast) => toast.id !== id));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ToastContext.Provider value={{ toasts, showToast, removeToast }}>
|
||||||
|
{children}
|
||||||
|
<div className="fixed top-4 right-4 z-50 space-y-2">
|
||||||
|
{toasts.map((toast) => (
|
||||||
|
<Toast
|
||||||
|
key={toast.id}
|
||||||
|
type={toast.type}
|
||||||
|
message={toast.message}
|
||||||
|
onClose={() => removeToast(toast.id)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</ToastContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useToast() {
|
||||||
|
const context = useContext(ToastContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('useToast must be used within ToastProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user