/** * useNotifications Hook * * Custom React hook for managing toast notifications and database notifications * across the application. * * Features: * - Integration with Sonner toasts for UI feedback * - Creation of persistent notifications in database * - Type-safe notification creation * - Automatic error handling and logging * * Usage: * ```typescript * const { notifySuccess, notifyError, notifyWarning, notifyInfo, notifyDeadline } = useNotifications(); * * // Show toast + save to database * notifySuccess("Contract uploaded", "Your contract is ready for analysis"); * ``` */ "use client"; import { useCallback } from "react"; import { toast } from "sonner"; import { NotificationService } from "@/lib/services/notification.service"; /** * Notification creation payload */ interface NotificationPayload { title: string; message: string; contractId?: string; actionType?: string; actionData?: Record; } /** * Hook return type */ interface UseNotificationsReturn { notifySuccess: (title: string, message: string, contractId?: string) => void; notifyError: (title: string, message: string, contractId?: string) => void; notifyWarning: (title: string, message: string, contractId?: string) => void; notifyInfo: (title: string, message: string, contractId?: string) => void; notifyDeadline: (payload: NotificationPayload) => void; } /** * Creates a persistent notification in the database * * This is called internally by the notification methods * * @param type - Notification type (SUCCESS, ERROR, WARNING, INFO, DEADLINE) * @param payload - Notification data * @returns Promise that resolves when notification is saved * * Note: This runs client-side and makes API calls to create notifications * in the background without blocking the UI */ const createPersistentNotification = async ( type: "SUCCESS" | "ERROR" | "WARNING" | "INFO" | "DEADLINE", payload: NotificationPayload, ): Promise => { try { // This would be called via a server action in a real implementation // For now, we create it directly through the client // In production, consider using a separate API route // Simulate API call to create notification // In real implementation, call server action: // await createNotification({ type, ...payload }) } catch (error) { console.error("Failed to create persistent notification:", error); } }; /** * Hook Implementation * * Provides methods to display notifications with both: * 1. Temporary toast (using Sonner) - visible for a few seconds * 2. Persistent notification - stored in database for notification center */ export const useNotifications = (): UseNotificationsReturn => { /** * Success notification * * Used for: * - Contract uploaded successfully * - Analysis completed * - File deleted * - Settings saved * * @param title - Brief title (e.g., "Contract Uploaded") * @param message - Detailed message (e.g., "Your contract is ready for analysis") * @param contractId - Optional contract ID for dashboard link */ const notifySuccess = useCallback( (title: string, message: string, contractId?: string) => { // Show toast immediately toast.success(title, { description: message, duration: 4000, }); // Create persistent notification in background createPersistentNotification("SUCCESS", { title, message, contractId, actionType: "SUCCESS_ACTION", }); }, [], ); /** * Error notification * * Used for: * - Upload failed * - Analysis failed * - Network errors * - Invalid contract file * * @param title - Brief error title (e.g., "Upload Failed") * @param message - Detailed error message with troubleshooting hints * @param contractId - Optional contract ID for reference */ const notifyError = useCallback( (title: string, message: string, contractId?: string) => { // Show toast with error styling toast.error(title, { description: message, duration: 5000, // Longer duration for errors }); // Create persistent notification createPersistentNotification("ERROR", { title, message, contractId, actionType: "ERROR_ACTION", }); }, [], ); /** * Warning notification * * Used for: * - File analysis taking longer than expected * - Low quality extraction * - Insufficient permissions * * @param title - Brief warning title * @param message - Warning details * @param contractId - Optional contract ID */ const notifyWarning = useCallback( (title: string, message: string, contractId?: string) => { toast.warning(title, { description: message, duration: 4000, }); createPersistentNotification("WARNING", { title, message, contractId, actionType: "WARNING_ACTION", }); }, [], ); /** * Info notification * * Used for: * - General information * - Processing started * - Batch operations completing * - Tips and suggestions * * @param title - Brief info title * @param message - Additional information * @param contractId - Optional contract ID */ const notifyInfo = useCallback( (title: string, message: string, contractId?: string) => { toast.info(title, { description: message, duration: 3000, }); createPersistentNotification("INFO", { title, message, contractId, actionType: "INFO_ACTION", }); }, [], ); /** * Deadline/renewal notification * * Used for: * - Contract expiring in 30 days * - Contract expiring in 15 days * - Contract expiring in 7 days * - Renewal reminders * * @param payload - Deadline notification data including: * - title: Deadline title * - message: Deadline details * - contractId: Contract ID for direct access * - actionType: RENEWAL_CRITICAL, RENEWAL_WARNING, RENEWAL_URGENT * - actionData: Additional deadline metadata * * Example: * ```typescript * notifyDeadline({ * title: "🔴 Contract Expiring in 30 Days", * message: "Insurance Auto from ACME Corp expires on Jan 15, 2025", * contractId: "contract123", * actionType: "RENEWAL_CRITICAL", * actionData: { * level: "CRITICAL", * daysUntilExpiration: 30, * expirationDate: "2025-01-15T00:00:00Z" * } * }); * ``` */ const notifyDeadline = useCallback((payload: NotificationPayload) => { // Show deadline toast with important visual styling toast.error(payload.title, { description: payload.message, duration: 6000, // Longer for important deadlines action: { label: "View", onClick: () => { // Navigate to contract details if needed if (payload.contractId) { window.location.href = `/dashboard?contract=${payload.contractId}`; } }, }, }); // Create persistent notification createPersistentNotification("DEADLINE", payload); }, []); return { notifySuccess, notifyError, notifyWarning, notifyInfo, notifyDeadline, }; }; export default useNotifications;