From 1891d0f9e9471c155890df6ed67d0b0cd888599a Mon Sep 17 00:00:00 2001 From: gin-melodic <4485145+gin-melodic@users.noreply.github.com> Date: Sun, 4 Jan 2026 17:04:27 +0800 Subject: [PATCH] feat: improve account delete logic. Delete account directly if has not transport records. --- src/components/features/EditAccountModal.tsx | 144 ++++++++++++------- src/lib/hooks/index.ts | 1 + src/lib/hooks/useAccounts.ts | 9 ++ src/lib/services/accountService.ts | 4 + src/locales/en/accounts.json | 5 +- src/locales/ja/accounts.json | 5 +- src/locales/zh-CN/accounts.json | 5 +- src/locales/zh-TW/accounts.json | 5 +- 8 files changed, 121 insertions(+), 57 deletions(-) diff --git a/src/components/features/EditAccountModal.tsx b/src/components/features/EditAccountModal.tsx index 279cc64..728d66d 100644 --- a/src/components/features/EditAccountModal.tsx +++ b/src/components/features/EditAccountModal.tsx @@ -2,6 +2,7 @@ import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useGlobal } from '@/context/GlobalContext'; import { useUpdateAccount, useDeleteAccount, useCreateAccount, useAllAccounts, AccountType, Account } from '@/lib/hooks'; +import { accountService } from '@/lib/services'; import { Dialog, DialogContent, @@ -71,6 +72,8 @@ const EditAccountForm = ({ account, onClose }: EditAccountFormProps) => { const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false); const [migrationTargets, setMigrationTargets] = useState>({}); + const [transactionCount, setTransactionCount] = useState(null); + const [isLoadingCount, setIsLoadingCount] = useState(false); const handleAddChild = () => { setChildren([...children, { @@ -158,7 +161,25 @@ const EditAccountForm = ({ account, onClose }: EditAccountFormProps) => { ); }; - const prepareDelete = () => { + const prepareDelete = async () => { + setIsLoadingCount(true); + setTransactionCount(null); + try { + // Get transaction count for this account and all children + const accountIds = [account.id, ...children.filter(c => !c.isNew).map(c => c.id)]; + let totalCount = 0; + for (const id of accountIds) { + const { count } = await accountService.getTransactionCount(id); + totalCount += count; + } + setTransactionCount(totalCount); + } catch (error) { + console.error('Failed to get transaction count:', error); + // Default to require migration if we can't determine + setTransactionCount(1); + } finally { + setIsLoadingCount(false); + } setMigrationTargets({}); setIsDeleteAlertOpen(true); }; @@ -317,60 +338,85 @@ const EditAccountForm = ({ account, onClose }: EditAccountFormProps) => { {t('accounts:delete_account_title')}
-

{t('accounts:delete_account_confirm')}

-
- {requiredCurrencies.map(curr => { - const targets = getAvailableTargets(curr); - const isTargetMissing = targets.length === 0; - - return ( -
- - - {isTargetMissing ? ( -
- - - {t('accounts:no_available_funding_accounts', { - type: account?.type, - defaultValue: `No available ${account?.type} funding accounts, please create one before proceeding with deletion` - })} - + {isLoadingCount ? ( +

{t('common:loading') || '加载中...'}

+ ) : transactionCount === 0 ? ( + // No transactions - simple confirmation +

{t('accounts:delete_no_transactions_confirm')}

+ ) : ( + // Has transactions - show migration UI + <> +

{t('accounts:delete_account_confirm')}

+
+ {requiredCurrencies.map(curr => { + const targets = getAvailableTargets(curr); + const isTargetMissing = targets.length === 0; + + return ( +
+ + + {isTargetMissing ? ( +
+ + + {t('accounts:no_available_funding_accounts', { + type: account?.type, + defaultValue: `No available ${account?.type} funding accounts, please create one before proceeding with deletion` + })} + +
+ ) : ( + + )}
- ) : ( - - )} -
- ); - })} -
+ ); + })} +
+ + )}
- + {transactionCount === 0 ? ( + // No transactions - direct delete button + + ) : ( + // Has transactions - require migration selection + + )} diff --git a/src/lib/hooks/index.ts b/src/lib/hooks/index.ts index 13f77a7..1fcd20c 100644 --- a/src/lib/hooks/index.ts +++ b/src/lib/hooks/index.ts @@ -9,6 +9,7 @@ export { useDeleteAccount, useAllAccounts, useAllAccountsSuspense, + useAccountTransactionCount, accountKeys, } from './useAccounts'; diff --git a/src/lib/hooks/useAccounts.ts b/src/lib/hooks/useAccounts.ts index dc1e971..3ecbb32 100644 --- a/src/lib/hooks/useAccounts.ts +++ b/src/lib/hooks/useAccounts.ts @@ -108,6 +108,15 @@ export function useDeleteAccount() { }); } +// Get account transaction count +export function useAccountTransactionCount(id: string, enabled = true) { + return useQuery({ + queryKey: [...accountKeys.detail(id), 'transactionCount'], + queryFn: () => accountService.getTransactionCount(id), + enabled: !!id && enabled, + }); +} + // ========== Convenience Hooks ========== // Get all accounts (flat list) diff --git a/src/lib/services/accountService.ts b/src/lib/services/accountService.ts index e86c1b2..51c5192 100644 --- a/src/lib/services/accountService.ts +++ b/src/lib/services/accountService.ts @@ -37,4 +37,8 @@ export const accountService = { method: 'DELETE', body: migrationTargets ? JSON.stringify({ migrationTargets }) : undefined, }), + + getTransactionCount: (id: string): Promise<{ count: number }> => + apiRequest(`/api/accounts/${id}/transaction-count`), }; + diff --git a/src/locales/en/accounts.json b/src/locales/en/accounts.json index b152908..ffb8fbb 100644 --- a/src/locales/en/accounts.json +++ b/src/locales/en/accounts.json @@ -28,12 +28,13 @@ "delete_child_hint": "To delete a sub-account, please go to its specific page or delete the parent account.", "delete_account_title": "Delete Account", "delete_account_confirm": "Are you sure you want to delete this account? This action cannot be undone.", - "migrate_balance_for": "Migrate {{currency}} balance to:", + "migrate_balance_for": "Migrate {{currency}} balance and transaction records to:", "select_account": "Select Account", "delete_success": "Account deleted successfully", "migration_error_no_target": "Cannot delete: No other {{currencies}} account found for balance migration.", "quick_add_currency": "Quick add new currency", "no_available_funding_accounts": "No available {{type}} funding accounts, please create one before proceeding with deletion", "free_asset_limit_reached": "Free users can create up to 5 asset accounts. Upgrade to Pro for unlimited accounts.", - "free_group_disabled": "Parent-child accounts are available for Pro users only. Upgrade to unlock multi-currency account management." + "free_group_disabled": "Parent-child accounts are available for Pro users only. Upgrade to unlock multi-currency account management.", + "delete_no_transactions_confirm": "This account has no transactions. Are you sure you want to delete it? The balance will be cleared and this action cannot be undone." } \ No newline at end of file diff --git a/src/locales/ja/accounts.json b/src/locales/ja/accounts.json index e0dca2d..740afd9 100644 --- a/src/locales/ja/accounts.json +++ b/src/locales/ja/accounts.json @@ -28,12 +28,13 @@ "delete_child_hint": "子アカウントを削除するには、その子アカウントの詳細ページに移動するか、親アカウントを削除してください。", "delete_account_title": "アカウントを削除", "delete_account_confirm": "このアカウントを削除してもよろしいですか?この操作は取り消せません。", - "migrate_balance_for": "{{currency}} 残高の移行先:", + "migrate_balance_for": "{{currency}} 残高と取引記録の移行先:", "select_account": "アカウントを選択", "delete_success": "アカウントが削除されました", "migration_error_no_target": "削除できません:残高移行用の他の {{currencies}} 口座が見つかりません。", "quick_add_currency": "新しい通貨を素早く追加", "no_available_funding_accounts": "利用可能な {{type}} 資金口座がありません。削除を進める前に作成してください。", "free_asset_limit_reached": "無料ユーザーは最大5つの資産口座を作成できます。Proにアップグレードして無制限に。", - "free_group_disabled": "親子口座はProユーザー限定です。アップグレードして多通貨管理を解除。" + "free_group_disabled": "親子口座はProユーザー限定です。アップグレードして多通貨管理を解除。", + "delete_no_transactions_confirm": "このアカウントには取引記録がありません。削除してもよろしいですか?残高はゼロになり、この操作は取り消せません。" } \ No newline at end of file diff --git a/src/locales/zh-CN/accounts.json b/src/locales/zh-CN/accounts.json index 6fa7fe0..3e96f67 100644 --- a/src/locales/zh-CN/accounts.json +++ b/src/locales/zh-CN/accounts.json @@ -28,12 +28,13 @@ "delete_child_hint": "如需删除子账户,请前往该子账户详情页或删除父账户。", "delete_account_title": "删除账户", "delete_account_confirm": "确定要删除该账户吗?此操作无法撤销。", - "migrate_balance_for": "迁移 {{currency}} 余额至:", + "migrate_balance_for": "迁移 {{currency}} 余额和交易记录至:", "select_account": "选择账户", "delete_success": "账户已删除", "migration_error_no_target": "无法删除:未找到其他 {{currencies}} 账户用于迁移余额。", "quick_add_currency": "快速添加新币种", "no_available_funding_accounts": "没有可用的 {{type}} 资金账户,请在继续删除之前创建一个。", "free_asset_limit_reached": "免费用户最多只能创建5个资产账户,升级到 Pro 解锁无限账户", - "free_group_disabled": "父子账户功能仅限 Pro 用户,升级后可使用多币种账户管理" + "free_group_disabled": "父子账户功能仅限 Pro 用户,升级后可使用多币种账户管理", + "delete_no_transactions_confirm": "该账户没有交易记录,确定要删除吗?删除后余额将直接清零,此操作无法撤销。" } \ No newline at end of file diff --git a/src/locales/zh-TW/accounts.json b/src/locales/zh-TW/accounts.json index cacc305..6e78ff4 100644 --- a/src/locales/zh-TW/accounts.json +++ b/src/locales/zh-TW/accounts.json @@ -28,12 +28,13 @@ "delete_child_hint": "如需刪除子帳戶,請前往該子帳戶詳情頁或刪除父帳戶。", "delete_account_title": "刪除帳戶", "delete_account_confirm": "確定要刪除該帳戶嗎?此操作無法復原。", - "migrate_balance_for": "遷移 {{currency}} 餘額至:", + "migrate_balance_for": "遷移 {{currency}} 餘額和交易記錄至:", "select_account": "選擇帳戶", "delete_success": "帳戶已刪除", "migration_error_no_target": "無法刪除:未找到其他 {{currencies}} 帳戶用於餘額遷移。", "quick_add_currency": "快速添加新幣種", "no_available_funding_accounts": "沒有可用的 {{type}} 資金帳戶,請在繼續刪除之前創建一個。", "free_asset_limit_reached": "免費用戶最多只能創建5個資產帳戶,升級到 Pro 解鎖無限帳戶", - "free_group_disabled": "父子帳戶功能僅限 Pro 用戶,升級後可使用多幣種帳戶管理" + "free_group_disabled": "父子帳戶功能僅限 Pro 用戶,升級後可使用多幣種帳戶管理", + "delete_no_transactions_confirm": "該帳戶沒有交易記錄,確定要刪除嗎?刪除後餘額將直接清零,此操作無法撤銷。" } \ No newline at end of file