udp-schema 0.2.0 → 1.0.0

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.
Files changed (69) hide show
  1. package/dist/field-helpers.d.ts +10 -38
  2. package/dist/field-helpers.d.ts.map +1 -1
  3. package/dist/field-helpers.js +40 -66
  4. package/dist/field-helpers.js.map +1 -1
  5. package/dist/field-meta.d.ts +46 -28
  6. package/dist/field-meta.d.ts.map +1 -1
  7. package/dist/field-meta.js +304 -1016
  8. package/dist/field-meta.js.map +1 -1
  9. package/dist/index.d.ts +18 -18
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +34 -34
  12. package/dist/index.js.map +1 -1
  13. package/dist/onboarding-config.d.ts +44 -0
  14. package/dist/onboarding-config.d.ts.map +1 -0
  15. package/dist/onboarding-config.js +705 -0
  16. package/dist/onboarding-config.js.map +1 -0
  17. package/dist/progress-fields.d.ts +3 -3
  18. package/dist/progress-fields.d.ts.map +1 -1
  19. package/dist/progress-fields.js +73 -101
  20. package/dist/progress-fields.js.map +1 -1
  21. package/dist/step-01.schema.d.ts +84 -111
  22. package/dist/step-01.schema.d.ts.map +1 -1
  23. package/dist/step-01.schema.js +94 -101
  24. package/dist/step-01.schema.js.map +1 -1
  25. package/dist/step-02.schema.d.ts +31 -21
  26. package/dist/step-02.schema.d.ts.map +1 -1
  27. package/dist/step-02.schema.js +34 -27
  28. package/dist/step-02.schema.js.map +1 -1
  29. package/dist/step-03.schema.d.ts +24 -300
  30. package/dist/step-03.schema.d.ts.map +1 -1
  31. package/dist/step-03.schema.js +24 -60
  32. package/dist/step-03.schema.js.map +1 -1
  33. package/dist/step-04.schema.d.ts +56 -50
  34. package/dist/step-04.schema.d.ts.map +1 -1
  35. package/dist/step-04.schema.js +48 -43
  36. package/dist/step-04.schema.js.map +1 -1
  37. package/dist/step-05.schema.d.ts +13 -52
  38. package/dist/step-05.schema.d.ts.map +1 -1
  39. package/dist/step-05.schema.js +19 -40
  40. package/dist/step-05.schema.js.map +1 -1
  41. package/dist/step-06.schema.d.ts +101 -117
  42. package/dist/step-06.schema.d.ts.map +1 -1
  43. package/dist/step-06.schema.js +70 -75
  44. package/dist/step-06.schema.js.map +1 -1
  45. package/dist/step-07.schema.d.ts +44 -95
  46. package/dist/step-07.schema.d.ts.map +1 -1
  47. package/dist/step-07.schema.js +51 -78
  48. package/dist/step-07.schema.js.map +1 -1
  49. package/dist/step-08.schema.d.ts +31 -44
  50. package/dist/step-08.schema.d.ts.map +1 -1
  51. package/dist/step-08.schema.js +30 -47
  52. package/dist/step-08.schema.js.map +1 -1
  53. package/dist/step-09.schema.d.ts +48 -85
  54. package/dist/step-09.schema.d.ts.map +1 -1
  55. package/dist/step-09.schema.js +42 -120
  56. package/dist/step-09.schema.js.map +1 -1
  57. package/dist/step-10.schema.d.ts +32 -86
  58. package/dist/step-10.schema.d.ts.map +1 -1
  59. package/dist/step-10.schema.js +44 -120
  60. package/dist/step-10.schema.js.map +1 -1
  61. package/dist/step-11.schema.d.ts +36 -92
  62. package/dist/step-11.schema.d.ts.map +1 -1
  63. package/dist/step-11.schema.js +32 -111
  64. package/dist/step-11.schema.js.map +1 -1
  65. package/dist/step-12.schema.d.ts +56 -93
  66. package/dist/step-12.schema.d.ts.map +1 -1
  67. package/dist/step-12.schema.js +77 -133
  68. package/dist/step-12.schema.js.map +1 -1
  69. package/package.json +1 -1
@@ -1,117 +1,110 @@
1
1
  /**
2
- * Step 01 — Profile Onboarding Schema
2
+ * Step 01 — Profile
3
3
  *
4
- * Single source of truth used by both frontend and backend.
5
- * Field names match the MongoDB document keys exactly.
4
+ * Fields: firstName, middleName, lastName, gender, dateOfBirth,
5
+ * whatsappNumber, primaryLanguage, secondaryLanguages,
6
+ * familyReligion, personalReligion, reservationStatus, minorityStatus
6
7
  *
7
8
  * @module udp-schema/step-01
8
9
  */
9
10
  import { z } from 'zod';
10
- import { emptyStringToUndefined, optionalTrimmedString } from './zod-helpers.js';
11
- // ─── Sub-schemas ────────────────────────────────────────
12
- /** Language value (code / nativeName / englishName / script). */
13
- export const languageValueSchema = z
14
- .object({
15
- code: optionalTrimmedString,
16
- nativeName: optionalTrimmedString,
17
- englishName: optionalTrimmedString,
18
- script: optionalTrimmedString,
19
- })
20
- .refine((v) => Boolean(v.code || v.nativeName || v.englishName), 'Language must include at least code, native name, or english name');
21
- /** One entry in the secondaryLanguages array. */
22
- export const secondaryLanguageItemSchema = z.object({
23
- language: languageValueSchema,
24
- fluency: z.enum(['basic', 'conversational', 'professional', 'native']),
25
- canSpeak: z.boolean().optional(),
26
- canRead: z.boolean().optional(),
27
- canWrite: z.boolean().optional(),
28
- });
29
- /**
30
- * Profile photo — accepts either:
31
- * • a plain URL string (returned by backend on prefill)
32
- * • an upload-result object (sent after fresh upload)
33
- * • a File-like object (frontend pre-upload state)
34
- */
35
- export const profilePhotoSchema = z
36
- .union([
37
- z.object({
38
- name: z.string().optional(),
39
- type: z.string().optional(),
40
- size: z.number().min(0).optional(),
41
- lastModified: z.number().min(0).optional(),
42
- }),
43
- z.string(),
44
- z.object({
45
- assetId: z.string().trim().optional(),
46
- url: z.string().trim().optional(),
47
- mimeType: z.string().trim().optional(),
48
- sizeBytes: z.number().min(0).optional(),
49
- }),
50
- ])
51
- .optional();
52
- /** Volunteer who assisted with the form. */
53
- export const assistedByVolunteerSchema = z
54
- .object({
55
- volunteerId: z.string().optional(),
56
- displayName: optionalTrimmedString,
57
- source: z.enum(['selected', 'manual']).optional(),
58
- })
59
- .optional();
60
- // ─── Main step-01 schema ────────────────────────────────
61
- export const step01OnboardingSchema = z.object({
62
- email: z.string().trim().toLowerCase().email('Enter a valid email address'),
11
+ import { emptyStringToUndefined, optionalTrimmedString, optionalPhoneSchema } from './zod-helpers.js';
12
+ // ─── Main Step 01 Schema ────────────────────────────────────────────────────
13
+ export const step01ProfileSchema = z.object({
63
14
  firstName: z
64
15
  .string()
65
16
  .trim()
66
17
  .min(1, 'First name is required')
67
18
  .max(50, 'First name must be at most 50 characters'),
68
19
  middleName: optionalTrimmedString,
69
- lastName: optionalTrimmedString,
70
- gender: z.enum(['male', 'female', 'other', 'prefer_not']).optional(),
71
- dateOfBirth: z.preprocess(emptyStringToUndefined, z.coerce.date().optional()),
72
- aadhaarNumber: z.preprocess((value) => {
73
- const normalized = emptyStringToUndefined(value);
74
- if (typeof normalized === 'string') {
75
- return normalized.replace(/\D/g, '');
76
- }
77
- return normalized;
78
- }, z
20
+ lastName: z
79
21
  .string()
80
- .regex(/^\d{12}$/, 'Aadhaar must be exactly 12 digits')
81
- .optional()),
82
- profilePhotoUrl: profilePhotoSchema,
83
- assistedByVolunteer: assistedByVolunteerSchema,
84
- formFilledLocation: z
85
- .object({
86
- latitude: z.number().min(-90).max(90),
87
- longitude: z.number().min(-180).max(180),
88
- accuracy: z.number().optional(),
89
- capturedAt: z.coerce.date().optional(),
90
- })
22
+ .trim()
23
+ .min(1, 'Last name is required')
24
+ .max(50, 'Last name must be at most 50 characters'),
25
+ gender: z
26
+ .enum([
27
+ 'man',
28
+ 'woman',
29
+ 'non_binary',
30
+ 'transgender_man',
31
+ 'transgender_woman',
32
+ 'genderqueer',
33
+ 'genderfluid',
34
+ 'agender',
35
+ 'two_spirit',
36
+ 'other',
37
+ 'prefer_not_to_say',
38
+ ])
39
+ .optional(),
40
+ dateOfBirth: z.preprocess(emptyStringToUndefined, z.coerce.date().optional()),
41
+ whatsappNumber: optionalPhoneSchema,
42
+ /** Single language code string (e.g., "hindi", "english") — matches dating motherTongue options */
43
+ primaryLanguage: z.string().trim().optional(),
44
+ /** Array of language code strings */
45
+ secondaryLanguages: z.array(z.string().trim()).max(10).optional(),
46
+ /**
47
+ * Family religion — uses dating-schema religion option values.
48
+ * e.g., "hindu", "muslim_sunni", "christian_catholic", etc.
49
+ */
50
+ familyReligion: z
51
+ .enum([
52
+ 'hindu',
53
+ 'muslim_sunni',
54
+ 'muslim_shia',
55
+ 'muslim_sufi',
56
+ 'muslim_other',
57
+ 'christian_catholic',
58
+ 'christian_protestant',
59
+ 'christian_other',
60
+ 'sikh',
61
+ 'jain_digambar',
62
+ 'jain_shwetambar',
63
+ 'buddhist',
64
+ 'parsi_zoroastrian',
65
+ 'jewish',
66
+ 'bahai',
67
+ 'spiritual',
68
+ 'atheist',
69
+ 'agnostic',
70
+ 'no_religion',
71
+ 'inter_religion',
72
+ 'other',
73
+ 'prefer_not_to_say',
74
+ ])
75
+ .optional(),
76
+ /** Personal religion — same options as familyReligion */
77
+ personalReligion: z
78
+ .enum([
79
+ 'hindu',
80
+ 'muslim_sunni',
81
+ 'muslim_shia',
82
+ 'muslim_sufi',
83
+ 'muslim_other',
84
+ 'christian_catholic',
85
+ 'christian_protestant',
86
+ 'christian_other',
87
+ 'sikh',
88
+ 'jain_digambar',
89
+ 'jain_shwetambar',
90
+ 'buddhist',
91
+ 'parsi_zoroastrian',
92
+ 'jewish',
93
+ 'bahai',
94
+ 'spiritual',
95
+ 'atheist',
96
+ 'agnostic',
97
+ 'no_religion',
98
+ 'inter_religion',
99
+ 'other',
100
+ 'prefer_not_to_say',
101
+ ])
102
+ .optional(),
103
+ /** Reservation / caste category */
104
+ reservationStatus: z
105
+ .enum(['SC', 'ST', 'OBC_NC', 'OBC_C', 'EWS', 'GENERAL', 'DONT_KNOW', 'PREFER_NOT_SAY'])
91
106
  .optional(),
92
- primaryLanguage: languageValueSchema.optional(),
93
- secondaryLanguages: z
94
- .array(secondaryLanguageItemSchema)
95
- .max(5, 'You can add up to 5 secondary languages')
96
- .optional()
97
- .superRefine((items, context) => {
98
- if (!items)
99
- return;
100
- const seenCodes = new Map();
101
- items.forEach((item, index) => {
102
- const code = item.language.code?.toLowerCase();
103
- if (!code)
104
- return;
105
- if (seenCodes.has(code)) {
106
- context.addIssue({
107
- code: 'custom',
108
- path: [index, 'language', 'code'],
109
- message: 'Duplicate secondary language is not allowed',
110
- });
111
- return;
112
- }
113
- seenCodes.set(code, index);
114
- });
115
- }),
107
+ /** Minority community status */
108
+ minorityStatus: z.enum(['NO', 'RELIGIOUS', 'LINGUISTIC', 'NOT_SURE']).optional(),
116
109
  });
117
110
  //# sourceMappingURL=step-01.schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"step-01.schema.js","sourceRoot":"","sources":["../src/step-01.schema.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Step 01 — Profile Onboarding Schema\n *\n * Single source of truth used by both frontend and backend.\n * Field names match the MongoDB document keys exactly.\n *\n * @module udp-schema/step-01\n */\n\nimport { z } from 'zod';\nimport { emptyStringToUndefined, optionalTrimmedString } from './zod-helpers.js';\n\n// ─── Sub-schemas ────────────────────────────────────────\n\n/** Language value (code / nativeName / englishName / script). */\nexport const languageValueSchema = z\n .object({\n code: optionalTrimmedString,\n nativeName: optionalTrimmedString,\n englishName: optionalTrimmedString,\n script: optionalTrimmedString,\n })\n .refine(\n (v) => Boolean(v.code || v.nativeName || v.englishName),\n 'Language must include at least code, native name, or english name',\n );\n\n/** One entry in the secondaryLanguages array. */\nexport const secondaryLanguageItemSchema = z.object({\n language: languageValueSchema,\n fluency: z.enum(['basic', 'conversational', 'professional', 'native']),\n canSpeak: z.boolean().optional(),\n canRead: z.boolean().optional(),\n canWrite: z.boolean().optional(),\n});\n\n/**\n * Profile photo — accepts either:\n * • a plain URL string (returned by backend on prefill)\n * • an upload-result object (sent after fresh upload)\n * • a File-like object (frontend pre-upload state)\n */\nexport const profilePhotoSchema = z\n .union([\n z.object({\n name: z.string().optional(),\n type: z.string().optional(),\n size: z.number().min(0).optional(),\n lastModified: z.number().min(0).optional(),\n }),\n z.string(),\n z.object({\n assetId: z.string().trim().optional(),\n url: z.string().trim().optional(),\n mimeType: z.string().trim().optional(),\n sizeBytes: z.number().min(0).optional(),\n }),\n ])\n .optional();\n\n/** Volunteer who assisted with the form. */\nexport const assistedByVolunteerSchema = z\n .object({\n volunteerId: z.string().optional(),\n displayName: optionalTrimmedString,\n source: z.enum(['selected', 'manual']).optional(),\n })\n .optional();\n\n// ─── Main step-01 schema ────────────────────────────────\n\nexport const step01OnboardingSchema = z.object({\n email: z.string().trim().toLowerCase().email('Enter a valid email address'),\n firstName: z\n .string()\n .trim()\n .min(1, 'First name is required')\n .max(50, 'First name must be at most 50 characters'),\n middleName: optionalTrimmedString,\n lastName: optionalTrimmedString,\n gender: z.enum(['male', 'female', 'other', 'prefer_not']).optional(),\n dateOfBirth: z.preprocess(emptyStringToUndefined, z.coerce.date().optional()),\n aadhaarNumber: z.preprocess(\n (value) => {\n const normalized = emptyStringToUndefined(value);\n if (typeof normalized === 'string') {\n return normalized.replace(/\\D/g, '');\n }\n return normalized;\n },\n z\n .string()\n .regex(/^\\d{12}$/, 'Aadhaar must be exactly 12 digits')\n .optional(),\n ),\n profilePhotoUrl: profilePhotoSchema,\n assistedByVolunteer: assistedByVolunteerSchema,\n formFilledLocation: z\n .object({\n latitude: z.number().min(-90).max(90),\n longitude: z.number().min(-180).max(180),\n accuracy: z.number().optional(),\n capturedAt: z.coerce.date().optional(),\n })\n .optional(),\n primaryLanguage: languageValueSchema.optional(),\n secondaryLanguages: z\n .array(secondaryLanguageItemSchema)\n .max(5, 'You can add up to 5 secondary languages')\n .optional()\n .superRefine((items, context) => {\n if (!items) return;\n const seenCodes = new Map<string, number>();\n items.forEach((item, index) => {\n const code = item.language.code?.toLowerCase();\n if (!code) return;\n if (seenCodes.has(code)) {\n context.addIssue({\n code: 'custom',\n path: [index, 'language', 'code'],\n message: 'Duplicate secondary language is not allowed',\n });\n return;\n }\n seenCodes.set(code, index);\n });\n }),\n});\n\n// ─── Inferred types ─────────────────────────────────────\n\nexport type Step01OnboardingInput = z.infer<typeof step01OnboardingSchema>;\nexport type Step01OnboardingFormInput = z.input<typeof step01OnboardingSchema>;\n"]}
1
+ {"version":3,"file":"step-01.schema.js","sourceRoot":"","sources":["../src/step-01.schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEtG,+EAA+E;AAE/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,EAAE,wBAAwB,CAAC;SAChC,GAAG,CAAC,EAAE,EAAE,0CAA0C,CAAC;IAEtD,UAAU,EAAE,qBAAqB;IAEjC,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,EAAE,uBAAuB,CAAC;SAC/B,GAAG,CAAC,EAAE,EAAE,yCAAyC,CAAC;IAErD,MAAM,EAAE,CAAC;SACN,IAAI,CAAC;QACJ,KAAK;QACL,OAAO;QACP,YAAY;QACZ,iBAAiB;QACjB,mBAAmB;QACnB,aAAa;QACb,aAAa;QACb,SAAS;QACT,YAAY;QACZ,OAAO;QACP,mBAAmB;KACpB,CAAC;SACD,QAAQ,EAAE;IAEb,WAAW,EAAE,CAAC,CAAC,UAAU,CAAC,sBAAsB,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC;IAE7E,cAAc,EAAE,mBAAmB;IAEnC,mGAAmG;IACnG,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;IAE7C,qCAAqC;IACrC,kBAAkB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IAEjE;;;OAGG;IACH,cAAc,EAAE,CAAC;SACd,IAAI,CAAC;QACJ,OAAO;QACP,cAAc;QACd,aAAa;QACb,aAAa;QACb,cAAc;QACd,oBAAoB;QACpB,sBAAsB;QACtB,iBAAiB;QACjB,MAAM;QACN,eAAe;QACf,iBAAiB;QACjB,UAAU;QACV,mBAAmB;QACnB,QAAQ;QACR,OAAO;QACP,WAAW;QACX,SAAS;QACT,UAAU;QACV,aAAa;QACb,gBAAgB;QAChB,OAAO;QACP,mBAAmB;KACpB,CAAC;SACD,QAAQ,EAAE;IAEb,yDAAyD;IACzD,gBAAgB,EAAE,CAAC;SAChB,IAAI,CAAC;QACJ,OAAO;QACP,cAAc;QACd,aAAa;QACb,aAAa;QACb,cAAc;QACd,oBAAoB;QACpB,sBAAsB;QACtB,iBAAiB;QACjB,MAAM;QACN,eAAe;QACf,iBAAiB;QACjB,UAAU;QACV,mBAAmB;QACnB,QAAQ;QACR,OAAO;QACP,WAAW;QACX,SAAS;QACT,UAAU;QACV,aAAa;QACb,gBAAgB;QAChB,OAAO;QACP,mBAAmB;KACpB,CAAC;SACD,QAAQ,EAAE;IAEb,mCAAmC;IACnC,iBAAiB,EAAE,CAAC;SACjB,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC;SACtF,QAAQ,EAAE;IAEb,gCAAgC;IAChC,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE;CACjF,CAAC,CAAC","sourcesContent":["/**\n * Step 01 — Profile\n *\n * Fields: firstName, middleName, lastName, gender, dateOfBirth,\n * whatsappNumber, primaryLanguage, secondaryLanguages,\n * familyReligion, personalReligion, reservationStatus, minorityStatus\n *\n * @module udp-schema/step-01\n */\n\nimport { z } from 'zod';\nimport { emptyStringToUndefined, optionalTrimmedString, optionalPhoneSchema } from './zod-helpers.js';\n\n// ─── Main Step 01 Schema ────────────────────────────────────────────────────\n\nexport const step01ProfileSchema = z.object({\n firstName: z\n .string()\n .trim()\n .min(1, 'First name is required')\n .max(50, 'First name must be at most 50 characters'),\n\n middleName: optionalTrimmedString,\n\n lastName: z\n .string()\n .trim()\n .min(1, 'Last name is required')\n .max(50, 'Last name must be at most 50 characters'),\n\n gender: z\n .enum([\n 'man',\n 'woman',\n 'non_binary',\n 'transgender_man',\n 'transgender_woman',\n 'genderqueer',\n 'genderfluid',\n 'agender',\n 'two_spirit',\n 'other',\n 'prefer_not_to_say',\n ])\n .optional(),\n\n dateOfBirth: z.preprocess(emptyStringToUndefined, z.coerce.date().optional()),\n\n whatsappNumber: optionalPhoneSchema,\n\n /** Single language code string (e.g., \"hindi\", \"english\") matches dating motherTongue options */\n primaryLanguage: z.string().trim().optional(),\n\n /** Array of language code strings */\n secondaryLanguages: z.array(z.string().trim()).max(10).optional(),\n\n /**\n * Family religion uses dating-schema religion option values.\n * e.g., \"hindu\", \"muslim_sunni\", \"christian_catholic\", etc.\n */\n familyReligion: z\n .enum([\n 'hindu',\n 'muslim_sunni',\n 'muslim_shia',\n 'muslim_sufi',\n 'muslim_other',\n 'christian_catholic',\n 'christian_protestant',\n 'christian_other',\n 'sikh',\n 'jain_digambar',\n 'jain_shwetambar',\n 'buddhist',\n 'parsi_zoroastrian',\n 'jewish',\n 'bahai',\n 'spiritual',\n 'atheist',\n 'agnostic',\n 'no_religion',\n 'inter_religion',\n 'other',\n 'prefer_not_to_say',\n ])\n .optional(),\n\n /** Personal religion — same options as familyReligion */\n personalReligion: z\n .enum([\n 'hindu',\n 'muslim_sunni',\n 'muslim_shia',\n 'muslim_sufi',\n 'muslim_other',\n 'christian_catholic',\n 'christian_protestant',\n 'christian_other',\n 'sikh',\n 'jain_digambar',\n 'jain_shwetambar',\n 'buddhist',\n 'parsi_zoroastrian',\n 'jewish',\n 'bahai',\n 'spiritual',\n 'atheist',\n 'agnostic',\n 'no_religion',\n 'inter_religion',\n 'other',\n 'prefer_not_to_say',\n ])\n .optional(),\n\n /** Reservation / caste category */\n reservationStatus: z\n .enum(['SC', 'ST', 'OBC_NC', 'OBC_C', 'EWS', 'GENERAL', 'DONT_KNOW', 'PREFER_NOT_SAY'])\n .optional(),\n\n /** Minority community status */\n minorityStatus: z.enum(['NO', 'RELIGIOUS', 'LINGUISTIC', 'NOT_SURE']).optional(),\n});\n\n// ─── Inferred types ─────────────────────────────────────────────────────────\n\nexport type Step01ProfileInput = z.infer<typeof step01ProfileSchema>;\n"]}
@@ -1,29 +1,39 @@
1
1
  /**
2
- * Step 02 — Contact Details Schema
2
+ * Step 02 — Political Association & History
3
3
  *
4
- * Single source of truth used by both frontend and backend.
4
+ * Fields: politicalSpectrum, selfPartyAssociation, familyPartyAssociation,
5
+ * publicOfficeAndElections, networkAndCivicEngagement
5
6
  *
6
7
  * @module udp-schema/step-02
7
8
  */
8
9
  import { z } from 'zod';
9
- /** Accepts a valid URL, an empty string, or undefined. */
10
- export declare const optionalUrlSchema: z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"">, z.ZodUndefined]>;
11
- export declare const step02ContactDetailsSchema: z.ZodObject<{
12
- phonePrimary: z.ZodOptional<z.ZodString>;
13
- whatsappSameAsPrimary: z.ZodOptional<z.ZodBoolean>;
14
- whatsappNumber: z.ZodOptional<z.ZodString>;
15
- socialMedia: z.ZodObject<{
16
- facebook: z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"">, z.ZodUndefined]>;
17
- twitter: z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"">, z.ZodUndefined]>;
18
- instagram: z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"">, z.ZodUndefined]>;
19
- linkedin: z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"">, z.ZodUndefined]>;
20
- youtube: z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"">, z.ZodUndefined]>;
21
- }, z.core.$strip>;
22
- emergencyContact: z.ZodObject<{
23
- contactName: z.ZodOptional<z.ZodString>;
24
- contactRelation: z.ZodOptional<z.ZodString>;
25
- contactPhone: z.ZodOptional<z.ZodString>;
26
- }, z.core.$strip>;
10
+ export declare const step02PoliticalSchema: z.ZodObject<{
11
+ politicalSpectrum: z.ZodOptional<z.ZodEnum<{
12
+ prefer_not_to_say: "prefer_not_to_say";
13
+ "1_tradition_faith": "1_tradition_faith";
14
+ "2_faith_curious": "2_faith_curious";
15
+ "3_multiplicity_open": "3_multiplicity_open";
16
+ "4_pragmatic_flexible": "4_pragmatic_flexible";
17
+ "5_evidence_reasoning": "5_evidence_reasoning";
18
+ "6_critical_reflective": "6_critical_reflective";
19
+ "7_skeptic_optimize": "7_skeptic_optimize";
20
+ }>>;
21
+ selfPartyAssociation: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodOptional<z.ZodString>>;
22
+ familyPartyAssociation: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodOptional<z.ZodString>>;
23
+ publicOfficeAndElections: z.ZodOptional<z.ZodObject<{
24
+ hasHeldOffice: z.ZodOptional<z.ZodEnum<{
25
+ prefer_not_to_say: "prefer_not_to_say";
26
+ yes: "yes";
27
+ no: "no";
28
+ }>>;
29
+ officeDetails: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodOptional<z.ZodString>>;
30
+ electionContested: z.ZodOptional<z.ZodEnum<{
31
+ yes: "yes";
32
+ no: "no";
33
+ }>>;
34
+ electionDetails: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodOptional<z.ZodString>>;
35
+ }, z.core.$strip>>;
36
+ networkAndCivicEngagement: z.ZodOptional<z.ZodArray<z.ZodString>>;
27
37
  }, z.core.$strip>;
28
- export type Step02ContactDetailsInput = z.infer<typeof step02ContactDetailsSchema>;
38
+ export type Step02PoliticalInput = z.infer<typeof step02PoliticalSchema>;
29
39
  //# sourceMappingURL=step-02.schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"step-02.schema.d.ts","sourceRoot":"","sources":["../src/step-02.schema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,0DAA0D;AAC1D,eAAO,MAAM,iBAAiB,sEAI5B,CAAC;AAIH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;iBAgBrC,CAAC;AAIH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
1
+ {"version":3,"file":"step-02.schema.d.ts","sourceRoot":"","sources":["../src/step-02.schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiChC,CAAC;AAIH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
@@ -1,35 +1,42 @@
1
1
  /**
2
- * Step 02 — Contact Details Schema
2
+ * Step 02 — Political Association & History
3
3
  *
4
- * Single source of truth used by both frontend and backend.
4
+ * Fields: politicalSpectrum, selfPartyAssociation, familyPartyAssociation,
5
+ * publicOfficeAndElections, networkAndCivicEngagement
5
6
  *
6
7
  * @module udp-schema/step-02
7
8
  */
8
9
  import { z } from 'zod';
9
- import { optionalPhoneSchema } from './zod-helpers.js';
10
- // ─── Sub-schemas ────────────────────────────────────────
11
- /** Accepts a valid URL, an empty string, or undefined. */
12
- export const optionalUrlSchema = z.union([
13
- z.string().url('Enter a valid URL'),
14
- z.literal(''),
15
- z.undefined(),
16
- ]);
17
- // ─── Main step-02 schema ────────────────────────────────
18
- export const step02ContactDetailsSchema = z.object({
19
- phonePrimary: optionalPhoneSchema,
20
- whatsappSameAsPrimary: z.boolean().optional(),
21
- whatsappNumber: optionalPhoneSchema,
22
- socialMedia: z.object({
23
- facebook: optionalUrlSchema,
24
- twitter: optionalUrlSchema,
25
- instagram: optionalUrlSchema,
26
- linkedin: optionalUrlSchema,
27
- youtube: optionalUrlSchema,
28
- }),
29
- emergencyContact: z.object({
30
- contactName: z.string().trim().optional(),
31
- contactRelation: z.string().trim().optional(),
32
- contactPhone: optionalPhoneSchema,
33
- }),
10
+ import { optionalTrimmedString } from './zod-helpers.js';
11
+ // ─── Main Step 02 Schema ────────────────────────────────────────────────────
12
+ export const step02PoliticalSchema = z.object({
13
+ /** Political spectrum uses dating-schema cognitiveBand values */
14
+ politicalSpectrum: z
15
+ .enum([
16
+ '1_tradition_faith',
17
+ '2_faith_curious',
18
+ '3_multiplicity_open',
19
+ '4_pragmatic_flexible',
20
+ '5_evidence_reasoning',
21
+ '6_critical_reflective',
22
+ '7_skeptic_optimize',
23
+ 'prefer_not_to_say',
24
+ ])
25
+ .optional(),
26
+ /** Self party association */
27
+ selfPartyAssociation: optionalTrimmedString,
28
+ /** Family party association */
29
+ familyPartyAssociation: optionalTrimmedString,
30
+ /** Public office and elections history */
31
+ publicOfficeAndElections: z
32
+ .object({
33
+ hasHeldOffice: z.enum(['yes', 'no', 'prefer_not_to_say']).optional(),
34
+ officeDetails: optionalTrimmedString,
35
+ electionContested: z.enum(['yes', 'no']).optional(),
36
+ electionDetails: optionalTrimmedString,
37
+ })
38
+ .optional(),
39
+ /** Network and civic engagement (multi-select) */
40
+ networkAndCivicEngagement: z.array(z.string().trim()).optional(),
34
41
  });
35
42
  //# sourceMappingURL=step-02.schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"step-02.schema.js","sourceRoot":"","sources":["../src/step-02.schema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,2DAA2D;AAE3D,0DAA0D;AAC1D,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC;IACvC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,mBAAmB,CAAC;IACnC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACb,CAAC,CAAC,SAAS,EAAE;CACd,CAAC,CAAC;AAEH,2DAA2D;AAE3D,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,YAAY,EAAE,mBAAmB;IACjC,qBAAqB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC7C,cAAc,EAAE,mBAAmB;IACnC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,QAAQ,EAAE,iBAAiB;QAC3B,OAAO,EAAE,iBAAiB;QAC1B,SAAS,EAAE,iBAAiB;QAC5B,QAAQ,EAAE,iBAAiB;QAC3B,OAAO,EAAE,iBAAiB;KAC3B,CAAC;IACF,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC;QACzB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;QACzC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;QAC7C,YAAY,EAAE,mBAAmB;KAClC,CAAC;CACH,CAAC,CAAC","sourcesContent":["/**\n * Step 02 — Contact Details Schema\n *\n * Single source of truth used by both frontend and backend.\n *\n * @module udp-schema/step-02\n */\n\nimport { z } from 'zod';\nimport { optionalPhoneSchema } from './zod-helpers.js';\n\n// ─── Sub-schemas ────────────────────────────────────────\n\n/** Accepts a valid URL, an empty string, or undefined. */\nexport const optionalUrlSchema = z.union([\n z.string().url('Enter a valid URL'),\n z.literal(''),\n z.undefined(),\n]);\n\n// ─── Main step-02 schema ────────────────────────────────\n\nexport const step02ContactDetailsSchema = z.object({\n phonePrimary: optionalPhoneSchema,\n whatsappSameAsPrimary: z.boolean().optional(),\n whatsappNumber: optionalPhoneSchema,\n socialMedia: z.object({\n facebook: optionalUrlSchema,\n twitter: optionalUrlSchema,\n instagram: optionalUrlSchema,\n linkedin: optionalUrlSchema,\n youtube: optionalUrlSchema,\n }),\n emergencyContact: z.object({\n contactName: z.string().trim().optional(),\n contactRelation: z.string().trim().optional(),\n contactPhone: optionalPhoneSchema,\n }),\n});\n\n// ─── Inferred types ─────────────────────────────────────\n\nexport type Step02ContactDetailsInput = z.infer<typeof step02ContactDetailsSchema>;\n"]}
1
+ {"version":3,"file":"step-02.schema.js","sourceRoot":"","sources":["../src/step-02.schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,+EAA+E;AAE/E,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,mEAAmE;IACnE,iBAAiB,EAAE,CAAC;SACjB,IAAI,CAAC;QACJ,mBAAmB;QACnB,iBAAiB;QACjB,qBAAqB;QACrB,sBAAsB;QACtB,sBAAsB;QACtB,uBAAuB;QACvB,oBAAoB;QACpB,mBAAmB;KACpB,CAAC;SACD,QAAQ,EAAE;IAEb,6BAA6B;IAC7B,oBAAoB,EAAE,qBAAqB;IAE3C,+BAA+B;IAC/B,sBAAsB,EAAE,qBAAqB;IAE7C,0CAA0C;IAC1C,wBAAwB,EAAE,CAAC;SACxB,MAAM,CAAC;QACN,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,mBAAmB,CAAC,CAAC,CAAC,QAAQ,EAAE;QACpE,aAAa,EAAE,qBAAqB;QACpC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE;QACnD,eAAe,EAAE,qBAAqB;KACvC,CAAC;SACD,QAAQ,EAAE;IAEb,kDAAkD;IAClD,yBAAyB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE;CACjE,CAAC,CAAC","sourcesContent":["/**\n * Step 02 — Political Association & History\n *\n * Fields: politicalSpectrum, selfPartyAssociation, familyPartyAssociation,\n * publicOfficeAndElections, networkAndCivicEngagement\n *\n * @module udp-schema/step-02\n */\n\nimport { z } from 'zod';\nimport { optionalTrimmedString } from './zod-helpers.js';\n\n// ─── Main Step 02 Schema ────────────────────────────────────────────────────\n\nexport const step02PoliticalSchema = z.object({\n /** Political spectrum uses dating-schema cognitiveBand values */\n politicalSpectrum: z\n .enum([\n '1_tradition_faith',\n '2_faith_curious',\n '3_multiplicity_open',\n '4_pragmatic_flexible',\n '5_evidence_reasoning',\n '6_critical_reflective',\n '7_skeptic_optimize',\n 'prefer_not_to_say',\n ])\n .optional(),\n\n /** Self party association */\n selfPartyAssociation: optionalTrimmedString,\n\n /** Family party association */\n familyPartyAssociation: optionalTrimmedString,\n\n /** Public office and elections history */\n publicOfficeAndElections: z\n .object({\n hasHeldOffice: z.enum(['yes', 'no', 'prefer_not_to_say']).optional(),\n officeDetails: optionalTrimmedString,\n electionContested: z.enum(['yes', 'no']).optional(),\n electionDetails: optionalTrimmedString,\n })\n .optional(),\n\n /** Network and civic engagement (multi-select) */\n networkAndCivicEngagement: z.array(z.string().trim()).optional(),\n});\n\n// ─── Inferred types ─────────────────────────────────────────────────────────\n\nexport type Step02PoliticalInput = z.infer<typeof step02PoliticalSchema>;\n"]}