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
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 });
|
|
};
|