106 lines
3.2 KiB
TypeScript
106 lines
3.2 KiB
TypeScript
'use client';
|
|
|
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
import { useFamilyOverlay } from '@/components/family/family-overlay-provider';
|
|
import { useAuth } from '@/components/id/auth-provider';
|
|
import {
|
|
FamilyGroup,
|
|
FamilyPresenceMember,
|
|
fetchFamilyGroup,
|
|
fetchFamilyGroups,
|
|
fetchFamilyPresence,
|
|
getAccessToken
|
|
} from '@/lib/api';
|
|
|
|
export function useSelectedFamily(enabled = true) {
|
|
const { user, token, isPinLocked, isLoading, isApiReady } = useAuth();
|
|
const { selectedGroupId, setSelectedGroupId } = useFamilyOverlay();
|
|
const [groups, setGroups] = useState<FamilyGroup[]>([]);
|
|
const [group, setGroup] = useState<FamilyGroup | null>(null);
|
|
const [presenceMembers, setPresenceMembers] = useState<FamilyPresenceMember[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
const refresh = useCallback(async () => {
|
|
const accessToken = getAccessToken() ?? token?.trim() ?? null;
|
|
if (!enabled || !user || !accessToken || isPinLocked || isLoading || !isApiReady) {
|
|
setGroups([]);
|
|
setGroup(null);
|
|
setPresenceMembers([]);
|
|
setLoading(false);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const groupsResponse = await fetchFamilyGroups(user.id, accessToken);
|
|
const list = groupsResponse.groups ?? [];
|
|
setGroups(list);
|
|
|
|
if (!list.length) {
|
|
setGroup(null);
|
|
setPresenceMembers([]);
|
|
if (selectedGroupId) setSelectedGroupId(null);
|
|
return;
|
|
}
|
|
|
|
const effectiveId =
|
|
selectedGroupId && list.some((item) => item.id === selectedGroupId) ? selectedGroupId : list[0]!.id;
|
|
|
|
if (effectiveId !== selectedGroupId) {
|
|
setSelectedGroupId(effectiveId);
|
|
}
|
|
|
|
const [groupResponse, presenceResponse] = await Promise.all([
|
|
fetchFamilyGroup(effectiveId, accessToken),
|
|
fetchFamilyPresence(effectiveId, accessToken)
|
|
]);
|
|
setGroup(groupResponse);
|
|
setPresenceMembers(presenceResponse.members ?? []);
|
|
} catch {
|
|
setGroups([]);
|
|
setGroup(null);
|
|
setPresenceMembers([]);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [enabled, isApiReady, isLoading, isPinLocked, selectedGroupId, setSelectedGroupId, token, user]);
|
|
|
|
useEffect(() => {
|
|
setLoading(true);
|
|
void refresh();
|
|
}, [refresh]);
|
|
|
|
useEffect(() => {
|
|
const accessToken = getAccessToken() ?? token?.trim() ?? null;
|
|
if (!enabled || !accessToken || isPinLocked || isLoading || !isApiReady || !group) return;
|
|
const timer = window.setInterval(() => void refresh(), 25_000);
|
|
return () => window.clearInterval(timer);
|
|
}, [enabled, group, isApiReady, isLoading, isPinLocked, refresh, token]);
|
|
|
|
const presenceByUserId = useMemo(
|
|
() => new Map(presenceMembers.map((member) => [member.userId, member])),
|
|
[presenceMembers]
|
|
);
|
|
|
|
const groupSummaries = useMemo(
|
|
() => groups.map((item) => ({ id: item.id, name: item.name })),
|
|
[groups]
|
|
);
|
|
|
|
return {
|
|
groups,
|
|
groupSummaries,
|
|
group,
|
|
loading,
|
|
hasFamily: Boolean(group),
|
|
selectedGroupId: group?.id ?? selectedGroupId,
|
|
setSelectedGroupId,
|
|
presenceByUserId,
|
|
refresh
|
|
};
|
|
}
|
|
|
|
/** @deprecated Используйте useSelectedFamily */
|
|
export function usePrimaryFamily(enabled = true) {
|
|
return useSelectedFamily(enabled);
|
|
}
|