Add accounts list as a provider
This commit is contained in:
parent
90bb4db806
commit
ad4c0d2885
41
moneymgr_web/src/api/AccountApi.ts
Normal file
41
moneymgr_web/src/api/AccountApi.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { APIClient } from "./ApiClient";
|
||||||
|
|
||||||
|
export interface Account {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
user_id: number;
|
||||||
|
time_create: number;
|
||||||
|
time_update: number;
|
||||||
|
default_account: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AccountsList {
|
||||||
|
list: Account[];
|
||||||
|
|
||||||
|
constructor(list: Account[]) {
|
||||||
|
this.list = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a single account by its id
|
||||||
|
*/
|
||||||
|
get(id: number): Account | null {
|
||||||
|
return this.list.find((a) => a.id === id) ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AccountApi {
|
||||||
|
/**
|
||||||
|
* Get the current list of accounts of the user
|
||||||
|
*/
|
||||||
|
static async GetList(): Promise<AccountsList> {
|
||||||
|
const array = (
|
||||||
|
await APIClient.exec({
|
||||||
|
uri: "/accounts",
|
||||||
|
method: "GET",
|
||||||
|
})
|
||||||
|
).data;
|
||||||
|
|
||||||
|
return new AccountsList(array);
|
||||||
|
}
|
||||||
|
}
|
68
moneymgr_web/src/hooks/AccountsListProvider.tsx
Normal file
68
moneymgr_web/src/hooks/AccountsListProvider.tsx
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Account, AccountApi, AccountsList } from "../api/AccountApi";
|
||||||
|
import { AsyncWidget } from "../widgets/AsyncWidget";
|
||||||
|
|
||||||
|
interface AccountContext {
|
||||||
|
list: AccountsList;
|
||||||
|
reload: () => void;
|
||||||
|
get(id: number): Account | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AccountContextK = React.createContext<AccountContext | null>(null);
|
||||||
|
|
||||||
|
export function AccountsListProvider(
|
||||||
|
p: React.PropsWithChildren
|
||||||
|
): React.ReactElement {
|
||||||
|
const [list, setList] = React.useState<AccountsList | null>(null);
|
||||||
|
|
||||||
|
const loadKey = React.useRef(1);
|
||||||
|
|
||||||
|
const loadPromise = React.useRef<(() => void) | null>(null);
|
||||||
|
|
||||||
|
const load = async () => {
|
||||||
|
setList(await AccountApi.GetList());
|
||||||
|
};
|
||||||
|
|
||||||
|
const onReload = async () => {
|
||||||
|
loadKey.current += 1;
|
||||||
|
setList(null);
|
||||||
|
|
||||||
|
return new Promise<void>((res) => {
|
||||||
|
loadPromise.current = () => {
|
||||||
|
res();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AsyncWidget
|
||||||
|
loadKey={loadKey.current}
|
||||||
|
load={load}
|
||||||
|
errMsg="Failed to load the list of accounts!"
|
||||||
|
build={() => {
|
||||||
|
if (loadPromise.current != null) {
|
||||||
|
loadPromise.current();
|
||||||
|
loadPromise.current = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AccountContextK
|
||||||
|
value={{
|
||||||
|
list: list!,
|
||||||
|
get(id) {
|
||||||
|
return list!.get(id);
|
||||||
|
},
|
||||||
|
reload: onReload,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{p.children}
|
||||||
|
</AccountContextK>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useAccounts(): AccountContext {
|
||||||
|
return React.use(AccountContextK)!;
|
||||||
|
}
|
@ -1,3 +1,7 @@
|
|||||||
|
import { useAccounts } from "../hooks/AccountsListProvider";
|
||||||
|
|
||||||
export function HomeRoute(): React.ReactElement {
|
export function HomeRoute(): React.ReactElement {
|
||||||
|
const accounts = useAccounts();
|
||||||
|
console.log(accounts.list.list);
|
||||||
return <>home authenticated todo</>;
|
return <>home authenticated todo</>;
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,10 @@ import * as React from "react";
|
|||||||
import { Outlet, useNavigate } from "react-router-dom";
|
import { Outlet, useNavigate } from "react-router-dom";
|
||||||
import { useAuth } from "../App";
|
import { useAuth } from "../App";
|
||||||
import { AuthApi, AuthInfo } from "../api/AuthApi";
|
import { AuthApi, AuthInfo } from "../api/AuthApi";
|
||||||
|
import { AccountsListProvider } from "../hooks/AccountsListProvider";
|
||||||
import { AsyncWidget } from "./AsyncWidget";
|
import { AsyncWidget } from "./AsyncWidget";
|
||||||
import { MoneyWebAppBar } from "./MoneyWebAppBar";
|
|
||||||
import { MoneyNavList } from "./MoneyNavList";
|
import { MoneyNavList } from "./MoneyNavList";
|
||||||
|
import { MoneyWebAppBar } from "./MoneyWebAppBar";
|
||||||
|
|
||||||
interface AuthInfoContext {
|
interface AuthInfoContext {
|
||||||
info: AuthInfo;
|
info: AuthInfo;
|
||||||
@ -46,44 +47,46 @@ export function BaseAuthenticatedPage(): React.ReactElement {
|
|||||||
reloadAuthInfo: load,
|
reloadAuthInfo: load,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<AccountsListProvider>
|
||||||
component="div"
|
|
||||||
sx={{
|
|
||||||
minHeight: "100vh",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
backgroundColor: (theme) =>
|
|
||||||
theme.palette.mode === "light"
|
|
||||||
? theme.palette.grey[100]
|
|
||||||
: theme.palette.grey[900],
|
|
||||||
color: (theme) =>
|
|
||||||
theme.palette.mode === "light"
|
|
||||||
? theme.palette.grey[900]
|
|
||||||
: theme.palette.grey[100],
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MoneyWebAppBar onSignOut={signOut} />
|
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
|
component="div"
|
||||||
sx={{
|
sx={{
|
||||||
|
minHeight: "100vh",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flex: "2",
|
flexDirection: "column",
|
||||||
|
backgroundColor: (theme) =>
|
||||||
|
theme.palette.mode === "light"
|
||||||
|
? theme.palette.grey[100]
|
||||||
|
: theme.palette.grey[900],
|
||||||
|
color: (theme) =>
|
||||||
|
theme.palette.mode === "light"
|
||||||
|
? theme.palette.grey[900]
|
||||||
|
: theme.palette.grey[100],
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MoneyNavList />
|
<MoneyWebAppBar onSignOut={signOut} />
|
||||||
<div
|
|
||||||
style={{
|
<Box
|
||||||
flexGrow: 1,
|
sx={{
|
||||||
flexShrink: 0,
|
|
||||||
flexBasis: 0,
|
|
||||||
minWidth: 0,
|
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
flex: "2",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Outlet />
|
<MoneyNavList />
|
||||||
</div>
|
<div
|
||||||
|
style={{
|
||||||
|
flexGrow: 1,
|
||||||
|
flexShrink: 0,
|
||||||
|
flexBasis: 0,
|
||||||
|
minWidth: 0,
|
||||||
|
display: "flex",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Outlet />
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</AccountsListProvider>
|
||||||
</AuthInfoContextK>
|
</AuthInfoContextK>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user