Exibe loading em máquinas e moderniza time picker
This commit is contained in:
parent
9bfdb451bc
commit
aef5e66718
2 changed files with 57 additions and 67 deletions
|
|
@ -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<HTMLInputElement>) => {
|
||||
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 (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="outline" className={cn("w-full justify-between font-normal", className)}>
|
||||
{value ? value : placeholder}
|
||||
<ChevronDownIcon className="ml-2 size-4 opacity-60" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-auto p-0" align="start">
|
||||
<div className="flex gap-2 p-2">
|
||||
<div className="max-h-56 w-16 overflow-auto rounded-md border">
|
||||
{Array.from({ length: 24 }, (_, h) => pad2(h)).map((h) => (
|
||||
<button
|
||||
key={h}
|
||||
type="button"
|
||||
className={cn(
|
||||
"block w-full px-3 py-1.5 text-left text-sm hover:bg-muted",
|
||||
h === hours && "bg-muted/70 font-semibold"
|
||||
)}
|
||||
onClick={() => onChange?.(`${h}:${minutes || "00"}`)}
|
||||
>
|
||||
{h}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="max-h-56 w-16 overflow-auto rounded-md border">
|
||||
{minuteOptions.map((m) => (
|
||||
<button
|
||||
key={m}
|
||||
type="button"
|
||||
className={cn(
|
||||
"block w-full px-3 py-1.5 text-left text-sm hover:bg-muted",
|
||||
m === minutes && "bg-muted/70 font-semibold"
|
||||
)}
|
||||
onClick={() => onChange?.(`${hours || "00"}:${m}`)}
|
||||
>
|
||||
{m}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<div className="relative">
|
||||
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 text-muted-foreground">
|
||||
<Clock8Icon aria-hidden className="size-4" />
|
||||
</div>
|
||||
<Input
|
||||
type="time"
|
||||
value={value ?? ""}
|
||||
onChange={handleChange}
|
||||
step={stepSeconds}
|
||||
disabled={disabled}
|
||||
aria-label={placeholder}
|
||||
className={cn(
|
||||
"pl-9 text-sm [appearance:textfield] [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none",
|
||||
className
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue