feat: modernize report scheduling UI and date inputs

This commit is contained in:
Esdras Renan 2025-11-10 11:05:53 -03:00
parent 8cc513c532
commit 616fe42e10
10 changed files with 384 additions and 60 deletions

View file

@ -72,6 +72,8 @@ import type { Id } from "@/convex/_generated/dataModel"
import { TicketStatusBadge } from "@/components/tickets/status-badge"
import type { TicketPriority, TicketStatus } from "@/lib/schemas/ticket"
import { DeviceCustomFieldManager } from "@/components/admin/devices/device-custom-field-manager"
import { DatePicker } from "@/components/ui/date-picker"
import { SearchableCombobox, type SearchableComboboxOption } from "@/components/ui/searchable-combobox"
type DeviceMetrics = Record<string, unknown> | null
@ -1342,6 +1344,13 @@ export function AdminDevicesOverview({ tenantId, initialCompanyFilterSlug = "all
.sort((a, b) => a.name.localeCompare(b.name, "pt-BR"))
}, [companies, devices])
const companyComboboxOptions = useMemo<SearchableComboboxOption[]>(() => {
return companyOptions.map((company) => ({
value: company.slug,
label: company.name,
}))
}, [companyOptions])
const deviceFields = useQuery(
api.deviceFields.listForTenant,
convexUserId ? { tenantId, viewerId: convexUserId as Id<"users"> } : "skip"
@ -2250,23 +2259,17 @@ export function AdminDevicesOverview({ tenantId, initialCompanyFilterSlug = "all
</div>
<div className="grid gap-2">
<label className="text-sm font-medium text-slate-700">Empresa</label>
<Select
value={newDeviceCompanySlug ?? "all"}
onValueChange={(value) => setNewDeviceCompanySlug(value === "all" ? null : value)}
<SearchableCombobox
value={newDeviceCompanySlug}
onValueChange={setNewDeviceCompanySlug}
options={companyComboboxOptions}
placeholder="Sem empresa"
searchPlaceholder="Buscar empresa..."
emptyText="Nenhuma empresa encontrada."
allowClear
clearLabel="Sem empresa"
disabled={createDeviceLoading}
>
<SelectTrigger>
<SelectValue placeholder="Sem empresa" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">Sem empresa</SelectItem>
{companyOptions.map((option) => (
<SelectItem key={option.slug} value={option.slug}>
{option.name}
</SelectItem>
))}
</SelectContent>
</Select>
/>
</div>
<div className="grid gap-2">
<label htmlFor="device-serials" className="text-sm font-medium text-slate-700">
@ -5595,7 +5598,11 @@ export function DeviceDetails({ device }: DeviceDetailsProps) {
) : field.type === "number" ? (
<Input type="number" value={value == null ? "" : String(value)} onChange={(e) => setValue(e.target.value === "" ? null : Number(e.target.value))} />
) : field.type === "date" ? (
<Input type="date" value={value ? String(value).slice(0, 10) : ""} onChange={(e) => setValue(e.target.value || null)} />
<DatePicker
value={value ? String(value).slice(0, 10) : null}
onChange={(next) => setValue(next ?? null)}
placeholder="Selecionar data"
/>
) : field.type === "boolean" ? (
<label className="inline-flex items-center gap-2 text-sm text-slate-700">
<Checkbox checked={Boolean(value)} onCheckedChange={(v) => setValue(Boolean(v))} />