v0.12.49 family rules update
This commit is contained in:
@@ -1,17 +1,34 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useToast } from '../contexts/ToastContext.jsx';
|
||||
import { useAuth } from '../contexts/AuthContext.jsx';
|
||||
import { api } from '../utils/api.js';
|
||||
|
||||
export default function AddChildAliasModal({ onClose }) {
|
||||
const toast = useToast();
|
||||
const [aliases, setAliases] = useState([]);
|
||||
const [editingAlias, setEditingAlias] = useState(null); // null = new entry
|
||||
const [form, setForm] = useState({ firstName: '', lastName: '', dob: '', phone: '', email: '' });
|
||||
const [avatarFile, setAvatarFile] = useState(null);
|
||||
const [saving, setSaving] = useState(false);
|
||||
const { user: currentUser } = useAuth();
|
||||
const [aliases, setAliases] = useState([]);
|
||||
const [editingAlias, setEditingAlias] = useState(null); // null = new entry
|
||||
const [form, setForm] = useState({ firstName: '', lastName: '', dob: '', phone: '', email: '' });
|
||||
const [avatarFile, setAvatarFile] = useState(null);
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
// Partner state
|
||||
const [partner, setPartner] = useState(null);
|
||||
const [selectedPartnerId, setSelectedPartnerId] = useState('');
|
||||
const [allUsers, setAllUsers] = useState([]);
|
||||
const [savingPartner, setSavingPartner] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
api.getAliases().then(({ aliases }) => setAliases(aliases || [])).catch(() => {});
|
||||
Promise.all([
|
||||
api.getAliases(),
|
||||
api.getPartner(),
|
||||
api.searchUsers(''),
|
||||
]).then(([aliasRes, partnerRes, usersRes]) => {
|
||||
setAliases(aliasRes.aliases || []);
|
||||
setPartner(partnerRes.partner || null);
|
||||
setSelectedPartnerId(partnerRes.partner?.id?.toString() || '');
|
||||
setAllUsers((usersRes.users || []).filter(u => u.id !== currentUser?.id));
|
||||
}).catch(() => {});
|
||||
}, []);
|
||||
|
||||
const set = k => e => setForm(p => ({ ...p, [k]: e.target.value }));
|
||||
@@ -35,6 +52,27 @@ export default function AddChildAliasModal({ onClose }) {
|
||||
setAvatarFile(null);
|
||||
};
|
||||
|
||||
const handleSavePartner = async () => {
|
||||
setSavingPartner(true);
|
||||
try {
|
||||
if (!selectedPartnerId) {
|
||||
await api.removePartner();
|
||||
setPartner(null);
|
||||
toast('Spouse/Partner removed', 'success');
|
||||
} else {
|
||||
const { partner: p } = await api.setPartner(parseInt(selectedPartnerId));
|
||||
setPartner(p);
|
||||
const { aliases: fresh } = await api.getAliases();
|
||||
setAliases(fresh || []);
|
||||
toast('Spouse/Partner saved', 'success');
|
||||
}
|
||||
} catch (e) {
|
||||
toast(e.message, 'error');
|
||||
} finally {
|
||||
setSavingPartner(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
if (!form.firstName.trim() || !form.lastName.trim())
|
||||
return toast('First and last name required', 'error');
|
||||
@@ -93,7 +131,7 @@ export default function AddChildAliasModal({ onClose }) {
|
||||
|
||||
{/* Header */}
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 20 }}>
|
||||
<h2 className="modal-title" style={{ margin: 0 }}>Add Child Alias</h2>
|
||||
<h2 className="modal-title" style={{ margin: 0 }}>Family Manager</h2>
|
||||
<button className="btn-icon" onClick={onClose} aria-label="Close">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
|
||||
@@ -101,6 +139,37 @@ export default function AddChildAliasModal({ onClose }) {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Spouse/Partner section */}
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
{lbl('Spouse/Partner')}
|
||||
<div style={{ display: 'flex', gap: 8 }}>
|
||||
<select
|
||||
className="input"
|
||||
style={{ flex: 1 }}
|
||||
value={selectedPartnerId}
|
||||
onChange={e => setSelectedPartnerId(e.target.value)}
|
||||
>
|
||||
<option value="">— None —</option>
|
||||
{allUsers.map(u => (
|
||||
<option key={u.id} value={u.id}>{u.display_name || u.name}</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={handleSavePartner}
|
||||
disabled={savingPartner}
|
||||
style={{ whiteSpace: 'nowrap' }}
|
||||
>
|
||||
{savingPartner ? 'Saving…' : 'Save'}
|
||||
</button>
|
||||
</div>
|
||||
{partner && (
|
||||
<div className="text-sm" style={{ color: 'var(--text-secondary)', marginTop: 4 }}>
|
||||
Linked with {partner.display_name || partner.name}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Existing aliases list */}
|
||||
{aliases.length > 0 && (
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
|
||||
Reference in New Issue
Block a user