import { useCallback, useEffect, useRef } from 'react'; import { useUserManagerStore } from './userStore'; import { userManager } from './UserManager'; import type { UserDTO } from '../../types/dto'; import { useAuthStore } from '../auth/authStore'; export interface UseCurrentUserResult { user: UserDTO | null; isLoading: boolean; refresh: () => Promise; } export function useCurrentUser(): UseCurrentUserResult { const user = useUserManagerStore(state => state.currentUser); const isLoading = useUserManagerStore(state => state.isLoadingCurrentUser); const lastFetchedRef = useRef(null); useEffect(() => { const authUser = useAuthStore.getState().currentUser; const userId = authUser?.id; if (userId && lastFetchedRef.current !== userId) { lastFetchedRef.current = userId; useUserManagerStore.getState().setLoadingCurrentUser(true); userManager.getCurrentUser().finally(() => { useUserManagerStore.getState().setLoadingCurrentUser(false); }); } }, []); useEffect(() => { return useAuthStore.subscribe((state, prev) => { if (!state.currentUser && prev.currentUser) { lastFetchedRef.current = null; } }); }, []); const refresh = useCallback(async () => { useUserManagerStore.getState().setLoadingCurrentUser(true); try { return await userManager.getCurrentUser(true); } finally { useUserManagerStore.getState().setLoadingCurrentUser(false); } }, []); return { user, isLoading, refresh }; } export interface UseUserResult { user: UserDTO | null; isLoading: boolean; refresh: () => Promise; } export function useUser(userId: string | undefined | null): UseUserResult { const user = useUserManagerStore(state => userId ? (state.usersMap.get(userId)?.data ?? null) : null ); const isLoading = useUserManagerStore(state => userId ? state.loadingUserIds.has(userId) : false ); const lastFetchedRef = useRef(null); useEffect(() => { if (!userId) return; if (lastFetchedRef.current !== userId) { lastFetchedRef.current = userId; useUserManagerStore.getState().setLoadingUser(userId, true); userManager.getUserById(userId).finally(() => { useUserManagerStore.getState().setLoadingUser(userId, false); }); } }, [userId]); const refresh = useCallback(async () => { if (!userId) return null; useUserManagerStore.getState().setLoadingUser(userId, true); try { return await userManager.getUserById(userId, true); } finally { useUserManagerStore.getState().setLoadingUser(userId, false); } }, [userId]); return { user, isLoading, refresh }; } export interface UseUsersResult { getUser: (id: string) => UserDTO | null; refreshUser: (id: string) => Promise; } export function useUsers(userIds: string[]): UseUsersResult { const usersMap = useUserManagerStore(state => state.usersMap); const loadingUserIds = useUserManagerStore(state => state.loadingUserIds); const fetchedIdsRef = useRef>(new Set()); useEffect(() => { userIds.forEach(id => { if (!fetchedIdsRef.current.has(id) && !loadingUserIds.has(id)) { fetchedIdsRef.current = new Set(fetchedIdsRef.current).add(id); useUserManagerStore.getState().setLoadingUser(id, true); userManager.getUserById(id).finally(() => { useUserManagerStore.getState().setLoadingUser(id, false); }); } }); }, [userIds, loadingUserIds]); const getUser = useCallback((id: string) => { return usersMap.get(id)?.data ?? null; }, [usersMap]); const refreshUser = useCallback(async (id: string) => { useUserManagerStore.getState().setLoadingUser(id, true); try { return await userManager.getUserById(id, true); } finally { useUserManagerStore.getState().setLoadingUser(id, false); } }, []); return { getUser, refreshUser }; }