Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ export default function AddUserForm({
const { hasPermission } = usePermissions();
const onExit = useUnloadEventOnExit();
const { isPnpgTheOnlyProduct, pnpgProduct, activeOnboardings, isAdminEaOnProdIO } =
useAddUserFormComputedValues(party, products);
const { validate, validTaxcode, setValidTaxcode } = useFormValidation(t);
useAddUserFormComputedValues(party, products, userProduct);
const { validate, validTaxcode, setValidTaxcode } = useFormValidation(t, isAdminEaOnProdIO);

useEffect(() => {
if (!initialFormData.taxCode) {
Expand Down Expand Up @@ -441,7 +441,10 @@ export default function AddUserForm({
/>
}
aria-label={t(titleKey)}
onClick={() => formik.setFieldValue('toAddOnAggregates', value, true)}
onClick={async () => {
setIsAddInBulkEAFlow(value);
await formik.setFieldValue('toAddOnAggregates', value, true);
}}
/>
))}
</RadioGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,26 @@ import { useState } from 'react';
import { Party } from '../../../../../../model/Party';
import { PartyUserOnCreation } from '../../../../../../model/PartyUser';
import { Product } from '../../../../../../model/Product';
import { PRODUCT_IDS } from '../../../../../../utils/constants';
import { validateUserForm } from '../utils/addUserFormUtils';

export const useAddUserFormComputedValues = (party: Party, products: Array<Product>) => {
const isPnpgTheOnlyProduct =
!!products.find((p) => p.id === 'prod-pn-pg') && products.length === 1;
const pnpgProduct = products.find((p) => p.id === 'prod-pn-pg');
export const useAddUserFormComputedValues = (
party: Party,
products: Array<Product>,
userProduct: Product | undefined
) => {
const isPnpgTheOnlyProduct = !!products.find(
(p) => p.id === PRODUCT_IDS.PNPG && products.length === 1
);
const pnpgProduct = products.find((p) => p.id === PRODUCT_IDS.PNPG);

const activeOnboardings = party.products.filter((p) => p.productOnBoardingStatus === 'ACTIVE');

const isAdminEaOnProdIO = party.products.some(
(p) => p.productOnBoardingStatus === 'ACTIVE' && p.productId === 'prod-io' && p.isAggregator
);
const isAdminEaOnProdIO =
party.products.some(
(p) =>
p.productOnBoardingStatus === 'ACTIVE' && p.productId === PRODUCT_IDS.IO && p.isAggregator
) && userProduct?.id === PRODUCT_IDS.IO;

return {
isPnpgTheOnlyProduct,
Expand All @@ -24,11 +32,11 @@ export const useAddUserFormComputedValues = (party: Party, products: Array<Produ
};

// Custom hook for form validation
export const useFormValidation = (t: any) => {
export const useFormValidation = (t: any, isAdminEaOnProdIO: boolean) => {
const [validTaxcode, setValidTaxcode] = useState<string>();

const validate = (values: Partial<PartyUserOnCreation>) => {
const errors = validateUserForm(values, t);
const errors = validateUserForm(values, t, isAdminEaOnProdIO);

if (!errors.taxCode) {
setValidTaxcode(values.taxCode);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,70 @@
import { emailRegexp } from '@pagopa/selfcare-common-frontend/lib/utils/constants';
import { verifyChecksumMatchWithTaxCode } from '@pagopa/selfcare-common-frontend/lib/utils/verifyChecksumMatchWithTaxCode';
import { verifyNameMatchWithTaxCode } from '@pagopa/selfcare-common-frontend/lib/utils/verifyNameMatchWithTaxCode';
import { verifySurnameMatchWithTaxCode } from '@pagopa/selfcare-common-frontend/lib/utils/verifySurnameMatchWithTaxCode';
import { FormikProps } from 'formik';
import { PartyUserOnCreation } from '../../../../../../model/PartyUser';
import { UserRegistry } from '../../../../../../model/UserRegistry';
import { requiredError, taxCodeRegexp } from '../../../../utils/validation';
import {
requiredError,
validateName,
validateSurname,
validateTaxCode,
} from '../../../../utils/validation';

const validateEmail = (email: string | undefined, t: (key: string) => string) => {
if (!email) {
return requiredError;
}
if (!emailRegexp.test(email)) {
return t('userEdit.addForm.errors.invalidEmail');
}
return undefined;
};

const validateConfirmEmail = (
confirmEmail: string | undefined,
email: string | undefined,
t: (key: string) => string
) => {
if (!confirmEmail) {
return requiredError;
}
if (email && confirmEmail.toLocaleLowerCase() !== email.toLocaleLowerCase()) {
return t('userEdit.addForm.errors.mismatchEmail');
}
return undefined;
};

const validateProductRoles = (productRoles: Array<any> | undefined) =>
productRoles?.length === 0 ? requiredError : undefined;

const validateToAddOnAggregates = (toAddOnAggregates: any, isAdminEaOnProdIO: boolean) => {
// Only validate if isAdminEaOnProdIO is true
if (!isAdminEaOnProdIO) {
return undefined;
}

return toAddOnAggregates === undefined ? requiredError : undefined;
};

// Pure validation utilities
export const validateUserForm = (
values: Partial<PartyUserOnCreation>,
t: (key: string) => string
// eslint-disable-next-line sonarjs/cognitive-complexity
) =>
Object.fromEntries(
Object.entries({
name: !values.name
? requiredError
: verifyNameMatchWithTaxCode(values.name, values.taxCode)
? t('userEdit.mismatchWithTaxCode.name')
: undefined,
surname: !values.surname
? requiredError
: verifySurnameMatchWithTaxCode(values.surname, values.taxCode)
? t('userEdit.mismatchWithTaxCode.surname')
: undefined,
taxCode: !values.taxCode
? requiredError
: !taxCodeRegexp.test(values.taxCode) || verifyChecksumMatchWithTaxCode(values.taxCode)
? t('userEdit.addForm.errors.invalidFiscalCode')
: undefined,
email: !values.email
? requiredError
: !emailRegexp.test(values.email)
? t('userEdit.addForm.errors.invalidEmail')
: undefined,
confirmEmail: !values.confirmEmail
? requiredError
: values.email &&
values.confirmEmail.toLocaleLowerCase() !== values.email.toLocaleLowerCase()
? t('userEdit.addForm.errors.mismatchEmail')
: undefined,
productRoles: values.productRoles?.length === 0 ? requiredError : undefined,
toAddOnAggregates: values.toAddOnAggregates === undefined ? requiredError : undefined,
}).filter(([_key, value]) => value)
t: (key: string) => string,
isAdminEaOnProdIO: boolean
) => {
const validationResults = {
name: validateName(values.name, values.taxCode, t),
surname: validateSurname(values.surname, values.taxCode, t),
taxCode: validateTaxCode(values.taxCode, t),
email: validateEmail(values.email, t),
confirmEmail: validateConfirmEmail(values.confirmEmail, values.email, t),
productRoles: validateProductRoles(values.productRoles),
toAddOnAggregates: validateToAddOnAggregates(values.toAddOnAggregates, isAdminEaOnProdIO),
};

// Filter out undefined values (no errors)
return Object.fromEntries(
Object.entries(validationResults).filter(([_key, value]) => value !== undefined)
);
};

// Pure utility functions
export const isAddRoleFromDashboard = (phasesAdditionAllowed?: Array<string>) =>
Expand All @@ -55,12 +75,12 @@ export const isAddRoleFromDashboardAsync = (phasesAdditionAllowed?: Array<string

export const EA_RADIO_OPTIONS = [
{
value: true,
value: false,
titleKey: 'userEdit.addForm.addOnAggregatedEntities.radioTitle1',
descriptionKey: 'userEdit.addForm.addOnAggregatedEntities.radioDescription1',
},
{
value: false,
value: true,
titleKey: 'userEdit.addForm.addOnAggregatedEntities.radioTitle2',
descriptionKey: 'userEdit.addForm.addOnAggregatedEntities.radioDescription2',
},
Expand Down
56 changes: 41 additions & 15 deletions src/pages/addUserFlow/utils/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,44 @@ export const checkDuplicateTaxCodeWithDifferentEmail = (
return undefined;
};

export const validateName = (
name: string | undefined,
taxCode: string | undefined,
t: (key: string) => string
) => {
if (!name) {
return requiredError;
}
if (verifyNameMatchWithTaxCode(name, taxCode)) {
return t('userEdit.mismatchWithTaxCode.name');
}
return undefined;
};

export const validateSurname = (
surname: string | undefined,
taxCode: string | undefined,
t: (key: string) => string
) => {
if (!surname) {
return requiredError;
}
if (verifySurnameMatchWithTaxCode(surname, taxCode)) {
return t('userEdit.mismatchWithTaxCode.surname');
}
return undefined;
};

export const validateTaxCode = (taxCode: string | undefined, t: (key: string) => string) => {
if (!taxCode) {
return requiredError;
}
if (!taxCodeRegexp.test(taxCode) || verifyChecksumMatchWithTaxCode(taxCode)) {
return t('userEdit.addForm.errors.invalidFiscalCode');
}
return undefined;
};

export const validateManagerForm = (
manager: Partial<AddedUsersList>,
addedUserList: Array<AddedUsersList>,
Expand All @@ -38,21 +76,9 @@ export const validateManagerForm = (

return Object.fromEntries(
Object.entries({
name: !manager.name
? requiredField
: verifyNameMatchWithTaxCode(manager.name, manager.taxCode)
? t('userEdit.mismatchWithTaxCode.name')
: undefined,
surname: !manager.surname
? requiredField
: verifySurnameMatchWithTaxCode(manager.surname, manager.taxCode)
? t('userEdit.mismatchWithTaxCode.surname')
: undefined,
taxCode: !manager.taxCode
? requiredField
: !taxCodeRegexp.test(manager.taxCode) || verifyChecksumMatchWithTaxCode(manager.taxCode)
? t('userEdit.addForm.errors.invalidFiscalCode')
: undefined,
name: validateName(manager.name, manager.taxCode, t),
surname: validateSurname(manager.surname, manager.taxCode, t),
taxCode: validateTaxCode(manager.taxCode, t),
email: !manager.email
? requiredField
: !emailRegexp.test(manager.email)
Expand Down
Loading