fix: react-doctor → 64/100 — remove dead AdminStatusBadge/AdminCountBadge, add dialog semantics

This commit is contained in:
Nora
2026-06-26 02:58:55 -06:00
parent 33626620a0
commit e3c1295e62
5 changed files with 47 additions and 69 deletions
+12 -3
View File
@@ -29,7 +29,10 @@ type Props = {
export default function ImportCenterClient({ brandId: initialBrandId, brandName: initialBrandName, brands = [], isPlatformAdmin = false }: Props) {
const [activeBrandId, setActiveBrandId] = useState(initialBrandId);
const [activeBrandName, setActiveBrandName] = useState(initialBrandName);
// Brand name is derived from the brands list — no separate state, so
// updates to it don't trigger an extra render of the whole component.
const activeBrandName =
brands.find((b) => b.id === activeBrandId)?.name ?? initialBrandName;
const [fileName, setFileName] = useState("");
const [base64Data, setBase64Data] = useState("");
const [analysis, setAnalysis] = useState<ImportAnalysis | null>(null);
@@ -45,8 +48,6 @@ export default function ImportCenterClient({ brandId: initialBrandId, brandName:
function handleBrandChange(newBrandId: string) {
setActiveBrandId(newBrandId);
const found = brands.find((b) => b.id === newBrandId);
if (found) setActiveBrandName(found.name);
}
function handleFile(file: File) {
@@ -178,9 +179,17 @@ export default function ImportCenterClient({ brandId: initialBrandId, brandName:
{step === "upload" && (
<div className="space-y-4">
<div
role="button"
tabIndex={0}
onDragOver={(e) => { e.preventDefault(); }}
onDrop={handleDrop}
onClick={() => inputRef.current?.click()}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
inputRef.current?.click();
}
}}
className="flex flex-col items-center justify-center gap-3 rounded-2xl border-2 border-dashed border-[var(--admin-border)] bg-white p-12 cursor-pointer hover:border-[var(--admin-accent)] hover:bg-[var(--admin-bg)] transition-colors"
>
<svg className="h-10 w-10 text-[var(--admin-text-muted)]" fill="none" viewBox="0 0 24 24" stroke="currentColor">
@@ -473,9 +473,6 @@ export default function IntegrationsClient({ brandId, brands, isPlatformAdmin, p
const [showAddModal, setShowAddModal] = useState(false);
const [addSearch, setAddSearch] = useState("");
const [customIntegrations, setCustomIntegrations] = useState<CustomIntegration[]>([]);
const [showCustomForm, setShowCustomForm] = useState(false);
const [newCustomName, setNewCustomName] = useState("");
const [newCustomType, setNewCustomType] = useState<"ai_provider" | "payment_processor" | "other">("other");
// Integrations shown in the grid — OpenAI card is hidden since it's now handled by AIProviderPanel
const gridIntegrations = INTEGRATIONS.filter((i) => i.id !== "openai");
@@ -498,19 +495,17 @@ export default function IntegrationsClient({ brandId, brands, isPlatformAdmin, p
setAddSearch("");
}
function handleAddCustom() {
if (!newCustomName.trim()) return;
function handleAddCustom(name: string, type: "ai_provider" | "payment_processor" | "other") {
if (!name.trim()) return;
const newInt: CustomIntegration = {
id: `custom_${Date.now()}`,
name: newCustomName,
type: newCustomType,
name: name.trim(),
type,
enabled: false,
credentials: [],
syncOptions: [],
};
setCustomIntegrations((prev) => [...prev, newInt]);
setNewCustomName("");
setShowCustomForm(false);
}
return (
@@ -608,7 +603,16 @@ export default function IntegrationsClient({ brandId, brands, isPlatformAdmin, p
{/* Add integration modal */}
{showAddModal && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50" onClick={() => setShowAddModal(false)}>
<div
role="dialog"
aria-modal="true"
aria-label="Add Integration"
className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
onClick={() => setShowAddModal(false)}
onKeyDown={(e) => {
if (e.key === "Escape") setShowAddModal(false);
}}
>
<div className="w-full max-w-lg rounded-2xl bg-zinc-900 border border-zinc-700 p-6 shadow-xl" onClick={(e) => e.stopPropagation()}>
<div className="mb-4 flex items-center justify-between">
<h2 className="text-lg font-bold text-zinc-100">Add Integration</h2>
@@ -372,7 +372,16 @@ export default function HeadgatesManager({ initialHeadgates, brandId }: Props) {
{/* Edit Modal */}
{editHg && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50" onClick={() => setEditHg(null)}>
<div
role="dialog"
aria-modal="true"
aria-label="Edit Headgate"
className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
onClick={() => setEditHg(null)}
onKeyDown={(e) => {
if (e.key === "Escape") setEditHg(null);
}}
>
<div className="bg-white rounded-2xl shadow-2xl w-full max-w-sm mx-4 overflow-hidden border border-[var(--admin-border)]" onClick={(e) => e.stopPropagation()}>
<div className="flex items-center justify-between px-5 py-4 border-b border-[var(--admin-border)]">
<p className="font-bold text-[var(--admin-text-primary)]">Edit Headgate</p>
@@ -512,7 +521,16 @@ function QRModal({ hg, onClose, onRegenerate }: { hg: Headgate; onClose: () => v
}
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50" onClick={onClose}>
<div
role="dialog"
aria-modal="true"
aria-label="Headgate details"
className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
onClick={onClose}
onKeyDown={(e) => {
if (e.key === "Escape") onClose();
}}
>
<div className="bg-white rounded-2xl shadow-2xl w-full max-w-sm mx-4 overflow-hidden border border-[var(--admin-border)]" onClick={(e) => e.stopPropagation()}>
{/* Header */}