fix: checkbox logic (#1537)
## Description <!--- Describe the changes introduced by this pull request. --> <!--- Explain what problem it solves or what feature/fix it adds. --> ## Related Issue <!--- If this pull request is related to a specific issue, reference it here using #issue_number. --> <!--- For example, "Fixes #123" or "Addresses #456". --> ## Changes Made <!--- Provide a summary of the changes made in this pull request. --> <!--- Include any relevant technical details or architecture changes. --> - Change 1 - Change 2 - ... ## Testing Performed <!--- Describe the testing that you have performed to validate these changes. --> <!--- Include information about test cases, testing environments, and results. --> - Tested feature X in scenario Y. - Ran unit tests for component Z. - Tested on browsers A, B, and C. - ... ## Checklist <!--- Please check the boxes that apply to this pull request. --> <!--- You can add or remove items as needed. --> - [ ] I have tested these changes locally and they work as expected. - [ ] I have added/updated tests that prove the effectiveness of these changes. - [ ] I have updated the documentation to reflect these changes, if applicable. - [ ] I have followed the project's coding style guidelines. - [ ] I have addressed the code review feedback from the previous submission, if applicable. ## Additional Notes <!--- Provide any additional context or notes for the reviewers. --> <!--- This might include details about design decisions, potential concerns, or anything else relevant. -->
This commit is contained in:
@@ -12,6 +12,7 @@ import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/tr
|
|||||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||||
import type { TRecipientActionAuth } from '@documenso/lib/types/document-auth';
|
import type { TRecipientActionAuth } from '@documenso/lib/types/document-auth';
|
||||||
import { ZCheckboxFieldMeta } from '@documenso/lib/types/field-meta';
|
import { ZCheckboxFieldMeta } from '@documenso/lib/types/field-meta';
|
||||||
|
import { fromCheckboxValue, toCheckboxValue } from '@documenso/lib/universal/field-checkbox';
|
||||||
import type { Recipient } from '@documenso/prisma/client';
|
import type { Recipient } from '@documenso/prisma/client';
|
||||||
import type { FieldWithSignatureAndFieldMeta } from '@documenso/prisma/types/field-with-signature-and-fieldmeta';
|
import type { FieldWithSignatureAndFieldMeta } from '@documenso/prisma/types/field-with-signature-and-fieldmeta';
|
||||||
import { trpc } from '@documenso/trpc/react';
|
import { trpc } from '@documenso/trpc/react';
|
||||||
@@ -54,6 +55,7 @@ export const CheckboxField = ({
|
|||||||
...item,
|
...item,
|
||||||
value: item.value.length > 0 ? item.value : `empty-value-${item.id}`,
|
value: item.value.length > 0 ? item.value : `empty-value-${item.id}`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const [checkedValues, setCheckedValues] = useState(
|
const [checkedValues, setCheckedValues] = useState(
|
||||||
values
|
values
|
||||||
?.map((item) =>
|
?.map((item) =>
|
||||||
@@ -97,7 +99,7 @@ export const CheckboxField = ({
|
|||||||
const payload: TSignFieldWithTokenMutationSchema = {
|
const payload: TSignFieldWithTokenMutationSchema = {
|
||||||
token: recipient.token,
|
token: recipient.token,
|
||||||
fieldId: field.id,
|
fieldId: field.id,
|
||||||
value: checkedValues.join(','),
|
value: toCheckboxValue(checkedValues),
|
||||||
isBase64: true,
|
isBase64: true,
|
||||||
authOptions,
|
authOptions,
|
||||||
};
|
};
|
||||||
@@ -191,7 +193,7 @@ export const CheckboxField = ({
|
|||||||
await signFieldWithToken({
|
await signFieldWithToken({
|
||||||
token: recipient.token,
|
token: recipient.token,
|
||||||
fieldId: field.id,
|
fieldId: field.id,
|
||||||
value: updatedValues.join(','),
|
value: toCheckboxValue(checkedValues),
|
||||||
isBase64: true,
|
isBase64: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -228,6 +230,11 @@ export const CheckboxField = ({
|
|||||||
}
|
}
|
||||||
}, [checkedValues, isLengthConditionMet, field.inserted]);
|
}, [checkedValues, isLengthConditionMet, field.inserted]);
|
||||||
|
|
||||||
|
const parsedCheckedValues = useMemo(
|
||||||
|
() => fromCheckboxValue(field.customText),
|
||||||
|
[field.customText],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SigningFieldContainer field={field} onSign={onSign} onRemove={onRemove} type="Checkbox">
|
<SigningFieldContainer field={field} onSign={onSign} onRemove={onRemove} type="Checkbox">
|
||||||
{isLoading && (
|
{isLoading && (
|
||||||
@@ -277,9 +284,7 @@ export const CheckboxField = ({
|
|||||||
className="h-3 w-3"
|
className="h-3 w-3"
|
||||||
checkClassName="text-white"
|
checkClassName="text-white"
|
||||||
id={`checkbox-${index}`}
|
id={`checkbox-${index}`}
|
||||||
checked={field.customText
|
checked={parsedCheckedValues.includes(itemValue)}
|
||||||
.split(',')
|
|
||||||
.some((customValue) => customValue === itemValue)}
|
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onCheckedChange={() => void handleCheckboxOptionClick(item)}
|
onCheckedChange={() => void handleCheckboxOptionClick(item)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { validateDropdownField } from '@documenso/lib/advanced-fields-validation
|
|||||||
import { validateNumberField } from '@documenso/lib/advanced-fields-validation/validate-number';
|
import { validateNumberField } from '@documenso/lib/advanced-fields-validation/validate-number';
|
||||||
import { validateRadioField } from '@documenso/lib/advanced-fields-validation/validate-radio';
|
import { validateRadioField } from '@documenso/lib/advanced-fields-validation/validate-radio';
|
||||||
import { validateTextField } from '@documenso/lib/advanced-fields-validation/validate-text';
|
import { validateTextField } from '@documenso/lib/advanced-fields-validation/validate-text';
|
||||||
|
import { fromCheckboxValue } from '@documenso/lib/universal/field-checkbox';
|
||||||
import { prisma } from '@documenso/prisma';
|
import { prisma } from '@documenso/prisma';
|
||||||
import { DocumentStatus, FieldType, SigningStatus } from '@documenso/prisma/client';
|
import { DocumentStatus, FieldType, SigningStatus } from '@documenso/prisma/client';
|
||||||
|
|
||||||
@@ -119,7 +120,8 @@ export const signFieldWithToken = async ({
|
|||||||
|
|
||||||
if (field.type === FieldType.CHECKBOX && field.fieldMeta) {
|
if (field.type === FieldType.CHECKBOX && field.fieldMeta) {
|
||||||
const checkboxFieldParsedMeta = ZCheckboxFieldMeta.parse(field.fieldMeta);
|
const checkboxFieldParsedMeta = ZCheckboxFieldMeta.parse(field.fieldMeta);
|
||||||
const checkboxFieldValues = value.split(',');
|
const checkboxFieldValues: string[] = fromCheckboxValue(value);
|
||||||
|
|
||||||
const errors = validateCheckboxField(checkboxFieldValues, checkboxFieldParsedMeta, true);
|
const errors = validateCheckboxField(checkboxFieldValues, checkboxFieldParsedMeta, true);
|
||||||
|
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
MIN_HANDWRITING_FONT_SIZE,
|
MIN_HANDWRITING_FONT_SIZE,
|
||||||
MIN_STANDARD_FONT_SIZE,
|
MIN_STANDARD_FONT_SIZE,
|
||||||
} from '@documenso/lib/constants/pdf';
|
} from '@documenso/lib/constants/pdf';
|
||||||
|
import { fromCheckboxValue } from '@documenso/lib/universal/field-checkbox';
|
||||||
import { FieldType } from '@documenso/prisma/client';
|
import { FieldType } from '@documenso/prisma/client';
|
||||||
import { isSignatureFieldType } from '@documenso/prisma/guards/is-signature-field';
|
import { isSignatureFieldType } from '@documenso/prisma/guards/is-signature-field';
|
||||||
import type { FieldWithSignature } from '@documenso/prisma/types/field-with-signature';
|
import type { FieldWithSignature } from '@documenso/prisma/types/field-with-signature';
|
||||||
@@ -194,7 +195,7 @@ export const insertFieldInPDF = async (pdf: PDFDocument, field: FieldWithSignatu
|
|||||||
value: item.value.length > 0 ? item.value : `empty-value-${item.id}`,
|
value: item.value.length > 0 ? item.value : `empty-value-${item.id}`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const selected = field.customText.split(',');
|
const selected: string[] = fromCheckboxValue(field.customText);
|
||||||
|
|
||||||
for (const [index, item] of (values ?? []).entries()) {
|
for (const [index, item] of (values ?? []).entries()) {
|
||||||
const offsetY = index * 16;
|
const offsetY = index * 16;
|
||||||
|
|||||||
21
packages/lib/universal/field-checkbox.ts
Normal file
21
packages/lib/universal/field-checkbox.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
export const fromCheckboxValue = (customText: string): string[] => {
|
||||||
|
if (!customText) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(customText);
|
||||||
|
|
||||||
|
if (!Array.isArray(parsed)) {
|
||||||
|
throw new Error('Parsed checkbox values are not an array');
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
} catch {
|
||||||
|
return customText.split(',').filter(Boolean);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const toCheckboxValue = (values: string[]): string => {
|
||||||
|
return JSON.stringify(values);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user