Vlad Chikalkin 3589ab974a
Refactor/components folder structure (#24)
* refactor components/navigation

* refactor components/orders

* refactor components/profile

* refactor components/schedule

* remove components/common/spinner
2025-05-23 17:35:13 +03:00

63 lines
1.8 KiB
TypeScript

/* eslint-disable promise/prefer-await-to-then */
'use client';
import { Checkbox, type CheckboxProps } from '@repo/ui/components/ui/checkbox';
import { useState } from 'react';
import { useDebouncedCallback } from 'use-debounce';
type Props = Pick<CheckboxProps, 'checked'> & {
readonly description?: string;
readonly onChange?: (value: boolean) => Promise<void> | void;
readonly text: string;
};
export function CheckboxWithText({ checked: initialValue, description, onChange, text }: Props) {
const [checked, setChecked] = useState(initialValue);
const { debouncedCallback, isPending } = useDebouncedOnChangeCallback(onChange);
const handleChange = () => {
const newValue = !checked;
setChecked(newValue);
debouncedCallback(newValue);
};
return (
<div className="flex items-start space-x-2">
<Checkbox checked={checked} disabled={isPending} id="terms1" onCheckedChange={handleChange} />
<div className="grid gap-1.5 leading-none">
<label
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
htmlFor="terms1"
>
{text}
</label>
{description ? <p className="text-sm text-muted-foreground">{description}</p> : false}
</div>
</div>
);
}
function useDebouncedOnChangeCallback(
callback: ((value: boolean) => Promise<void> | void) | undefined,
) {
const [isPending, setIsPending] = useState(false);
const debouncedCallback = useDebouncedCallback((checked: boolean) => {
if (!callback) return;
setIsPending(true);
const result = callback(checked);
if (result instanceof Promise) {
result.finally(() => setIsPending(false));
} else {
setIsPending(false);
}
}, 300);
return {
debouncedCallback,
isPending,
};
}