Files

144 lines
4.8 KiB
JavaScript
Raw Permalink Normal View History

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>
);
}