import React from "react" import { base44 } from "@/api/base44Client"; const TOAST_LIMIT = 5 const TOAST_REMOVE_DELAY = 1000000 let count = 0 function genId() { count = (count + 1) % Number.MAX_VALUE return count.toString() } const toastTimeouts = new Map() const addToRemoveQueue = (toastId) => { if (toastTimeouts.has(toastId)) { return } const timeout = setTimeout(() => { toastTimeouts.delete(toastId) dispatch({ type: "REMOVE_TOAST", toastId: toastId, }) }, TOAST_REMOVE_DELAY) toastTimeouts.set(toastId, timeout) } const reducer = (state, action) => { switch (action.type) { case "ADD_TOAST": return { ...state, toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), } case "UPDATE_TOAST": return { ...state, toasts: state.toasts.map((t) => t.id === action.toast.id ? { ...t, ...action.toast } : t ), } case "DISMISS_TOAST": { const { toastId } = action if (toastId) { addToRemoveQueue(toastId) } else { state.toasts.forEach((toast) => { addToRemoveQueue(toast.id) }) } return { ...state, toasts: state.toasts.map((t) => t.id === toastId || toastId === undefined ? { ...t, open: false, } : t ), } } case "REMOVE_TOAST": if (action.toastId === undefined) { return { ...state, toasts: [], } } return { ...state, toasts: state.toasts.filter((t) => t.id !== action.toastId), } } } const listeners = [] let memoryState = { toasts: [] } function dispatch(action) { memoryState = reducer(memoryState, action) listeners.forEach((listener) => { listener(memoryState) }) } // Helper function to create notification in ActivityLog instead of toast async function createNotification(title, description, variant) { try { const user = await base44.auth.me(); // Determine icon and color based on variant and title let icon_type = "check"; let icon_color = "blue"; let activity_type = "message_received"; if (variant === "destructive" || title.includes("Failed") || title.includes("Error")) { icon_type = "alert"; icon_color = "red"; activity_type = "event_updated"; } else if (title.includes("Success") || title.includes("✅") || title.includes("Saved") || title.includes("Created")) { icon_type = "check"; icon_color = "green"; activity_type = "event_created"; } else if (title.includes("Invoice") || title.includes("Payment")) { icon_type = "invoice"; icon_color = "purple"; activity_type = "invoice_created"; } else if (title.includes("Event") || title.includes("Order")) { icon_type = "calendar"; icon_color = "blue"; activity_type = "event_created"; } else if (title.includes("User") || title.includes("Staff") || title.includes("Member")) { icon_type = "user"; icon_color = "green"; activity_type = "staff_assigned"; } await base44.entities.ActivityLog.create({ title: title.replace(/✅|❌|⚠️/g, '').trim(), description: description || "", activity_type: activity_type, user_id: user.id, is_read: false, icon_type: icon_type, icon_color: icon_color, }); } catch (error) { console.error("Failed to create notification:", error); } } function toast({ title, description, variant, ...props }) { const id = genId() // Instead of showing a toast, create a notification in ActivityLog createNotification(title, description, variant); const update = (props) => dispatch({ type: "UPDATE_TOAST", toast: { ...props, id }, }) const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }) // Don't actually add to visible toasts // Just return the interface for compatibility return { id: id, dismiss, update, } } function useToast() { const [state, setState] = React.useState(memoryState) React.useEffect(() => { listeners.push(setState) return () => { const index = listeners.indexOf(setState) if (index > -1) { listeners.splice(index, 1) } } }, [state]) return { ...state, toast, dismiss: (toastId) => dispatch({ type: "DISMISS_TOAST", toastId }), } } export { useToast, toast }