import type { ReactNode } from "react" import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "~/components/ui/card" import { Button } from "~/components/ui/button" import { DialogError } from "~/components/data-state" /** * The shared frame every tenant-detail settings tab renders through: a titled * card whose footer holds a Save button and, on failure, an inline error in the * same place (never a page-level banner). Keeps the eight tabs visually and * behaviourally identical so the operator learns the surface once. */ export function TenantSection({ title, description, children, onSubmit, saving, error, errorContext, saveLabel = "Save changes", dirty = true, dataAction, footerExtra, }: { title: string description?: ReactNode children: ReactNode onSubmit: () => void saving: boolean error: unknown errorContext: string saveLabel?: string /** Disable Save until something changed. Defaults to always-enabled. */ dirty?: boolean dataAction: string /** Rendered to the left of Save (e.g. a "Send test" or "Remove" button). */ footerExtra?: ReactNode }) { return ( {title} {description ? {description} : null}
{ e.preventDefault() onSubmit() }} className="flex flex-col gap-5" > {children} {error ? : null}
{footerExtra}
) } /** A labelled form row — label, control, and an optional hint underneath. */ export function Field({ label, htmlFor, hint, children, }: { label: string htmlFor?: string hint?: ReactNode children: ReactNode }) { return (
{children} {hint ?

{hint}

: null}
) }