'use client'; import { createContext, useContext, useEffect, useRef, type ReactNode } from 'react'; import { useParams } from 'next/navigation'; import { useUIStore } from '@/stores/ui-store'; import { apiFetch } from '@/lib/api/client'; import type { Port } from '@/lib/db/schema/ports'; interface PortContextValue { ports: Port[]; currentPort: Port | null; currentPortId: string | null; currentPortSlug: string | null; } const PortContext = createContext({ ports: [], currentPort: null, currentPortId: null, currentPortSlug: null, }); interface PortProviderProps { children: ReactNode; ports: Port[]; defaultPortId: string | null; } export function PortProvider({ children, ports, defaultPortId }: PortProviderProps) { const params = useParams(); const portSlugFromUrl = params?.portSlug as string | undefined; const setPort = useUIStore((s) => s.setPort); const currentPortId = useUIStore((s) => s.currentPortId); const currentPortSlug = useUIStore((s) => s.currentPortSlug); // Resolve current port - URL slug takes priority over stored port const currentPort = ports.find((p) => p.slug === portSlugFromUrl) ?? ports.find((p) => p.id === currentPortId) ?? (defaultPortId ? (ports.find((p) => p.id === defaultPortId) ?? null) : null); // Sync Zustand store whenever the active port changes useEffect(() => { if (currentPort && (currentPort.id !== currentPortId || currentPort.slug !== currentPortSlug)) { setPort(currentPort.id, currentPort.slug); } }, [currentPort, currentPortId, currentPortSlug, setPort]); // Remember the last port the user landed on (URL-derived or // explicit-switch) so the next login routes here automatically. Tracked // in a ref-keyed dedupe so we only PATCH when the active port actually // changes - re-renders inside the same port don't write. Fire-and-forget; // a transient network failure shouldn't block navigation, and the // post-login resolver verifies access so a stale value can't strand the // user on a 403. const lastPersistedPortIdRef = useRef(null); useEffect(() => { if (!currentPort) return; if (lastPersistedPortIdRef.current === currentPort.id) return; lastPersistedPortIdRef.current = currentPort.id; void apiFetch('/api/v1/me', { method: 'PATCH', body: { preferences: { defaultPortId: currentPort.id } }, }).catch(() => { /* silent - best-effort */ }); }, [currentPort]); return ( {children} ); } export function usePortContext(): PortContextValue { return useContext(PortContext); }