Init commit
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
"use client"
|
||||
|
||||
import { createContext, useContext, useEffect, useState, useCallback } from "react"
|
||||
|
||||
// ── types ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
export type DataSourceMode = "mock" | "live"
|
||||
|
||||
interface DataSourceContextValue {
|
||||
mode: DataSourceMode
|
||||
setMode: (m: DataSourceMode) => void
|
||||
backendUrl: string
|
||||
setBackendUrl: (url: string) => void
|
||||
/** undefined = не проверялось, true = OK, false = недоступен */
|
||||
backendStatus: boolean | undefined
|
||||
checkBackend: () => Promise<void>
|
||||
}
|
||||
|
||||
// ── context ───────────────────────────────────────────────────────────────────
|
||||
|
||||
const DataSourceContext = createContext<DataSourceContextValue | null>(null)
|
||||
|
||||
const LS_MODE = "routerlists:data-source"
|
||||
const LS_BACKEND = "routerlists:backend-url"
|
||||
const DEFAULT_URL = "http://localhost:8000"
|
||||
|
||||
export function DataSourceProvider({ children }: { children: React.ReactNode }) {
|
||||
const [mode, setModeState] = useState<DataSourceMode>("mock")
|
||||
const [backendUrl, setBackendUrlState] = useState(DEFAULT_URL)
|
||||
const [backendStatus, setBackendStatus] = useState<boolean | undefined>(undefined)
|
||||
|
||||
// Restore from localStorage on mount
|
||||
useEffect(() => {
|
||||
const storedMode = localStorage.getItem(LS_MODE) as DataSourceMode | null
|
||||
const storedUrl = localStorage.getItem(LS_BACKEND)
|
||||
if (storedMode === "mock" || storedMode === "live") setModeState(storedMode)
|
||||
if (storedUrl) setBackendUrlState(storedUrl)
|
||||
}, [])
|
||||
|
||||
const setMode = useCallback((m: DataSourceMode) => {
|
||||
setModeState(m)
|
||||
localStorage.setItem(LS_MODE, m)
|
||||
}, [])
|
||||
|
||||
const setBackendUrl = useCallback((url: string) => {
|
||||
setBackendUrlState(url)
|
||||
localStorage.setItem(LS_BACKEND, url)
|
||||
}, [])
|
||||
|
||||
const checkBackend = useCallback(async () => {
|
||||
const url = (localStorage.getItem(LS_BACKEND) ?? DEFAULT_URL).replace(/\/$/, "")
|
||||
try {
|
||||
const res = await fetch(`${url}/health`, { signal: AbortSignal.timeout(3000) })
|
||||
setBackendStatus(res.ok)
|
||||
} catch {
|
||||
setBackendStatus(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Auto-check when mode switches to live
|
||||
useEffect(() => {
|
||||
if (mode === "live") checkBackend()
|
||||
}, [mode, checkBackend])
|
||||
|
||||
return (
|
||||
<DataSourceContext.Provider value={{ mode, setMode, backendUrl, setBackendUrl, backendStatus, checkBackend }}>
|
||||
{children}
|
||||
</DataSourceContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export function useDataSource(): DataSourceContextValue {
|
||||
const ctx = useContext(DataSourceContext)
|
||||
if (!ctx) throw new Error("useDataSource must be used inside <DataSourceProvider>")
|
||||
return ctx
|
||||
}
|
||||
Reference in New Issue
Block a user