zapishis-client/apps/web/components/profile/checkbox-with-text.tsx
Vlad Chikalkin b936a79c2b
feature/profile-page (#8)
* add basic profile page

* apps/web: detect telegram/browser
support browser (dev only)

* apps/web: add dark mode

* apps/web: support dark theme in tma

* apps/web: add loading spinner
remove dev info from page

* apps\web\app\(auth)\page.tsx: remove useState

* app/web: handle update profile name

* move debounce functional to hook

* add role checkbox
2025-01-10 11:51:14 +03:00

64 lines
2.0 KiB
TypeScript

/* eslint-disable canonical/id-match */
/* eslint-disable promise/prefer-await-to-then */
'use client';
import { Enum_Customer_Role } from '@repo/graphql/types';
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: Enum_Customer_Role) => 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: Enum_Customer_Role) => Promise<void> | void) | undefined,
) {
const [isPending, setIsPending] = useState(false);
const debouncedCallback = useDebouncedCallback((checked: boolean) => {
if (!callback) return;
setIsPending(true);
const result = callback(checked ? Enum_Customer_Role.Master : Enum_Customer_Role.Client);
if (result instanceof Promise) {
result.finally(() => setIsPending(false));
} else {
setIsPending(false);
}
}, 300);
return {
debouncedCallback,
isPending,
};
}