- 更新.gitignore,添加frontend/.next/忽略 - 优化RecordModal、index、recurring、search、stats页面标题栏样式 - 新增frontend/lib/utils.js工具函数 - 更新useCategories.js钩子 - 添加代码优化计划文档 Co-Authored-By: Claude <noreply@anthropic.com>
144 lines
4.8 KiB
JavaScript
144 lines
4.8 KiB
JavaScript
import { Icon } from './icons';
|
||
|
||
export default function RecordModal({
|
||
isOpen,
|
||
onClose,
|
||
onSubmit,
|
||
onDelete,
|
||
formData,
|
||
setFormData,
|
||
formError,
|
||
submitting,
|
||
deleting,
|
||
editingRecord,
|
||
categories,
|
||
}) {
|
||
if (!isOpen) return null;
|
||
|
||
const handleTypeChange = (type) => {
|
||
setFormData({ ...formData, type, category: '' });
|
||
};
|
||
|
||
const isDisabled = submitting || deleting;
|
||
|
||
return (
|
||
<div className="modal-overlay modal-overlay--fullscreen" onClick={onClose}>
|
||
<div className="modal modal--fullscreen" onClick={(e) => e.stopPropagation()}>
|
||
<div className="modal-header" style={{minHeight: 56, height: 56, padding: 'calc(var(--safe-top) + 8px) 16px 8px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', boxSizing: 'border-box'}}>
|
||
<h2 style={{margin: 0, fontSize: '1.1rem'}}>{editingRecord ? '编辑记录' : '新增记录'}</h2>
|
||
<button
|
||
type="button"
|
||
className="icon-button icon-button--ghost"
|
||
aria-label="关闭弹窗"
|
||
onClick={onClose}
|
||
disabled={isDisabled}
|
||
>
|
||
<Icon name="close" size={18} />
|
||
</button>
|
||
</div>
|
||
{formError && <div className="error-msg">{formError}</div>}
|
||
<form onSubmit={onSubmit}>
|
||
<div className="type-switch">
|
||
<button
|
||
type="button"
|
||
className={`type-btn expense ${formData.type === 'expense' ? 'active' : ''}`}
|
||
onClick={() => handleTypeChange('expense')}
|
||
disabled={isDisabled}
|
||
>
|
||
支出
|
||
</button>
|
||
<button
|
||
type="button"
|
||
className={`type-btn income ${formData.type === 'income' ? 'active' : ''}`}
|
||
onClick={() => handleTypeChange('income')}
|
||
disabled={isDisabled}
|
||
>
|
||
收入
|
||
</button>
|
||
</div>
|
||
<div className="form-group">
|
||
<label htmlFor="record-amount">金额</label>
|
||
<input
|
||
id="record-amount"
|
||
type="number"
|
||
className="amount-input"
|
||
value={formData.amount}
|
||
onChange={(e) => setFormData({ ...formData, amount: e.target.value })}
|
||
placeholder="0.00"
|
||
step="0.01"
|
||
required
|
||
disabled={isDisabled}
|
||
/>
|
||
</div>
|
||
<div className="form-group">
|
||
<label>分类</label>
|
||
<div className="category-grid">
|
||
{categories[formData.type].map((cat) => (
|
||
<button
|
||
key={cat.name}
|
||
type="button"
|
||
className={`category-btn ${formData.category === cat.name ? 'active' : ''}`}
|
||
onClick={() => setFormData({ ...formData, category: cat.name })}
|
||
disabled={isDisabled}
|
||
>
|
||
<span className="icon">{cat.icon}</span>
|
||
<span>{cat.name}</span>
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
<div className="form-group">
|
||
<label>日期</label>
|
||
<div className="datetime-picker">
|
||
<input
|
||
type="date"
|
||
value={formData.date}
|
||
onChange={(e) => setFormData({ ...formData, date: e.target.value })}
|
||
required
|
||
disabled={isDisabled}
|
||
/>
|
||
<input
|
||
type="time"
|
||
value={formData.time || '00:00'}
|
||
onChange={(e) => setFormData({ ...formData, time: e.target.value })}
|
||
disabled={isDisabled}
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div className="form-group">
|
||
<label htmlFor="record-note">备注(可选)</label>
|
||
<input
|
||
id="record-note"
|
||
type="text"
|
||
value={formData.note}
|
||
onChange={(e) => setFormData({ ...formData, note: e.target.value })}
|
||
placeholder="添加备注..."
|
||
disabled={isDisabled}
|
||
/>
|
||
</div>
|
||
<div className="modal-actions">
|
||
<button type="submit" className="btn btn-primary" disabled={isDisabled}>
|
||
{submitting ? (
|
||
<span className="button-content">
|
||
<Icon name="spinner" size={16} className="is-spinning" />
|
||
保存中...
|
||
</span>
|
||
) : '保存'}
|
||
</button>
|
||
{editingRecord && (
|
||
<button
|
||
type="button"
|
||
className="btn btn-danger"
|
||
onClick={onDelete}
|
||
disabled={isDisabled}
|
||
>
|
||
{deleting ? '删除中...' : '删除'}
|
||
</button>
|
||
)}
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|