[FIX] fix(frontend): Add missing useToast hook, date-fns dep, api export, and vite-env types
- Created useToast.ts hook for toast notifications - Added date-fns dependency for NotificationItem.tsx - Exported api instance as named export for whatsapp.api.ts - Added vite-env.d.ts for import.meta.env types - Fixed notification.store.ts unused get parameter Build now passes successfully (2131 modules) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
07064e3346
commit
99ec74d9f8
4299
apps/frontend/package-lock.json
generated
Normal file
4299
apps/frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,7 @@
|
|||||||
"@tanstack/react-query": "^5.62.16",
|
"@tanstack/react-query": "^5.62.16",
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"date-fns": "^4.1.0",
|
||||||
"lucide-react": "^0.468.0",
|
"lucide-react": "^0.468.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
|
|||||||
103
apps/frontend/src/hooks/useToast.ts
Normal file
103
apps/frontend/src/hooks/useToast.ts
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import { useState, useCallback, useEffect } from 'react';
|
||||||
|
|
||||||
|
export interface Toast {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
description?: string;
|
||||||
|
variant?: 'default' | 'success' | 'destructive';
|
||||||
|
duration?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ToastOptions {
|
||||||
|
title: string;
|
||||||
|
description?: string;
|
||||||
|
variant?: 'default' | 'success' | 'destructive';
|
||||||
|
duration?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple toast state management using a singleton pattern
|
||||||
|
// For a production app, consider using a context provider
|
||||||
|
let toastListeners: ((toasts: Toast[]) => void)[] = [];
|
||||||
|
let toasts: Toast[] = [];
|
||||||
|
|
||||||
|
const notifyListeners = () => {
|
||||||
|
toastListeners.forEach((listener) => listener([...toasts]));
|
||||||
|
};
|
||||||
|
|
||||||
|
const addToast = (toast: Toast) => {
|
||||||
|
toasts = [...toasts, toast];
|
||||||
|
notifyListeners();
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeToast = (id: string) => {
|
||||||
|
toasts = toasts.filter((t) => t.id !== id);
|
||||||
|
notifyListeners();
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useToast() {
|
||||||
|
const [, setLocalToasts] = useState<Toast[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const listener = (newToasts: Toast[]) => setLocalToasts(newToasts);
|
||||||
|
toastListeners.push(listener);
|
||||||
|
return () => {
|
||||||
|
toastListeners = toastListeners.filter((l) => l !== listener);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const toast = useCallback((options: ToastOptions) => {
|
||||||
|
const id = Math.random().toString(36).substring(2, 9);
|
||||||
|
const duration = options.duration ?? 5000;
|
||||||
|
|
||||||
|
const newToast: Toast = {
|
||||||
|
id,
|
||||||
|
title: options.title,
|
||||||
|
description: options.description,
|
||||||
|
variant: options.variant ?? 'default',
|
||||||
|
duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
addToast(newToast);
|
||||||
|
|
||||||
|
// Auto-dismiss after duration
|
||||||
|
if (duration > 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
removeToast(id);
|
||||||
|
}, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const dismiss = useCallback((toastId: string) => {
|
||||||
|
removeToast(toastId);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const dismissAll = useCallback(() => {
|
||||||
|
toasts = [];
|
||||||
|
notifyListeners();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return {
|
||||||
|
toast,
|
||||||
|
dismiss,
|
||||||
|
dismissAll,
|
||||||
|
toasts,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hook for components that want to render toasts
|
||||||
|
export function useToasts() {
|
||||||
|
const [localToasts, setLocalToasts] = useState<Toast[]>(toasts);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const listener = (newToasts: Toast[]) => setLocalToasts(newToasts);
|
||||||
|
toastListeners.push(listener);
|
||||||
|
setLocalToasts(toasts); // Sync initial state
|
||||||
|
return () => {
|
||||||
|
toastListeners = toastListeners.filter((l) => l !== listener);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return localToasts;
|
||||||
|
}
|
||||||
@ -1158,5 +1158,5 @@ export const featureFlagsApi = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Export utilities
|
// Export utilities
|
||||||
export { getTenantId };
|
export { getTenantId, api };
|
||||||
export default api;
|
export default api;
|
||||||
|
|||||||
@ -37,7 +37,7 @@ export interface NotificationState {
|
|||||||
|
|
||||||
export const useNotificationStore = create<NotificationState>()(
|
export const useNotificationStore = create<NotificationState>()(
|
||||||
persist(
|
persist(
|
||||||
(set, get) => ({
|
(set) => ({
|
||||||
notifications: [],
|
notifications: [],
|
||||||
unreadCount: 0,
|
unreadCount: 0,
|
||||||
preferences: {
|
preferences: {
|
||||||
|
|||||||
9
apps/frontend/src/vite-env.d.ts
vendored
Normal file
9
apps/frontend/src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
interface ImportMetaEnv {
|
||||||
|
readonly VITE_API_URL: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ImportMeta {
|
||||||
|
readonly env: ImportMetaEnv;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user