const { useState, useEffect, useCallback, useRef } = React; const ProfileEditModal = ({ profile, onClose, onSaved }) => { const { showToast } = useApp(); const overlayRef = useRef(null); const contentRef = useRef(null); const closingRef = useRef(false); const [saving, setSaving] = useState(false); const [form, setForm] = useState({ name: profile?.name || '', company: profile?.company || '', tax_id: profile?.tax_id || '', contact_person: profile?.contact_person || '', mobile: profile?.mobile || '', phone: profile?.phone || '', address: profile?.address || '', }); const fieldLabels = [ { key: 'name', label: '姓名' }, { key: 'company', label: '公司' }, { key: 'tax_id', label: '統一編號' }, { key: 'contact_person', label: '聯絡人' }, { key: 'mobile', label: '手機' }, { key: 'phone', label: '電話' }, { key: 'address', label: '地址' }, ]; const animateClose = useCallback(() => { if (closingRef.current) return; closingRef.current = true; const content = contentRef.current; const overlay = overlayRef.current; if (!content || !overlay) { onClose(); return; } Motion.animate(content, { opacity: 0, transform: 'translateY(60px)' }, { duration: 0.2, easing: 'ease-in' }) .then(() => Motion.animate(overlay, { opacity: 0 }, { duration: 0.1 })) .then(() => onClose()); }, [onClose]); useEffect(() => { const overlay = overlayRef.current; const content = contentRef.current; if (!overlay || !content) return; Motion.animate(overlay, { opacity: [0, 1] }, { duration: 0.15 }); Motion.animate(content, { opacity: [0, 1], transform: ['translateY(60px) scale(0.97)', 'translateY(0px) scale(1)'] }, { duration: 0.35, easing: [0.22, 1, 0.36, 1] } ); const handleKey = (e) => { if (e.key === 'Escape') animateClose(); }; document.addEventListener('keydown', handleKey); document.body.style.overflow = 'hidden'; return () => { document.removeEventListener('keydown', handleKey); document.body.style.overflow = ''; }; }, [animateClose]); const handleBackdropClick = (e) => { if (e.target === overlayRef.current) animateClose(); }; const handleChange = (e) => { setForm({ ...form, [e.target.name]: e.target.value }); }; const handleSave = async () => { setSaving(true); try { const updated = await api.updateProfile(form); showToast('資料已更新'); onSaved(updated); onClose(); } catch (error) { console.error('Profile update error:', error); showToast('更新失敗,請稍後再試'); setSaving(false); } }; return (

編輯個人資料

{fieldLabels.map(({ key, label }) => (
{key === 'address' ? (