gymmonk-schema 0.2.0 → 0.3.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.
Files changed (97) hide show
  1. package/dist/announcement.d.ts +56 -0
  2. package/dist/announcement.d.ts.map +1 -0
  3. package/dist/announcement.js +40 -0
  4. package/dist/announcement.js.map +1 -0
  5. package/dist/center.d.ts +381 -0
  6. package/dist/center.d.ts.map +1 -0
  7. package/dist/center.js +96 -0
  8. package/dist/center.js.map +1 -0
  9. package/dist/common.d.ts +28 -0
  10. package/dist/common.d.ts.map +1 -1
  11. package/dist/common.js +37 -0
  12. package/dist/common.js.map +1 -1
  13. package/dist/equipment.d.ts +93 -0
  14. package/dist/equipment.d.ts.map +1 -0
  15. package/dist/equipment.js +54 -0
  16. package/dist/equipment.js.map +1 -0
  17. package/dist/exercise.d.ts +234 -0
  18. package/dist/exercise.d.ts.map +1 -0
  19. package/dist/exercise.js +93 -0
  20. package/dist/exercise.js.map +1 -0
  21. package/dist/feedback.d.ts +119 -0
  22. package/dist/feedback.d.ts.map +1 -0
  23. package/dist/feedback.js +77 -0
  24. package/dist/feedback.js.map +1 -0
  25. package/dist/home.d.ts +74 -0
  26. package/dist/home.d.ts.map +1 -0
  27. package/dist/home.js +28 -0
  28. package/dist/home.js.map +1 -0
  29. package/dist/index.d.ts +27 -4
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +33 -5
  32. package/dist/index.js.map +1 -1
  33. package/dist/insights.d.ts +143 -0
  34. package/dist/insights.d.ts.map +1 -0
  35. package/dist/insights.js +79 -0
  36. package/dist/insights.js.map +1 -0
  37. package/dist/member-profile.d.ts +312 -0
  38. package/dist/member-profile.d.ts.map +1 -0
  39. package/dist/member-profile.js +103 -0
  40. package/dist/member-profile.js.map +1 -0
  41. package/dist/member.d.ts +365 -0
  42. package/dist/member.d.ts.map +1 -0
  43. package/dist/member.js +169 -0
  44. package/dist/member.js.map +1 -0
  45. package/dist/membership-plan.d.ts +244 -0
  46. package/dist/membership-plan.d.ts.map +1 -0
  47. package/dist/membership-plan.js +80 -0
  48. package/dist/membership-plan.js.map +1 -0
  49. package/dist/membership.d.ts +154 -0
  50. package/dist/membership.d.ts.map +1 -0
  51. package/dist/membership.js +103 -0
  52. package/dist/membership.js.map +1 -0
  53. package/dist/notification.d.ts +59 -0
  54. package/dist/notification.d.ts.map +1 -0
  55. package/dist/notification.js +49 -0
  56. package/dist/notification.js.map +1 -0
  57. package/dist/onboarding.d.ts +421 -0
  58. package/dist/onboarding.d.ts.map +1 -0
  59. package/dist/onboarding.js +124 -0
  60. package/dist/onboarding.js.map +1 -0
  61. package/dist/organisation.d.ts +199 -0
  62. package/dist/organisation.d.ts.map +1 -0
  63. package/dist/organisation.js +51 -0
  64. package/dist/organisation.js.map +1 -0
  65. package/dist/owner-profile.d.ts +50 -0
  66. package/dist/owner-profile.d.ts.map +1 -0
  67. package/dist/owner-profile.js +34 -0
  68. package/dist/owner-profile.js.map +1 -0
  69. package/dist/pricing.d.ts +103 -0
  70. package/dist/pricing.d.ts.map +1 -0
  71. package/dist/pricing.js +73 -0
  72. package/dist/pricing.js.map +1 -0
  73. package/dist/session.d.ts +90 -0
  74. package/dist/session.d.ts.map +1 -0
  75. package/dist/session.js +59 -0
  76. package/dist/session.js.map +1 -0
  77. package/dist/shared.d.ts +199 -0
  78. package/dist/shared.d.ts.map +1 -0
  79. package/dist/shared.js +107 -0
  80. package/dist/shared.js.map +1 -0
  81. package/dist/staff.d.ts +288 -0
  82. package/dist/staff.d.ts.map +1 -0
  83. package/dist/staff.js +115 -0
  84. package/dist/staff.js.map +1 -0
  85. package/dist/subscription.d.ts +69 -0
  86. package/dist/subscription.d.ts.map +1 -0
  87. package/dist/subscription.js +47 -0
  88. package/dist/subscription.js.map +1 -0
  89. package/dist/user.d.ts +63 -0
  90. package/dist/user.d.ts.map +1 -0
  91. package/dist/user.js +44 -0
  92. package/dist/user.js.map +1 -0
  93. package/dist/workout-plan.d.ts +201 -0
  94. package/dist/workout-plan.d.ts.map +1 -0
  95. package/dist/workout-plan.js +71 -0
  96. package/dist/workout-plan.js.map +1 -0
  97. package/package.json +1 -1
@@ -0,0 +1,79 @@
1
+ /**
2
+ * gymmonk-schema — Owner dashboard & insights
3
+ * ============================================
4
+ * The owner home summary (KPIs, crowd load, top equipment, alert) and the
5
+ * analytics response shapes (revenue / attendance / plan-mix / demographics /
6
+ * peak-hours). Chart series carry raw numbers; the frontend renders + formats.
7
+ *
8
+ * @module gymmonk-schema/insights
9
+ */
10
+ import { z } from 'zod';
11
+ import { priceInrSchema } from './common.js';
12
+ // ─── Chart primitives ────────────────────────────────────────────────────────
13
+ export const seriesPointSchema = z.object({
14
+ label: z.string(),
15
+ value: z.number(),
16
+ });
17
+ export const lineSeriesSchema = z.object({
18
+ labels: z.array(z.string()),
19
+ values: z.array(z.number()),
20
+ });
21
+ export const donutSegmentSchema = z.object({
22
+ label: z.string(),
23
+ value: z.number(),
24
+ color: z.string(),
25
+ });
26
+ // ─── Owner home summary ──────────────────────────────────────────────────────
27
+ export const kpiIconSchema = z.enum(['members', 'attendance', 'birthdays', 'revenue', 'devices']);
28
+ export const kpiChipSchema = z.object({
29
+ key: z.string(),
30
+ icon: kpiIconSchema,
31
+ label: z.string(),
32
+ value: z.number(),
33
+ unit: z.string(),
34
+ /** Optional period-over-period delta, e.g. +5 (%). */
35
+ deltaPct: z.number().nullable(),
36
+ });
37
+ export const ownerAlertSchema = z.object({
38
+ title: z.string(),
39
+ body: z.string(),
40
+ });
41
+ export const equipmentLoadSchema = z.object({
42
+ name: z.string(),
43
+ /** 0–100 usage percentage. */
44
+ value: z.number().min(0).max(100),
45
+ /** Peak time label, e.g. "6 AM". */
46
+ time: z.string(),
47
+ });
48
+ export const ownerHomeSummarySchema = z.object({
49
+ ownerName: z.string(),
50
+ branch: z.string(),
51
+ kpis: z.array(kpiChipSchema),
52
+ alert: ownerAlertSchema.nullable(),
53
+ crowdLoad: lineSeriesSchema,
54
+ topEquipment: z.array(equipmentLoadSchema),
55
+ todaysRevenueInr: priceInrSchema,
56
+ });
57
+ // ─── Insights (analytics) ────────────────────────────────────────────────────
58
+ export const insightCategoryOptionSchema = z.object({
59
+ value: z.string(),
60
+ label: z.string(),
61
+ });
62
+ export const ownerInsightsSchema = z.object({
63
+ revenue: z.object({
64
+ categories: z.array(insightCategoryOptionSchema),
65
+ byCategory: z.record(z.string(), lineSeriesSchema),
66
+ year: z.string(),
67
+ }),
68
+ attendance: z.object({
69
+ byPeriod: z.record(z.string(), z.object({ total: z.number(), data: z.array(seriesPointSchema) })),
70
+ }),
71
+ planMix: z.record(z.string(), z.array(donutSegmentSchema)),
72
+ demographics: z.record(z.string(), z.object({ center: z.string(), segments: z.array(donutSegmentSchema) })),
73
+ peakHours: z.record(z.string(), z.array(seriesPointSchema)),
74
+ });
75
+ // ─── Query ───────────────────────────────────────────────────────────────────
76
+ export const insightsQuerySchema = z.object({
77
+ centerId: z.string().trim().optional(),
78
+ });
79
+ //# sourceMappingURL=insights.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insights.js","sourceRoot":"","sources":["../src/insights.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gymmonk-schema — Owner dashboard & insights\n * ============================================\n * The owner home summary (KPIs, crowd load, top equipment, alert) and the\n * analytics response shapes (revenue / attendance / plan-mix / demographics /\n * peak-hours). Chart series carry raw numbers; the frontend renders + formats.\n *\n * @module gymmonk-schema/insights\n */\n\nimport { z } from 'zod';\nimport { priceInrSchema } from './common.js';\n\n// ─── Chart primitives ────────────────────────────────────────────────────────\n\nexport const seriesPointSchema = z.object({\n label: z.string(),\n value: z.number(),\n});\nexport type SeriesPoint = z.infer<typeof seriesPointSchema>;\n\nexport const lineSeriesSchema = z.object({\n labels: z.array(z.string()),\n values: z.array(z.number()),\n});\nexport type LineSeries = z.infer<typeof lineSeriesSchema>;\n\nexport const donutSegmentSchema = z.object({\n label: z.string(),\n value: z.number(),\n color: z.string(),\n});\nexport type DonutSegment = z.infer<typeof donutSegmentSchema>;\n\n// ─── Owner home summary ──────────────────────────────────────────────────────\n\nexport const kpiIconSchema = z.enum(['members', 'attendance', 'birthdays', 'revenue', 'devices']);\nexport type KpiIcon = z.infer<typeof kpiIconSchema>;\n\nexport const kpiChipSchema = z.object({\n key: z.string(),\n icon: kpiIconSchema,\n label: z.string(),\n value: z.number(),\n unit: z.string(),\n /** Optional period-over-period delta, e.g. +5 (%). */\n deltaPct: z.number().nullable(),\n});\nexport type KpiChip = z.infer<typeof kpiChipSchema>;\n\nexport const ownerAlertSchema = z.object({\n title: z.string(),\n body: z.string(),\n});\nexport type OwnerAlert = z.infer<typeof ownerAlertSchema>;\n\nexport const equipmentLoadSchema = z.object({\n name: z.string(),\n /** 0–100 usage percentage. */\n value: z.number().min(0).max(100),\n /** Peak time label, e.g. \"6 AM\". */\n time: z.string(),\n});\nexport type EquipmentLoad = z.infer<typeof equipmentLoadSchema>;\n\nexport const ownerHomeSummarySchema = z.object({\n ownerName: z.string(),\n branch: z.string(),\n kpis: z.array(kpiChipSchema),\n alert: ownerAlertSchema.nullable(),\n crowdLoad: lineSeriesSchema,\n topEquipment: z.array(equipmentLoadSchema),\n todaysRevenueInr: priceInrSchema,\n});\nexport type OwnerHomeSummary = z.infer<typeof ownerHomeSummarySchema>;\n\n// ─── Insights (analytics) ────────────────────────────────────────────────────\n\nexport const insightCategoryOptionSchema = z.object({\n value: z.string(),\n label: z.string(),\n});\nexport type InsightCategoryOption = z.infer<typeof insightCategoryOptionSchema>;\n\nexport const ownerInsightsSchema = z.object({\n revenue: z.object({\n categories: z.array(insightCategoryOptionSchema),\n byCategory: z.record(z.string(), lineSeriesSchema),\n year: z.string(),\n }),\n attendance: z.object({\n byPeriod: z.record(\n z.string(),\n z.object({ total: z.number(), data: z.array(seriesPointSchema) }),\n ),\n }),\n planMix: z.record(z.string(), z.array(donutSegmentSchema)),\n demographics: z.record(\n z.string(),\n z.object({ center: z.string(), segments: z.array(donutSegmentSchema) }),\n ),\n peakHours: z.record(z.string(), z.array(seriesPointSchema)),\n});\nexport type OwnerInsights = z.infer<typeof ownerInsightsSchema>;\n\n// ─── Query ───────────────────────────────────────────────────────────────────\n\nexport const insightsQuerySchema = z.object({\n centerId: z.string().trim().optional(),\n});\nexport type InsightsQuery = z.infer<typeof insightsQuerySchema>;\n"]}
@@ -0,0 +1,312 @@
1
+ /**
2
+ * gymmonk-schema — Member fitness profile
3
+ * =======================================
4
+ * Product-owned personal + fitness data for a gym member, separate from the
5
+ * auth-mirrored `User` (which holds name/email/phone/avatar). One profile per
6
+ * user, scoped to the single center they belong to.
7
+ *
8
+ * Body measurements are stored RAW (cm / kg); BMI and body-fat % are derived at
9
+ * the edge, never persisted. Full Aadhaar is never stored — only its last four
10
+ * digits and/or an uploaded ID-proof URL (DPDP data-minimisation).
11
+ *
12
+ * @module gymmonk-schema/member-profile
13
+ */
14
+ import { z } from 'zod';
15
+ /**
16
+ * Raw body measurements in metric units. Height + weight anchor BMI; neck /
17
+ * waist / hips feed the U.S.-Navy body-fat estimate; the rest are progress
18
+ * tracking. All optional so a partial update touches only what changed.
19
+ */
20
+ export declare const bodyMetricsSchema: z.ZodObject<{
21
+ heightCm: z.ZodOptional<z.ZodNumber>;
22
+ weightKg: z.ZodOptional<z.ZodNumber>;
23
+ neckCm: z.ZodOptional<z.ZodNumber>;
24
+ waistCm: z.ZodOptional<z.ZodNumber>;
25
+ hipsCm: z.ZodOptional<z.ZodNumber>;
26
+ forearmCm: z.ZodOptional<z.ZodNumber>;
27
+ armsCm: z.ZodOptional<z.ZodNumber>;
28
+ chestCm: z.ZodOptional<z.ZodNumber>;
29
+ thighCm: z.ZodOptional<z.ZodNumber>;
30
+ calfCm: z.ZodOptional<z.ZodNumber>;
31
+ }, z.core.$strip>;
32
+ export type BodyMetrics = z.infer<typeof bodyMetricsSchema>;
33
+ export declare const emergencyContactSchema: z.ZodObject<{
34
+ name: z.ZodString;
35
+ phone: z.ZodString;
36
+ relationship: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
37
+ }, z.core.$strip>;
38
+ export type EmergencyContact = z.infer<typeof emergencyContactSchema>;
39
+ /**
40
+ * Upsert the member's profile. Used by member onboarding, owner "add member",
41
+ * and the member's own edit-profile screen.
42
+ */
43
+ export declare const upsertMemberProfileBodySchema: z.ZodObject<{
44
+ gender: z.ZodEnum<{
45
+ male: "male";
46
+ female: "female";
47
+ other: "other";
48
+ }>;
49
+ dob: z.ZodString;
50
+ bloodGroup: z.ZodOptional<z.ZodEnum<{
51
+ "A+": "A+";
52
+ "A-": "A-";
53
+ "B+": "B+";
54
+ "B-": "B-";
55
+ "O+": "O+";
56
+ "O-": "O-";
57
+ "AB+": "AB+";
58
+ "AB-": "AB-";
59
+ }>>;
60
+ address: z.ZodOptional<z.ZodObject<{
61
+ street: z.ZodString;
62
+ city: z.ZodString;
63
+ state: z.ZodEnum<{
64
+ "Andhra Pradesh": "Andhra Pradesh";
65
+ "Arunachal Pradesh": "Arunachal Pradesh";
66
+ Assam: "Assam";
67
+ Bihar: "Bihar";
68
+ Chhattisgarh: "Chhattisgarh";
69
+ Goa: "Goa";
70
+ Gujarat: "Gujarat";
71
+ Haryana: "Haryana";
72
+ "Himachal Pradesh": "Himachal Pradesh";
73
+ Jharkhand: "Jharkhand";
74
+ Karnataka: "Karnataka";
75
+ Kerala: "Kerala";
76
+ "Madhya Pradesh": "Madhya Pradesh";
77
+ Maharashtra: "Maharashtra";
78
+ Manipur: "Manipur";
79
+ Meghalaya: "Meghalaya";
80
+ Mizoram: "Mizoram";
81
+ Nagaland: "Nagaland";
82
+ Odisha: "Odisha";
83
+ Punjab: "Punjab";
84
+ Rajasthan: "Rajasthan";
85
+ Sikkim: "Sikkim";
86
+ "Tamil Nadu": "Tamil Nadu";
87
+ Telangana: "Telangana";
88
+ Tripura: "Tripura";
89
+ "Uttar Pradesh": "Uttar Pradesh";
90
+ Uttarakhand: "Uttarakhand";
91
+ "West Bengal": "West Bengal";
92
+ "Andaman and Nicobar Islands": "Andaman and Nicobar Islands";
93
+ Chandigarh: "Chandigarh";
94
+ "Dadra and Nagar Haveli and Daman and Diu": "Dadra and Nagar Haveli and Daman and Diu";
95
+ Delhi: "Delhi";
96
+ "Jammu and Kashmir": "Jammu and Kashmir";
97
+ Ladakh: "Ladakh";
98
+ Lakshadweep: "Lakshadweep";
99
+ Puducherry: "Puducherry";
100
+ }>;
101
+ pincode: z.ZodString;
102
+ }, z.core.$strip>>;
103
+ emergencyContacts: z.ZodDefault<z.ZodArray<z.ZodObject<{
104
+ name: z.ZodString;
105
+ phone: z.ZodString;
106
+ relationship: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
107
+ }, z.core.$strip>>>;
108
+ body: z.ZodDefault<z.ZodObject<{
109
+ heightCm: z.ZodOptional<z.ZodNumber>;
110
+ weightKg: z.ZodOptional<z.ZodNumber>;
111
+ neckCm: z.ZodOptional<z.ZodNumber>;
112
+ waistCm: z.ZodOptional<z.ZodNumber>;
113
+ hipsCm: z.ZodOptional<z.ZodNumber>;
114
+ forearmCm: z.ZodOptional<z.ZodNumber>;
115
+ armsCm: z.ZodOptional<z.ZodNumber>;
116
+ chestCm: z.ZodOptional<z.ZodNumber>;
117
+ thighCm: z.ZodOptional<z.ZodNumber>;
118
+ calfCm: z.ZodOptional<z.ZodNumber>;
119
+ }, z.core.$strip>>;
120
+ idProofUrl: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
121
+ aadhaarLast4: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
122
+ }, z.core.$strip>;
123
+ export type UpsertMemberProfileBody = z.infer<typeof upsertMemberProfileBodySchema>;
124
+ /** Partial edit — every field optional. */
125
+ export declare const updateMemberProfileBodySchema: z.ZodObject<{
126
+ gender: z.ZodOptional<z.ZodEnum<{
127
+ male: "male";
128
+ female: "female";
129
+ other: "other";
130
+ }>>;
131
+ dob: z.ZodOptional<z.ZodString>;
132
+ bloodGroup: z.ZodOptional<z.ZodOptional<z.ZodEnum<{
133
+ "A+": "A+";
134
+ "A-": "A-";
135
+ "B+": "B+";
136
+ "B-": "B-";
137
+ "O+": "O+";
138
+ "O-": "O-";
139
+ "AB+": "AB+";
140
+ "AB-": "AB-";
141
+ }>>>;
142
+ address: z.ZodOptional<z.ZodOptional<z.ZodObject<{
143
+ street: z.ZodString;
144
+ city: z.ZodString;
145
+ state: z.ZodEnum<{
146
+ "Andhra Pradesh": "Andhra Pradesh";
147
+ "Arunachal Pradesh": "Arunachal Pradesh";
148
+ Assam: "Assam";
149
+ Bihar: "Bihar";
150
+ Chhattisgarh: "Chhattisgarh";
151
+ Goa: "Goa";
152
+ Gujarat: "Gujarat";
153
+ Haryana: "Haryana";
154
+ "Himachal Pradesh": "Himachal Pradesh";
155
+ Jharkhand: "Jharkhand";
156
+ Karnataka: "Karnataka";
157
+ Kerala: "Kerala";
158
+ "Madhya Pradesh": "Madhya Pradesh";
159
+ Maharashtra: "Maharashtra";
160
+ Manipur: "Manipur";
161
+ Meghalaya: "Meghalaya";
162
+ Mizoram: "Mizoram";
163
+ Nagaland: "Nagaland";
164
+ Odisha: "Odisha";
165
+ Punjab: "Punjab";
166
+ Rajasthan: "Rajasthan";
167
+ Sikkim: "Sikkim";
168
+ "Tamil Nadu": "Tamil Nadu";
169
+ Telangana: "Telangana";
170
+ Tripura: "Tripura";
171
+ "Uttar Pradesh": "Uttar Pradesh";
172
+ Uttarakhand: "Uttarakhand";
173
+ "West Bengal": "West Bengal";
174
+ "Andaman and Nicobar Islands": "Andaman and Nicobar Islands";
175
+ Chandigarh: "Chandigarh";
176
+ "Dadra and Nagar Haveli and Daman and Diu": "Dadra and Nagar Haveli and Daman and Diu";
177
+ Delhi: "Delhi";
178
+ "Jammu and Kashmir": "Jammu and Kashmir";
179
+ Ladakh: "Ladakh";
180
+ Lakshadweep: "Lakshadweep";
181
+ Puducherry: "Puducherry";
182
+ }>;
183
+ pincode: z.ZodString;
184
+ }, z.core.$strip>>>;
185
+ emergencyContacts: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodObject<{
186
+ name: z.ZodString;
187
+ phone: z.ZodString;
188
+ relationship: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
189
+ }, z.core.$strip>>>>;
190
+ body: z.ZodOptional<z.ZodDefault<z.ZodObject<{
191
+ heightCm: z.ZodOptional<z.ZodNumber>;
192
+ weightKg: z.ZodOptional<z.ZodNumber>;
193
+ neckCm: z.ZodOptional<z.ZodNumber>;
194
+ waistCm: z.ZodOptional<z.ZodNumber>;
195
+ hipsCm: z.ZodOptional<z.ZodNumber>;
196
+ forearmCm: z.ZodOptional<z.ZodNumber>;
197
+ armsCm: z.ZodOptional<z.ZodNumber>;
198
+ chestCm: z.ZodOptional<z.ZodNumber>;
199
+ thighCm: z.ZodOptional<z.ZodNumber>;
200
+ calfCm: z.ZodOptional<z.ZodNumber>;
201
+ }, z.core.$strip>>>;
202
+ idProofUrl: z.ZodOptional<z.ZodPreprocess<z.ZodOptional<z.ZodString>>>;
203
+ aadhaarLast4: z.ZodOptional<z.ZodPreprocess<z.ZodOptional<z.ZodString>>>;
204
+ }, z.core.$strip>;
205
+ export type UpdateMemberProfileBody = z.infer<typeof updateMemberProfileBodySchema>;
206
+ /**
207
+ * Lifecycle of a member record. `invited` = the gym created it and the person
208
+ * has not claimed their login yet (the roster still works fully); `active` = a
209
+ * central-auth account is linked.
210
+ */
211
+ export declare const memberRecordStatusSchema: z.ZodEnum<{
212
+ active: "active";
213
+ invited: "invited";
214
+ }>;
215
+ export type MemberRecordStatus = z.infer<typeof memberRecordStatusSchema>;
216
+ export declare const memberProfileSchema: z.ZodObject<{
217
+ id: z.ZodString;
218
+ userId: z.ZodNullable<z.ZodString>;
219
+ status: z.ZodEnum<{
220
+ active: "active";
221
+ invited: "invited";
222
+ }>;
223
+ inviteEmail: z.ZodNullable<z.ZodString>;
224
+ invitePhone: z.ZodNullable<z.ZodString>;
225
+ claimedAt: z.ZodNullable<z.ZodISODateTime>;
226
+ centerId: z.ZodString;
227
+ memberCode: z.ZodString;
228
+ gender: z.ZodEnum<{
229
+ male: "male";
230
+ female: "female";
231
+ other: "other";
232
+ }>;
233
+ dob: z.ZodNullable<z.ZodString>;
234
+ bloodGroup: z.ZodNullable<z.ZodEnum<{
235
+ "A+": "A+";
236
+ "A-": "A-";
237
+ "B+": "B+";
238
+ "B-": "B-";
239
+ "O+": "O+";
240
+ "O-": "O-";
241
+ "AB+": "AB+";
242
+ "AB-": "AB-";
243
+ }>>;
244
+ address: z.ZodNullable<z.ZodObject<{
245
+ street: z.ZodString;
246
+ city: z.ZodString;
247
+ state: z.ZodEnum<{
248
+ "Andhra Pradesh": "Andhra Pradesh";
249
+ "Arunachal Pradesh": "Arunachal Pradesh";
250
+ Assam: "Assam";
251
+ Bihar: "Bihar";
252
+ Chhattisgarh: "Chhattisgarh";
253
+ Goa: "Goa";
254
+ Gujarat: "Gujarat";
255
+ Haryana: "Haryana";
256
+ "Himachal Pradesh": "Himachal Pradesh";
257
+ Jharkhand: "Jharkhand";
258
+ Karnataka: "Karnataka";
259
+ Kerala: "Kerala";
260
+ "Madhya Pradesh": "Madhya Pradesh";
261
+ Maharashtra: "Maharashtra";
262
+ Manipur: "Manipur";
263
+ Meghalaya: "Meghalaya";
264
+ Mizoram: "Mizoram";
265
+ Nagaland: "Nagaland";
266
+ Odisha: "Odisha";
267
+ Punjab: "Punjab";
268
+ Rajasthan: "Rajasthan";
269
+ Sikkim: "Sikkim";
270
+ "Tamil Nadu": "Tamil Nadu";
271
+ Telangana: "Telangana";
272
+ Tripura: "Tripura";
273
+ "Uttar Pradesh": "Uttar Pradesh";
274
+ Uttarakhand: "Uttarakhand";
275
+ "West Bengal": "West Bengal";
276
+ "Andaman and Nicobar Islands": "Andaman and Nicobar Islands";
277
+ Chandigarh: "Chandigarh";
278
+ "Dadra and Nagar Haveli and Daman and Diu": "Dadra and Nagar Haveli and Daman and Diu";
279
+ Delhi: "Delhi";
280
+ "Jammu and Kashmir": "Jammu and Kashmir";
281
+ Ladakh: "Ladakh";
282
+ Lakshadweep: "Lakshadweep";
283
+ Puducherry: "Puducherry";
284
+ }>;
285
+ pincode: z.ZodString;
286
+ }, z.core.$strip>>;
287
+ emergencyContacts: z.ZodArray<z.ZodObject<{
288
+ name: z.ZodString;
289
+ phone: z.ZodString;
290
+ relationship: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
291
+ }, z.core.$strip>>;
292
+ body: z.ZodObject<{
293
+ heightCm: z.ZodOptional<z.ZodNumber>;
294
+ weightKg: z.ZodOptional<z.ZodNumber>;
295
+ neckCm: z.ZodOptional<z.ZodNumber>;
296
+ waistCm: z.ZodOptional<z.ZodNumber>;
297
+ hipsCm: z.ZodOptional<z.ZodNumber>;
298
+ forearmCm: z.ZodOptional<z.ZodNumber>;
299
+ armsCm: z.ZodOptional<z.ZodNumber>;
300
+ chestCm: z.ZodOptional<z.ZodNumber>;
301
+ thighCm: z.ZodOptional<z.ZodNumber>;
302
+ calfCm: z.ZodOptional<z.ZodNumber>;
303
+ }, z.core.$strip>;
304
+ idProofUrl: z.ZodNullable<z.ZodString>;
305
+ aadhaarLast4: z.ZodNullable<z.ZodString>;
306
+ assignedWorkoutPlanId: z.ZodNullable<z.ZodString>;
307
+ assignedTrainerId: z.ZodNullable<z.ZodString>;
308
+ createdAt: z.ZodISODateTime;
309
+ updatedAt: z.ZodISODateTime;
310
+ }, z.core.$strip>;
311
+ export type MemberProfile = z.infer<typeof memberProfileSchema>;
312
+ //# sourceMappingURL=member-profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"member-profile.d.ts","sourceRoot":"","sources":["../src/member-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAYxB;;;;GAIG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;iBAW5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAI5D,eAAO,MAAM,sBAAsB;;;;iBAIjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAItE;;;GAGG;AACH,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkBxC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF,2CAA2C;AAC3C,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA0C,CAAC;AACrF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAIpF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB;;;EAAgC,CAAC;AACtE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+B9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * gymmonk-schema — Member fitness profile
3
+ * =======================================
4
+ * Product-owned personal + fitness data for a gym member, separate from the
5
+ * auth-mirrored `User` (which holds name/email/phone/avatar). One profile per
6
+ * user, scoped to the single center they belong to.
7
+ *
8
+ * Body measurements are stored RAW (cm / kg); BMI and body-fat % are derived at
9
+ * the edge, never persisted. Full Aadhaar is never stored — only its last four
10
+ * digits and/or an uploaded ID-proof URL (DPDP data-minimisation).
11
+ *
12
+ * @module gymmonk-schema/member-profile
13
+ */
14
+ import { z } from 'zod';
15
+ import { isoDateSchema, isoDateTimeSchema, objectIdSchema, optionalTrimmedString, phoneSchema, } from './common.js';
16
+ import { addressSchema, bloodGroupSchema, genderSchema } from './shared.js';
17
+ // ─── Body measurements ───────────────────────────────────────────────────────
18
+ /**
19
+ * Raw body measurements in metric units. Height + weight anchor BMI; neck /
20
+ * waist / hips feed the U.S.-Navy body-fat estimate; the rest are progress
21
+ * tracking. All optional so a partial update touches only what changed.
22
+ */
23
+ export const bodyMetricsSchema = z.object({
24
+ heightCm: z.number().min(120).max(230).optional(),
25
+ weightKg: z.number().min(30).max(300).optional(),
26
+ neckCm: z.number().min(20).max(80).optional(),
27
+ waistCm: z.number().min(40).max(200).optional(),
28
+ hipsCm: z.number().min(50).max(200).optional(),
29
+ forearmCm: z.number().min(10).max(80).optional(),
30
+ armsCm: z.number().min(10).max(100).optional(),
31
+ chestCm: z.number().min(40).max(200).optional(),
32
+ thighCm: z.number().min(20).max(120).optional(),
33
+ calfCm: z.number().min(15).max(80).optional(),
34
+ });
35
+ // ─── Emergency contact ───────────────────────────────────────────────────────
36
+ export const emergencyContactSchema = z.object({
37
+ name: z.string().trim().min(1).max(120),
38
+ phone: phoneSchema,
39
+ relationship: optionalTrimmedString(60),
40
+ });
41
+ // ─── Create / update body ────────────────────────────────────────────────────
42
+ /**
43
+ * Upsert the member's profile. Used by member onboarding, owner "add member",
44
+ * and the member's own edit-profile screen.
45
+ */
46
+ export const upsertMemberProfileBodySchema = z.object({
47
+ gender: genderSchema,
48
+ dob: isoDateSchema,
49
+ bloodGroup: bloodGroupSchema.optional(),
50
+ address: addressSchema.optional(),
51
+ emergencyContacts: z.array(emergencyContactSchema).max(5).default([]),
52
+ body: bodyMetricsSchema.default({}),
53
+ /** Uploaded ID-proof document URL (Aadhaar/PAN/etc.). */
54
+ idProofUrl: optionalTrimmedString(2000),
55
+ /** Last four digits of Aadhaar for display only. */
56
+ aadhaarLast4: z.preprocess((v) => (typeof v === 'string' && v.trim() === '' ? undefined : v), z
57
+ .string()
58
+ .trim()
59
+ .regex(/^\d{4}$/, 'Enter the last 4 digits')
60
+ .optional()),
61
+ });
62
+ /** Partial edit — every field optional. */
63
+ export const updateMemberProfileBodySchema = upsertMemberProfileBodySchema.partial();
64
+ // ─── Entity (API response) ───────────────────────────────────────────────────
65
+ /**
66
+ * Lifecycle of a member record. `invited` = the gym created it and the person
67
+ * has not claimed their login yet (the roster still works fully); `active` = a
68
+ * central-auth account is linked.
69
+ */
70
+ export const memberRecordStatusSchema = z.enum(['invited', 'active']);
71
+ export const memberProfileSchema = z.object({
72
+ id: objectIdSchema,
73
+ /**
74
+ * The linked central-auth user. NULL until the member claims their invite —
75
+ * gyms add members at the desk long before (or without) an app login.
76
+ */
77
+ userId: objectIdSchema.nullable(),
78
+ status: memberRecordStatusSchema,
79
+ /** The address the invite was issued to; the claim must match it. */
80
+ inviteEmail: z.string().nullable(),
81
+ /** WhatsApp number the owner shares the invite link on. */
82
+ invitePhone: z.string().nullable(),
83
+ claimedAt: isoDateTimeSchema.nullable(),
84
+ centerId: objectIdSchema,
85
+ /** Public member code within the gym, `GM-YYYY-NNNNN`. Server-generated. */
86
+ memberCode: z.string(),
87
+ gender: genderSchema,
88
+ /** Null when the gym added the member without their date of birth. */
89
+ dob: isoDateSchema.nullable(),
90
+ bloodGroup: bloodGroupSchema.nullable(),
91
+ address: addressSchema.nullable(),
92
+ emergencyContacts: z.array(emergencyContactSchema),
93
+ body: bodyMetricsSchema,
94
+ idProofUrl: z.string().nullable(),
95
+ aadhaarLast4: z.string().nullable(),
96
+ /** The workout plan the gym assigned to this member (owner action). */
97
+ assignedWorkoutPlanId: objectIdSchema.nullable(),
98
+ /** The trainer looking after this member (owner action). */
99
+ assignedTrainerId: objectIdSchema.nullable(),
100
+ createdAt: isoDateTimeSchema,
101
+ updatedAt: isoDateTimeSchema,
102
+ });
103
+ //# sourceMappingURL=member-profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"member-profile.js","sourceRoot":"","sources":["../src/member-profile.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gymmonk-schema — Member fitness profile\n * =======================================\n * Product-owned personal + fitness data for a gym member, separate from the\n * auth-mirrored `User` (which holds name/email/phone/avatar). One profile per\n * user, scoped to the single center they belong to.\n *\n * Body measurements are stored RAW (cm / kg); BMI and body-fat % are derived at\n * the edge, never persisted. Full Aadhaar is never stored — only its last four\n * digits and/or an uploaded ID-proof URL (DPDP data-minimisation).\n *\n * @module gymmonk-schema/member-profile\n */\n\nimport { z } from 'zod';\nimport {\n isoDateSchema,\n isoDateTimeSchema,\n objectIdSchema,\n optionalTrimmedString,\n phoneSchema,\n} from './common.js';\nimport { addressSchema, bloodGroupSchema, genderSchema } from './shared.js';\n\n// ─── Body measurements ───────────────────────────────────────────────────────\n\n/**\n * Raw body measurements in metric units. Height + weight anchor BMI; neck /\n * waist / hips feed the U.S.-Navy body-fat estimate; the rest are progress\n * tracking. All optional so a partial update touches only what changed.\n */\nexport const bodyMetricsSchema = z.object({\n heightCm: z.number().min(120).max(230).optional(),\n weightKg: z.number().min(30).max(300).optional(),\n neckCm: z.number().min(20).max(80).optional(),\n waistCm: z.number().min(40).max(200).optional(),\n hipsCm: z.number().min(50).max(200).optional(),\n forearmCm: z.number().min(10).max(80).optional(),\n armsCm: z.number().min(10).max(100).optional(),\n chestCm: z.number().min(40).max(200).optional(),\n thighCm: z.number().min(20).max(120).optional(),\n calfCm: z.number().min(15).max(80).optional(),\n});\nexport type BodyMetrics = z.infer<typeof bodyMetricsSchema>;\n\n// ─── Emergency contact ───────────────────────────────────────────────────────\n\nexport const emergencyContactSchema = z.object({\n name: z.string().trim().min(1).max(120),\n phone: phoneSchema,\n relationship: optionalTrimmedString(60),\n});\nexport type EmergencyContact = z.infer<typeof emergencyContactSchema>;\n\n// ─── Create / update body ────────────────────────────────────────────────────\n\n/**\n * Upsert the member's profile. Used by member onboarding, owner \"add member\",\n * and the member's own edit-profile screen.\n */\nexport const upsertMemberProfileBodySchema = z.object({\n gender: genderSchema,\n dob: isoDateSchema,\n bloodGroup: bloodGroupSchema.optional(),\n address: addressSchema.optional(),\n emergencyContacts: z.array(emergencyContactSchema).max(5).default([]),\n body: bodyMetricsSchema.default({}),\n /** Uploaded ID-proof document URL (Aadhaar/PAN/etc.). */\n idProofUrl: optionalTrimmedString(2000),\n /** Last four digits of Aadhaar for display only. */\n aadhaarLast4: z.preprocess(\n (v) => (typeof v === 'string' && v.trim() === '' ? undefined : v),\n z\n .string()\n .trim()\n .regex(/^\\d{4}$/, 'Enter the last 4 digits')\n .optional(),\n ),\n});\nexport type UpsertMemberProfileBody = z.infer<typeof upsertMemberProfileBodySchema>;\n\n/** Partial edit — every field optional. */\nexport const updateMemberProfileBodySchema = upsertMemberProfileBodySchema.partial();\nexport type UpdateMemberProfileBody = z.infer<typeof updateMemberProfileBodySchema>;\n\n// ─── Entity (API response) ───────────────────────────────────────────────────\n\n/**\n * Lifecycle of a member record. `invited` = the gym created it and the person\n * has not claimed their login yet (the roster still works fully); `active` = a\n * central-auth account is linked.\n */\nexport const memberRecordStatusSchema = z.enum(['invited', 'active']);\nexport type MemberRecordStatus = z.infer<typeof memberRecordStatusSchema>;\n\nexport const memberProfileSchema = z.object({\n id: objectIdSchema,\n /**\n * The linked central-auth user. NULL until the member claims their invite —\n * gyms add members at the desk long before (or without) an app login.\n */\n userId: objectIdSchema.nullable(),\n status: memberRecordStatusSchema,\n /** The address the invite was issued to; the claim must match it. */\n inviteEmail: z.string().nullable(),\n /** WhatsApp number the owner shares the invite link on. */\n invitePhone: z.string().nullable(),\n claimedAt: isoDateTimeSchema.nullable(),\n centerId: objectIdSchema,\n /** Public member code within the gym, `GM-YYYY-NNNNN`. Server-generated. */\n memberCode: z.string(),\n gender: genderSchema,\n /** Null when the gym added the member without their date of birth. */\n dob: isoDateSchema.nullable(),\n bloodGroup: bloodGroupSchema.nullable(),\n address: addressSchema.nullable(),\n emergencyContacts: z.array(emergencyContactSchema),\n body: bodyMetricsSchema,\n idProofUrl: z.string().nullable(),\n aadhaarLast4: z.string().nullable(),\n /** The workout plan the gym assigned to this member (owner action). */\n assignedWorkoutPlanId: objectIdSchema.nullable(),\n /** The trainer looking after this member (owner action). */\n assignedTrainerId: objectIdSchema.nullable(),\n createdAt: isoDateTimeSchema,\n updatedAt: isoDateTimeSchema,\n});\nexport type MemberProfile = z.infer<typeof memberProfileSchema>;\n"]}