2025-08-04 17:45:44 +02:00
|
|
|
import { Minus, Plus } from "lucide-react";
|
2026-03-18 17:44:42 +01:00
|
|
|
import Input from "~/components/ui/input";
|
2026-03-20 17:03:35 +01:00
|
|
|
import { cn } from "~/lib/utils";
|
2025-08-04 17:45:44 +02:00
|
|
|
export const Counter = ({
|
2025-08-28 18:27:07 +02:00
|
|
|
value,
|
|
|
|
|
setValue,
|
|
|
|
|
name,
|
|
|
|
|
onlyPositive,
|
|
|
|
|
disabled,
|
2025-08-04 17:45:44 +02:00
|
|
|
}: {
|
2025-08-28 18:27:07 +02:00
|
|
|
value: number;
|
|
|
|
|
setValue: (value: number) => void;
|
|
|
|
|
name: string;
|
|
|
|
|
onlyPositive?: boolean;
|
|
|
|
|
disabled?: boolean;
|
2025-08-04 17:45:44 +02:00
|
|
|
}) => {
|
2025-08-28 18:27:07 +02:00
|
|
|
const handleChange = (change: number) => {
|
|
|
|
|
const newValue = value + change;
|
|
|
|
|
if (onlyPositive && newValue < 0) return;
|
|
|
|
|
setValue(newValue);
|
|
|
|
|
};
|
|
|
|
|
return (
|
2026-03-12 12:11:57 +01:00
|
|
|
<div className="w-38 bg-card">
|
2025-08-29 16:18:32 +02:00
|
|
|
<label className="sr-only" htmlFor={name}>
|
2025-08-28 18:27:07 +02:00
|
|
|
{name}
|
|
|
|
|
</label>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
<div className="flex items-center rounded-md border px-1">
|
|
|
|
|
<button
|
2026-03-20 17:03:35 +01:00
|
|
|
className={cn(
|
|
|
|
|
"flex size-10 cursor-pointer items-center justify-center leading-10 transition hover:opacity-75 disabled:opacity-50",
|
|
|
|
|
disabled && "cursor-default",
|
|
|
|
|
)}
|
2025-08-28 18:27:07 +02:00
|
|
|
disabled={disabled}
|
2025-08-29 16:18:32 +02:00
|
|
|
onClick={() => handleChange(-1)}
|
|
|
|
|
type="button"
|
2025-08-28 18:27:07 +02:00
|
|
|
>
|
|
|
|
|
<Minus />
|
|
|
|
|
</button>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
<Input
|
2025-08-29 16:18:32 +02:00
|
|
|
className="no-spinner h-10 w-16 rounded-md border-none text-center shadow-none disabled:cursor-default sm:text-sm"
|
|
|
|
|
disabled={disabled}
|
2025-08-28 18:27:07 +02:00
|
|
|
id={name}
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
if (!Number.isNaN(Number.parseInt(e.target.value))) {
|
|
|
|
|
setValue(Number.parseInt(e.target.value));
|
|
|
|
|
} else {
|
|
|
|
|
e.target.value = String(value);
|
|
|
|
|
}
|
|
|
|
|
}}
|
2025-08-29 16:18:32 +02:00
|
|
|
type="number"
|
|
|
|
|
value={value}
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
<button
|
2026-03-20 17:03:35 +01:00
|
|
|
className={cn(
|
|
|
|
|
"flex size-10 cursor-pointer items-center justify-center leading-10 transition hover:opacity-75 disabled:opacity-50",
|
|
|
|
|
disabled && "cursor-default",
|
|
|
|
|
)}
|
2025-08-28 18:27:07 +02:00
|
|
|
disabled={disabled}
|
2025-08-29 16:18:32 +02:00
|
|
|
onClick={() => handleChange(1)}
|
|
|
|
|
type="button"
|
2025-08-28 18:27:07 +02:00
|
|
|
>
|
|
|
|
|
<Plus />
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|