import { useState } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { motion, AnimatePresence } from 'framer-motion';
import { Plus, Pencil, Trash2, ArrowLeft } from 'lucide-react';
import { Link } from 'react-router-dom';
import { api, type Member } from '@/lib/api';
import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';
import { Modal } from '@/components/ui/Modal';
import { Avatar } from '@/components/ui/Avatar';
const PRESET_COLORS = [
'#6366f1', '#14b8a6', '#f43f5e', '#f59e0b', '#64748b',
'#8b5cf6', '#ec4899', '#10b981', '#f97316', '#06b6d4',
];
interface MemberFormData {
name: string;
color: string;
}
function MemberForm({
initial,
onSubmit,
onCancel,
loading,
}: {
initial?: MemberFormData;
onSubmit: (data: MemberFormData) => void;
onCancel: () => void;
loading: boolean;
}) {
const [name, setName] = useState(initial?.name ?? '');
const [color, setColor] = useState(initial?.color ?? PRESET_COLORS[0]);
return (
setName(e.target.value)}
placeholder="Family member's name"
autoFocus
/>
Color
{PRESET_COLORS.map((c) => (
setColor(e.target.value)}
className="h-8 w-12 cursor-pointer rounded border border-theme bg-transparent"
/>
{color}
{/* Preview */}
{name && (
)}
);
}
export default function MembersPage() {
const qc = useQueryClient();
const [addOpen, setAddOpen] = useState(false);
const [editTarget, setEditTarget] = useState(null);
const [deleteTarget, setDeleteTarget] = useState(null);
const { data: members = [], isLoading } = useQuery({
queryKey: ['members'],
queryFn: () => api.get('/members').then((r) => r.data),
});
const createMutation = useMutation({
mutationFn: (data: MemberFormData) => api.post('/members', data).then((r) => r.data),
onSuccess: () => { qc.invalidateQueries({ queryKey: ['members'] }); setAddOpen(false); },
});
const updateMutation = useMutation({
mutationFn: ({ id, data }: { id: number; data: MemberFormData }) =>
api.put(`/members/${id}`, data).then((r) => r.data),
onSuccess: () => { qc.invalidateQueries({ queryKey: ['members'] }); setEditTarget(null); },
});
const deleteMutation = useMutation({
mutationFn: (id: number) => api.delete(`/members/${id}`),
onSuccess: () => { qc.invalidateQueries({ queryKey: ['members'] }); setDeleteTarget(null); },
});
return (
{/* Header */}
Family Members
{members.length} member{members.length !== 1 ? 's' : ''}
{/* Member list */}
{isLoading ? (
{[1, 2, 3].map((i) => (
))}
) : members.length === 0 ? (
๐จโ๐ฉโ๐งโ๐ฆ
No family members yet
Add your family members to assign chores, events, and more.
) : (
{members.map((member) => (
{member.name}
{member.color}
))}
)}
{/* Add modal */}
setAddOpen(false)} title="Add Family Member">
createMutation.mutate(data)}
onCancel={() => setAddOpen(false)}
loading={createMutation.isPending}
/>
{/* Edit modal */}
setEditTarget(null)} title="Edit Family Member">
{editTarget && (
updateMutation.mutate({ id: editTarget.id, data })}
onCancel={() => setEditTarget(null)}
loading={updateMutation.isPending}
/>
)}
{/* Delete confirm modal */}
setDeleteTarget(null)} title="Remove Member" size="sm">
{deleteTarget && (
Removing this member won't delete their assigned chores or events โ those will simply become unassigned.
)}
);
}