diff --git a/src/App.tsx b/src/App.tsx index 03b54f3..8922571 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,5 @@ import { createBrowserRouter, RouterProvider } from 'react-router-dom'; +import { ColorFunctionProvider } from './ColorFunctionContext'; import { Notifications } from './components/Notifications'; import { Home } from './pages/Home'; import { MainLayout } from './pages/MainLayout'; @@ -28,9 +29,11 @@ const routes = createBrowserRouter([ export function App() { return ( - - Color Lab - - + + + Color Lab + + + ); } diff --git a/src/ColorFunctionContext.tsx b/src/ColorFunctionContext.tsx new file mode 100644 index 0000000..eba7730 --- /dev/null +++ b/src/ColorFunctionContext.tsx @@ -0,0 +1,56 @@ +import { + createContext, + ReactNode, + useCallback, + useEffect, + useMemo, + useState, + useTransition, +} from 'react'; +import type * as Wasm from './pkg/color_module'; +import init from './pkg/color_module'; + +export const ColorFunctionContext = createContext<{ + colorFn: Wasm.InitOutput | null; + isLoading: boolean; + error: Error | null; +}>({ + colorFn: null, + isLoading: true, + error: null, +}); + +type WasmProviderProps = { + children?: ReactNode; +}; + +export function ColorFunctionProvider({ children }: WasmProviderProps) { + const [wasmInstance, setWasmInstance] = useState(null); + const [isPending, startTransition] = useTransition(); + const [error, setError] = useState(null); + + const loadWasm = useCallback(() => { + startTransition(async () => { + try { + const wasm = await init(); + setWasmInstance(wasm); + } catch (e) { + console.error('[Load WASM]', e); + setError(e); + } + }); + }, []); + const contextValue = useMemo( + () => ({ + colorFn: wasmInstance, + isLoading: isPending, + error, + }), + [wasmInstance, isPending, error], + ); + useEffect(() => { + loadWasm(); + }, []); + + return {children}; +} diff --git a/src/pages/SchemeDetail.tsx b/src/pages/SchemeDetail.tsx index b509597..e0be4a3 100644 --- a/src/pages/SchemeDetail.tsx +++ b/src/pages/SchemeDetail.tsx @@ -1,3 +1,23 @@ +import { isNil } from 'lodash-es'; +import { useEffect } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; +import { useScheme } from '../stores/schemes'; + export function SchemeDetail() { - return
; + const { id } = useParams(); + const scheme = useScheme(id); + const navigate = useNavigate(); + + useEffect(() => { + if (isNil(scheme)) { + navigate('../not-found'); + } + }, [scheme, navigate]); + + return ( +
+

{scheme?.name}

+

{scheme?.description}

+
+ ); }