[FIX] fix(frontend): Add missing useToast hook, date-fns dep, api export, and vite-env types
Some checks are pending
CI / Backend CI (push) Waiting to run
CI / Frontend CI (push) Waiting to run
CI / Security Scan (push) Waiting to run
CI / CI Summary (push) Blocked by required conditions

- 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:
Adrian Flores Cortes 2026-01-25 02:14:47 -06:00
parent 07064e3346
commit 99ec74d9f8
6 changed files with 4414 additions and 2 deletions

4299
apps/frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,7 @@
"@tanstack/react-query": "^5.62.16",
"axios": "^1.7.9",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
"lucide-react": "^0.468.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",

View 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;
}

View File

@ -1158,5 +1158,5 @@ export const featureFlagsApi = {
};
// Export utilities
export { getTenantId };
export { getTenantId, api };
export default api;

View File

@ -37,7 +37,7 @@ export interface NotificationState {
export const useNotificationStore = create<NotificationState>()(
persist(
(set, get) => ({
(set) => ({
notifications: [],
unreadCount: 0,
preferences: {

9
apps/frontend/src/vite-env.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_URL: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}