feat: TrpcProvider and SelectedClientProvider
This commit is contained in:
69
src/components/providers/SelectedClientProvider.tsx
Normal file
69
src/components/providers/SelectedClientProvider.tsx
Normal file
@@ -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<SelectedClientContextValue | null>(null)
|
||||
|
||||
export function SelectedClientProvider({ children }: { children: ReactNode }) {
|
||||
const [selectedClientId, setState] = useState<string | null>(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 (
|
||||
<SelectedClientContext.Provider value={value}>
|
||||
{children}
|
||||
</SelectedClientContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export function useSelectedClient() {
|
||||
const ctx = useContext(SelectedClientContext)
|
||||
if (!ctx) {
|
||||
throw new Error('useSelectedClient must be used within SelectedClientProvider')
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
46
src/components/providers/TrpcProvider.tsx
Normal file
46
src/components/providers/TrpcProvider.tsx
Normal file
@@ -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 (
|
||||
<trpc.Provider client={trpcClient} queryClient={queryClient}>
|
||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||
</trpc.Provider>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user