Reorganiza gestão de usuários e remove dados mock
This commit is contained in:
parent
630110bf3a
commit
dded6d1927
20 changed files with 1863 additions and 1368 deletions
|
|
@ -82,6 +82,18 @@ type MachineSummary = {
|
|||
architecture?: string | null
|
||||
}
|
||||
|
||||
function formatCnpjInput(value: string): string {
|
||||
const digits = value.replace(/\D/g, "").slice(0, 14)
|
||||
if (digits.length <= 2) return digits
|
||||
if (digits.length <= 5) return `${digits.slice(0, 2)}.${digits.slice(2)}`
|
||||
if (digits.length <= 8) return `${digits.slice(0, 2)}.${digits.slice(2, 5)}.${digits.slice(5)}`
|
||||
if (digits.length <= 12) {
|
||||
return `${digits.slice(0, 2)}.${digits.slice(2, 5)}.${digits.slice(5, 8)}/${digits.slice(8)}`
|
||||
}
|
||||
return `${digits.slice(0, 2)}.${digits.slice(2, 5)}.${digits.slice(5, 8)}/${digits.slice(8, 12)}-${digits.slice(12)}`
|
||||
}
|
||||
|
||||
|
||||
export function AdminCompaniesManager({ initialCompanies }: { initialCompanies: Company[] }) {
|
||||
const [companies, setCompanies] = useState<Company[]>(() => initialCompanies ?? [])
|
||||
const [isPending, startTransition] = useTransition()
|
||||
|
|
@ -139,6 +151,7 @@ export function AdminCompaniesManager({ initialCompanies }: { initialCompanies:
|
|||
setForm({
|
||||
...c,
|
||||
contractedHoursPerMonth: c.contractedHoursPerMonth ?? undefined,
|
||||
cnpj: c.cnpj ? formatCnpjInput(c.cnpj) : null,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -163,11 +176,13 @@ export function AdminCompaniesManager({ initialCompanies }: { initialCompanies:
|
|||
? form.contractedHoursPerMonth
|
||||
: null
|
||||
|
||||
const cnpjDigits = form.cnpj ? form.cnpj.replace(/\D/g, "") : ""
|
||||
|
||||
const payload = {
|
||||
name: form.name?.trim(),
|
||||
slug: form.slug?.trim(),
|
||||
isAvulso: Boolean(form.isAvulso ?? false),
|
||||
cnpj: form.cnpj?.trim() || null,
|
||||
cnpj: cnpjDigits ? cnpjDigits : null,
|
||||
domain: form.domain?.trim() || null,
|
||||
phone: form.phone?.trim() || null,
|
||||
description: form.description?.trim() || null,
|
||||
|
|
@ -331,7 +346,7 @@ export function AdminCompaniesManager({ initialCompanies }: { initialCompanies:
|
|||
name="companyName"
|
||||
value={form.name ?? ""}
|
||||
onChange={(e) => setForm((p) => ({ ...p, name: e.target.value }))}
|
||||
placeholder="Nome da empresa ou apelido interno"
|
||||
placeholder="Nome da empresa"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
|
|
@ -360,7 +375,7 @@ export function AdminCompaniesManager({ initialCompanies }: { initialCompanies:
|
|||
id={cnpjId}
|
||||
name="companyCnpj"
|
||||
value={form.cnpj ?? ""}
|
||||
onChange={(e) => setForm((p) => ({ ...p, cnpj: e.target.value }))}
|
||||
onChange={(e) => setForm((p) => ({ ...p, cnpj: formatCnpjInput(e.target.value) }))}
|
||||
placeholder="00.000.000/0000-00"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -472,7 +487,7 @@ export function AdminCompaniesManager({ initialCompanies }: { initialCompanies:
|
|||
) : null}
|
||||
|
||||
<Card className="border-slate-200/80 shadow-none">
|
||||
<CardHeader className="gap-4 border-b border-slate-100 py-6 dark:border-slate-800/60">
|
||||
<CardHeader className="gap-4 bg-white px-6 py-6">
|
||||
<div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div className="space-y-1">
|
||||
<CardTitle className="text-xl font-semibold tracking-tight">Empresas cadastradas</CardTitle>
|
||||
|
|
@ -489,14 +504,14 @@ export function AdminCompaniesManager({ initialCompanies }: { initialCompanies:
|
|||
value={searchTerm}
|
||||
onChange={(event) => setSearchTerm(event.target.value)}
|
||||
placeholder="Buscar por nome, slug ou domínio..."
|
||||
className="pl-9"
|
||||
className="h-9 pl-9"
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="sm:self-start"
|
||||
className="gap-2 self-start sm:self-auto"
|
||||
disabled={isPending}
|
||||
onClick={() => startTransition(() => { void refresh() })}
|
||||
>
|
||||
|
|
@ -505,9 +520,9 @@ export function AdminCompaniesManager({ initialCompanies }: { initialCompanies:
|
|||
</Button>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="p-0">
|
||||
<CardContent className="bg-white p-4">
|
||||
{isMobile ? (
|
||||
<div className="space-y-4 p-4">
|
||||
<div className="space-y-4 rounded-xl border border-slate-200 bg-white p-4 shadow-sm">
|
||||
{hasCompanies ? (
|
||||
filteredCompanies.map((company) => {
|
||||
const companyMachines = machinesByCompanyId.get(company.id) ?? []
|
||||
|
|
@ -554,6 +569,10 @@ export function AdminCompaniesManager({ initialCompanies }: { initialCompanies:
|
|||
<IconPencil className="size-4" />
|
||||
Editar empresa
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onSelect={() => setMachinesDialog({ companyId: company.id, name: company.name })}>
|
||||
<IconDeviceDesktop className="size-4" />
|
||||
Ver máquinas
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onSelect={() => void toggleAvulso(company)}>
|
||||
<IconSwitchHorizontal className="size-4" />
|
||||
{company.isAvulso ? "Marcar como recorrente" : "Marcar como avulso"}
|
||||
|
|
@ -673,9 +692,9 @@ export function AdminCompaniesManager({ initialCompanies }: { initialCompanies:
|
|||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="overflow-hidden rounded-lg border border-slate-200">
|
||||
<div className="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
|
||||
<Table className="min-w-full table-fixed text-sm">
|
||||
<TableHeader className="sticky top-0 z-10 bg-muted/60 backdrop-blur supports-[backdrop-filter]:bg-muted/40">
|
||||
<TableHeader className="bg-slate-50">
|
||||
<TableRow className="border-b border-slate-200 dark:border-slate-800/60 [&_th]:h-10 [&_th]:text-xs [&_th]:font-medium [&_th]:uppercase [&_th]:tracking-wide [&_th]:text-muted-foreground [&_th:first-child]:rounded-tl-lg [&_th:last-child]:rounded-tr-lg">
|
||||
<TableHead className="w-[30%] min-w-[220px] pl-6">Empresa</TableHead>
|
||||
<TableHead className="w-[22%] min-w-[180px] pl-4">Provisionamento</TableHead>
|
||||
|
|
@ -935,23 +954,26 @@ export function AdminCompaniesManager({ initialCompanies }: { initialCompanies:
|
|||
}
|
||||
}}
|
||||
>
|
||||
<DialogContent>
|
||||
<DialogContent className="max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Excluir empresa</DialogTitle>
|
||||
<DialogDescription>
|
||||
<div className="flex items-center gap-2 text-amber-600">
|
||||
<IconAlertTriangle className="size-5" />
|
||||
<DialogTitle className="text-base font-semibold text-neutral-900">Confirmar exclusão</DialogTitle>
|
||||
</div>
|
||||
<DialogDescription className="text-sm text-neutral-600">
|
||||
Esta operação remove o cadastro do cliente e impede novos vínculos automáticos.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="space-y-2 text-sm text-neutral-600">
|
||||
<p>
|
||||
Confirme a exclusão de{" "}
|
||||
<span className="font-semibold text-neutral-900">{deleteTarget?.name ?? "empresa selecionada"}</span>.
|
||||
Deseja remover definitivamente{" "}
|
||||
<span className="font-semibold text-neutral-900">{deleteTarget?.name ?? "a empresa selecionada"}</span>?
|
||||
</p>
|
||||
<p className="text-xs text-neutral-500">
|
||||
Registros históricos que apontem para a empresa poderão impedir a exclusão.
|
||||
Registros históricos podem impedir a exclusão. Usuários e tickets ainda vinculados serão desvinculados automaticamente.
|
||||
</p>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<DialogFooter className="gap-2 sm:justify-end">
|
||||
<Button variant="outline" onClick={() => setDeleteId(null)} disabled={isDeleting}>
|
||||
Cancelar
|
||||
</Button>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue