Phase 20: Admin Member Editor & Form Declutter #25

Merged
luckberg merged 37 commits from gsd/phase-20-admin-member-editor-form-declutter into main 2026-06-18 20:40:35 -04:00
Showing only changes of commit ee04aee4fb - Show all commits
+14 -3
View File
@@ -80,7 +80,11 @@ export function AdminPage() {
// create ("Add member" trigger) modes (D-07 unification).
const [editorOpen, setEditorOpen] = useState(false);
const [editorMode, setEditorMode] = useState<'edit' | 'create'>('edit');
const [editorMember, setEditorMember] = useState<AdminMember | null>(null);
// CR-02: store only the id, not the full member object. The full member is
// derived from live query data each render (see below, after membersQuery),
// so per-section saves + invalidations keep the editor's member prop fresh
// without a stale captured reference.
const [editorMemberId, setEditorMemberId] = useState<number | null>(null);
// Ref to the element that opened the sheet — focus returns here on close (a11y)
const editorTriggerRef = useRef<HTMLElement | null>(null);
// Ref for the "Add member" ghost trigger button
@@ -115,6 +119,13 @@ export function AdminPage() {
staleTime: 60 * 1000,
});
// CR-02: derive editorMember from live query data so saves + invalidations always
// reflect the latest server state rather than a snapshot from when the row was tapped.
const editorMember =
editorMemberId !== null
? (membersQuery.data?.members.find((m) => m.id === editorMemberId) ?? null)
: null;
// Calendars query
const calendarsQuery = useQuery({
queryKey: ['admin', 'calendars'],
@@ -240,7 +251,7 @@ export function AdminPage() {
// Open the editor for a specific member (row tap → edit mode)
function openEditorForMember(member: AdminMember, rowEl: HTMLElement) {
editorTriggerRef.current = rowEl;
setEditorMember(member);
setEditorMemberId(member.id); // CR-02: store id only; editorMember is derived from live data
setEditorMode('edit');
setEditorOpen(true);
}
@@ -248,7 +259,7 @@ export function AdminPage() {
// Open the editor in create mode ("Add member" trigger)
function openEditorForCreate() {
editorTriggerRef.current = addMemberTriggerRef.current;
setEditorMember(null);
setEditorMemberId(null);
setEditorMode('create');
setEditorOpen(true);
}