fix(compiler): migrate custom-fields-manager to useQuery

set-state-in-effect: 44 → 43.

Eight admin list/load sites migrated total this session; the
remaining ~43 hits are predominantly the dialog/form open→reset
pattern (intentional setState-in-effect when a dialog opens to
populate fields from props). Cleanest fix is key-based remount
of the dialog body; tracked in BACKLOG as a focused refactor pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-12 23:37:30 +02:00
parent 96c6b7c01c
commit 8a8cff4c4c

View File

@@ -1,6 +1,7 @@
'use client';
import { useState, useCallback, useEffect } from 'react';
import { useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { type ColumnDef } from '@tanstack/react-table';
import { Pencil, Trash2, Plus } from 'lucide-react';
@@ -33,27 +34,29 @@ const FIELD_TYPE_LABELS: Record<string, string> = {
// ─── Component ────────────────────────────────────────────────────────────────
const FIELDS_QUERY_KEY = ['admin', 'custom-fields'] as const;
export function CustomFieldsManager() {
const queryClient = useQueryClient();
const [activeTab, setActiveTab] = useState<EntityTab>('client');
const [fields, setFields] = useState<CustomFieldDefinition[]>([]);
const [loading, setLoading] = useState(true);
const [formOpen, setFormOpen] = useState(false);
const [editingField, setEditingField] = useState<CustomFieldDefinition | null>(null);
const [deletingId, setDeletingId] = useState<string | null>(null);
const fetchFields = useCallback(async () => {
setLoading(true);
try {
const res = await apiFetch<{ data: CustomFieldDefinition[] }>('/api/v1/admin/custom-fields');
setFields(res.data);
} finally {
setLoading(false);
}
}, []);
const { data: fields = [], isLoading: loading } = useQuery<CustomFieldDefinition[]>({
queryKey: FIELDS_QUERY_KEY,
queryFn: () =>
apiFetch<{ data: CustomFieldDefinition[] }>('/api/v1/admin/custom-fields').then(
(r) => r.data,
),
});
useEffect(() => {
void fetchFields();
}, [fetchFields]);
const fetchFields = () => queryClient.invalidateQueries({ queryKey: FIELDS_QUERY_KEY });
const deleteMutation = useMutation({
mutationFn: (id: string) => apiFetch(`/api/v1/admin/custom-fields/${id}`, { method: 'DELETE' }),
onSuccess: () => fetchFields(),
});
const deletingId = deleteMutation.isPending ? deleteMutation.variables : null;
const filteredFields = fields.filter((f) => f.entityType === activeTab);
@@ -67,14 +70,8 @@ export function CustomFieldsManager() {
setFormOpen(true);
}
async function handleDelete(id: string) {
setDeletingId(id);
try {
await apiFetch(`/api/v1/admin/custom-fields/${id}`, { method: 'DELETE' });
await fetchFields();
} finally {
setDeletingId(null);
}
function handleDelete(id: string) {
deleteMutation.mutate(id);
}
function getDeleteDescription(field: CustomFieldDefinition): string {