import { Alert, Box, Button, CircularProgress, MenuItem, Snackbar, Stack, TextField, Typography, } from "@mui/material"; import { useState, type ReactNode } from "react"; export type SettingsFormField = | { name: string; label: string; type?: "text" | "email" | "number"; required?: boolean; } | { name: string; label: string; type: "select"; required?: boolean; options: Array<{ value: string; label: string }>; }; type SettingsFormShellProps = { title: string; testId: string; fields: SettingsFormField[]; initialValues: Record; formKey?: string; isLoading?: boolean; isError?: boolean; errorMessage?: string; notFound?: boolean; onCancel: () => void; onSave: (values: Record) => Promise; extra?: ReactNode; }; type SettingsFormFieldsProps = { title: string; testId: string; fields: SettingsFormField[]; initialValues: Record; onCancel: () => void; onSave: (values: Record) => Promise; extra?: ReactNode; }; function SettingsFormFields({ title, testId, fields, initialValues, onCancel, onSave, extra, }: SettingsFormFieldsProps) { const [values, setValues] = useState(initialValues); const [saving, setSaving] = useState(false); const [snackbar, setSnackbar] = useState(null); const [validationError, setValidationError] = useState(null); const handleSave = async () => { for (const field of fields) { if (field.required !== false && !values[field.name]?.trim()) { setValidationError(`${field.label} is required.`); return; } } setValidationError(null); setSaving(true); try { await onSave(values); setSnackbar("Saved to mock store"); } catch (error) { setValidationError(error instanceof Error ? error.message : "Save failed"); } finally { setSaving(false); } }; return ( {title} {validationError ? {validationError} : null} {fields.map((field) => { if (field.type === "select") { return ( setValues((current) => ({ ...current, [field.name]: event.target.value })) } required={field.required !== false} data-testid={`${testId}-field-${field.name}`} > {field.options.map((option) => ( {option.label} ))} ); } return ( setValues((current) => ({ ...current, [field.name]: event.target.value })) } required={field.required !== false} data-testid={`${testId}-field-${field.name}`} /> ); })} {extra} setSnackbar(null)} message={snackbar} data-testid={`${testId}-snackbar`} /> ); } export function SettingsFormShell({ title, testId, fields, initialValues, formKey = "new", isLoading = false, isError = false, errorMessage, notFound = false, onCancel, onSave, extra, }: SettingsFormShellProps) { if (isLoading) { return ( ); } if (isError) { return ( {errorMessage ?? `Failed to load ${title.toLowerCase()}`} ); } if (notFound) { return Record not found.; } return ( ); }