diff --git a/src/components/providers/SelectedClientProvider.tsx b/src/components/providers/SelectedClientProvider.tsx new file mode 100644 index 0000000..42bf715 --- /dev/null +++ b/src/components/providers/SelectedClientProvider.tsx @@ -0,0 +1,69 @@ +'use client' + +import { + createContext, + useCallback, + useContext, + useEffect, + useState, + type ReactNode, +} from 'react' + +const STORAGE_KEY = 'msp-selected-client-id' + +type SelectedClientContextValue = { + selectedClientId: string | null + setSelectedClientId: (id: string | null) => void +} + +const SelectedClientContext = createContext(null) + +export function SelectedClientProvider({ children }: { children: ReactNode }) { + const [selectedClientId, setState] = useState(null) + const [hydrated, setHydrated] = useState(false) + + useEffect(() => { + try { + const stored = typeof window !== 'undefined' ? localStorage.getItem(STORAGE_KEY) : null + const legacy = typeof window !== 'undefined' ? localStorage.getItem('msp-selected-cliente-id') : null + const value = stored || legacy || null + if (value) setState(value) + if (legacy && !stored && typeof window !== 'undefined') { + localStorage.setItem(STORAGE_KEY, value!) + localStorage.removeItem('msp-selected-cliente-id') + } + } finally { + setHydrated(true) + } + }, []) + + const setSelectedClientId = useCallback((id: string | null) => { + setState(id) + try { + if (typeof window !== 'undefined') { + if (id) localStorage.setItem(STORAGE_KEY, id) + else localStorage.removeItem(STORAGE_KEY) + } + } catch { + // ignore + } + }, []) + + const value: SelectedClientContextValue = hydrated + ? { selectedClientId, setSelectedClientId } + : { selectedClientId: null, setSelectedClientId } + + return ( + + {children} + + ) +} + +export function useSelectedClient() { + const ctx = useContext(SelectedClientContext) + if (!ctx) { + throw new Error('useSelectedClient must be used within SelectedClientProvider') + } + return ctx +} diff --git a/src/components/providers/TrpcProvider.tsx b/src/components/providers/TrpcProvider.tsx new file mode 100644 index 0000000..19c4f9e --- /dev/null +++ b/src/components/providers/TrpcProvider.tsx @@ -0,0 +1,46 @@ +'use client' + +import { useState } from 'react' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { httpBatchLink } from '@trpc/client' +import superjson from 'superjson' +import { trpc } from '@/lib/trpc-client' + +function getBaseUrl() { + if (typeof window !== 'undefined') return '' + if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}` + return `http://localhost:${process.env.PORT ?? 3000}` +} + +export default function TrpcProvider({ children }: { children: React.ReactNode }) { + const [queryClient] = useState( + () => + new QueryClient({ + defaultOptions: { + queries: { + staleTime: 5 * 1000, + }, + }, + }) + ) + + const [trpcClient] = useState(() => + trpc.createClient({ + links: [ + httpBatchLink({ + url: `${getBaseUrl()}/api/trpc`, + fetch(url, options) { + return fetch(url, { ...options, credentials: 'include' }) + }, + }), + ], + transformer: superjson, + }) + ) + + return ( + + {children} + + ) +}