diff --git a/package-lock.json b/package-lock.json index d297282..714581f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "react": "^19.2.0", "react-confetti": "^6.4.0", "react-dom": "^19.2.0", + "react-hot-toast": "^2.6.0", "react-icons": "^5.5.0", "react-markdown": "^10.1.0", "react-router-dom": "^7.12.0", @@ -3938,6 +3939,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/goober": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.18.tgz", + "integrity": "sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==", + "license": "MIT", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -5867,6 +5877,23 @@ "react": "^19.2.3" } }, + "node_modules/react-hot-toast": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.6.0.tgz", + "integrity": "sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==", + "license": "MIT", + "dependencies": { + "csstype": "^3.1.3", + "goober": "^2.1.16" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/react-icons": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", diff --git a/package.json b/package.json index 8e47c5c..dcbaab0 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "react": "^19.2.0", "react-confetti": "^6.4.0", "react-dom": "^19.2.0", + "react-hot-toast": "^2.6.0", "react-icons": "^5.5.0", "react-markdown": "^10.1.0", "react-router-dom": "^7.12.0", diff --git a/src/App.tsx b/src/App.tsx index 81b2f33..b01fa81 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,6 +4,7 @@ import { router } from './router'; import { ThemeProvider, PrivacyProvider, NotificationProvider, GuideProvider, useAutoTokenRefresh } from './hooks'; import { SettingsProvider } from './contexts/SettingsContext'; +import { Toaster } from 'react-hot-toast'; /** * App Content Component @@ -28,6 +29,7 @@ function App() { + diff --git a/src/components/budget/PiggyBankTransactionModal/PiggyBankTransactionModal.tsx b/src/components/budget/PiggyBankTransactionModal/PiggyBankTransactionModal.tsx index 33f9585..8de3aa6 100644 --- a/src/components/budget/PiggyBankTransactionModal/PiggyBankTransactionModal.tsx +++ b/src/components/budget/PiggyBankTransactionModal/PiggyBankTransactionModal.tsx @@ -4,6 +4,7 @@ */ import React, { useState } from 'react'; +import toast from 'react-hot-toast'; import type { PiggyBank, Account } from '../../../types'; import { formatCurrency } from '../../../utils/format'; import { Icon } from '@iconify/react'; @@ -28,7 +29,6 @@ export const PiggyBankTransactionModal: React.FC }) => { const [amount, setAmount] = useState(''); const [note, setNote] = useState(''); - const [error, setError] = useState(''); const isDeposit = type === 'deposit'; const title = isDeposit ? '存入' : '取出'; @@ -38,7 +38,6 @@ export const PiggyBankTransactionModal: React.FC const handleAmountChange = (e: React.ChangeEvent) => { const value = e.target.value; setAmount(value); - setError(''); }; const handleSubmit = (e: React.FormEvent) => { @@ -48,17 +47,17 @@ export const PiggyBankTransactionModal: React.FC // Validation if (!amount || isNaN(numAmount) || numAmount <= 0) { - setError('请输入有效的金额'); + toast.error('请输入有效的金额'); return; } if (!isDeposit && numAmount > piggyBank.currentAmount) { - setError('取出金额不能超过当前余额'); + toast.error('取出金额不能超过当前余额'); return; } if (isDeposit && linkedAccount && numAmount > linkedAccount.balance) { - setError(`账户余额不足 (可用: ${formatCurrency(linkedAccount.balance, linkedAccount.currency)})`); + toast.error(`账户余额不足 (可用: ${formatCurrency(linkedAccount.balance, linkedAccount.currency)})`); return; } @@ -67,7 +66,6 @@ export const PiggyBankTransactionModal: React.FC const handleQuickAmount = (value: number) => { setAmount(value.toString()); - setError(''); }; // Quick amount buttons @@ -163,8 +161,7 @@ export const PiggyBankTransactionModal: React.FC id="amount" value={amount} onChange={handleAmountChange} - className={`piggy-bank-transaction-modal__input ${error ? 'piggy-bank-transaction-modal__input--error' : '' - }`} + className="piggy-bank-transaction-modal__input" placeholder="0.00" step="0.01" min="0" @@ -172,7 +169,7 @@ export const PiggyBankTransactionModal: React.FC disabled={isLoading} autoFocus /> - {error && {error}} + {/* Error handled by toast */} {linkedAccount ? (