Add account type
This commit is contained in:
parent
342af2c443
commit
5a51dee8b0
1
moneymgr_backend/assets/cash.svg
Normal file
1
moneymgr_backend/assets/cash.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3,6H21V18H3V6M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9M7,8A2,2 0 0,1 5,10V14A2,2 0 0,1 7,16H17A2,2 0 0,1 19,14V10A2,2 0 0,1 17,8H7Z" /></svg>
|
After Width: | Height: | Size: 237 B |
1
moneymgr_backend/assets/credit-card.svg
Normal file
1
moneymgr_backend/assets/credit-card.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20,8H4V6H20M20,18H4V12H20M20,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V6C22,4.89 21.1,4 20,4Z" /></svg>
|
After Width: | Height: | Size: 190 B |
1
moneymgr_backend/assets/saving.svg
Normal file
1
moneymgr_backend/assets/saving.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M16,9C20,11 21,18 21,18C21,18 22,22 16,22C10,22 8,22 8,22C2,22 3,18 3,18C3,18 4,11 8,9M14,4L12,2L10,4L6,2L8,7H16L18,2L14,4Z" /></svg>
|
After Width: | Height: | Size: 202 B |
@ -43,6 +43,7 @@ CREATE TABLE accounts
|
|||||||
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
|
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
|
||||||
time_create BIGINT NOT NULL,
|
time_create BIGINT NOT NULL,
|
||||||
time_update BIGINT NOT NULL,
|
time_update BIGINT NOT NULL,
|
||||||
|
type VARCHAR(1) NOT NULL DEFAULT 'C',
|
||||||
default_account BOOLEAN NOT NULL DEFAULT false
|
default_account BOOLEAN NOT NULL DEFAULT false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
//! # Project constants
|
//! # Project constants
|
||||||
|
|
||||||
|
use crate::models::accounts::AccountType;
|
||||||
|
|
||||||
/// Length of generated tokens
|
/// Length of generated tokens
|
||||||
pub const TOKENS_LEN: usize = 50;
|
pub const TOKENS_LEN: usize = 50;
|
||||||
|
|
||||||
@ -24,3 +26,30 @@ pub const MAX_UPLOAD_FILE_SIZE: usize = 15 * 1024 * 1024;
|
|||||||
|
|
||||||
/// Minimum elapsed time before a file can be deleted by garbage collector (2 hours)
|
/// Minimum elapsed time before a file can be deleted by garbage collector (2 hours)
|
||||||
pub const MIN_FILE_LIFETIME: u64 = 3600 * 2;
|
pub const MIN_FILE_LIFETIME: u64 = 3600 * 2;
|
||||||
|
|
||||||
|
/// Description of an account type
|
||||||
|
#[derive(serde::Serialize, Debug)]
|
||||||
|
pub struct AccountTypeDesc {
|
||||||
|
label: &'static str,
|
||||||
|
code: AccountType,
|
||||||
|
icon: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enumeration of accounts types
|
||||||
|
pub const ACCOUNT_TYPES: [AccountTypeDesc; 3] = [
|
||||||
|
AccountTypeDesc {
|
||||||
|
label: "Cash",
|
||||||
|
code: AccountType::Cash,
|
||||||
|
icon: include_str!("../assets/cash.svg"),
|
||||||
|
},
|
||||||
|
AccountTypeDesc {
|
||||||
|
label: "Bank",
|
||||||
|
code: AccountType::Bank,
|
||||||
|
icon: include_str!("../assets/credit-card.svg"),
|
||||||
|
},
|
||||||
|
AccountTypeDesc {
|
||||||
|
label: "Saving",
|
||||||
|
code: AccountType::Saving,
|
||||||
|
icon: include_str!("../assets/saving.svg"),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::app_config::AppConfig;
|
use crate::app_config::AppConfig;
|
||||||
|
use crate::constants::{ACCOUNT_TYPES, AccountTypeDesc};
|
||||||
use actix_web::HttpResponse;
|
use actix_web::HttpResponse;
|
||||||
|
|
||||||
/// Serve robots.txt (disallow ranking)
|
/// Serve robots.txt (disallow ranking)
|
||||||
@ -57,6 +58,7 @@ impl Default for ServerConstraints {
|
|||||||
struct ServerConfig {
|
struct ServerConfig {
|
||||||
auth_disabled: bool,
|
auth_disabled: bool,
|
||||||
oidc_provider_name: &'static str,
|
oidc_provider_name: &'static str,
|
||||||
|
accounts_types: &'static [AccountTypeDesc],
|
||||||
constraints: ServerConstraints,
|
constraints: ServerConstraints,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +68,7 @@ impl Default for ServerConfig {
|
|||||||
auth_disabled: AppConfig::get().is_auth_disabled(),
|
auth_disabled: AppConfig::get().is_auth_disabled(),
|
||||||
oidc_provider_name: AppConfig::get().openid_provider().name,
|
oidc_provider_name: AppConfig::get().openid_provider().name,
|
||||||
constraints: Default::default(),
|
constraints: Default::default(),
|
||||||
|
accounts_types: &ACCOUNT_TYPES,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,31 @@
|
|||||||
use crate::models::users::UserID;
|
use crate::models::users::UserID;
|
||||||
use crate::schema::*;
|
use crate::schema::*;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
|
||||||
pub struct AccountID(pub i32);
|
pub struct AccountID(pub i32);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
|
||||||
|
pub enum AccountType {
|
||||||
|
#[serde(rename = "C")]
|
||||||
|
Cash,
|
||||||
|
#[serde(rename = "B")]
|
||||||
|
Bank,
|
||||||
|
#[serde(rename = "S")]
|
||||||
|
Saving,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for AccountType {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
serde_json::to_string(self).unwrap().replace('"', "")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Queryable, Debug, Clone, serde::Serialize)]
|
#[derive(Queryable, Debug, Clone, serde::Serialize)]
|
||||||
pub struct Account {
|
pub struct Account {
|
||||||
id: i32,
|
id: i32,
|
||||||
@ -12,6 +33,7 @@ pub struct Account {
|
|||||||
user_id: i32,
|
user_id: i32,
|
||||||
pub time_create: i64,
|
pub time_create: i64,
|
||||||
pub time_update: i64,
|
pub time_update: i64,
|
||||||
|
r#type: String,
|
||||||
pub default_account: bool,
|
pub default_account: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,13 +45,22 @@ impl Account {
|
|||||||
pub fn user_id(&self) -> UserID {
|
pub fn user_id(&self) -> UserID {
|
||||||
UserID(self.user_id)
|
UserID(self.user_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn account_type(&self) -> AccountType {
|
||||||
|
serde_json::from_str(format!("\"{}\"", self.r#type).as_str()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable)]
|
pub fn set_account_type(&mut self, t: AccountType) {
|
||||||
|
self.r#type = t.to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Insertable, Debug)]
|
||||||
#[diesel(table_name = accounts)]
|
#[diesel(table_name = accounts)]
|
||||||
pub struct NewAccount<'a> {
|
pub struct NewAccount<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub user_id: i32,
|
pub user_id: i32,
|
||||||
pub time_create: i64,
|
pub time_create: i64,
|
||||||
pub time_update: i64,
|
pub time_update: i64,
|
||||||
|
pub type_: String,
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,9 @@ diesel::table! {
|
|||||||
user_id -> Int4,
|
user_id -> Int4,
|
||||||
time_create -> Int8,
|
time_create -> Int8,
|
||||||
time_update -> Int8,
|
time_update -> Int8,
|
||||||
|
#[sql_name = "type"]
|
||||||
|
#[max_length = 1]
|
||||||
|
type_ -> Varchar,
|
||||||
default_account -> Bool,
|
default_account -> Bool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::connections::db_connection::db;
|
use crate::connections::db_connection::db;
|
||||||
use crate::controllers::server_controller::ServerConstraints;
|
use crate::controllers::server_controller::ServerConstraints;
|
||||||
use crate::models::accounts::{Account, AccountID, NewAccount};
|
use crate::models::accounts::{Account, AccountID, AccountType, NewAccount};
|
||||||
use crate::models::users::UserID;
|
use crate::models::users::UserID;
|
||||||
use crate::schema::accounts;
|
use crate::schema::accounts;
|
||||||
use crate::utils::time_utils::time;
|
use crate::utils::time_utils::time;
|
||||||
@ -10,6 +10,7 @@ use diesel::prelude::*;
|
|||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
pub struct UpdateAccountQuery {
|
pub struct UpdateAccountQuery {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub r#type: AccountType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UpdateAccountQuery {
|
impl UpdateAccountQuery {
|
||||||
@ -31,6 +32,7 @@ pub async fn create(user_id: UserID, query: &UpdateAccountQuery) -> anyhow::Resu
|
|||||||
user_id: user_id.0,
|
user_id: user_id.0,
|
||||||
time_create: time() as i64,
|
time_create: time() as i64,
|
||||||
time_update: time() as i64,
|
time_update: time() as i64,
|
||||||
|
type_: query.r#type.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let res: Account = diesel::insert_into(accounts::table)
|
let res: Account = diesel::insert_into(accounts::table)
|
||||||
@ -48,6 +50,7 @@ pub async fn update(id: AccountID, q: &UpdateAccountQuery) -> anyhow::Result<()>
|
|||||||
.set((
|
.set((
|
||||||
accounts::dsl::time_update.eq(time() as i64),
|
accounts::dsl::time_update.eq(time() as i64),
|
||||||
accounts::dsl::name.eq(&q.name),
|
accounts::dsl::name.eq(&q.name),
|
||||||
|
accounts::dsl::type_.eq(&q.r#type.to_string()),
|
||||||
))
|
))
|
||||||
.execute(&mut db()?)?;
|
.execute(&mut db()?)?;
|
||||||
|
|
||||||
|
24
moneymgr_web/package-lock.json
generated
24
moneymgr_web/package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
"@fontsource/roboto": "^5.2.5",
|
"@fontsource/roboto": "^5.2.5",
|
||||||
|
"@jsonjoy.com/base64": "^1.1.2",
|
||||||
"@mdi/js": "^7.4.47",
|
"@mdi/js": "^7.4.47",
|
||||||
"@mdi/react": "^1.6.1",
|
"@mdi/react": "^1.6.1",
|
||||||
"@mui/icons-material": "^7.0.1",
|
"@mui/icons-material": "^7.0.1",
|
||||||
@ -1321,6 +1322,22 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@jsonjoy.com/base64": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/streamich"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"tslib": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@mdi/js": {
|
"node_modules/@mdi/js": {
|
||||||
"version": "7.4.47",
|
"version": "7.4.47",
|
||||||
"resolved": "https://registry.npmjs.org/@mdi/js/-/js-7.4.47.tgz",
|
"resolved": "https://registry.npmjs.org/@mdi/js/-/js-7.4.47.tgz",
|
||||||
@ -4238,6 +4255,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/tslib": {
|
||||||
|
"version": "2.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||||
|
"license": "0BSD",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"node_modules/turbo-stream": {
|
"node_modules/turbo-stream": {
|
||||||
"version": "2.4.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
"@fontsource/roboto": "^5.2.5",
|
"@fontsource/roboto": "^5.2.5",
|
||||||
|
"@jsonjoy.com/base64": "^1.1.2",
|
||||||
"@mdi/js": "^7.4.47",
|
"@mdi/js": "^7.4.47",
|
||||||
"@mdi/react": "^1.6.1",
|
"@mdi/react": "^1.6.1",
|
||||||
"@mui/icons-material": "^7.0.1",
|
"@mui/icons-material": "^7.0.1",
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { APIClient } from "./ApiClient";
|
import { APIClient } from "./ApiClient";
|
||||||
|
import { ServerApi } from "./ServerApi";
|
||||||
|
|
||||||
export interface Account {
|
export interface Account {
|
||||||
id: number;
|
id: number;
|
||||||
@ -6,6 +7,7 @@ export interface Account {
|
|||||||
user_id: number;
|
user_id: number;
|
||||||
time_create: number;
|
time_create: number;
|
||||||
time_update: number;
|
time_update: number;
|
||||||
|
type: string;
|
||||||
default_account: boolean;
|
default_account: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +68,7 @@ export class AccountApi {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
jsonData: {
|
jsonData: {
|
||||||
name,
|
name,
|
||||||
|
type: ServerApi.Config.accounts_types[0].code,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -79,6 +82,7 @@ export class AccountApi {
|
|||||||
method: "PUT",
|
method: "PUT",
|
||||||
jsonData: {
|
jsonData: {
|
||||||
name: account.name,
|
name: account.name,
|
||||||
|
type: account.type,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,16 @@ import { APIClient } from "./ApiClient";
|
|||||||
export interface ServerConfig {
|
export interface ServerConfig {
|
||||||
auth_disabled: boolean;
|
auth_disabled: boolean;
|
||||||
oidc_provider_name: string;
|
oidc_provider_name: string;
|
||||||
|
accounts_types: AccountType[];
|
||||||
constraints: ServerConstraints;
|
constraints: ServerConstraints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AccountType {
|
||||||
|
label: string;
|
||||||
|
code: string;
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ServerConstraints {
|
export interface ServerConstraints {
|
||||||
token_name: LenConstraint;
|
token_name: LenConstraint;
|
||||||
token_ip_net: LenConstraint;
|
token_ip_net: LenConstraint;
|
||||||
|
@ -10,6 +10,8 @@ import { MoneyMgrWebRouteContainer } from "../widgets/MoneyMgrWebRouteContainer"
|
|||||||
import { TimeWidget } from "../widgets/TimeWidget";
|
import { TimeWidget } from "../widgets/TimeWidget";
|
||||||
import DeleteIcon from "@mui/icons-material/DeleteOutlined";
|
import DeleteIcon from "@mui/icons-material/DeleteOutlined";
|
||||||
import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider";
|
import { useConfirm } from "../hooks/context_providers/ConfirmDialogProvider";
|
||||||
|
import { AccountWidget } from "../widgets/AccountWidget";
|
||||||
|
import { ServerApi } from "../api/ServerApi";
|
||||||
|
|
||||||
export function AccountsRoute(): React.ReactElement {
|
export function AccountsRoute(): React.ReactElement {
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
@ -88,6 +90,35 @@ export function AccountsRoute(): React.ReactElement {
|
|||||||
|
|
||||||
const columns: GridColDef<(typeof list)[number]>[] = [
|
const columns: GridColDef<(typeof list)[number]>[] = [
|
||||||
{ field: "id", headerName: "ID", flex: 1 },
|
{ field: "id", headerName: "ID", flex: 1 },
|
||||||
|
{
|
||||||
|
field: "type",
|
||||||
|
headerName: "Type",
|
||||||
|
flex: 2,
|
||||||
|
editable: true,
|
||||||
|
type: "singleSelect",
|
||||||
|
valueOptions: ServerApi.Config.accounts_types.map((v) => {
|
||||||
|
return { label: v.label, value: v.code };
|
||||||
|
}),
|
||||||
|
renderCell(params) {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "start",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AccountWidget account={params.row} />
|
||||||
|
{
|
||||||
|
ServerApi.Config.accounts_types.find(
|
||||||
|
(t) => t.code === params.row.type
|
||||||
|
)!.label
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
{ field: "name", headerName: "Name", flex: 6, editable: true },
|
{ field: "name", headerName: "Name", flex: 6, editable: true },
|
||||||
{
|
{
|
||||||
field: "time_create",
|
field: "time_create",
|
||||||
@ -159,7 +190,10 @@ export function AccountsRoute(): React.ReactElement {
|
|||||||
return setDefaultAccount(updated);
|
return setDefaultAccount(updated);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updated.name !== original.name) {
|
if (
|
||||||
|
updated.name !== original.name ||
|
||||||
|
updated.type !== original.type
|
||||||
|
) {
|
||||||
return updateAccount(updated);
|
return updateAccount(updated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
25
moneymgr_web/src/widgets/AccountWidget.tsx
Normal file
25
moneymgr_web/src/widgets/AccountWidget.tsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { Account } from "../api/AccountApi";
|
||||||
|
import { ServerApi } from "../api/ServerApi";
|
||||||
|
import { useDarkTheme } from "../hooks/context_providers/DarkThemeProvider";
|
||||||
|
import { toBase64 } from "@jsonjoy.com/base64";
|
||||||
|
|
||||||
|
export function AccountWidget(p: { account: Account }): React.ReactElement {
|
||||||
|
const darkTheme = useDarkTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
style={{
|
||||||
|
height: "1.5em",
|
||||||
|
width: "1.5em",
|
||||||
|
backgroundColor: darkTheme.enabled ? "white" : "black",
|
||||||
|
mask: `url(\"data:image/svg+xml;base64,${toBase64(
|
||||||
|
new TextEncoder().encode(
|
||||||
|
ServerApi.Config.accounts_types.find(
|
||||||
|
(t) => t.code === p.account.type
|
||||||
|
)!.icon
|
||||||
|
)
|
||||||
|
)}\")`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { mdiAccount, mdiApi, mdiCashMultiple, mdiHome } from "@mdi/js";
|
import { mdiApi, mdiCashMultiple, mdiHome } from "@mdi/js";
|
||||||
import Icon from "@mdi/react";
|
import Icon from "@mdi/react";
|
||||||
import {
|
import {
|
||||||
Divider,
|
Divider,
|
||||||
@ -8,8 +8,10 @@ import {
|
|||||||
ListItemText,
|
ListItemText,
|
||||||
Typography,
|
Typography,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import React from "react";
|
||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
import { useAccounts } from "../hooks/AccountsListProvider";
|
import { useAccounts } from "../hooks/AccountsListProvider";
|
||||||
|
import { AccountWidget } from "./AccountWidget";
|
||||||
import { RouterLink } from "./RouterLink";
|
import { RouterLink } from "./RouterLink";
|
||||||
|
|
||||||
export function MoneyNavList(): React.ReactElement {
|
export function MoneyNavList(): React.ReactElement {
|
||||||
@ -59,7 +61,7 @@ export function MoneyNavList(): React.ReactElement {
|
|||||||
<NavLink
|
<NavLink
|
||||||
label={a.name}
|
label={a.name}
|
||||||
uri={`/account/${a.id}`}
|
uri={`/account/${a.id}`}
|
||||||
icon={<Icon path={mdiAccount} size={1} />}
|
icon={<AccountWidget account={a} />}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user