From bfbbfd951e45bbdb695868670a5e66fb8aad9b40 Mon Sep 17 00:00:00 2001 From: jvictordev1 Date: Mon, 2 Feb 2026 11:59:56 -0300 Subject: [PATCH 1/5] =?UTF-8?q?refactor:=20adiciona=20tratamento=20para=20?= =?UTF-8?q?campos=20nulos=20do=20cidad=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.vue | 14 +++-------- src/models/Citizen.ts | 36 ++++++++++++++++----------- src/services/citizen/citizen.types.ts | 6 ++--- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/App.vue b/src/App.vue index f305469..6bf6837 100644 --- a/src/App.vue +++ b/src/App.vue @@ -63,24 +63,16 @@ function changeModel() { citizen.value = { id: '05954ccb-188b-4e56-bba8-53211d60e343', name: 'Dr. Monique Orn', - gender: 'F', + gender: null, cpf_responsible: null, mother_name: 'Jaime Powlowski DDS', cpf: '56826137918', cns: '440541140933040', - birth_date: '1946-10-02', + birth_date: null, phone: '38 4017-7733', cellphone: '83 7530-1849', email: 'joaopaulosncastro@sysvale.com.br', - address: { - cep: '44443', - street: 'Jakubowski Manors', - number: '625', - complement: 'Suite 152', - neighborhood: 'Shanahan Glen', - city: 'Albinborough', - uf: 'NY', - }, + address: null, race: 'black', co_cidadao: 2852, is_dead: true, diff --git a/src/models/Citizen.ts b/src/models/Citizen.ts index 40abc9f..ceaaa96 100644 --- a/src/models/Citizen.ts +++ b/src/models/Citizen.ts @@ -1,20 +1,20 @@ +import { genderFromType } from '@/constants/genders'; +import { raceByValue } from '@/constants/races'; import type { CitizenParams } from '@/services/citizen/citizen.types'; import type { Address, Gender, Race } from '@/types'; -import { genders } from '@/constants/genders'; import { Address as AddressModel } from './Address'; -import { raceByValue } from '@/constants/races'; -import { genderFromType } from '@/constants/genders'; // @ts-ignore -import { DateTime } from 'luxon'; import { - removeCpfMask, - removeCnsMask, - maskCpf, maskCns, + maskCpf, maskPhone, + removeCnsMask, + removeCpfMask, removePhoneMask, // @ts-ignore } from '@sysvale/foundry'; +// @ts-ignore +import { DateTime } from 'luxon'; export class Citizen { public id?: string; @@ -22,7 +22,7 @@ export class Citizen { public cpf_responsible: string | undefined; public cns: string | undefined; public name: string; - public birth_date: string; + public birth_date?: string; public identification_document: string; public pregnant: boolean; public mother_name?: string; @@ -30,7 +30,7 @@ export class Citizen { public phone: string; public email: string; public issuing_agency?: string; - private _gender: Gender = genders()[0] as Gender; + private _gender: Gender | null = null; private _race?: Race; private _address: Address | null = null; @@ -51,14 +51,14 @@ export class Citizen { this.email = args.email; this.issuing_agency = args.issuing_agency; this.address = args.address - ?? { + ? { city: args.city, uf: args.uf, street: args.street, neighborhood: args.neighborhood, number: args.number, complement: args.complement, - }; + } : args.address; } set race(race: Race | string) { @@ -73,6 +73,8 @@ export class Citizen { } set gender(gender: Gender | string) { + if (!gender) return; + if (typeof gender === 'string') { this._gender = genderFromType(gender); return; @@ -82,6 +84,8 @@ export class Citizen { } set address(address: Address) { + if (!address) return; + this._address = new AddressModel(address); } @@ -117,7 +121,7 @@ export class Citizen { return this._race; } - get gender(): Gender { + get gender(): Gender | null { return this._gender; } @@ -126,8 +130,10 @@ export class Citizen { { label: 'CPF', value: this.cpf ? maskCpf(this.cpf) : 'Não informado', field: 'cpf' }, { label: 'CNS', value: this.cns ? maskCns(this.cns) : 'Não informado', field: 'cns' }, { label: 'RG', value: this.identification_document || 'Não informado', field: 'identification_document' }, - { label: 'Data de nascimento', value: DateTime.fromISO(this.birth_date).toFormat('dd/MM/yyyy'), field: 'birth_date' }, - { label: 'Sexo', value: this._gender.name, field: 'gender' }, + { label: 'Data de nascimento', value: this.birth_date + ? DateTime.fromISO(this.birth_date).toFormat('dd/MM/yyyy') + : 'Não informada', field: 'birth_date' }, + { label: 'Sexo', value: this._gender ? this._gender.name : 'Não informado', field: 'gender' }, { label: 'Raça/Cor', value: this.race?.name || 'Não informado', field: 'race' }, ]; @@ -146,7 +152,7 @@ export class Citizen { } get isPregnant() { - return this._gender.value === 'F' && this.pregnant; + return this._gender && this._gender.value === 'F' && this.pregnant; } get fancyAddress() { diff --git a/src/services/citizen/citizen.types.ts b/src/services/citizen/citizen.types.ts index 6276412..837b0dd 100644 --- a/src/services/citizen/citizen.types.ts +++ b/src/services/citizen/citizen.types.ts @@ -31,14 +31,14 @@ export interface Citizen { cpf: string; cns: string; name: string; - gender: string; + gender?: Nullable; cpf_responsible?: Nullable; mother_name: string; - birth_date: string; + birth_date?: Nullable; phone: Nullable; cellphone: Nullable; email: Nullable; - address: Address; + address?: Nullable
; race: string; co_cidadao: number; is_dead: boolean; From 9ad61e6d7afb15971c142a094fe1f2b03228955e Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 4 Feb 2026 16:41:28 -0300 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20Adiciona=20l=C3=B3gica=20de=20aviso?= =?UTF-8?q?=20de=20cadastro=20incompleto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/CitizenSummaryViewer.vue | 90 +++++++++++++++++-- .../CitizenSummaryViewer.test.ts.snap | 1 + src/models/Address.ts | 41 +++++---- src/models/Citizen.ts | 30 ++++--- 4 files changed, 125 insertions(+), 37 deletions(-) diff --git a/src/components/CitizenSummaryViewer.vue b/src/components/CitizenSummaryViewer.vue index 30fc282..d3e1717 100644 --- a/src/components/CitizenSummaryViewer.vue +++ b/src/components/CitizenSummaryViewer.vue @@ -2,7 +2,10 @@
- + @@ -52,11 +55,30 @@ + + + + Cadastro incompleto + + import { watch, ref, onMounted, toRef } from 'vue'; +import { isEmpty, isNil, isObject, isString } from 'lodash'; // @ts-ignore import { smartTitleCase } from '@sysvale/foundry'; import { Citizen as CitizenModel } from '@/models/Citizen'; @@ -118,16 +141,71 @@ const emits = defineEmits(['create', 'edit', 'close']); const internalCitizen = ref(); const emptyStateImage = emptyState; +const hasMissingFields = ref(false); -onMounted(() => fillCitizen(props.citizen)); +onMounted(() => { + checkMissingRequiredFields(props.citizen); + fillCitizen(props.citizen); +}); -watch(toRef(props, 'citizen'), (newValue) => fillCitizen(newValue)); +watch(toRef(props, 'citizen'), (newValue) => { + checkMissingRequiredFields(newValue); + fillCitizen(newValue); +}); function fillCitizen(citizenInfo: any | null) { if (!citizenInfo) return; internalCitizen.value = new CitizenModel(citizenInfo); } + +function checkMissingRequiredFields(value: Partial | null) { + if (!value) { + hasMissingFields.value = false; + return; + } + + const citizen = value as Record; + const genderValue = citizen['gender'] ?? citizen['_gender']; + const addressValue = citizen['address'] ?? citizen['_address']; + const addressSource = (addressValue as Record) ?? { + street: citizen['street'], + number: citizen['number'], + neighborhood: citizen['neighborhood'], + city: citizen['city'], + uf: citizen['uf'], + }; + + const missingCpfAndCnsFields = ['cpf', 'cns'].some(field => isEmptyValue(citizen[field])); + + const missingCitizenFields = ['name', 'birth_date', 'mother_name'].some(field => + isEmptyValue(citizen[field]) + ) || isEmptyValue(genderValue); + + const missingAddressFields = ['street', 'number', 'neighborhood', 'city', 'uf'].some( + field => isEmptyValue(addressSource?.[field]) + ); + + hasMissingFields.value = missingCitizenFields || missingAddressFields || missingCpfAndCnsFields; +} + +function isEmptyValue(value: unknown) { + if (isNil(value)) return true; + if (isString(value)) return value.trim() === ''; + if (!isObject(value)) return false; + + const obj = value as Record; + if ('value' in obj) return isEmptyValue(obj.value); + if ('name' in obj) return isEmptyValue(obj.name); + if ('shortName' in obj) return isEmptyValue(obj.shortName); + if ('id' in obj) return isEmptyValue(obj.id); + + return isEmpty(obj); +} + +defineExpose({ + hasMissingFields, +})