feat: add account management types and zustand store implementation

This commit is contained in:
GW_MC
2026-05-28 05:47:54 +00:00
parent a60cf8fc43
commit a725d348e1
5 changed files with 117 additions and 1 deletions

View File

@@ -24,6 +24,7 @@
"@tauri-apps/plugin-opener": "^2", "@tauri-apps/plugin-opener": "^2",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"isbot": "^5",
"lucide-react": "^1.16.0", "lucide-react": "^1.16.0",
"radix-ui": "^1.4.3", "radix-ui": "^1.4.3",
"react": "^19.1.0", "react": "^19.1.0",
@@ -33,7 +34,8 @@
"tailwind-merge": "^3.6.0", "tailwind-merge": "^3.6.0",
"tailwindcss": "^4.3.0", "tailwindcss": "^4.3.0",
"tw-animate-css": "^1.4.0", "tw-animate-css": "^1.4.0",
"isbot": "^5" "vaul": "^1.1.2",
"zustand": "^5.0.13"
}, },
"devDependencies": { "devDependencies": {
"@react-router/dev": "^7.15.1", "@react-router/dev": "^7.15.1",

45
pnpm-lock.yaml generated
View File

@@ -62,6 +62,12 @@ importers:
tw-animate-css: tw-animate-css:
specifier: ^1.4.0 specifier: ^1.4.0
version: 1.4.0 version: 1.4.0
vaul:
specifier: ^1.1.2
version: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.15))(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
zustand:
specifier: ^5.0.13
version: 5.0.13(@types/react@19.2.15)(react@19.2.6)(use-sync-external-store@1.6.0(react@19.2.6))
devDependencies: devDependencies:
'@react-router/dev': '@react-router/dev':
specifier: ^7.15.1 specifier: ^7.15.1
@@ -3185,6 +3191,12 @@ packages:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
vaul@1.1.2:
resolution: {integrity: sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==}
peerDependencies:
react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc
vite-node@3.2.4: vite-node@3.2.4:
resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@@ -3286,6 +3298,24 @@ packages:
zod@3.25.76: zod@3.25.76:
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
zustand@5.0.13:
resolution: {integrity: sha512-efI2tVaVQPqtOh114loML/Z80Y4NP3yc+Ff0fYiZJPauNeWZeIp/bRFD7I9bfmCOYBh/PHxlglQ9+wvlwnPikQ==}
engines: {node: '>=12.20.0'}
peerDependencies:
'@types/react': '>=18.0.0'
immer: '>=9.0.6'
react: '>=18.0.0'
use-sync-external-store: '>=1.2.0'
peerDependenciesMeta:
'@types/react':
optional: true
immer:
optional: true
react:
optional: true
use-sync-external-store:
optional: true
snapshots: snapshots:
'@babel/code-frame@7.29.7': '@babel/code-frame@7.29.7':
@@ -6377,6 +6407,15 @@ snapshots:
vary@1.1.2: {} vary@1.1.2: {}
vaul@1.1.2(@types/react-dom@19.2.3(@types/react@19.2.15))(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6):
dependencies:
'@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.15))(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
react: 19.2.6
react-dom: 19.2.6(react@19.2.6)
transitivePeerDependencies:
- '@types/react'
- '@types/react-dom'
vite-node@3.2.4(@types/node@25.9.1)(jiti@2.7.0)(lightningcss@1.32.0): vite-node@3.2.4(@types/node@25.9.1)(jiti@2.7.0)(lightningcss@1.32.0):
dependencies: dependencies:
cac: 6.7.14 cac: 6.7.14
@@ -6462,3 +6501,9 @@ snapshots:
zod: 3.25.76 zod: 3.25.76
zod@3.25.76: {} zod@3.25.76: {}
zustand@5.0.13(@types/react@19.2.15)(react@19.2.6)(use-sync-external-store@1.6.0(react@19.2.6)):
optionalDependencies:
'@types/react': 19.2.15
react: 19.2.6
use-sync-external-store: 1.6.0(react@19.2.6)

View File

@@ -0,0 +1,11 @@
export type AccountType = 'Asset' | 'Liability' | 'Unknown';
export type Account = {
id: string;
name: string;
accountType: AccountType;
balance: string;
accountCategory: string;
//
createdAt: string;
updatedAt: string;
};

50
src/store/accounts.ts Normal file
View File

@@ -0,0 +1,50 @@
import { StateCreator } from 'zustand';
import { Account as TauriAccount } from '../lib/tauri/types/account';
export type Account = TauriAccount;
export interface AccountsSlice {
accounts: Account[];
selectedAccountId?: string;
//
selectAccount: (accountId: string) => void;
addAccount: (account: Account) => void;
removeAccount: (accountId: string) => void;
updateAccount: (account: Account) => void;
reloadAccounts: (accounts?: Account[]) => void;
}
export const createAccountsSlice: StateCreator<AccountsSlice, [], [], AccountsSlice> = (set) => ({
accounts: [
{
id: '1',
name: 'Checking Account',
accountType: 'Asset',
balance: '5000.00',
accountCategory: 'Bank',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
},
],
selectedAccountId: '1',
selectAccount: (accountId) =>
set(() => {
return { selectedAccountId: accountId };
}),
addAccount: (account) =>
set((state) => {
return { accounts: [...state.accounts, account] };
}),
removeAccount: (accountId) =>
set((state) => {
return { accounts: state.accounts.filter((account) => account.id !== accountId) };
}),
updateAccount: (updatedAccount) =>
set((state) => {
return { accounts: state.accounts.map((account) => (account.id === updatedAccount.id ? updatedAccount : account)) };
}),
reloadAccounts: (accounts?: Account[]) =>
set((_state) => {
return { accounts: accounts ?? [] };
}),
});

8
src/store/index.ts Normal file
View File

@@ -0,0 +1,8 @@
import { create } from 'zustand';
import { type AccountsSlice, createAccountsSlice } from './accounts';
export interface AppStore extends AccountsSlice {}
export const useAppStore = create<AppStore>()((...a) => ({
...createAccountsSlice(...a),
}));