Files
DeveloperandClaude 127f491167 feat: 前端UI标题栏优化与配置更新
- 更新.gitignore,添加frontend/.next/忽略
- 优化RecordModal、index、recurring、search、stats页面标题栏样式
- 新增frontend/lib/utils.js工具函数
- 更新useCategories.js钩子
- 添加代码优化计划文档

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-18 16:33:29 +08:00

144 lines
4.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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>
);
}