import { useEffect } from 'react'; import { useAppDispatch, useAppSelector } from '@/hooks/redux-hooks'; import { fetchThemeAsync } from '@/store/themeSlice'; import apiClient from '@/services/api-client'; /** * Hook to fetch and apply tenant theme * Should be used in tenant admin screens and login */ export const useTenantTheme = (): void => { const dispatch = useAppDispatch(); const { faviconUrl, isInitialized, isLoading } = useAppSelector((state) => state.theme); useEffect(() => { // Only fetch if not already initialized if (!isInitialized && !isLoading) { dispatch(fetchThemeAsync()); } }, [dispatch, isInitialized, isLoading]); // Apply favicon useEffect(() => { if (!faviconUrl) return; let isMounted = true; let blobUrl: string | null = null; const applyFavicon = async () => { const baseUrl = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000/api/v1'; const isBackendUrl = faviconUrl.includes(`${baseUrl}/files/`) && faviconUrl.includes('/preview'); let finalUrl = faviconUrl; // If it's a backend URL, fetch it with authentication if (isBackendUrl) { try { const response = await apiClient.get(faviconUrl, { responseType: 'blob' }); if (isMounted) { blobUrl = URL.createObjectURL(response.data); finalUrl = blobUrl; } } catch (err) { console.error('Failed to fetch authenticated favicon:', err); // Fallback to original URL, although it might still fail at browser level } } if (isMounted) { // Remove existing favicon links const existingFavicons = document.querySelectorAll("link[rel='icon'], link[rel='shortcut icon']"); existingFavicons.forEach((favicon) => favicon.remove()); // Add new favicon const link = document.createElement('link'); link.rel = 'icon'; // Try to detect type or default to image/png link.type = faviconUrl.endsWith('.ico') ? 'image/x-icon' : 'image/png'; link.href = finalUrl; document.head.appendChild(link); } }; applyFavicon(); return () => { isMounted = false; if (blobUrl) { URL.revokeObjectURL(blobUrl); } }; }, [faviconUrl]); };