chore: sync staging

This commit is contained in:
Esdras Renan 2025-11-10 01:57:45 -03:00
parent c5ddd54a3e
commit 561b19cf66
610 changed files with 105285 additions and 1206 deletions

View file

@ -1796,105 +1796,116 @@ export function AdminDevicesOverview({ tenantId, initialCompanyFilterSlug = "all
</div>
</CardHeader>
<CardContent className="overflow-hidden">
<div className="mb-3 flex flex-wrap items-center gap-2">
<div className="min-w-[220px] flex-1">
<Input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Buscar hostname, e-mail, MAC, serial..." />
<div className="mb-3 flex flex-col gap-3">
<div className="flex flex-wrap gap-3">
<label className="flex min-w-[260px] flex-1 flex-col gap-1 text-xs font-semibold uppercase tracking-wide text-neutral-500">
Buscar hostname, e-mail, MAC, serial...
<Input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Digite para filtrar" />
</label>
<label className="flex w-auto min-w-[170px] max-w-[220px] flex-col gap-1 text-xs font-semibold uppercase tracking-wide text-neutral-500">
Todos status
<Select value={statusFilter} onValueChange={setStatusFilter}>
<SelectTrigger className="justify-between text-sm">
<SelectValue placeholder="Status" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">Todos status</SelectItem>
<SelectItem value="online">Online</SelectItem>
<SelectItem value="offline">Offline</SelectItem>
<SelectItem value="stale">Sem sinal</SelectItem>
<SelectItem value="unknown">Desconhecido</SelectItem>
</SelectContent>
</Select>
</label>
<label className="flex w-auto min-w-[180px] max-w-[240px] flex-col gap-1 text-xs font-semibold uppercase tracking-wide text-neutral-500">
Todos os tipos
<Select value={deviceTypeFilter} onValueChange={setDeviceTypeFilter}>
<SelectTrigger className="justify-between text-sm">
<SelectValue placeholder="Tipo de dispositivo" />
</SelectTrigger>
<SelectContent>
{DEVICE_TYPE_FILTER_OPTIONS.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</label>
</div>
<Select value={statusFilter} onValueChange={setStatusFilter}>
<SelectTrigger className="min-w-36">
<SelectValue placeholder="Status" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">Todos status</SelectItem>
<SelectItem value="online">Online</SelectItem>
<SelectItem value="offline">Offline</SelectItem>
<SelectItem value="stale">Sem sinal</SelectItem>
<SelectItem value="unknown">Desconhecido</SelectItem>
</SelectContent>
</Select>
<Select value={deviceTypeFilter} onValueChange={setDeviceTypeFilter}>
<SelectTrigger className="min-w-40">
<SelectValue placeholder="Tipo de dispositivo" />
</SelectTrigger>
<SelectContent>
{DEVICE_TYPE_FILTER_OPTIONS.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
<Popover open={isCompanyPopoverOpen} onOpenChange={setIsCompanyPopoverOpen}>
<PopoverTrigger asChild>
<Button variant="outline" className="min-w-56 justify-between">
{(() => {
if (companyFilterSlug === "all") return "Todas empresas"
const found = companyOptions.find((c) => c.slug === companyFilterSlug)
return found?.name ?? companyFilterSlug
})()}
<span className="ml-2 text-slate-400"></span>
</Button>
</PopoverTrigger>
<PopoverContent className="w-72 p-2" align="start">
<div className="space-y-2">
<Input
value={companySearch}
onChange={(e) => setCompanySearch(e.target.value)}
placeholder="Buscar empresa..."
/>
<div className="max-h-64 overflow-auto rounded-md border border-slate-200">
<button
type="button"
onClick={() => {
setCompanyFilterSlug("all")
setCompanySearch("")
setIsCompanyPopoverOpen(false)
}}
className="block w-full px-3 py-2 text-left text-sm hover:bg-slate-100"
>
Todas empresas
</button>
{companyOptions
.filter((c) => c.name.toLowerCase().includes(companySearch.toLowerCase()))
.map((c) => (
<button
key={c.slug}
type="button"
onClick={() => {
setCompanyFilterSlug(c.slug)
setCompanySearch("")
setIsCompanyPopoverOpen(false)
}}
className="block w-full px-3 py-2 text-left text-sm hover:bg-slate-100"
>
{c.name}
</button>
))}
<div className="flex flex-wrap items-center gap-3">
<Popover open={isCompanyPopoverOpen} onOpenChange={setIsCompanyPopoverOpen}>
<PopoverTrigger asChild>
<Button variant="outline" className="min-w-56 justify-between">
{(() => {
if (companyFilterSlug === "all") return "Todas empresas"
const found = companyOptions.find((c) => c.slug === companyFilterSlug)
return found?.name ?? companyFilterSlug
})()}
<span className="ml-2 text-slate-400"></span>
</Button>
</PopoverTrigger>
<PopoverContent className="w-72 p-2" align="start">
<div className="space-y-2">
<Input
value={companySearch}
onChange={(e) => setCompanySearch(e.target.value)}
placeholder="Buscar empresa..."
/>
<div className="max-h-64 overflow-auto rounded-md border border-slate-200">
<button
type="button"
onClick={() => {
setCompanyFilterSlug("all")
setCompanySearch("")
setIsCompanyPopoverOpen(false)
}}
className="block w-full px-3 py-2 text-left text-sm hover:bg-slate-100"
>
Todas empresas
</button>
{companyOptions
.filter((c) => c.name.toLowerCase().includes(companySearch.toLowerCase()))
.map((c) => (
<button
key={c.slug}
type="button"
onClick={() => {
setCompanyFilterSlug(c.slug)
setCompanySearch("")
setIsCompanyPopoverOpen(false)
}}
className="block w-full px-3 py-2 text-left text-sm hover:bg-slate-100"
>
{c.name}
</button>
))}
</div>
</div>
</div>
</PopoverContent>
</Popover>
<label className="inline-flex items-center gap-2 rounded-md border border-slate-200 bg-slate-50/80 px-3 py-1.5 text-sm">
<Checkbox checked={onlyAlerts} onCheckedChange={(v) => setOnlyAlerts(Boolean(v))} />
<span>Somente com alertas</span>
</label>
<Button
variant="outline"
onClick={() => {
setQ("")
setStatusFilter("all")
setCompanyFilterSlug("all")
setCompanySearch("")
setOnlyAlerts(false)
setIsCompanyPopoverOpen(false)
}}
>
Limpar
</Button>
<Button size="sm" variant="outline" className="gap-2" onClick={handleOpenExportDialog}>
<Download className="size-4" />
Exportar XLSX
</Button>
</PopoverContent>
</Popover>
<label className="inline-flex items-center gap-2 rounded-md border border-slate-200 bg-slate-50/80 px-3 py-1.5 text-sm">
<Checkbox checked={onlyAlerts} onCheckedChange={(v) => setOnlyAlerts(Boolean(v))} />
<span>Somente com alertas</span>
</label>
<Button
variant="outline"
onClick={() => {
setQ("")
setStatusFilter("all")
setCompanyFilterSlug("all")
setCompanySearch("")
setOnlyAlerts(false)
setIsCompanyPopoverOpen(false)
}}
>
Limpar
</Button>
<Button size="sm" variant="outline" className="gap-2" onClick={handleOpenExportDialog}>
<Download className="size-4" />
Exportar XLSX
</Button>
</div>
</div>
{isLoading ? (
<LoadingState />