Add accounts list as a provider
This commit is contained in:
		
							
								
								
									
										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> | ||||||
|       )} |       )} | ||||||
|     /> |     /> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user