96 lines
2.2 KiB
TypeScript
96 lines
2.2 KiB
TypeScript
import { createContext, use, useEffect, useRef } from "react";
|
|
import { Transactions } from "./transactions";
|
|
import { View } from "react-native";
|
|
import { Settings } from "./settings";
|
|
import type { AuthData } from "@money/shared/auth";
|
|
import { Budget } from "./budget";
|
|
import { ShortcutProvider, ShortcutDebug, keysStore } from "../lib/shortcuts";
|
|
import { useShortcut } from "../lib/shortcuts/hooks";
|
|
|
|
const PAGES = {
|
|
"/": {
|
|
screen: <Transactions />,
|
|
key: "1",
|
|
},
|
|
"/budget": {
|
|
screen: <Budget />,
|
|
key: "2",
|
|
},
|
|
"/settings": {
|
|
screen: <Settings />,
|
|
key: "3",
|
|
children: {
|
|
"/accounts": {},
|
|
"/family": {},
|
|
},
|
|
},
|
|
};
|
|
|
|
type Join<A extends string, B extends string> = `${A}${B}` extends `${infer X}`
|
|
? X
|
|
: never;
|
|
|
|
type ChildRoutes<Parent extends string, Children> = {
|
|
[K in keyof Children & string]: K extends `/${string}`
|
|
? Join<Parent, K>
|
|
: never;
|
|
}[keyof Children & string];
|
|
|
|
type Routes<T> = {
|
|
[K in keyof T & string]:
|
|
| K
|
|
| (T[K] extends { children: infer C } ? ChildRoutes<K, C> : never);
|
|
}[keyof T & string];
|
|
|
|
export type Route = Routes<typeof PAGES>;
|
|
|
|
interface RouterContextType {
|
|
auth: AuthData | null;
|
|
route: Route;
|
|
setRoute: (route: Route) => void;
|
|
}
|
|
|
|
export const RouterContext = createContext<RouterContextType>({
|
|
auth: null,
|
|
route: "/",
|
|
setRoute: () => {},
|
|
});
|
|
|
|
type AppProps = {
|
|
auth: AuthData | null;
|
|
route: Route;
|
|
setRoute: (page: Route) => void;
|
|
};
|
|
|
|
export function App({ auth, route, setRoute }: AppProps) {
|
|
return (
|
|
<RouterContext.Provider value={{ auth, route, setRoute }}>
|
|
<ShortcutProvider>
|
|
<ShortcutDebug />
|
|
<Main />
|
|
</ShortcutProvider>
|
|
</RouterContext.Provider>
|
|
);
|
|
}
|
|
|
|
function Main() {
|
|
const { route, setRoute } = use(RouterContext);
|
|
|
|
for (const [route, page] of Object.entries(PAGES)) {
|
|
useShortcut(page.key, () => setRoute(route as Route));
|
|
}
|
|
|
|
const match =
|
|
route in PAGES
|
|
? (route as keyof typeof PAGES)
|
|
: (Object.keys(PAGES)
|
|
.sort((a, b) => b.length - a.length)
|
|
.find((p) => route.startsWith(p)) as keyof typeof PAGES);
|
|
|
|
return (
|
|
<View style={{ backgroundColor: "white", flex: 1 }}>
|
|
{PAGES[match].screen}
|
|
</View>
|
|
);
|
|
}
|