diff --git a/src/components/admin/machines/admin-machines-overview.tsx b/src/components/admin/machines/admin-machines-overview.tsx index e90103e..bde9cd2 100644 --- a/src/components/admin/machines/admin-machines-overview.tsx +++ b/src/components/admin/machines/admin-machines-overview.tsx @@ -36,6 +36,7 @@ import { api } from "@/convex/_generated/api" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" +import { Spinner } from "@/components/ui/spinner" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" import { Checkbox } from "@/components/ui/checkbox" @@ -737,12 +738,16 @@ export function normalizeMachineItem(raw: Record): MachinesQuer } } -function useMachinesQuery(tenantId: string): MachinesQueryItem[] { +function useMachinesQuery(tenantId: string): { machines: MachinesQueryItem[]; isLoading: boolean } { const result = useQuery(api.machines.listByTenant, { tenantId, includeMetadata: true, }) as Array> | undefined - return useMemo(() => (result ?? []).map((item) => normalizeMachineItem(item)), [result]) + const machines = useMemo(() => (result ?? []).map((item) => normalizeMachineItem(item)), [result]) + return { + machines, + isLoading: result === undefined, + } } const DEFAULT_OFFLINE_THRESHOLD_MS = 10 * 60 * 1000 @@ -1047,7 +1052,7 @@ function OsIcon({ osName }: { osName?: string | null }) { } export function AdminMachinesOverview({ tenantId, initialCompanyFilterSlug = "all" }: { tenantId: string; initialCompanyFilterSlug?: string }) { - const machines = useMachinesQuery(tenantId) + const { machines, isLoading } = useMachinesQuery(tenantId) const [q, setQ] = useState("") const [statusFilter, setStatusFilter] = useState("all") const [companyFilterSlug, setCompanyFilterSlug] = useState(initialCompanyFilterSlug) @@ -1184,7 +1189,9 @@ const filteredMachines = useMemo(() => { - {machines.length === 0 ? ( + {isLoading ? ( + + ) : machines.length === 0 ? ( ) : ( @@ -1251,6 +1258,22 @@ function EmptyState() { ) } +function LoadingState() { + return ( +
+
+ +
+
+

Carregando máquinas...

+

+ Sincronizando o inventário em tempo real. Isso leva apenas alguns instantes. +

+
+
+ ) +} + type MachineDetailsProps = { machine: MachinesQueryItem | null } diff --git a/src/components/ui/time-picker.tsx b/src/components/ui/time-picker.tsx index 2c698a7..f296be3 100644 --- a/src/components/ui/time-picker.tsx +++ b/src/components/ui/time-picker.tsx @@ -1,10 +1,9 @@ "use client" import * as React from "react" -import { ChevronDownIcon } from "lucide-react" +import { Clock8Icon } from "lucide-react" -import { Button } from "@/components/ui/button" -import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" +import { Input } from "@/components/ui/input" import { cn } from "@/lib/utils" type TimePickerProps = { @@ -13,71 +12,39 @@ type TimePickerProps = { className?: string placeholder?: string stepMinutes?: number + disabled?: boolean } -function pad2(n: number) { - return String(n).padStart(2, "0") -} +export function TimePicker({ value, onChange, className, placeholder = "Selecionar horário", stepMinutes = 15, disabled }: TimePickerProps) { + const handleChange = React.useCallback( + (event: React.ChangeEvent) => { + onChange?.(event.target.value) + }, + [onChange] + ) -export function TimePicker({ value, onChange, className, placeholder = "Selecionar horário", stepMinutes = 15 }: TimePickerProps) { - const [open, setOpen] = React.useState(false) - - const [hours, minutes] = React.useMemo(() => { - if (!value || !/^\d{2}:\d{2}$/.test(value)) return ["", ""] - const [h, m] = value.split(":") - return [h, m] - }, [value]) - - const minuteOptions = React.useMemo(() => { - const list: string[] = [] - for (let i = 0; i < 60; i += stepMinutes) list.push(pad2(i)) - if (!list.includes("00")) list.unshift("00") - return list + const stepSeconds = React.useMemo(() => { + if (!stepMinutes || stepMinutes <= 0) return undefined + return Math.max(1, Math.round(stepMinutes * 60)) }, [stepMinutes]) return ( - - - - - -
-
- {Array.from({ length: 24 }, (_, h) => pad2(h)).map((h) => ( - - ))} -
-
- {minuteOptions.map((m) => ( - - ))} -
-
-
-
+
+
+ +
+ +
) } -