diff --git a/package-lock.json b/package-lock.json index 6ff2249..1ecd19e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sysvale/citizen-components", - "version": "1.8.1", + "version": "1.15.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@sysvale/citizen-components", - "version": "1.8.1", + "version": "1.15.4", "dependencies": { "@vee-validate/i18n": "^4.15.1", "@vee-validate/rules": "^4.15.1", @@ -21,7 +21,7 @@ "@semantic-release/github": "^12.0.0", "@semantic-release/npm": "^13.1.1", "@semantic-release/release-notes-generator": "^14.1.0", - "@sysvale/cuida": "^3.152.0", + "@sysvale/cuida": "^3.154.7", "@sysvale/foundry": "^1.7.0", "@tsconfig/node22": "^22.0.1", "@types/jsdom": "^21.1.7", @@ -55,7 +55,7 @@ "vue-tsc": "^2.2.8" }, "peerDependencies": { - "@sysvale/cuida": "^3.152.0", + "@sysvale/cuida": "^3.154.7", "@sysvale/foundry": "^1.7.0", "vee-validate": "^4.15.1", "vue": "^3.5.13" @@ -3697,9 +3697,9 @@ } }, "node_modules/@sysvale/cuida": { - "version": "3.152.0", - "resolved": "https://registry.npmjs.org/@sysvale/cuida/-/cuida-3.152.0.tgz", - "integrity": "sha512-9nmJZeGLkyqSOOtxUNvufAiquYx96HTX49sLvVODcj3n35PXe8V2FAkoFLl6rSsnB/25IRSaaulzh2QypGHpzA==", + "version": "3.154.7", + "resolved": "https://registry.npmjs.org/@sysvale/cuida/-/cuida-3.154.7.tgz", + "integrity": "sha512-PpoMZ84rarHAcQimW65+nldlZGx8FtwEm26xtU1xq34MMT6LrOOdlnybbNQFryThfx87MNnsFaG0ZkwMIPh6Rg==", "dev": true, "dependencies": { "@popperjs/core": "^2.11.6", diff --git a/package.json b/package.json index c4ac3a0..b249784 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "luxon": "^3.7.2" }, "peerDependencies": { - "@sysvale/cuida": "^3.152.0", + "@sysvale/cuida": "^3.154.7", "@sysvale/foundry": "^1.7.0", "vee-validate": "^4.15.1", "vue": "^3.5.13" @@ -57,7 +57,7 @@ "@semantic-release/github": "^12.0.0", "@semantic-release/npm": "^13.1.1", "@semantic-release/release-notes-generator": "^14.1.0", - "@sysvale/cuida": "^3.152.0", + "@sysvale/cuida": "^3.154.7", "@sysvale/foundry": "^1.7.0", "@tsconfig/node22": "^22.0.1", "@types/jsdom": "^21.1.7", diff --git a/src/components/InternalComponents/CitizenForm.vue b/src/components/InternalComponents/CitizenForm.vue index ec2dd83..57376f2 100644 --- a/src/components/InternalComponents/CitizenForm.vue +++ b/src/components/InternalComponents/CitizenForm.vue @@ -126,6 +126,20 @@ + }) => { cities.value = response.data.map((city) => ({ id: city.nome, value: city.nome })); + const selectedCity = formRef.value?.values.city; + + if (!selectedCity || !cities.value.find(({ id }) => id === selectedCity?.value)) { + clearValidationRefs([validationCityRef]); + } + if (!props.allowedCities) return; cities.value = cities.value.filter(({ id }) => props.allowedCities?.includes(id)); @@ -304,11 +324,14 @@ async function handleCitySelect(cityName: string) { .then((response: { data: Array<{ id: string, name: string }> }) => { neighborhoods.value = response.data.map((neighborhood) => ({ id: neighborhood.name, value: neighborhood.name })); - if (!internalCitizen.value.neighborhood || !neighborhoods.value.find(({ id }) => id === internalCitizen.value.neighborhood?.id)) { + const selectedNeighborhood = formRef.value?.values.neighborhood; + + if (!selectedNeighborhood || !neighborhoods.value.find(({ id }) => id === selectedNeighborhood?.value)) { + clearValidationRefs([validationNeighborhoodRef]); return; } - handleNeighborhoodSelect(internalCitizen.value.neighborhood); + handleNeighborhoodSelect(selectedNeighborhood); }).catch(() => { // @ts-ignore useToast().fire({ @@ -338,6 +361,14 @@ async function handleNeighborhoodSelect(neighborhood: { id: string, value: strin getStreetsFromNeighborhoods(neighborhoodCityUfObject) .then((response: { data: Array<{ name: string }> }) => { streets.value = response.data.map((street) => ({ id: street.name, value: street.name })); + + const selectedStreet = formRef.value?.values.street; + + if (selectedStreet && streets.value.find(({ id }) => id === selectedStreet?.value)) { + return; + } + + clearValidationRefs([validationStreetRef]); }).catch(() => { // @ts-ignore useToast().fire({ @@ -362,17 +393,17 @@ function handleFieldInput(fieldName: string, fieldValue: any) { handleGenderChange(fieldValue.value); break; case 'uf': - clearValidationRefs([validationCityRef, validationNeighborhoodRef, validationStreetRef]); handleUfSelect(fieldValue.ibgeCode); break; case 'city': - clearValidationRefs([validationNeighborhoodRef, validationStreetRef]); handleCitySelect(fieldValue.value); break; case 'neighborhood': - clearValidationRefs([validationStreetRef]); handleNeighborhoodSelect(fieldValue); break; + case 'birth_date': + formRef.value?.setFieldValue('birth_date', fieldValue); + break; default: break; } diff --git a/src/components/InternalComponents/__snapshots__/CitizenForm.test.ts.snap b/src/components/InternalComponents/__snapshots__/CitizenForm.test.ts.snap index 0a23609..deb33d0 100644 --- a/src/components/InternalComponents/__snapshots__/CitizenForm.test.ts.snap +++ b/src/components/InternalComponents/__snapshots__/CitizenForm.test.ts.snap @@ -14,7 +14,7 @@ exports[`CitizenForm > is rendered correctly 1`] = `
- +
@@ -26,10 +26,10 @@ exports[`CitizenForm > is rendered correctly 1`] = `
- +
- +
@@ -47,16 +47,16 @@ exports[`CitizenForm > is rendered correctly 1`] = `
- +
- +
- +
- +
diff --git a/src/constants/citizenFormFields.ts b/src/constants/citizenFormFields.ts index 479d9a2..e7bfdce 100644 --- a/src/constants/citizenFormFields.ts +++ b/src/constants/citizenFormFields.ts @@ -37,7 +37,7 @@ export default (hiddenFields: string[]): CitizenFormField[] => { name: 'birth_date', label: 'Data de nascimento', required: true, - rules: 'required', + rules: `required|maxDate:${new Date().toISOString().split('T')[0]}`, colSpan: 6, component: 'CdsDateInput', maxDate: new Date().toISOString().split('T')[0], diff --git a/src/utils/rules/citizenFormRules.ts b/src/utils/rules/citizenFormRules.ts index afed928..db829a3 100644 --- a/src/utils/rules/citizenFormRules.ts +++ b/src/utils/rules/citizenFormRules.ts @@ -4,6 +4,8 @@ import { localize, setLocale } from '@vee-validate/i18n'; // @ts-ignore import { cpfValidator, cnsValidator } from '@sysvale/foundry'; import requiredWithout from './requiredWithout'; +import maxDate from './maxDate'; +import { dmyFormatter } from '../dmyFormatter'; setLocale('pt-BR'); @@ -30,6 +32,22 @@ defineRule('required_without', (value: string, target: string[]) => { return true; }); +defineRule('maxDate', (value: string, target: string[]) => { + const res = maxDate(value, target); + + if (!res) { + const formattedMaxDate = dmyFormatter(target?.[0]?.trim?.() ?? ''); + + if (formattedMaxDate !== '--') { + return `A data deve ser menor ou igual a ${formattedMaxDate}`; + } + + return 'A data deve ser menor ou igual à data máxima permitida'; + } + + return true; +}); + defineRule('cpf', (value: string) => { const res = cpfValidator(value ?? ''); diff --git a/src/utils/rules/maxDate.ts b/src/utils/rules/maxDate.ts new file mode 100644 index 0000000..9dd0f03 --- /dev/null +++ b/src/utils/rules/maxDate.ts @@ -0,0 +1,37 @@ +const isValidYmdDate = (date: string) => { + const match = date.match(/^(\d{4})-(\d{2})-(\d{2})$/); + + if (!match) { + return false; + } + + const [, yearRaw, monthRaw, dayRaw] = match; + const year = Number(yearRaw); + const month = Number(monthRaw); + const day = Number(dayRaw); + const parsedDate = new Date(Date.UTC(year, month - 1, day)); + + return ( + parsedDate.getUTCFullYear() === year + && parsedDate.getUTCMonth() === month - 1 + && parsedDate.getUTCDate() === day + ); +}; + +const maxDate = (value: string, target: string[]) => { + const normalizedValue = value?.trim?.() ?? ''; + + if (!normalizedValue) { + return true; + } + + const max = target?.[0]?.trim?.() ?? ''; + + if (!max || !isValidYmdDate(normalizedValue) || !isValidYmdDate(max)) { + return false; + } + + return normalizedValue <= max; +}; + +export default maxDate;