refactor: address frontend review feedback
Frontend verify / commits (pull_request) Successful in 29s
Frontend verify / security (pull_request) Successful in 9s
Frontend verify / verify (pull_request) Successful in 8m54s
Frontend verify / commits (push) Skipped
Frontend verify / security (push) Successful in 12s
Frontend verify / verify (push) Successful in 9m59s
Frontend verify / commits (pull_request) Successful in 29s
Frontend verify / security (pull_request) Successful in 9s
Frontend verify / verify (pull_request) Successful in 8m54s
Frontend verify / commits (push) Skipped
Frontend verify / security (push) Successful in 12s
Frontend verify / verify (push) Successful in 9m59s
This commit was merged in pull request #43.
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
enum BankName {
|
||||
AlfaBank = "Альфа-Банк",
|
||||
Sberbank = "Сбербанк",
|
||||
TBank = "Т-Банк",
|
||||
Vtb = "ВТБ",
|
||||
}
|
||||
|
||||
export { BankName };
|
||||
@@ -32,7 +32,6 @@ function bankToday() {
|
||||
function moneyCents(value: string): bigint | null {
|
||||
const normalized = value.trim().replace(",", ".");
|
||||
if (!/^-?\d+$|^-?\d+\.\d{1,2}$/.test(normalized))
|
||||
// eslint-disable-next-line unicorn/no-null -- The money parser’s callers distinguish invalid input with null.
|
||||
return null;
|
||||
|
||||
const [whole, fraction = ""] = normalized
|
||||
|
||||
@@ -2,129 +2,68 @@ import type { OperationIconProps } from "@wealthledger/icons";
|
||||
|
||||
import type { BankOperation } from "../api/queries";
|
||||
|
||||
type OperationIcon = {
|
||||
animation?: string;
|
||||
color: string;
|
||||
variant: OperationIconProps["variant"];
|
||||
};
|
||||
const categoryIcons: {
|
||||
appearance: OperationIconProps;
|
||||
name: string;
|
||||
}[] = [
|
||||
{ appearance: { color: "grape", variant: "wine" }, name: "Алкоголь" },
|
||||
{ appearance: { color: "green", variant: "deposit" }, name: "Вклады" },
|
||||
{ appearance: { color: "orange", variant: "home" }, name: "Жильё" },
|
||||
{ appearance: { color: "red", variant: "medical" }, name: "Здоровье" },
|
||||
{
|
||||
appearance: { color: "green", variant: "growth" },
|
||||
name: "Инвестиции и накопления",
|
||||
},
|
||||
{ appearance: { color: "orange", variant: "coffee" }, name: "Кафе" },
|
||||
{ appearance: { color: "blue", variant: "education" }, name: "Образование" },
|
||||
{ appearance: { color: "blue", variant: "transfer" }, name: "Переводы" },
|
||||
{
|
||||
appearance: { color: "orange", variant: "repayment" },
|
||||
name: "Погашение кредита",
|
||||
},
|
||||
{
|
||||
appearance: { color: "grape", variant: "subscriptions" },
|
||||
name: "Подписки",
|
||||
},
|
||||
{ appearance: { color: "grape", variant: "shopping" }, name: "Покупки" },
|
||||
{ appearance: { color: "green", variant: "basket" }, name: "Продукты" },
|
||||
{ appearance: { color: "blue", variant: "travel" }, name: "Путешествия" },
|
||||
{ appearance: { color: "grape", variant: "music" }, name: "Развлечения" },
|
||||
{ appearance: { color: "blue", variant: "wifi" }, name: "Связь и интернет" },
|
||||
{
|
||||
appearance: { color: "green", variant: "cashWithdrawal" },
|
||||
name: "Снятие наличных",
|
||||
},
|
||||
{ appearance: { color: "grape", variant: "dice" }, name: "Ставки" },
|
||||
{ appearance: { color: "green", variant: "shield" }, name: "Страхование" },
|
||||
{ appearance: { color: "orange", variant: "smoking" }, name: "Табак" },
|
||||
{ appearance: { color: "yellow", variant: "taxi" }, name: "Такси" },
|
||||
{ appearance: { color: "blue", variant: "car" }, name: "Транспорт" },
|
||||
{
|
||||
appearance: { color: "grape", variant: "server" },
|
||||
name: "Хостинг и ИИ-сервисы",
|
||||
},
|
||||
{
|
||||
appearance: { color: "blue", variant: "download" },
|
||||
name: "Цифровые покупки",
|
||||
},
|
||||
];
|
||||
|
||||
const categoryIcons: Record<string, OperationIcon> = {
|
||||
"алкоголь": {
|
||||
animation: "wine",
|
||||
color: "grape",
|
||||
variant: "wine",
|
||||
},
|
||||
"вклады": {
|
||||
animation: "deposit",
|
||||
color: "green",
|
||||
variant: "deposit",
|
||||
},
|
||||
"жилье": { color: "orange", variant: "home" },
|
||||
"здоровье": { color: "red", variant: "medical" },
|
||||
"инвестиции и накопления": {
|
||||
animation: "growth",
|
||||
color: "green",
|
||||
variant: "growth",
|
||||
},
|
||||
"кафе": {
|
||||
animation: "coffee",
|
||||
color: "orange",
|
||||
variant: "coffee",
|
||||
},
|
||||
"образование": {
|
||||
color: "blue",
|
||||
variant: "education",
|
||||
},
|
||||
"переводы": {
|
||||
animation: "transfer",
|
||||
color: "blue",
|
||||
variant: "transfer",
|
||||
},
|
||||
"погашение кредита": {
|
||||
animation: "repayment",
|
||||
color: "orange",
|
||||
variant: "repayment",
|
||||
},
|
||||
"подписки": {
|
||||
color: "grape",
|
||||
variant: "subscriptions",
|
||||
},
|
||||
"покупки": {
|
||||
color: "grape",
|
||||
variant: "shopping",
|
||||
},
|
||||
"продукты": {
|
||||
animation: "basket",
|
||||
color: "green",
|
||||
variant: "basket",
|
||||
},
|
||||
"путешествия": {
|
||||
color: "blue",
|
||||
variant: "travel",
|
||||
},
|
||||
"развлечения": {
|
||||
color: "grape",
|
||||
variant: "music",
|
||||
},
|
||||
"связь и интернет": {
|
||||
animation: "wifi",
|
||||
color: "blue",
|
||||
variant: "wifi",
|
||||
},
|
||||
"снятие наличных": {
|
||||
color: "green",
|
||||
variant: "cashWithdrawal",
|
||||
},
|
||||
"ставки": {
|
||||
color: "grape",
|
||||
variant: "dice",
|
||||
},
|
||||
"страхование": {
|
||||
color: "green",
|
||||
variant: "shield",
|
||||
},
|
||||
"табак": {
|
||||
color: "orange",
|
||||
variant: "smoking",
|
||||
},
|
||||
"такси": {
|
||||
color: "yellow",
|
||||
variant: "taxi",
|
||||
},
|
||||
"транспорт": {
|
||||
animation: "car",
|
||||
color: "blue",
|
||||
variant: "car",
|
||||
},
|
||||
"хостинг и ии-сервисы": {
|
||||
animation: "server",
|
||||
color: "grape",
|
||||
variant: "server",
|
||||
},
|
||||
"цифровые покупки": {
|
||||
color: "blue",
|
||||
variant: "download",
|
||||
},
|
||||
};
|
||||
|
||||
const otherIcon: OperationIcon = {
|
||||
animation: "grid",
|
||||
const otherIcon: OperationIconProps = {
|
||||
color: "gray",
|
||||
variant: "grid",
|
||||
};
|
||||
|
||||
const operationIcons: Record<
|
||||
Exclude<BankOperation["kind"], "expense">,
|
||||
OperationIcon
|
||||
OperationIconProps
|
||||
> = {
|
||||
refund: { color: "teal", variant: "refund" },
|
||||
topup: {
|
||||
animation: "topup",
|
||||
color: "green",
|
||||
variant: "topup",
|
||||
},
|
||||
transfer: {
|
||||
animation: "transfer",
|
||||
color: "blue",
|
||||
variant: "transfer",
|
||||
},
|
||||
@@ -135,17 +74,20 @@ function bankOperationAppearance(
|
||||
categoryName?: null | string,
|
||||
) {
|
||||
if (kind !== "expense")
|
||||
// eslint-disable-next-line security/detect-object-injection -- Operation kinds are finite; category names are guarded by Object.hasOwn.
|
||||
// eslint-disable-next-line security/detect-object-injection -- Operation kinds are a finite API union.
|
||||
return operationIcons[kind];
|
||||
|
||||
const name = categoryName
|
||||
?.trim()
|
||||
.toLocaleLowerCase("ru-RU")
|
||||
.replaceAll("ё", "е");
|
||||
const name = normalizeCategoryName(categoryName ?? "");
|
||||
|
||||
return name && Object.hasOwn(categoryIcons, name)
|
||||
? categoryIcons[name] // eslint-disable-line security/detect-object-injection -- Operation kinds are finite; category names are guarded by Object.hasOwn.
|
||||
: otherIcon;
|
||||
const category = categoryIcons.find(
|
||||
item => normalizeCategoryName(item.name) === name,
|
||||
);
|
||||
|
||||
return category?.appearance ?? otherIcon;
|
||||
}
|
||||
|
||||
function normalizeCategoryName(name: string) {
|
||||
return name.trim().toLocaleLowerCase("ru-RU").replaceAll("ё", "е");
|
||||
}
|
||||
|
||||
export { bankOperationAppearance };
|
||||
|
||||
Reference in New Issue
Block a user