Files
IdP/apps/frontend/components/family/family-overlay-provider.tsx
2026-06-25 23:48:57 +03:00

115 lines
3.6 KiB
TypeScript

'use client';
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
const SELECTED_FAMILY_STORAGE_KEY = 'id-selected-family-group-id';
type FamilyOverlayContextValue = {
openMiniChat: () => void;
openChatRoom: (roomId: string) => void;
openChatWithMember: (memberUserId: string, memberName: string, options?: { isBot?: boolean; botUsername?: string }) => void;
closeMiniChat: () => void;
miniChatOpen: boolean;
pendingRoomId: string | null;
pendingMember: { userId: string; name: string; isBot?: boolean; botUsername?: string } | null;
clearPending: () => void;
selectedGroupId: string | null;
setSelectedGroupId: (groupId: string | null) => void;
};
const FamilyOverlayContext = createContext<FamilyOverlayContextValue | null>(null);
export function FamilyOverlayProvider({ children }: { children: React.ReactNode }) {
const [miniChatOpen, setMiniChatOpen] = useState(false);
const [pendingRoomId, setPendingRoomId] = useState<string | null>(null);
const [pendingMember, setPendingMember] = useState<{ userId: string; name: string; isBot?: boolean; botUsername?: string } | null>(null);
const [selectedGroupId, setSelectedGroupIdState] = useState<string | null>(null);
const pendingMemberRef = useRef<{ userId: string; name: string; isBot?: boolean; botUsername?: string } | null>(null);
const selectionHydratedRef = useRef(false);
useEffect(() => {
if (selectionHydratedRef.current) return;
selectionHydratedRef.current = true;
const stored = window.localStorage.getItem(SELECTED_FAMILY_STORAGE_KEY);
if (stored) setSelectedGroupIdState(stored);
}, []);
const setSelectedGroupId = useCallback((groupId: string | null) => {
setSelectedGroupIdState(groupId);
if (groupId) {
window.localStorage.setItem(SELECTED_FAMILY_STORAGE_KEY, groupId);
} else {
window.localStorage.removeItem(SELECTED_FAMILY_STORAGE_KEY);
}
}, []);
const openMiniChat = useCallback(() => {
setMiniChatOpen(true);
}, []);
const closeMiniChat = useCallback(() => {
setMiniChatOpen(false);
}, []);
const openChatRoom = useCallback((roomId: string) => {
setPendingRoomId(roomId);
setPendingMember(null);
pendingMemberRef.current = null;
setMiniChatOpen(true);
}, []);
const openChatWithMember = useCallback(
(memberUserId: string, memberName: string, options?: { isBot?: boolean; botUsername?: string }) => {
const payload = { userId: memberUserId, name: memberName, ...options };
setPendingMember(payload);
pendingMemberRef.current = payload;
setPendingRoomId(null);
setMiniChatOpen(true);
},
[]
);
const clearPending = useCallback(() => {
setPendingRoomId(null);
setPendingMember(null);
pendingMemberRef.current = null;
}, []);
const value = useMemo(
() => ({
openMiniChat,
openChatRoom,
openChatWithMember,
closeMiniChat,
miniChatOpen,
pendingRoomId,
pendingMember,
clearPending,
selectedGroupId,
setSelectedGroupId
}),
[
clearPending,
closeMiniChat,
miniChatOpen,
openChatRoom,
openChatWithMember,
openMiniChat,
pendingMember,
pendingRoomId,
selectedGroupId,
setSelectedGroupId
]
);
return <FamilyOverlayContext.Provider value={value}>{children}</FamilyOverlayContext.Provider>;
}
export function useFamilyOverlay() {
const context = useContext(FamilyOverlayContext);
if (!context) {
throw new Error('useFamilyOverlay must be used within FamilyOverlayProvider');
}
return context;
}