You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
2.0 KiB
TypeScript

import { ComponentChild, Fragment, VNode, createContext, h } from "preact";
import { useContext, useEffect, useMemo, useReducer } from "preact/hooks";
import { Home } from "../Home/Home.ts";
import { Action, State, ViewState, ViewStateKind, reduce } from "./state.ts";
import { Dispatch } from "../../utils.ts";
import { saveStateToLocalStorage } from "../../state/store.ts";
import { Const } from "../../../common/utils.ts";
import { SchemaEditor } from "../SchemaEditor/SchemaEditor.ts";
import { goHome } from "./state.ts";
import { MakeClient, makeClient } from "../../../common/deps/yaypi.ts";
import { Api } from "../../../common/api.ts";
type ViewStates = {
[K in ViewState["kind"]]: ViewState & { kind: K };
};
type ViewRegistry_ = {
// @ts-ignore: weird
[K in keyof ViewStates]: ViewStates[K]["state"];
};
type ViewRegistry = {
[K in keyof ViewRegistry_]: (p: {
state: ViewRegistry_[K];
dispatch: Dispatch<Action>;
client: Client;
}) => VNode;
};
const VIEW_REGISTRY: ViewRegistry = {
Home: (p) => h(Home, p),
SchemaEditor: (p) => h(SchemaEditor, p),
};
const AppView = (
p: ViewState & { dispatch: Dispatch<Action>; client: Client },
) => {
const View = VIEW_REGISTRY[p.kind];
return h(View as any, p);
};
const VIEW_NAMES: Record<ViewStateKind, string> = {
Home: "Home",
SchemaEditor: "Schema Editor",
};
const Layout = (p: {
state: State;
dispatch: Dispatch<Action>;
client: Client;
}) => {
const view = h(AppView, {
...p.state.view,
dispatch: p.dispatch,
client: p.client,
});
const name = VIEW_NAMES[p.state.view.kind];
const onClickHome = () => {
p.dispatch(goHome());
};
return h(
Fragment,
{},
h("nav", {}, h("a", { onClick: onClickHome }, "Zchema"), h("a", {}, name)),
h("main", {}, view),
);
};
export const App = (p: State) => {
const [appState, dispatch] = useReducer(reduce, p);
const client = useMemo(() => makeClient(Api, "/api"), []);
useEffect(() => {
saveStateToLocalStorage(appState as Const<State>);
}, [appState]);
return h(Layout, { state: appState, dispatch, client });
};