udp-schema 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/progress-fields.d.ts.map +1 -1
- package/dist/progress-fields.js +4 -0
- package/dist/progress-fields.js.map +1 -1
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +1 -2
- package/dist/validation.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*
|
|
17
17
|
* @module udp-schema
|
|
18
18
|
*/
|
|
19
|
-
export {
|
|
19
|
+
export { type OnboardingFormData, udpOnboardingFormSchema, } from './onboarding-form.js';
|
|
20
20
|
export { canProceed } from './validation.js';
|
|
21
21
|
export { calcAge, labelFor, labelsFor } from './helpers.js';
|
|
22
22
|
export { allFieldGroups, type BaseField, casteDiscriminationPlaceOptions, civicEngagementOptions, dietOptions, digitalAccessOptions, disabilityOptions, education, electoralBehaviour, employment, employmentStatusOptions, type FieldGroup, type FieldOption, familyMemberOptions, genderOptions, healthLifestyle, household, householdIncomeOptions, incomeRangeOptions, languageOptions, leadershipAmbitions, leadershipSkillsetOptions, lgbtqStatementOptions, type MultiSelectField, mbtiOptions, minorityOptions, type NumberField, neurodiversity, neurodiversityConditionOptions, type ProfileField, partyOptions, politicalAssociation, politicalSpectrumOptions, profile, psychologicalAssessment, qualificationOptions, religionOptions, reservationOptions, residence, type SelectField, sensoryPreferenceOptions, shiftOptions, substanceUseOptions, supportNeedOptions, type TextField, transgenderStatementOptions, votingIssueOptions, worldView, } from './profile-fields/index.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EACL,KAAK,kBAAkB,EACvB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAI7C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAI5D,OAAO,EAEL,cAAc,EAEd,KAAK,SAAS,EACd,+BAA+B,EAC/B,sBAAsB,EACtB,WAAW,EACX,oBAAoB,EACpB,iBAAiB,EACjB,SAAS,EACT,kBAAkB,EAClB,UAAU,EACV,uBAAuB,EACvB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,mBAAmB,EAEnB,aAAa,EACb,eAAe,EACf,SAAS,EACT,sBAAsB,EACtB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,WAAW,EACX,eAAe,EACf,KAAK,WAAW,EAChB,cAAc,EACd,8BAA8B,EAC9B,KAAK,YAAY,EACjB,YAAY,EACZ,oBAAoB,EACpB,wBAAwB,EACxB,OAAO,EACP,uBAAuB,EACvB,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,SAAS,EACT,KAAK,WAAW,EAChB,wBAAwB,EACxB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,KAAK,SAAS,EACd,2BAA2B,EAC3B,kBAAkB,EAClB,SAAS,GACV,MAAM,2BAA2B,CAAC;AAInC,OAAO,EACL,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,aAAa,GACd,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,EACrB,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,GAC5B,MAAM,wBAAwB,CAAC;AAIhC,OAAO,EACL,wBAAwB,IAAI,2BAA2B,EACvD,qBAAqB,IAAI,wBAAwB,EACjD,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EAAE,KAAK,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EAAE,KAAK,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,KAAK,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,KAAK,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,KAAK,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EACL,KAAK,qBAAqB,EAC1B,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,iBAAiB,EACjB,KAAK,oBAAoB,EACzB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,KAAK,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAE,KAAK,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAE,KAAK,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EACL,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAIvF,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,+EAA+E;AAE/E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,+EAA+E;AAE/E,OAAO,EAEL,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAE9B,+EAA+E;AAE/E,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,+EAA+E;AAE/E,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE5D,+EAA+E;AAE/E,OAAO;AACL,eAAe;AACf,cAAc,EAGd,+BAA+B,EAC/B,sBAAsB,EACtB,WAAW,EACX,oBAAoB,EACpB,iBAAiB,EACjB,SAAS,EACT,kBAAkB,EAClB,UAAU,EACV,uBAAuB,EAGvB,mBAAmB;AACnB,6CAA6C;AAC7C,aAAa,EACb,eAAe,EACf,SAAS,EACT,sBAAsB,EACtB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,EAErB,WAAW,EACX,eAAe,EAEf,cAAc,EACd,8BAA8B,EAE9B,YAAY,EACZ,oBAAoB,EACpB,wBAAwB,EACxB,OAAO,EACP,uBAAuB,EACvB,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,SAAS,EAET,wBAAwB,EACxB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAElB,2BAA2B,EAC3B,kBAAkB,EAClB,SAAS,GACV,MAAM,2BAA2B,CAAC;AAEnC,+EAA+E;AAE/E,OAAO,EACL,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,aAAa,GACd,MAAM,oBAAoB,CAAC;AAE5B,+EAA+E;AAE/E,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,EACrB,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,GAGpB,MAAM,wBAAwB,CAAC;AAEhC,+EAA+E;AAE/E,OAAO,EACL,wBAAwB,IAAI,2BAA2B,EACvD,qBAAqB,IAAI,wBAAwB,EACjD,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAE9B,+EAA+E;AAE/E,OAAO,EAA2B,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EAA6B,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAA6B,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAA8B,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAiC,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EAEL,sBAAsB,EAEtB,iBAAiB,EAEjB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAA8B,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAkC,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAA0B,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAA6B,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAGL,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAA6B,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEvF,+EAA+E;AAE/E,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC","sourcesContent":["/**\n * udp-schema — Shared schemas for User Detailed Profile (v2)\n *\n * Single source of truth consumed by both reform frontends and reform-backend.\n * 12-step \"1 question per screen\" architecture.\n *\n * Follows the same pattern as dating-schema:\n * - profile-fields/ with rich FieldGroup definitions\n * - getFieldOptions() / getFieldMeta() for runtime introspection\n * - Unified onboarding form schema (udpOnboardingFormSchema)\n * - Validation (canProceed) exported for frontend + backend\n * - Helpers (calcAge, labelFor, labelsFor) shared across codebases\n * - Onboarding-config for step grouping\n * - Zod step schemas for per-step validation\n * - Progress tracking (per-step + overall)\n *\n * @module udp-schema\n */\n\n// ─── Unified Form Schema (like dating's onboardingFormSchema) ───────────────\n\nexport {\n type OnboardingFormData,\n udpOnboardingFormSchema,\n} from './onboarding-form.js';\n\n// ─── Validation (single source of truth — used by frontend + backend) ───────\n\nexport { canProceed } from './validation.js';\n\n// ─── Shared Helpers ─────────────────────────────────────────────────────────\n\nexport { calcAge, labelFor, labelsFor } from './helpers.js';\n\n// ─── Profile Fields (rich metadata — like dating-schema) ────────────────────\n\nexport {\n // Field groups\n allFieldGroups,\n // Types\n type BaseField,\n casteDiscriminationPlaceOptions,\n civicEngagementOptions,\n dietOptions,\n digitalAccessOptions,\n disabilityOptions,\n education,\n electoralBehaviour,\n employment,\n employmentStatusOptions,\n type FieldGroup,\n type FieldOption,\n familyMemberOptions,\n // Option arrays (with labels + descriptions)\n genderOptions,\n healthLifestyle,\n household,\n householdIncomeOptions,\n incomeRangeOptions,\n languageOptions,\n leadershipAmbitions,\n leadershipSkillsetOptions,\n lgbtqStatementOptions,\n type MultiSelectField,\n mbtiOptions,\n minorityOptions,\n type NumberField,\n neurodiversity,\n neurodiversityConditionOptions,\n type ProfileField,\n partyOptions,\n politicalAssociation,\n politicalSpectrumOptions,\n profile,\n psychologicalAssessment,\n qualificationOptions,\n religionOptions,\n reservationOptions,\n residence,\n type SelectField,\n sensoryPreferenceOptions,\n shiftOptions,\n substanceUseOptions,\n supportNeedOptions,\n type TextField,\n transgenderStatementOptions,\n votingIssueOptions,\n worldView,\n} from './profile-fields/index.js';\n\n// ─── Field Helpers (like dating-schema) ─────────────────────────────────────\n\nexport {\n getFieldMeta,\n getFieldOptions,\n getImmutableFields,\n getStepSchema,\n} from './field-helpers.js';\n\n// ─── Onboarding Configuration ───────────────────────────────────────────────\n\nexport {\n getUdpOnboardingFieldConfig,\n UDP_ONBOARDING_FIELDS,\n UDP_ONBOARDING_STEP_GROUPS,\n UDP_TOTAL_MAIN_STEPS,\n UDP_TOTAL_SUB_STEPS,\n type UdpOnboardingFieldConfig,\n type UdpOnboardingStepGroup,\n} from './onboarding-config.js';\n\n// ─── Progress Fields ────────────────────────────────────────────────────────\n\nexport {\n calculateOverallProgress as calculateUdpOverallProgress,\n calculateStepProgress as calculateUdpStepProgress,\n getNestedValue,\n isFieldFilled,\n UDP_PROGRESS_FIELDS,\n UDP_TOTAL_STEPS,\n} from './progress-fields.js';\n\n// ─── Step Schemas (Zod validation) ──────────────────────────────────────────\n\nexport { type Step01ProfileInput, step01ProfileSchema } from './step-01.schema.js';\nexport { type Step02PoliticalInput, step02PoliticalSchema } from './step-02.schema.js';\nexport { type Step03ElectoralInput, step03ElectoralSchema } from './step-03.schema.js';\nexport { type Step04LeadershipInput, step04LeadershipSchema } from './step-04.schema.js';\nexport { type Step05PsychologicalInput, step05PsychologicalSchema } from './step-05.schema.js';\nexport {\n type CertificateEntryInput,\n certificateEntrySchema,\n type DegreeEntryInput,\n degreeEntrySchema,\n type Step06EducationInput,\n step06EducationSchema,\n} from './step-06.schema.js';\nexport { type Step07EmploymentInput, step07EmploymentSchema } from './step-07.schema.js';\nexport { type Step08NeurodiversityInput, step08NeurodiversitySchema } from './step-08.schema.js';\nexport { type Step09HealthInput, step09HealthSchema } from './step-09.schema.js';\nexport { type Step10WorldViewInput, step10WorldViewSchema } from './step-10.schema.js';\nexport {\n type SimplifiedAddressInput,\n type Step11ResidenceInput,\n simplifiedAddressSchema,\n step11ResidenceSchema,\n} from './step-11.schema.js';\nexport { type Step12HouseholdInput, step12HouseholdSchema } from './step-12.schema.js';\n\n// ─── Zod Helpers ────────────────────────────────────────────────────────────\n\nexport {\n emptyStringToUndefined,\n optionalPhoneSchema,\n optionalTrimmedString,\n optionalYearSchema,\n} from './zod-helpers.js';\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"progress-fields.d.ts","sourceRoot":"","sources":["../src/progress-fields.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"progress-fields.d.ts","sourceRoot":"","sources":["../src/progress-fields.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAmHxD,CAAC;AAEX,gCAAgC;AAChC,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAYlF;AAED,iEAAiE;AACjE,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAcrD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,GACnD;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAenC;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC,GACnE;IACD,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAeA"}
|
package/dist/progress-fields.js
CHANGED
|
@@ -58,6 +58,8 @@ export const UDP_PROGRESS_FIELDS = {
|
|
|
58
58
|
'postGraduations',
|
|
59
59
|
'doctorates',
|
|
60
60
|
'postDoctorates',
|
|
61
|
+
'otherCertificates',
|
|
62
|
+
'educationNotes',
|
|
61
63
|
],
|
|
62
64
|
7: [
|
|
63
65
|
'employmentStatus',
|
|
@@ -89,7 +91,9 @@ export const UDP_PROGRESS_FIELDS = {
|
|
|
89
91
|
10: [
|
|
90
92
|
'viewOnAnimalCruelty',
|
|
91
93
|
'viewOnLgbtqStatements',
|
|
94
|
+
'viewOnLgbtqOpinion',
|
|
92
95
|
'viewOnTransgenderInclusion',
|
|
96
|
+
'viewOnTransgenderOpinion',
|
|
93
97
|
'facingCasteDiscrimination',
|
|
94
98
|
'casteDiscriminationPlaces',
|
|
95
99
|
'viewOnGenderEquality',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"progress-fields.js","sourceRoot":"","sources":["../src/progress-fields.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * UDP Progress Fields — Single source of truth for step progress counting.\n *\n * Used by both frontend (stepper UI) and backend (computeStepProgressCounts).\n * Each step lists the curated fields that determine filled/total progress.\n *\n * Dot-paths (e.g., \"currentAddress.state\") resolve nested subdocument fields.\n * Only these fields count toward progress — extra fields in the schema are ignored.\n */\n\nexport const UDP_PROGRESS_FIELDS: Record<number, readonly string[]> = {\n 1: [\n 'firstName',\n 'lastName',\n 'gender',\n 'dateOfBirth',\n 'whatsappNumber',\n 'primaryLanguage',\n 'secondaryLanguages',\n 'familyReligion',\n 'personalReligion',\n 'reservationStatus',\n 'minorityStatus',\n ],\n 2: [\n 'politicalSpectrum',\n 'selfPartyAssociation',\n 'familyPartyAssociation',\n 'publicOfficeAndElections',\n 'networkAndCivicEngagement',\n ],\n 3: [\n 'epicNumber',\n 'willVoteThisTime',\n 'didVoteLastTime',\n 'votingFrequency',\n 'primaryVotingIssues',\n ],\n 4: [\n 'participateInRevolution',\n 'desiredPoliticalPosition',\n 'leadershipSkillset',\n 'politicalExposure',\n 'comfortWithVisibility',\n 'socialInfluenceLevel',\n 'pastExperience',\n 'changesYouWantToBring',\n ],\n 5: ['mbtiType', 'oceanScores'],\n 6: [\n 'highestQualification',\n 'education10th.board',\n 'education10th.schoolName',\n 'education10th.yearOfPassing',\n 'education12th.institutionName',\n 'education12th.yearOfPassing',\n 'diplomas',\n 'graduations',\n 'postGraduations',\n 'doctorates',\n 'postDoctorates',\n ],\n 7: [\n 'employmentStatus',\n 'occupation',\n 'workShift',\n 'comfortableWithShift',\n 'desiredShift',\n 'incomeRange',\n 'dreamOccupation',\n ],\n 8: [\n 'neurodiverseIdentity',\n 'conditions',\n 'sensoryPreferences',\n 'learningStyle',\n 'communicationPreference',\n 'supportNeeds',\n ],\n 9: [\n 'disabilityStatus',\n 'generalHealth',\n 'healthInsurance',\n 'diet',\n 'physicalActivity',\n 'sleepQuality',\n 'substanceUse',\n 'stressLevel',\n ],\n 10: [\n 'viewOnAnimalCruelty',\n 'viewOnLgbtqStatements',\n 'viewOnTransgenderInclusion',\n 'facingCasteDiscrimination',\n 'casteDiscriminationPlaces',\n 'viewOnGenderEquality',\n ],\n 11: [\n 'currentAddress.state',\n 'currentAddress.district',\n 'currentAddress.village',\n 'permanentAddress.state',\n 'permanentAddress.district',\n 'permanentAddress.village',\n 'homeNativePlace.state',\n 'homeNativePlace.district',\n 'ancestralPlace.state',\n 'ancestralPlace.district',\n ],\n 12: [\n 'maritalStatus',\n 'familyMembers',\n 'numberOfDependents',\n 'housingType',\n 'householdIncome',\n 'bplCard',\n 'digitalAccess',\n 'migrationStatus',\n 'landOwnership',\n 'primaryIncomeSource',\n ],\n} as const;\n\n/** Total number of UDP steps */\nexport const UDP_TOTAL_STEPS = 12;\n\n/**\n * Resolve a dot-path (e.g., \"currentAddress.state\") against a data object.\n * Works with both plain objects and Mongoose subdocuments.\n */\nexport function getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n const parts = path.split('.');\n let current: unknown = obj;\n\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n}\n\n/** Determine if a field value counts as \"filled\" for progress */\nexport function isFieldFilled(value: unknown): boolean {\n if (value === null || value === undefined) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (typeof value === 'number') return true;\n if (typeof value === 'boolean') return true;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') {\n // Area entity ref - check for name\n if ('name' in value && typeof (value as Record<string, unknown>).name === 'string') {\n return (value as Record<string, unknown>).name !== '';\n }\n return Object.keys(value).length > 0;\n }\n return false;\n}\n\n/**\n * Calculate progress for a single step.\n * Shared between frontend (stepper UI) and backend (API response).\n */\nexport function calculateStepProgress(\n stepNumber: number,\n formData: Record<string, unknown> | undefined | null,\n): { filled: number; total: number } {\n const fields = UDP_PROGRESS_FIELDS[stepNumber];\n if (!fields) return { filled: 0, total: 0 };\n\n const total = fields.length;\n if (!formData || total === 0) return { filled: 0, total };\n\n let filled = 0;\n for (const fieldPath of fields) {\n if (isFieldFilled(getNestedValue(formData, fieldPath))) {\n filled++;\n }\n }\n\n return { filled, total };\n}\n\n/**\n * Calculate overall progress across all steps.\n * Returns per-step breakdown + overall percentage.\n *\n * Mirrors dating-schema's calculateDatingOverallProgress().\n *\n * @param stepData - Map of step number → form data (e.g., { 1: {...}, 2: {...} })\n */\nexport function calculateOverallProgress(\n stepData: Record<number, Record<string, unknown> | undefined | null>,\n): {\n steps: { stepNumber: number; filled: number; total: number }[];\n totalFilled: number;\n totalFields: number;\n percent: number;\n} {\n const steps: { stepNumber: number; filled: number; total: number }[] = [];\n let totalFilled = 0;\n let totalFields = 0;\n\n for (let stepNumber = 1; stepNumber <= UDP_TOTAL_STEPS; stepNumber++) {\n const { filled, total } = calculateStepProgress(stepNumber, stepData[stepNumber]);\n steps.push({ stepNumber, filled, total });\n totalFilled += filled;\n totalFields += total;\n }\n\n const percent = totalFields > 0 ? Math.round((totalFilled / totalFields) * 100) : 0;\n\n return { steps, totalFilled, totalFields, percent };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"progress-fields.js","sourceRoot":"","sources":["../src/progress-fields.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAsC;IACpE,CAAC,EAAE;QACD,WAAW;QACX,UAAU;QACV,QAAQ;QACR,aAAa;QACb,gBAAgB;QAChB,iBAAiB;QACjB,oBAAoB;QACpB,gBAAgB;QAChB,kBAAkB;QAClB,mBAAmB;QACnB,gBAAgB;KACjB;IACD,CAAC,EAAE;QACD,mBAAmB;QACnB,sBAAsB;QACtB,wBAAwB;QACxB,0BAA0B;QAC1B,2BAA2B;KAC5B;IACD,CAAC,EAAE;QACD,YAAY;QACZ,kBAAkB;QAClB,iBAAiB;QACjB,iBAAiB;QACjB,qBAAqB;KACtB;IACD,CAAC,EAAE;QACD,yBAAyB;QACzB,0BAA0B;QAC1B,oBAAoB;QACpB,mBAAmB;QACnB,uBAAuB;QACvB,sBAAsB;QACtB,gBAAgB;QAChB,uBAAuB;KACxB;IACD,CAAC,EAAE,CAAC,UAAU,EAAE,aAAa,CAAC;IAC9B,CAAC,EAAE;QACD,sBAAsB;QACtB,qBAAqB;QACrB,0BAA0B;QAC1B,6BAA6B;QAC7B,+BAA+B;QAC/B,6BAA6B;QAC7B,UAAU;QACV,aAAa;QACb,iBAAiB;QACjB,YAAY;QACZ,gBAAgB;QAChB,mBAAmB;QACnB,gBAAgB;KACjB;IACD,CAAC,EAAE;QACD,kBAAkB;QAClB,YAAY;QACZ,WAAW;QACX,sBAAsB;QACtB,cAAc;QACd,aAAa;QACb,iBAAiB;KAClB;IACD,CAAC,EAAE;QACD,sBAAsB;QACtB,YAAY;QACZ,oBAAoB;QACpB,eAAe;QACf,yBAAyB;QACzB,cAAc;KACf;IACD,CAAC,EAAE;QACD,kBAAkB;QAClB,eAAe;QACf,iBAAiB;QACjB,MAAM;QACN,kBAAkB;QAClB,cAAc;QACd,cAAc;QACd,aAAa;KACd;IACD,EAAE,EAAE;QACF,qBAAqB;QACrB,uBAAuB;QACvB,oBAAoB;QACpB,4BAA4B;QAC5B,0BAA0B;QAC1B,2BAA2B;QAC3B,2BAA2B;QAC3B,sBAAsB;KACvB;IACD,EAAE,EAAE;QACF,sBAAsB;QACtB,yBAAyB;QACzB,wBAAwB;QACxB,wBAAwB;QACxB,2BAA2B;QAC3B,0BAA0B;QAC1B,uBAAuB;QACvB,0BAA0B;QAC1B,sBAAsB;QACtB,yBAAyB;KAC1B;IACD,EAAE,EAAE;QACF,eAAe;QACf,eAAe;QACf,oBAAoB;QACpB,aAAa;QACb,iBAAiB;QACjB,SAAS;QACT,eAAe;QACf,iBAAiB;QACjB,eAAe;QACf,qBAAqB;KACtB;CACO,CAAC;AAEX,gCAAgC;AAChC,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAElC;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAA4B,EAAE,IAAY;IACvE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,OAAO,GAAY,GAAG,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC7E,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,GAAI,OAAmC,CAAC,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAC9D,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,mCAAmC;QACnC,IAAI,MAAM,IAAI,KAAK,IAAI,OAAQ,KAAiC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACnF,OAAQ,KAAiC,CAAC,IAAI,KAAK,EAAE,CAAC;QACxD,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,UAAkB,EAClB,QAAoD;IAEpD,MAAM,MAAM,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAC/C,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAE5C,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;IAC5B,IAAI,CAAC,QAAQ,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;IAE1D,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,SAAS,IAAI,MAAM,EAAE,CAAC;QAC/B,IAAI,aAAa,CAAC,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;YACvD,MAAM,EAAE,CAAC;QACX,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB,CACtC,QAAoE;IAOpE,MAAM,KAAK,GAA4D,EAAE,CAAC;IAC1E,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,KAAK,IAAI,UAAU,GAAG,CAAC,EAAE,UAAU,IAAI,eAAe,EAAE,UAAU,EAAE,EAAE,CAAC;QACrE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,qBAAqB,CAAC,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;QAClF,KAAK,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1C,WAAW,IAAI,MAAM,CAAC;QACtB,WAAW,IAAI,KAAK,CAAC;IACvB,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEpF,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;AACtD,CAAC","sourcesContent":["/**\n * UDP Progress Fields — Single source of truth for step progress counting.\n *\n * Used by both frontend (stepper UI) and backend (computeStepProgressCounts).\n * Each step lists the curated fields that determine filled/total progress.\n *\n * Dot-paths (e.g., \"currentAddress.state\") resolve nested subdocument fields.\n * Only these fields count toward progress — extra fields in the schema are ignored.\n */\n\nexport const UDP_PROGRESS_FIELDS: Record<number, readonly string[]> = {\n 1: [\n 'firstName',\n 'lastName',\n 'gender',\n 'dateOfBirth',\n 'whatsappNumber',\n 'primaryLanguage',\n 'secondaryLanguages',\n 'familyReligion',\n 'personalReligion',\n 'reservationStatus',\n 'minorityStatus',\n ],\n 2: [\n 'politicalSpectrum',\n 'selfPartyAssociation',\n 'familyPartyAssociation',\n 'publicOfficeAndElections',\n 'networkAndCivicEngagement',\n ],\n 3: [\n 'epicNumber',\n 'willVoteThisTime',\n 'didVoteLastTime',\n 'votingFrequency',\n 'primaryVotingIssues',\n ],\n 4: [\n 'participateInRevolution',\n 'desiredPoliticalPosition',\n 'leadershipSkillset',\n 'politicalExposure',\n 'comfortWithVisibility',\n 'socialInfluenceLevel',\n 'pastExperience',\n 'changesYouWantToBring',\n ],\n 5: ['mbtiType', 'oceanScores'],\n 6: [\n 'highestQualification',\n 'education10th.board',\n 'education10th.schoolName',\n 'education10th.yearOfPassing',\n 'education12th.institutionName',\n 'education12th.yearOfPassing',\n 'diplomas',\n 'graduations',\n 'postGraduations',\n 'doctorates',\n 'postDoctorates',\n 'otherCertificates',\n 'educationNotes',\n ],\n 7: [\n 'employmentStatus',\n 'occupation',\n 'workShift',\n 'comfortableWithShift',\n 'desiredShift',\n 'incomeRange',\n 'dreamOccupation',\n ],\n 8: [\n 'neurodiverseIdentity',\n 'conditions',\n 'sensoryPreferences',\n 'learningStyle',\n 'communicationPreference',\n 'supportNeeds',\n ],\n 9: [\n 'disabilityStatus',\n 'generalHealth',\n 'healthInsurance',\n 'diet',\n 'physicalActivity',\n 'sleepQuality',\n 'substanceUse',\n 'stressLevel',\n ],\n 10: [\n 'viewOnAnimalCruelty',\n 'viewOnLgbtqStatements',\n 'viewOnLgbtqOpinion',\n 'viewOnTransgenderInclusion',\n 'viewOnTransgenderOpinion',\n 'facingCasteDiscrimination',\n 'casteDiscriminationPlaces',\n 'viewOnGenderEquality',\n ],\n 11: [\n 'currentAddress.state',\n 'currentAddress.district',\n 'currentAddress.village',\n 'permanentAddress.state',\n 'permanentAddress.district',\n 'permanentAddress.village',\n 'homeNativePlace.state',\n 'homeNativePlace.district',\n 'ancestralPlace.state',\n 'ancestralPlace.district',\n ],\n 12: [\n 'maritalStatus',\n 'familyMembers',\n 'numberOfDependents',\n 'housingType',\n 'householdIncome',\n 'bplCard',\n 'digitalAccess',\n 'migrationStatus',\n 'landOwnership',\n 'primaryIncomeSource',\n ],\n} as const;\n\n/** Total number of UDP steps */\nexport const UDP_TOTAL_STEPS = 12;\n\n/**\n * Resolve a dot-path (e.g., \"currentAddress.state\") against a data object.\n * Works with both plain objects and Mongoose subdocuments.\n */\nexport function getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n const parts = path.split('.');\n let current: unknown = obj;\n\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return undefined;\n }\n current = (current as Record<string, unknown>)[part];\n }\n\n return current;\n}\n\n/** Determine if a field value counts as \"filled\" for progress */\nexport function isFieldFilled(value: unknown): boolean {\n if (value === null || value === undefined) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (typeof value === 'number') return true;\n if (typeof value === 'boolean') return true;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') {\n // Area entity ref - check for name\n if ('name' in value && typeof (value as Record<string, unknown>).name === 'string') {\n return (value as Record<string, unknown>).name !== '';\n }\n return Object.keys(value).length > 0;\n }\n return false;\n}\n\n/**\n * Calculate progress for a single step.\n * Shared between frontend (stepper UI) and backend (API response).\n */\nexport function calculateStepProgress(\n stepNumber: number,\n formData: Record<string, unknown> | undefined | null,\n): { filled: number; total: number } {\n const fields = UDP_PROGRESS_FIELDS[stepNumber];\n if (!fields) return { filled: 0, total: 0 };\n\n const total = fields.length;\n if (!formData || total === 0) return { filled: 0, total };\n\n let filled = 0;\n for (const fieldPath of fields) {\n if (isFieldFilled(getNestedValue(formData, fieldPath))) {\n filled++;\n }\n }\n\n return { filled, total };\n}\n\n/**\n * Calculate overall progress across all steps.\n * Returns per-step breakdown + overall percentage.\n *\n * Mirrors dating-schema's calculateDatingOverallProgress().\n *\n * @param stepData - Map of step number → form data (e.g., { 1: {...}, 2: {...} })\n */\nexport function calculateOverallProgress(\n stepData: Record<number, Record<string, unknown> | undefined | null>,\n): {\n steps: { stepNumber: number; filled: number; total: number }[];\n totalFilled: number;\n totalFields: number;\n percent: number;\n} {\n const steps: { stepNumber: number; filled: number; total: number }[] = [];\n let totalFilled = 0;\n let totalFields = 0;\n\n for (let stepNumber = 1; stepNumber <= UDP_TOTAL_STEPS; stepNumber++) {\n const { filled, total } = calculateStepProgress(stepNumber, stepData[stepNumber]);\n steps.push({ stepNumber, filled, total });\n totalFilled += filled;\n totalFields += total;\n }\n\n const percent = totalFields > 0 ? Math.round((totalFilled / totalFields) * 100) : 0;\n\n return { steps, totalFilled, totalFields, percent };\n}\n"]}
|
package/dist/validation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,OAAO,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,OAAO,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAiLT"}
|
package/dist/validation.js
CHANGED
|
@@ -158,8 +158,7 @@ export function canProceed(fieldKey, required, form) {
|
|
|
158
158
|
case 'otherCertificates': {
|
|
159
159
|
if (!Array.isArray(value) || value.length === 0)
|
|
160
160
|
return false;
|
|
161
|
-
return value.some((entry) => typeof entry.certificateName === 'string' &&
|
|
162
|
-
entry.certificateName.trim().length > 0);
|
|
161
|
+
return value.some((entry) => typeof entry.certificateName === 'string' && entry.certificateName.trim().length > 0);
|
|
163
162
|
}
|
|
164
163
|
// ── Text opinions ──
|
|
165
164
|
case 'educationNotes':
|
package/dist/validation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * UDP Onboarding Validation — single source of truth.\n *\n * Pure functions, no framework dependencies (no React hooks, no DOM).\n * Used by both frontend (canProceed check) and backend (submission validation).\n *\n * @module udp-schema/validation\n */\n\nimport { calcAge } from './helpers.js';\n\n/**\n * Check if the user can proceed from the current sub-step.\n *\n * @param fieldKey - Current field being filled\n * @param required - Whether the field is required\n * @param form - Current form data (flat key-value object)\n * @returns true if the user can proceed\n */\nexport function canProceed(\n fieldKey: string,\n required: boolean,\n form: Record<string, unknown>,\n): boolean {\n if (!required) return true;\n\n const value = form[fieldKey];\n\n switch (fieldKey) {\n // ── Names: minimum 1 char trimmed ──\n case 'firstName':\n case 'lastName':\n return typeof value === 'string' && value.trim().length >= 1;\n\n // ── Date of birth: must exist AND user must be 18+ ──\n case 'dateOfBirth': {\n if (!value) return false;\n const age = calcAge(String(value));\n return age !== null && age >= 18;\n }\n\n // ── Phone: digits only, 7-15 chars ──\n case 'whatsappNumber': {\n if (!value) return false;\n const digits = String(value).replace(/\\D/g, '');\n return digits.length >= 7 && digits.length <= 15;\n }\n\n // ── Single-select enums: must be non-empty string ──\n case 'gender':\n case 'familyReligion':\n case 'personalReligion':\n case 'reservationStatus':\n case 'minorityStatus':\n case 'primaryLanguage':\n case 'highestQualification':\n case 'politicalSpectrum':\n case 'employmentStatus':\n case 'maritalStatus':\n case 'willVoteThisTime':\n case 'didVoteLastTime':\n case 'votingFrequency':\n case 'participateInRevolution':\n case 'desiredPoliticalPosition':\n case 'politicalExposure':\n case 'comfortWithVisibility':\n case 'socialInfluenceLevel':\n case 'pastExperience':\n case 'neurodiverseIdentity':\n case 'generalHealth':\n case 'healthInsurance':\n case 'physicalActivity':\n case 'sleepQuality':\n case 'stressLevel':\n case 'workShift':\n case 'comfortableWithShift':\n case 'desiredShift':\n case 'learningStyle':\n case 'communicationPreference':\n case 'viewOnAnimalCruelty':\n case 'facingCasteDiscrimination':\n case 'viewOnGenderEquality':\n case 'housingType':\n case 'bplCard':\n case 'migrationStatus':\n case 'landOwnership':\n case 'primaryIncomeSource':\n case 'diet':\n return typeof value === 'string' && value.length > 0;\n\n // ── Multi-select arrays: at least 1 selection ──\n case 'secondaryLanguages':\n case 'primaryVotingIssues':\n case 'leadershipSkillset':\n case 'networkAndCivicEngagement':\n case 'conditions':\n case 'sensoryPreferences':\n case 'supportNeeds':\n case 'disabilityStatus':\n case 'substanceUse':\n case 'viewOnLgbtqStatements':\n case 'viewOnTransgenderInclusion':\n case 'casteDiscriminationPlaces':\n case 'familyMembers':\n case 'digitalAccess':\n return Array.isArray(value) && value.length > 0;\n\n // ── Text inputs: non-empty trimmed string ──\n case 'epicNumber':\n case 'selfPartyAssociation':\n case 'familyPartyAssociation':\n case 'occupation':\n case 'incomeRange':\n case 'householdIncome':\n return typeof value === 'string' && value.trim().length > 0;\n\n // ── Free text: at least 5 chars ──\n case 'changesYouWantToBring':\n case 'dreamOccupation':\n return typeof value === 'string' && value.trim().length >= 5;\n\n // ── Number fields ──\n case 'numberOfDependents':\n return typeof value === 'number' && value >= 0;\n\n // ── Address: at least state and district ──\n case 'currentAddress':\n case 'permanentAddress':\n case 'homeNativePlace':\n case 'ancestralPlace': {\n if (!value || typeof value !== 'object') return false;\n const addr = value as Record<string, unknown>;\n return !!addr.state && !!addr.district;\n }\n\n // ── MBTI type ──\n case 'mbtiType':\n return typeof value === 'string' && value.length > 0;\n\n // ── OCEAN: at least one dimension set ──\n case 'oceanScores': {\n if (!value || typeof value !== 'object') return false;\n const scores = value as Record<string, unknown>;\n return Object.values(scores).some(\n (v) => typeof v === 'number' && v >= 1 && v <= 100,\n );\n }\n\n // ── Compound: publicOfficeAndElections ──\n case 'publicOfficeAndElections': {\n if (!value || typeof value !== 'object') return false;\n const office = value as Record<string, unknown>;\n return !!office.hasHeldOffice;\n }\n\n // ── Education multi-field: at least one field filled ──\n case 'education10th':\n case 'education12th': {\n if (!value || typeof value !== 'object') return false;\n return Object.values(value as Record<string, unknown>).some(\n (v) => typeof v === 'string' && v.trim().length > 0,\n );\n }\n\n // ── Degree repeaters ──\n case 'diplomas':\n case 'graduations':\n case 'postGraduations':\n case 'doctorates':\n case 'postDoctorates': {\n if (!Array.isArray(value) || value.length === 0) return false;\n return value.some(\n (entry: Record<string, unknown>) =>\n typeof entry.degreeName === 'string' && entry.degreeName.trim().length > 0,\n );\n }\n\n // ── Certificate repeater ──\n case 'otherCertificates': {\n if (!Array.isArray(value) || value.length === 0) return false;\n return value.some(\n (entry: Record<string, unknown>) =>\n typeof entry.certificateName === 'string' &&\n entry.certificateName.trim().length > 0,\n );\n }\n\n // ── Text opinions ──\n case 'educationNotes':\n case 'viewOnLgbtqOpinion':\n case 'viewOnTransgenderOpinion':\n return typeof value === 'string' && value.trim().length > 0;\n\n // ── Default: strict (not permissive) ──\n default:\n if (value === null || value === undefined) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (typeof value === 'number') return true;\n if (typeof value === 'boolean') return true;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') return Object.keys(value).length > 0;\n return false;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * UDP Onboarding Validation — single source of truth.\n *\n * Pure functions, no framework dependencies (no React hooks, no DOM).\n * Used by both frontend (canProceed check) and backend (submission validation).\n *\n * @module udp-schema/validation\n */\n\nimport { calcAge } from './helpers.js';\n\n/**\n * Check if the user can proceed from the current sub-step.\n *\n * @param fieldKey - Current field being filled\n * @param required - Whether the field is required\n * @param form - Current form data (flat key-value object)\n * @returns true if the user can proceed\n */\nexport function canProceed(\n fieldKey: string,\n required: boolean,\n form: Record<string, unknown>,\n): boolean {\n if (!required) return true;\n\n const value = form[fieldKey];\n\n switch (fieldKey) {\n // ── Names: minimum 1 char trimmed ──\n case 'firstName':\n case 'lastName':\n return typeof value === 'string' && value.trim().length >= 1;\n\n // ── Date of birth: must exist AND user must be 18+ ──\n case 'dateOfBirth': {\n if (!value) return false;\n const age = calcAge(String(value));\n return age !== null && age >= 18;\n }\n\n // ── Phone: digits only, 7-15 chars ──\n case 'whatsappNumber': {\n if (!value) return false;\n const digits = String(value).replace(/\\D/g, '');\n return digits.length >= 7 && digits.length <= 15;\n }\n\n // ── Single-select enums: must be non-empty string ──\n case 'gender':\n case 'familyReligion':\n case 'personalReligion':\n case 'reservationStatus':\n case 'minorityStatus':\n case 'primaryLanguage':\n case 'highestQualification':\n case 'politicalSpectrum':\n case 'employmentStatus':\n case 'maritalStatus':\n case 'willVoteThisTime':\n case 'didVoteLastTime':\n case 'votingFrequency':\n case 'participateInRevolution':\n case 'desiredPoliticalPosition':\n case 'politicalExposure':\n case 'comfortWithVisibility':\n case 'socialInfluenceLevel':\n case 'pastExperience':\n case 'neurodiverseIdentity':\n case 'generalHealth':\n case 'healthInsurance':\n case 'physicalActivity':\n case 'sleepQuality':\n case 'stressLevel':\n case 'workShift':\n case 'comfortableWithShift':\n case 'desiredShift':\n case 'learningStyle':\n case 'communicationPreference':\n case 'viewOnAnimalCruelty':\n case 'facingCasteDiscrimination':\n case 'viewOnGenderEquality':\n case 'housingType':\n case 'bplCard':\n case 'migrationStatus':\n case 'landOwnership':\n case 'primaryIncomeSource':\n case 'diet':\n return typeof value === 'string' && value.length > 0;\n\n // ── Multi-select arrays: at least 1 selection ──\n case 'secondaryLanguages':\n case 'primaryVotingIssues':\n case 'leadershipSkillset':\n case 'networkAndCivicEngagement':\n case 'conditions':\n case 'sensoryPreferences':\n case 'supportNeeds':\n case 'disabilityStatus':\n case 'substanceUse':\n case 'viewOnLgbtqStatements':\n case 'viewOnTransgenderInclusion':\n case 'casteDiscriminationPlaces':\n case 'familyMembers':\n case 'digitalAccess':\n return Array.isArray(value) && value.length > 0;\n\n // ── Text inputs: non-empty trimmed string ──\n case 'epicNumber':\n case 'selfPartyAssociation':\n case 'familyPartyAssociation':\n case 'occupation':\n case 'incomeRange':\n case 'householdIncome':\n return typeof value === 'string' && value.trim().length > 0;\n\n // ── Free text: at least 5 chars ──\n case 'changesYouWantToBring':\n case 'dreamOccupation':\n return typeof value === 'string' && value.trim().length >= 5;\n\n // ── Number fields ──\n case 'numberOfDependents':\n return typeof value === 'number' && value >= 0;\n\n // ── Address: at least state and district ──\n case 'currentAddress':\n case 'permanentAddress':\n case 'homeNativePlace':\n case 'ancestralPlace': {\n if (!value || typeof value !== 'object') return false;\n const addr = value as Record<string, unknown>;\n return !!addr.state && !!addr.district;\n }\n\n // ── MBTI type ──\n case 'mbtiType':\n return typeof value === 'string' && value.length > 0;\n\n // ── OCEAN: at least one dimension set ──\n case 'oceanScores': {\n if (!value || typeof value !== 'object') return false;\n const scores = value as Record<string, unknown>;\n return Object.values(scores).some((v) => typeof v === 'number' && v >= 1 && v <= 100);\n }\n\n // ── Compound: publicOfficeAndElections ──\n case 'publicOfficeAndElections': {\n if (!value || typeof value !== 'object') return false;\n const office = value as Record<string, unknown>;\n return !!office.hasHeldOffice;\n }\n\n // ── Education multi-field: at least one field filled ──\n case 'education10th':\n case 'education12th': {\n if (!value || typeof value !== 'object') return false;\n return Object.values(value as Record<string, unknown>).some(\n (v) => typeof v === 'string' && v.trim().length > 0,\n );\n }\n\n // ── Degree repeaters ──\n case 'diplomas':\n case 'graduations':\n case 'postGraduations':\n case 'doctorates':\n case 'postDoctorates': {\n if (!Array.isArray(value) || value.length === 0) return false;\n return value.some(\n (entry: Record<string, unknown>) =>\n typeof entry.degreeName === 'string' && entry.degreeName.trim().length > 0,\n );\n }\n\n // ── Certificate repeater ──\n case 'otherCertificates': {\n if (!Array.isArray(value) || value.length === 0) return false;\n return value.some(\n (entry: Record<string, unknown>) =>\n typeof entry.certificateName === 'string' && entry.certificateName.trim().length > 0,\n );\n }\n\n // ── Text opinions ──\n case 'educationNotes':\n case 'viewOnLgbtqOpinion':\n case 'viewOnTransgenderOpinion':\n return typeof value === 'string' && value.trim().length > 0;\n\n // ── Default: strict (not permissive) ──\n default:\n if (value === null || value === undefined) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (typeof value === 'number') return true;\n if (typeof value === 'boolean') return true;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') return Object.keys(value).length > 0;\n return false;\n }\n}\n"]}
|