Compare commits

...

1 Commits

Author SHA1 Message Date
9499a03668 fix: improve checkbox field rendering and interaction 2025-02-25 13:48:27 +00:00
3 changed files with 49 additions and 40 deletions

View File

@ -52,8 +52,15 @@ export const DocumentSigningCheckboxField = ({
value: item.value.length > 0 ? item.value : `empty-value-${item.id}`, value: item.value.length > 0 ? item.value : `empty-value-${item.id}`,
})); }));
const parsedCheckedValues = useMemo(
() => fromCheckboxValue(field.customText),
[field.customText],
);
const [checkedValues, setCheckedValues] = useState( const [checkedValues, setCheckedValues] = useState(
values field.inserted && parsedCheckedValues.length > 0
? parsedCheckedValues
: values
?.map((item) => ?.map((item) =>
item.checked ? (item.value.length > 0 ? item.value : `empty-value-${item.id}`) : '', item.checked ? (item.value.length > 0 ? item.value : `empty-value-${item.id}`) : '',
) )
@ -172,19 +179,13 @@ export const DocumentSigningCheckboxField = ({
let updatedValues: string[] = []; let updatedValues: string[] = [];
try { try {
const isChecked = checkedValues.includes( const itemValue = item.value.length > 0 ? item.value : `empty-value-${item.id}`;
item.value.length > 0 ? item.value : `empty-value-${item.id}`, const isChecked = checkedValues.includes(itemValue);
);
if (!isChecked) { if (!isChecked) {
updatedValues = [ updatedValues = [...checkedValues, itemValue];
...checkedValues,
item.value.length > 0 ? item.value : `empty-value-${item.id}`,
];
} else { } else {
updatedValues = checkedValues.filter( updatedValues = checkedValues.filter((v) => v !== itemValue);
(v) => v !== item.value && v !== `empty-value-${item.id}`,
);
} }
setCheckedValues(updatedValues); setCheckedValues(updatedValues);
@ -215,6 +216,12 @@ export const DocumentSigningCheckboxField = ({
} }
}; };
useEffect(() => {
if (field.inserted && parsedCheckedValues.length > 0) {
setCheckedValues(parsedCheckedValues);
}
}, [field.inserted, parsedCheckedValues]);
useEffect(() => { useEffect(() => {
if (shouldAutoSignField) { if (shouldAutoSignField) {
void executeActionAuthProcedure({ void executeActionAuthProcedure({
@ -224,11 +231,6 @@ export const DocumentSigningCheckboxField = ({
} }
}, [checkedValues, isLengthConditionMet, field.inserted]); }, [checkedValues, isLengthConditionMet, field.inserted]);
const parsedCheckedValues = useMemo(
() => fromCheckboxValue(field.customText),
[field.customText],
);
return ( return (
<DocumentSigningFieldContainer <DocumentSigningFieldContainer
field={field} field={field}
@ -252,16 +254,17 @@ export const DocumentSigningCheckboxField = ({
<div className="z-50 flex flex-col gap-y-2"> <div className="z-50 flex flex-col gap-y-2">
{values?.map((item: { id: number; value: string; checked: boolean }, index: number) => { {values?.map((item: { id: number; value: string; checked: boolean }, index: number) => {
const itemValue = item.value || `empty-value-${item.id}`; const itemValue = item.value || `empty-value-${item.id}`;
const checkboxId = `checkbox-field-${field.id}-${index}`;
return ( return (
<div key={index} className="flex items-center gap-x-1.5"> <div key={index} className="flex items-center gap-x-1.5">
<Checkbox <Checkbox
className="h-4 w-4" className="h-4 w-4"
id={`checkbox-${index}`} id={checkboxId}
checked={checkedValues.includes(itemValue)} checked={checkedValues.includes(itemValue)}
onCheckedChange={() => handleCheckboxChange(item.value, item.id)} onCheckedChange={() => handleCheckboxChange(item.value, item.id)}
/> />
<Label htmlFor={`checkbox-${index}`}> <Label htmlFor={checkboxId}>
{item.value.includes('empty-value-') ? '' : item.value} {item.value.includes('empty-value-') ? '' : item.value}
</Label> </Label>
</div> </div>
@ -272,20 +275,21 @@ export const DocumentSigningCheckboxField = ({
)} )}
{field.inserted && ( {field.inserted && (
<div className="flex flex-col gap-y-1"> <div className="flex flex-col gap-y-2">
{values?.map((item: { id: number; value: string; checked: boolean }, index: number) => { {values?.map((item: { id: number; value: string; checked: boolean }, index: number) => {
const itemValue = item.value || `empty-value-${item.id}`; const itemValue = item.value || `empty-value-${item.id}`;
const checkboxId = `checkbox-field-${field.id}-${index}-inserted`;
return ( return (
<div key={index} className="flex items-center gap-x-1.5"> <div key={index} className="flex items-center gap-x-1.5">
<Checkbox <Checkbox
className="h-3 w-3" className="h-4 w-4"
id={`checkbox-${index}`} id={checkboxId}
checked={parsedCheckedValues.includes(itemValue)} checked={checkedValues.includes(itemValue)}
disabled={isLoading} disabled={isLoading}
onCheckedChange={() => void handleCheckboxOptionClick(item)} onCheckedChange={() => void handleCheckboxOptionClick(item)}
/> />
<Label htmlFor={`checkbox-${index}`} className="text-xs"> <Label htmlFor={checkboxId}>
{item.value.includes('empty-value-') ? '' : item.value} {item.value.includes('empty-value-') ? '' : item.value}
</Label> </Label>
</div> </div>

View File

@ -1,5 +1,5 @@
import { ZCheckboxFieldMeta } from '@documenso/lib/types/field-meta';
import type { TCheckboxFieldMeta } from '@documenso/lib/types/field-meta'; import type { TCheckboxFieldMeta } from '@documenso/lib/types/field-meta';
import { ZCheckboxFieldMeta } from '@documenso/lib/types/field-meta';
import { Checkbox } from '@documenso/ui/primitives/checkbox'; import { Checkbox } from '@documenso/ui/primitives/checkbox';
import { Label } from '@documenso/ui/primitives/label'; import { Label } from '@documenso/ui/primitives/label';
@ -28,18 +28,22 @@ export const CheckboxField = ({ field }: CheckboxFieldProps) => {
{!parsedFieldMeta?.values ? ( {!parsedFieldMeta?.values ? (
<FieldIcon fieldMeta={field.fieldMeta} type={field.type} /> <FieldIcon fieldMeta={field.fieldMeta} type={field.type} />
) : ( ) : (
parsedFieldMeta.values.map((item: { value: string; checked: boolean }, index: number) => ( parsedFieldMeta.values.map((item: { value: string; checked: boolean }, index: number) => {
const checkboxId = `checkbox-field-${field.formId}-${index}`;
return (
<div key={index} className="flex items-center gap-x-1.5"> <div key={index} className="flex items-center gap-x-1.5">
<Checkbox <Checkbox
className="dark:border-field-border h-3 w-3 bg-white" className="dark:border-field-border h-3 w-3 bg-white"
id={`checkbox-${index}`} id={checkboxId}
checked={item.checked} checked={item.checked}
/> />
<Label htmlFor={`checkbox-${index}`} className="text-xs font-normal text-black"> <Label htmlFor={checkboxId} className="text-xs font-normal text-black">
{item.value} {item.value}
</Label> </Label>
</div> </div>
)) );
})
)} )}
</div> </div>
); );

View File

@ -205,6 +205,7 @@ export const CheckboxFieldAdvancedSettings = ({
<div key={index} className="mt-2 flex items-center gap-4"> <div key={index} className="mt-2 flex items-center gap-4">
<Checkbox <Checkbox
className="data-[state=checked]:bg-primary border-foreground/30 h-5 w-5" className="data-[state=checked]:bg-primary border-foreground/30 h-5 w-5"
id={`checkbox-${value.id}-${index}`}
checked={value.checked} checked={value.checked}
onCheckedChange={(checked) => handleCheckboxValue(index, 'checked', checked)} onCheckedChange={(checked) => handleCheckboxValue(index, 'checked', checked)}
/> />