gymmonk-schema 0.36.0 → 0.37.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.
- package/dist/center.d.ts +12 -12
- package/dist/equipment.d.ts +8 -8
- package/dist/gym-registration.d.ts +3 -3
- package/dist/member.d.ts +5 -44
- package/dist/member.d.ts.map +1 -1
- package/dist/member.js +0 -3
- package/dist/member.js.map +1 -1
- package/dist/membership-plan.d.ts +655 -128
- package/dist/membership-plan.d.ts.map +1 -1
- package/dist/membership-plan.js +180 -51
- package/dist/membership-plan.js.map +1 -1
- package/dist/membership.d.ts +5 -21
- package/dist/membership.d.ts.map +1 -1
- package/dist/membership.js +12 -5
- package/dist/membership.js.map +1 -1
- package/dist/messages.d.ts +3 -1
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +3 -1
- package/dist/messages.js.map +1 -1
- package/dist/onboarding-form.d.ts +6 -6
- package/dist/onboarding.d.ts +3 -3
- package/package.json +1 -1
package/dist/center.d.ts
CHANGED
|
@@ -54,20 +54,20 @@ import { z } from 'zod';
|
|
|
54
54
|
*/
|
|
55
55
|
export declare const CENTER_TYPES: readonly ["gym", "strength", "crossfit", "functional", "bodybuilding", "powerlifting", "calisthenics", "cardio", "hiit", "spinning", "bootcamp", "aerobics", "sports-conditioning", "yoga", "pilates", "meditation", "zumba", "dance", "boxing", "kickboxing", "mma", "martial-arts", "swimming", "physiotherapy"];
|
|
56
56
|
export declare const centerTypeSchema: z.ZodEnum<{
|
|
57
|
-
|
|
57
|
+
gym: "gym";
|
|
58
58
|
strength: "strength";
|
|
59
|
-
yoga: "yoga";
|
|
60
59
|
crossfit: "crossfit";
|
|
61
|
-
gym: "gym";
|
|
62
60
|
functional: "functional";
|
|
63
61
|
bodybuilding: "bodybuilding";
|
|
64
62
|
powerlifting: "powerlifting";
|
|
65
63
|
calisthenics: "calisthenics";
|
|
64
|
+
cardio: "cardio";
|
|
66
65
|
hiit: "hiit";
|
|
67
66
|
spinning: "spinning";
|
|
68
67
|
bootcamp: "bootcamp";
|
|
69
68
|
aerobics: "aerobics";
|
|
70
69
|
"sports-conditioning": "sports-conditioning";
|
|
70
|
+
yoga: "yoga";
|
|
71
71
|
pilates: "pilates";
|
|
72
72
|
meditation: "meditation";
|
|
73
73
|
zumba: "zumba";
|
|
@@ -92,20 +92,20 @@ export declare const createCenterBodySchema: z.ZodObject<{
|
|
|
92
92
|
name: z.ZodString;
|
|
93
93
|
description: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
|
|
94
94
|
types: z.ZodArray<z.ZodEnum<{
|
|
95
|
-
|
|
95
|
+
gym: "gym";
|
|
96
96
|
strength: "strength";
|
|
97
|
-
yoga: "yoga";
|
|
98
97
|
crossfit: "crossfit";
|
|
99
|
-
gym: "gym";
|
|
100
98
|
functional: "functional";
|
|
101
99
|
bodybuilding: "bodybuilding";
|
|
102
100
|
powerlifting: "powerlifting";
|
|
103
101
|
calisthenics: "calisthenics";
|
|
102
|
+
cardio: "cardio";
|
|
104
103
|
hiit: "hiit";
|
|
105
104
|
spinning: "spinning";
|
|
106
105
|
bootcamp: "bootcamp";
|
|
107
106
|
aerobics: "aerobics";
|
|
108
107
|
"sports-conditioning": "sports-conditioning";
|
|
108
|
+
yoga: "yoga";
|
|
109
109
|
pilates: "pilates";
|
|
110
110
|
meditation: "meditation";
|
|
111
111
|
zumba: "zumba";
|
|
@@ -206,20 +206,20 @@ export declare const updateCenterBodySchema: z.ZodObject<{
|
|
|
206
206
|
name: z.ZodOptional<z.ZodString>;
|
|
207
207
|
description: z.ZodOptional<z.ZodPreprocess<z.ZodOptional<z.ZodString>>>;
|
|
208
208
|
types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
209
|
-
|
|
209
|
+
gym: "gym";
|
|
210
210
|
strength: "strength";
|
|
211
|
-
yoga: "yoga";
|
|
212
211
|
crossfit: "crossfit";
|
|
213
|
-
gym: "gym";
|
|
214
212
|
functional: "functional";
|
|
215
213
|
bodybuilding: "bodybuilding";
|
|
216
214
|
powerlifting: "powerlifting";
|
|
217
215
|
calisthenics: "calisthenics";
|
|
216
|
+
cardio: "cardio";
|
|
218
217
|
hiit: "hiit";
|
|
219
218
|
spinning: "spinning";
|
|
220
219
|
bootcamp: "bootcamp";
|
|
221
220
|
aerobics: "aerobics";
|
|
222
221
|
"sports-conditioning": "sports-conditioning";
|
|
222
|
+
yoga: "yoga";
|
|
223
223
|
pilates: "pilates";
|
|
224
224
|
meditation: "meditation";
|
|
225
225
|
zumba: "zumba";
|
|
@@ -335,20 +335,20 @@ export declare const centerSchema: z.ZodObject<{
|
|
|
335
335
|
name: z.ZodString;
|
|
336
336
|
description: z.ZodNullable<z.ZodString>;
|
|
337
337
|
types: z.ZodArray<z.ZodEnum<{
|
|
338
|
-
|
|
338
|
+
gym: "gym";
|
|
339
339
|
strength: "strength";
|
|
340
|
-
yoga: "yoga";
|
|
341
340
|
crossfit: "crossfit";
|
|
342
|
-
gym: "gym";
|
|
343
341
|
functional: "functional";
|
|
344
342
|
bodybuilding: "bodybuilding";
|
|
345
343
|
powerlifting: "powerlifting";
|
|
346
344
|
calisthenics: "calisthenics";
|
|
345
|
+
cardio: "cardio";
|
|
347
346
|
hiit: "hiit";
|
|
348
347
|
spinning: "spinning";
|
|
349
348
|
bootcamp: "bootcamp";
|
|
350
349
|
aerobics: "aerobics";
|
|
351
350
|
"sports-conditioning": "sports-conditioning";
|
|
351
|
+
yoga: "yoga";
|
|
352
352
|
pilates: "pilates";
|
|
353
353
|
meditation: "meditation";
|
|
354
354
|
zumba: "zumba";
|
package/dist/equipment.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ import { z } from 'zod';
|
|
|
10
10
|
export declare const EQUIPMENT_CATEGORIES: readonly ["cardio", "strength", "weight", "training", "recovery", "custom"];
|
|
11
11
|
export declare const equipmentCategorySchema: z.ZodEnum<{
|
|
12
12
|
custom: "custom";
|
|
13
|
-
cardio: "cardio";
|
|
14
13
|
strength: "strength";
|
|
14
|
+
cardio: "cardio";
|
|
15
15
|
weight: "weight";
|
|
16
16
|
training: "training";
|
|
17
17
|
recovery: "recovery";
|
|
@@ -22,8 +22,8 @@ export declare const equipmentSchema: z.ZodObject<{
|
|
|
22
22
|
centerId: z.ZodString;
|
|
23
23
|
category: z.ZodEnum<{
|
|
24
24
|
custom: "custom";
|
|
25
|
-
cardio: "cardio";
|
|
26
25
|
strength: "strength";
|
|
26
|
+
cardio: "cardio";
|
|
27
27
|
weight: "weight";
|
|
28
28
|
training: "training";
|
|
29
29
|
recovery: "recovery";
|
|
@@ -39,8 +39,8 @@ export type Equipment = z.infer<typeof equipmentSchema>;
|
|
|
39
39
|
export declare const equipmentCategorySummarySchema: z.ZodObject<{
|
|
40
40
|
category: z.ZodEnum<{
|
|
41
41
|
custom: "custom";
|
|
42
|
-
cardio: "cardio";
|
|
43
42
|
strength: "strength";
|
|
43
|
+
cardio: "cardio";
|
|
44
44
|
weight: "weight";
|
|
45
45
|
training: "training";
|
|
46
46
|
recovery: "recovery";
|
|
@@ -53,8 +53,8 @@ export declare const createEquipmentBodySchema: z.ZodObject<{
|
|
|
53
53
|
centerId: z.ZodString;
|
|
54
54
|
category: z.ZodEnum<{
|
|
55
55
|
custom: "custom";
|
|
56
|
-
cardio: "cardio";
|
|
57
56
|
strength: "strength";
|
|
57
|
+
cardio: "cardio";
|
|
58
58
|
weight: "weight";
|
|
59
59
|
training: "training";
|
|
60
60
|
recovery: "recovery";
|
|
@@ -68,8 +68,8 @@ export declare const updateEquipmentBodySchema: z.ZodObject<{
|
|
|
68
68
|
name: z.ZodOptional<z.ZodString>;
|
|
69
69
|
category: z.ZodOptional<z.ZodEnum<{
|
|
70
70
|
custom: "custom";
|
|
71
|
-
cardio: "cardio";
|
|
72
71
|
strength: "strength";
|
|
72
|
+
cardio: "cardio";
|
|
73
73
|
weight: "weight";
|
|
74
74
|
training: "training";
|
|
75
75
|
recovery: "recovery";
|
|
@@ -101,8 +101,8 @@ export declare const EQUIPMENT_CATALOG: Record<EquipmentCategory, readonly strin
|
|
|
101
101
|
export declare const equipmentQuantityEntrySchema: z.ZodObject<{
|
|
102
102
|
category: z.ZodEnum<{
|
|
103
103
|
custom: "custom";
|
|
104
|
-
cardio: "cardio";
|
|
105
104
|
strength: "strength";
|
|
105
|
+
cardio: "cardio";
|
|
106
106
|
weight: "weight";
|
|
107
107
|
training: "training";
|
|
108
108
|
recovery: "recovery";
|
|
@@ -116,8 +116,8 @@ export declare const setEquipmentQuantitiesBodySchema: z.ZodObject<{
|
|
|
116
116
|
items: z.ZodArray<z.ZodObject<{
|
|
117
117
|
category: z.ZodEnum<{
|
|
118
118
|
custom: "custom";
|
|
119
|
-
cardio: "cardio";
|
|
120
119
|
strength: "strength";
|
|
120
|
+
cardio: "cardio";
|
|
121
121
|
weight: "weight";
|
|
122
122
|
training: "training";
|
|
123
123
|
recovery: "recovery";
|
|
@@ -131,8 +131,8 @@ export declare const equipmentQuerySchema: z.ZodObject<{
|
|
|
131
131
|
centerId: z.ZodString;
|
|
132
132
|
category: z.ZodOptional<z.ZodEnum<{
|
|
133
133
|
custom: "custom";
|
|
134
|
-
cardio: "cardio";
|
|
135
134
|
strength: "strength";
|
|
135
|
+
cardio: "cardio";
|
|
136
136
|
weight: "weight";
|
|
137
137
|
training: "training";
|
|
138
138
|
recovery: "recovery";
|
|
@@ -88,20 +88,20 @@ export declare const gymRegistrationBodySchema: z.ZodObject<{
|
|
|
88
88
|
name: z.ZodString;
|
|
89
89
|
description: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
|
|
90
90
|
types: z.ZodArray<z.ZodEnum<{
|
|
91
|
-
|
|
91
|
+
gym: "gym";
|
|
92
92
|
strength: "strength";
|
|
93
|
-
yoga: "yoga";
|
|
94
93
|
crossfit: "crossfit";
|
|
95
|
-
gym: "gym";
|
|
96
94
|
functional: "functional";
|
|
97
95
|
bodybuilding: "bodybuilding";
|
|
98
96
|
powerlifting: "powerlifting";
|
|
99
97
|
calisthenics: "calisthenics";
|
|
98
|
+
cardio: "cardio";
|
|
100
99
|
hiit: "hiit";
|
|
101
100
|
spinning: "spinning";
|
|
102
101
|
bootcamp: "bootcamp";
|
|
103
102
|
aerobics: "aerobics";
|
|
104
103
|
"sports-conditioning": "sports-conditioning";
|
|
104
|
+
yoga: "yoga";
|
|
105
105
|
pilates: "pilates";
|
|
106
106
|
meditation: "meditation";
|
|
107
107
|
zumba: "zumba";
|
package/dist/member.d.ts
CHANGED
|
@@ -32,12 +32,6 @@ export declare const memberRosterItemSchema: z.ZodObject<{
|
|
|
32
32
|
phone: z.ZodNullable<z.ZodString>;
|
|
33
33
|
email: z.ZodNullable<z.ZodEmail>;
|
|
34
34
|
planName: z.ZodNullable<z.ZodString>;
|
|
35
|
-
tier: z.ZodNullable<z.ZodEnum<{
|
|
36
|
-
free: "free";
|
|
37
|
-
basic: "basic";
|
|
38
|
-
standard: "standard";
|
|
39
|
-
premium: "premium";
|
|
40
|
-
}>>;
|
|
41
35
|
status: z.ZodNullable<z.ZodEnum<{
|
|
42
36
|
invited: "invited";
|
|
43
37
|
active: "active";
|
|
@@ -100,12 +94,6 @@ export declare const memberListQuerySchema: z.ZodObject<{
|
|
|
100
94
|
expiry: "expiry";
|
|
101
95
|
dues: "dues";
|
|
102
96
|
}>>;
|
|
103
|
-
tier: z.ZodOptional<z.ZodEnum<{
|
|
104
|
-
free: "free";
|
|
105
|
-
basic: "basic";
|
|
106
|
-
standard: "standard";
|
|
107
|
-
premium: "premium";
|
|
108
|
-
}>>;
|
|
109
97
|
q: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
|
|
110
98
|
}, z.core.$strip>;
|
|
111
99
|
export type MemberListQuery = z.infer<typeof memberListQuerySchema>;
|
|
@@ -206,20 +194,9 @@ export declare const memberDetailSchema: z.ZodObject<{
|
|
|
206
194
|
userId: z.ZodNullable<z.ZodString>;
|
|
207
195
|
centerId: z.ZodString;
|
|
208
196
|
planId: z.ZodString;
|
|
209
|
-
tier: z.ZodEnum<{
|
|
210
|
-
free: "free";
|
|
211
|
-
basic: "basic";
|
|
212
|
-
standard: "standard";
|
|
213
|
-
premium: "premium";
|
|
214
|
-
}>;
|
|
215
197
|
planName: z.ZodString;
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
"3m": "3m";
|
|
219
|
-
"6m": "6m";
|
|
220
|
-
"1y": "1y";
|
|
221
|
-
}>;
|
|
222
|
-
tenureLabel: z.ZodString;
|
|
198
|
+
variantId: z.ZodString;
|
|
199
|
+
variantLabel: z.ZodString;
|
|
223
200
|
priceInr: z.ZodNumber;
|
|
224
201
|
status: z.ZodEnum<{
|
|
225
202
|
invited: "invited";
|
|
@@ -306,12 +283,7 @@ export declare const createMemberBodySchema: z.ZodObject<{
|
|
|
306
283
|
assignedTrainerId: z.ZodOptional<z.ZodString>;
|
|
307
284
|
initialPlan: z.ZodOptional<z.ZodObject<{
|
|
308
285
|
planId: z.ZodString;
|
|
309
|
-
|
|
310
|
-
"1m": "1m";
|
|
311
|
-
"3m": "3m";
|
|
312
|
-
"6m": "6m";
|
|
313
|
-
"1y": "1y";
|
|
314
|
-
}>;
|
|
286
|
+
variantId: z.ZodString;
|
|
315
287
|
startDate: z.ZodOptional<z.ZodString>;
|
|
316
288
|
payment: z.ZodOptional<z.ZodObject<{
|
|
317
289
|
amountInr: z.ZodNumber;
|
|
@@ -450,20 +422,9 @@ export declare const provisionResultSchema: z.ZodObject<{
|
|
|
450
422
|
userId: z.ZodNullable<z.ZodString>;
|
|
451
423
|
centerId: z.ZodString;
|
|
452
424
|
planId: z.ZodString;
|
|
453
|
-
tier: z.ZodEnum<{
|
|
454
|
-
free: "free";
|
|
455
|
-
basic: "basic";
|
|
456
|
-
standard: "standard";
|
|
457
|
-
premium: "premium";
|
|
458
|
-
}>;
|
|
459
425
|
planName: z.ZodString;
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
"3m": "3m";
|
|
463
|
-
"6m": "6m";
|
|
464
|
-
"1y": "1y";
|
|
465
|
-
}>;
|
|
466
|
-
tenureLabel: z.ZodString;
|
|
426
|
+
variantId: z.ZodString;
|
|
427
|
+
variantLabel: z.ZodString;
|
|
467
428
|
priceInr: z.ZodNumber;
|
|
468
429
|
status: z.ZodEnum<{
|
|
469
430
|
invited: "invited";
|
package/dist/member.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"member.d.ts","sourceRoot":"","sources":["../src/member.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"member.d.ts","sourceRoot":"","sources":["../src/member.ts"],"names":[],"mappings":"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"}
|
package/dist/member.js
CHANGED
|
@@ -13,7 +13,6 @@ import { isoDateSchema, isoDateTimeSchema, objectIdSchema, optionalTrimmedString
|
|
|
13
13
|
import { enrolmentStatusSchema } from './enrolment.js';
|
|
14
14
|
import { emergencyContactSchema, MAX_EMERGENCY_CONTACTS } from './member-profile.js';
|
|
15
15
|
import { assignMembershipBodySchema, membershipSchema, membershipStatusSchema, } from './membership.js';
|
|
16
|
-
import { planTierSchema } from './membership-plan.js';
|
|
17
16
|
import { addressSchema, bloodGroupSchema, genderSchema } from './shared.js';
|
|
18
17
|
// ─── Segments ────────────────────────────────────────────────────────────────
|
|
19
18
|
/** Attention buckets surfaced on roster cards. */
|
|
@@ -46,7 +45,6 @@ export const memberRosterItemSchema = z.object({
|
|
|
46
45
|
phone: z.string().nullable(),
|
|
47
46
|
email: z.email().nullable(),
|
|
48
47
|
planName: z.string().nullable(),
|
|
49
|
-
tier: planTierSchema.nullable(),
|
|
50
48
|
status: membershipStatusSchema.nullable(),
|
|
51
49
|
endDate: isoDateSchema.nullable(),
|
|
52
50
|
lastVisitAt: isoDateTimeSchema.nullable(),
|
|
@@ -88,7 +86,6 @@ export const memberListQuerySchema = paginationSchema.extend({
|
|
|
88
86
|
centerId: objectIdSchema.optional(),
|
|
89
87
|
filter: memberFilterSchema.default('all'),
|
|
90
88
|
sort: memberSortSchema.default('recent'),
|
|
91
|
-
tier: planTierSchema.optional(),
|
|
92
89
|
q: optionalTrimmedString(120),
|
|
93
90
|
});
|
|
94
91
|
// ─── Detail projection ───────────────────────────────────────────────────────
|
package/dist/member.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"member.js","sourceRoot":"","sources":["../src/member.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gymmonk-schema — Member management (owner console)\n * ==================================================\n * Owner-facing roster + detail projections (User × MemberProfile × Membership)\n * and the \"add member\" provisioning payload. Adding a member provisions a real\n * central-auth account, so the result carries the login email + temp password.\n *\n * @module gymmonk-schema/member\n */\n\nimport { z } from 'zod';\nimport { gymMemberCodeSchema } from './codes.js';\nimport {\n isoDateSchema,\n isoDateTimeSchema,\n objectIdSchema,\n optionalTrimmedString,\n paginationSchema,\n phoneSchema,\n priceInrSchema,\n} from './common.js';\nimport { enrolmentStatusSchema } from './enrolment.js';\nimport { emergencyContactSchema, MAX_EMERGENCY_CONTACTS } from './member-profile.js';\nimport {\n assignMembershipBodySchema,\n membershipSchema,\n membershipStatusSchema,\n} from './membership.js';\nimport { planTierSchema } from './membership-plan.js';\nimport { addressSchema, bloodGroupSchema, genderSchema } from './shared.js';\n\n// ─── Segments ────────────────────────────────────────────────────────────────\n\n/** Attention buckets surfaced on roster cards. */\nexport const memberSegmentSchema = z.enum(['expiring', 'new', 'at-risk']);\nexport type MemberSegment = z.infer<typeof memberSegmentSchema>;\n\n// ─── Roster item (list projection) ───────────────────────────────────────────\n\nexport const memberRosterItemSchema = z.object({\n /** The gym record id — always present, even before the member claims. */\n enrolmentId: objectIdSchema,\n /** Null until claimed; the roster shows an \"Invited\" pill in that state. */\n userId: objectIdSchema.nullable(),\n recordStatus: enrolmentStatusSchema,\n membershipId: objectIdSchema.nullable(),\n gymMemberCode: gymMemberCodeSchema,\n name: z.string(),\n avatarUrl: z.string().nullable(),\n verified: z.boolean(),\n /**\n * Contact details, on the ROSTER row rather than only the detail record.\n *\n * The card's whole job when someone is overdue is to let the owner chase it\n * without leaving the list — call, WhatsApp, email. Those are `tel:` /\n * `wa.me` / `mailto:` links, so the row cannot build them without the raw\n * values, and fetching the full member just to dial them would be one\n * request per card.\n *\n * Nullable because an invited record may have only one of the two: the gym\n * creates it with whatever it has, and the member fills in the rest on claim.\n * Phone is RAW 10 digits — `+91` is display-only, never stored.\n */\n phone: z.string().nullable(),\n email: z.email().nullable(),\n planName: z.string().nullable(),\n tier: planTierSchema.nullable(),\n status: membershipStatusSchema.nullable(),\n endDate: isoDateSchema.nullable(),\n lastVisitAt: isoDateTimeSchema.nullable(),\n balanceDueInr: priceInrSchema,\n overdueDays: z.number().int().nullable(),\n segments: z.array(memberSegmentSchema),\n\n /**\n * When the gym record was created — NOT when the person claimed it. The\n * roster's \"Joined Date\" filter groups by how long someone has been a member\n * of the gym, which starts at the desk, not at the login.\n */\n joinedAt: isoDateTimeSchema,\n\n /**\n * Check-ins in the trailing 14 days, used by the roster's attendance filters\n * to separate a no-show from an irregular from a regular.\n *\n * Counted rather than derived from `lastVisitAt`, because the two answer\n * different questions: someone who came once yesterday and someone who comes\n * daily share a last visit but are not the same member to chase.\n */\n visits14d: z.number().int().nonnegative(),\n\n /** Assigned trainer, so the roster can be filtered down to one trainer's people. */\n trainerId: objectIdSchema.nullable(),\n trainerName: z.string().nullable(),\n});\n\n/** Trailing window the roster's attendance filters and `visits14d` are measured over. */\nexport const ATTENDANCE_WINDOW_DAYS = 14;\nexport type MemberRosterItem = z.infer<typeof memberRosterItemSchema>;\n\n/** Header counts for the roster. */\nexport const memberListSummarySchema = z.object({\n total: z.number().int().nonnegative(),\n active: z.number().int().nonnegative(),\n expiring: z.number().int().nonnegative(),\n inactive: z.number().int().nonnegative(),\n});\nexport type MemberListSummary = z.infer<typeof memberListSummarySchema>;\n\n// ─── List query ──────────────────────────────────────────────────────────────\n\nexport const memberFilterSchema = z.enum(['all', 'active', 'inactive', 'verified']);\nexport type MemberFilter = z.infer<typeof memberFilterSchema>;\n\nexport const memberSortSchema = z.enum(['recent', 'az', 'expiry', 'dues']);\nexport type MemberSort = z.infer<typeof memberSortSchema>;\n\nexport const memberListQuerySchema = paginationSchema.extend({\n centerId: objectIdSchema.optional(),\n filter: memberFilterSchema.default('all'),\n sort: memberSortSchema.default('recent'),\n tier: planTierSchema.optional(),\n q: optionalTrimmedString(120),\n});\nexport type MemberListQuery = z.infer<typeof memberListQuerySchema>;\n\n// ─── Detail projection ───────────────────────────────────────────────────────\n\n/** The identity slice a projection pulls from the auth `User`. */\nexport const memberUserRefSchema = z.object({\n /** Null while the record is still `invited` (no central-auth account linked). */\n id: objectIdSchema.nullable(),\n name: z.string(),\n email: z.string(),\n phone: z.string().nullable(),\n avatarUrl: z.string().nullable(),\n verified: z.boolean(),\n});\nexport type MemberUserRef = z.infer<typeof memberUserRefSchema>;\n\nexport const memberDetailSchema = z.object({\n enrolmentId: objectIdSchema,\n recordStatus: enrolmentStatusSchema,\n /**\n * Identity from central auth once claimed. Before that the gym still knows the\n * person (name / contact captured at the desk), so this carries the invited\n * details with `id: null`.\n */\n user: memberUserRefSchema,\n gymMemberCode: gymMemberCodeSchema,\n gender: genderSchema.nullable(),\n dob: isoDateSchema.nullable(),\n bloodGroup: bloodGroupSchema.nullable(),\n address: addressSchema.nullable(),\n emergencyContacts: z.array(emergencyContactSchema),\n /**\n * Last four digits of the member's Aadhaar, when one was recorded at the desk.\n * The full number is never stored (see `member-profile`), so this is all the\n * owner console can ever show — enough to match against the physical card the\n * member presents, useless to anyone who sees the screen.\n */\n aadhaarLast4: z.string().nullable(),\n /**\n * The scanned ID the desk took, if any. Carried on the detail projection so\n * the owner's edit form can round-trip it: a form that cannot see a stored\n * value sends back a blank one, and blank means \"clear it\".\n */\n idProofUrl: z.string().nullable(),\n joinedAt: isoDateTimeSchema,\n lastVisitAt: isoDateTimeSchema.nullable(),\n assignedWorkoutPlanId: objectIdSchema.nullable(),\n assignedTrainerId: objectIdSchema.nullable(),\n /**\n * The member's current membership, in FULL rather than by id.\n *\n * The profile screen shows the plan name, its billing cycle, the lifecycle\n * status pill and the expiry date all at once, and every one of those lives\n * here. Sending only the id forced the owner console to re-query the roster\n * for the same member just to read the plan columns back, and to match the\n * plan by NAME to find its perk icons — both of which this removes.\n */\n membership: membershipSchema.nullable(),\n /**\n * Still owed on the current term: its price less what has been recorded as\n * collected. Zero when settled, when the membership was cancelled, or when\n * there is no membership at all. Same definition as the roster's column, so\n * the profile and the list can never disagree about who owes money.\n */\n balanceDueInr: z.number().int().nonnegative(),\n});\nexport type MemberDetail = z.infer<typeof memberDetailSchema>;\n\n// ─── Add member (provisioning) ───────────────────────────────────────────────\n\nexport const createMemberBodySchema = z.object({\n firstName: z.string().trim().min(1, 'First name is required').max(80),\n lastName: optionalTrimmedString(80),\n email: z.email('A valid email is required'),\n phone: phoneSchema,\n gender: genderSchema,\n dob: isoDateSchema.optional(),\n bloodGroup: bloodGroupSchema.optional(),\n address: addressSchema.optional(),\n emergencyContacts: z.array(emergencyContactSchema).max(MAX_EMERGENCY_CONTACTS).default([]),\n idProofUrl: optionalTrimmedString(2000),\n avatarUrl: optionalTrimmedString(2000),\n assignedTrainerId: objectIdSchema.optional(),\n /** Optionally assign a plan in the same step. */\n initialPlan: assignMembershipBodySchema.optional(),\n});\nexport type CreateMemberBody = z.infer<typeof createMemberBodySchema>;\n\n/**\n * Edit a member's record from the owner console.\n *\n * Every field is optional — the console sends what the form holds, and a field\n * left out is left alone.\n *\n * ## What the gym may and may not change\n * `firstName` / `lastName` / `email` / `phone` are the INVITE details, and the\n * server accepts them only while the record is unclaimed. Once the member has\n * linked their central-auth account, that account is the source of truth for\n * their identity and is shared with the other products — a gym must not be able\n * to rewrite someone's name or email out from under them. The server ignores\n * those four on a claimed record rather than failing the whole request, so an\n * owner correcting a blood group is never blocked by a name they cannot change.\n *\n * Nullable fields (`dob`, `bloodGroup`, `address`, `assignedTrainerId`) accept\n * `null` to CLEAR a value, which `undefined` cannot express.\n */\nexport const updateMemberBodySchema = createMemberBodySchema\n .omit({\n initialPlan: true,\n dob: true,\n bloodGroup: true,\n address: true,\n assignedTrainerId: true,\n })\n .partial()\n .extend({\n dob: isoDateSchema.nullish(),\n bloodGroup: bloodGroupSchema.nullish(),\n address: addressSchema.nullish(),\n assignedTrainerId: objectIdSchema.nullish(),\n /** Last four digits only — the full number is never stored. */\n aadhaarLast4: z\n .string()\n .trim()\n .regex(/^\\d{4}$/, 'Enter the last four digits of the Aadhaar number')\n .nullish(),\n });\nexport type UpdateMemberBody = z.infer<typeof updateMemberBodySchema>;\n\n// ─── Invite & claim ──────────────────────────────────────────────────────────\n\n/**\n * The invite a gym hands to a new member.\n *\n * GymMonk never mints credentials for anyone: central auth is the SSOT for\n * identity, and an account there is shared across products. So adding a member\n * creates a gym record only, plus an unguessable invite code. The member\n * registers/logs in themselves through central auth (exactly as in jansathi) and\n * then CLAIMS the record. The owner shares `url` over WhatsApp or shows the QR.\n */\nexport const memberInviteSchema = z.object({\n /** Single-use, unguessable. Regenerating an invite invalidates the old one. */\n code: z.string(),\n /** Absolute claim URL the owner shares (also encoded into the QR). */\n url: z.string(),\n /** The address the member MUST register with for the claim to succeed. */\n email: z.string(),\n /** WhatsApp number to share on, when the gym recorded one. */\n phone: z.string().nullable(),\n expiresAt: isoDateTimeSchema,\n});\nexport type MemberInvite = z.infer<typeof memberInviteSchema>;\n\n/** Result of adding a member: the gym record + the invite to hand over. */\nexport const provisionResultSchema = z.object({\n /** The new member record (NOT a central-auth user — none is created). */\n enrolmentId: objectIdSchema,\n code: z.string(),\n invite: memberInviteSchema,\n /**\n * The membership created from `initialPlan`, or `null`.\n *\n * Null means one of two DIFFERENT things, and the caller can tell them apart\n * because it knows whether it sent `initialPlan`: no plan was chosen, or the\n * chosen plan could not be assigned. Adding a member never fails over the\n * second case — the person is on the roster either way — so this is how the\n * owner finds out the plan still needs assigning rather than assuming it took.\n */\n membership: membershipSchema.nullable(),\n});\nexport type ProvisionResult = z.infer<typeof provisionResultSchema>;\n\n/**\n * What the claim screen shows BEFORE the member authenticates, so they know\n * which address to register with. Public (the code is the bearer secret), and\n * deliberately minimal — gym name, member code, and the expected email.\n */\nexport const invitePreviewSchema = z.object({\n gymName: z.string(),\n gymMemberCode: gymMemberCodeSchema,\n /** Shown verbatim: the member must know exactly which address to use. */\n email: z.string(),\n expiresAt: isoDateTimeSchema,\n /** True once claimed / expired, so the screen can explain why it failed. */\n claimed: z.boolean(),\n expired: z.boolean(),\n});\nexport type InvitePreview = z.infer<typeof invitePreviewSchema>;\n\n/**\n * Claim an invite as the authenticated caller. The server links the record only\n * when the code is valid AND the caller's central-auth email matches the address\n * the invite was issued to.\n */\nexport const claimInviteBodySchema = z.object({\n code: z.string().trim().min(1),\n});\nexport type ClaimInviteBody = z.infer<typeof claimInviteBodySchema>;\n\n// ─── Mutations ───────────────────────────────────────────────────────────────\n\nexport const setMemberStatusBodySchema = z.object({ active: z.boolean() });\nexport type SetMemberStatusBody = z.infer<typeof setMemberStatusBodySchema>;\n\nexport const assignTrainerBodySchema = z.object({\n trainerId: objectIdSchema.nullable(),\n});\nexport type AssignTrainerBody = z.infer<typeof assignTrainerBodySchema>;\n\nexport const assignWorkoutPlanBodySchema = z.object({\n planId: objectIdSchema.nullable(),\n});\nexport type AssignWorkoutPlanBody = z.infer<typeof assignWorkoutPlanBodySchema>;\n\n/** Remove a member from the gym — echoes the member code to confirm. */\nexport const deleteMemberBodySchema = z.object({\n confirmationCode: z.string().trim().min(1),\n});\nexport type DeleteMemberBody = z.infer<typeof deleteMemberBodySchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"member.js","sourceRoot":"","sources":["../src/member.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gymmonk-schema — Member management (owner console)\n * ==================================================\n * Owner-facing roster + detail projections (User × MemberProfile × Membership)\n * and the \"add member\" provisioning payload. Adding a member provisions a real\n * central-auth account, so the result carries the login email + temp password.\n *\n * @module gymmonk-schema/member\n */\n\nimport { z } from 'zod';\nimport { gymMemberCodeSchema } from './codes.js';\nimport {\n isoDateSchema,\n isoDateTimeSchema,\n objectIdSchema,\n optionalTrimmedString,\n paginationSchema,\n phoneSchema,\n priceInrSchema,\n} from './common.js';\nimport { enrolmentStatusSchema } from './enrolment.js';\nimport { emergencyContactSchema, MAX_EMERGENCY_CONTACTS } from './member-profile.js';\nimport {\n assignMembershipBodySchema,\n membershipSchema,\n membershipStatusSchema,\n} from './membership.js';\nimport { addressSchema, bloodGroupSchema, genderSchema } from './shared.js';\n\n// ─── Segments ────────────────────────────────────────────────────────────────\n\n/** Attention buckets surfaced on roster cards. */\nexport const memberSegmentSchema = z.enum(['expiring', 'new', 'at-risk']);\nexport type MemberSegment = z.infer<typeof memberSegmentSchema>;\n\n// ─── Roster item (list projection) ───────────────────────────────────────────\n\nexport const memberRosterItemSchema = z.object({\n /** The gym record id — always present, even before the member claims. */\n enrolmentId: objectIdSchema,\n /** Null until claimed; the roster shows an \"Invited\" pill in that state. */\n userId: objectIdSchema.nullable(),\n recordStatus: enrolmentStatusSchema,\n membershipId: objectIdSchema.nullable(),\n gymMemberCode: gymMemberCodeSchema,\n name: z.string(),\n avatarUrl: z.string().nullable(),\n verified: z.boolean(),\n /**\n * Contact details, on the ROSTER row rather than only the detail record.\n *\n * The card's whole job when someone is overdue is to let the owner chase it\n * without leaving the list — call, WhatsApp, email. Those are `tel:` /\n * `wa.me` / `mailto:` links, so the row cannot build them without the raw\n * values, and fetching the full member just to dial them would be one\n * request per card.\n *\n * Nullable because an invited record may have only one of the two: the gym\n * creates it with whatever it has, and the member fills in the rest on claim.\n * Phone is RAW 10 digits — `+91` is display-only, never stored.\n */\n phone: z.string().nullable(),\n email: z.email().nullable(),\n planName: z.string().nullable(),\n status: membershipStatusSchema.nullable(),\n endDate: isoDateSchema.nullable(),\n lastVisitAt: isoDateTimeSchema.nullable(),\n balanceDueInr: priceInrSchema,\n overdueDays: z.number().int().nullable(),\n segments: z.array(memberSegmentSchema),\n\n /**\n * When the gym record was created — NOT when the person claimed it. The\n * roster's \"Joined Date\" filter groups by how long someone has been a member\n * of the gym, which starts at the desk, not at the login.\n */\n joinedAt: isoDateTimeSchema,\n\n /**\n * Check-ins in the trailing 14 days, used by the roster's attendance filters\n * to separate a no-show from an irregular from a regular.\n *\n * Counted rather than derived from `lastVisitAt`, because the two answer\n * different questions: someone who came once yesterday and someone who comes\n * daily share a last visit but are not the same member to chase.\n */\n visits14d: z.number().int().nonnegative(),\n\n /** Assigned trainer, so the roster can be filtered down to one trainer's people. */\n trainerId: objectIdSchema.nullable(),\n trainerName: z.string().nullable(),\n});\n\n/** Trailing window the roster's attendance filters and `visits14d` are measured over. */\nexport const ATTENDANCE_WINDOW_DAYS = 14;\nexport type MemberRosterItem = z.infer<typeof memberRosterItemSchema>;\n\n/** Header counts for the roster. */\nexport const memberListSummarySchema = z.object({\n total: z.number().int().nonnegative(),\n active: z.number().int().nonnegative(),\n expiring: z.number().int().nonnegative(),\n inactive: z.number().int().nonnegative(),\n});\nexport type MemberListSummary = z.infer<typeof memberListSummarySchema>;\n\n// ─── List query ──────────────────────────────────────────────────────────────\n\nexport const memberFilterSchema = z.enum(['all', 'active', 'inactive', 'verified']);\nexport type MemberFilter = z.infer<typeof memberFilterSchema>;\n\nexport const memberSortSchema = z.enum(['recent', 'az', 'expiry', 'dues']);\nexport type MemberSort = z.infer<typeof memberSortSchema>;\n\nexport const memberListQuerySchema = paginationSchema.extend({\n centerId: objectIdSchema.optional(),\n filter: memberFilterSchema.default('all'),\n sort: memberSortSchema.default('recent'),\n q: optionalTrimmedString(120),\n});\nexport type MemberListQuery = z.infer<typeof memberListQuerySchema>;\n\n// ─── Detail projection ───────────────────────────────────────────────────────\n\n/** The identity slice a projection pulls from the auth `User`. */\nexport const memberUserRefSchema = z.object({\n /** Null while the record is still `invited` (no central-auth account linked). */\n id: objectIdSchema.nullable(),\n name: z.string(),\n email: z.string(),\n phone: z.string().nullable(),\n avatarUrl: z.string().nullable(),\n verified: z.boolean(),\n});\nexport type MemberUserRef = z.infer<typeof memberUserRefSchema>;\n\nexport const memberDetailSchema = z.object({\n enrolmentId: objectIdSchema,\n recordStatus: enrolmentStatusSchema,\n /**\n * Identity from central auth once claimed. Before that the gym still knows the\n * person (name / contact captured at the desk), so this carries the invited\n * details with `id: null`.\n */\n user: memberUserRefSchema,\n gymMemberCode: gymMemberCodeSchema,\n gender: genderSchema.nullable(),\n dob: isoDateSchema.nullable(),\n bloodGroup: bloodGroupSchema.nullable(),\n address: addressSchema.nullable(),\n emergencyContacts: z.array(emergencyContactSchema),\n /**\n * Last four digits of the member's Aadhaar, when one was recorded at the desk.\n * The full number is never stored (see `member-profile`), so this is all the\n * owner console can ever show — enough to match against the physical card the\n * member presents, useless to anyone who sees the screen.\n */\n aadhaarLast4: z.string().nullable(),\n /**\n * The scanned ID the desk took, if any. Carried on the detail projection so\n * the owner's edit form can round-trip it: a form that cannot see a stored\n * value sends back a blank one, and blank means \"clear it\".\n */\n idProofUrl: z.string().nullable(),\n joinedAt: isoDateTimeSchema,\n lastVisitAt: isoDateTimeSchema.nullable(),\n assignedWorkoutPlanId: objectIdSchema.nullable(),\n assignedTrainerId: objectIdSchema.nullable(),\n /**\n * The member's current membership, in FULL rather than by id.\n *\n * The profile screen shows the plan name, its billing cycle, the lifecycle\n * status pill and the expiry date all at once, and every one of those lives\n * here. Sending only the id forced the owner console to re-query the roster\n * for the same member just to read the plan columns back, and to match the\n * plan by NAME to find its perk icons — both of which this removes.\n */\n membership: membershipSchema.nullable(),\n /**\n * Still owed on the current term: its price less what has been recorded as\n * collected. Zero when settled, when the membership was cancelled, or when\n * there is no membership at all. Same definition as the roster's column, so\n * the profile and the list can never disagree about who owes money.\n */\n balanceDueInr: z.number().int().nonnegative(),\n});\nexport type MemberDetail = z.infer<typeof memberDetailSchema>;\n\n// ─── Add member (provisioning) ───────────────────────────────────────────────\n\nexport const createMemberBodySchema = z.object({\n firstName: z.string().trim().min(1, 'First name is required').max(80),\n lastName: optionalTrimmedString(80),\n email: z.email('A valid email is required'),\n phone: phoneSchema,\n gender: genderSchema,\n dob: isoDateSchema.optional(),\n bloodGroup: bloodGroupSchema.optional(),\n address: addressSchema.optional(),\n emergencyContacts: z.array(emergencyContactSchema).max(MAX_EMERGENCY_CONTACTS).default([]),\n idProofUrl: optionalTrimmedString(2000),\n avatarUrl: optionalTrimmedString(2000),\n assignedTrainerId: objectIdSchema.optional(),\n /** Optionally assign a plan in the same step. */\n initialPlan: assignMembershipBodySchema.optional(),\n});\nexport type CreateMemberBody = z.infer<typeof createMemberBodySchema>;\n\n/**\n * Edit a member's record from the owner console.\n *\n * Every field is optional — the console sends what the form holds, and a field\n * left out is left alone.\n *\n * ## What the gym may and may not change\n * `firstName` / `lastName` / `email` / `phone` are the INVITE details, and the\n * server accepts them only while the record is unclaimed. Once the member has\n * linked their central-auth account, that account is the source of truth for\n * their identity and is shared with the other products — a gym must not be able\n * to rewrite someone's name or email out from under them. The server ignores\n * those four on a claimed record rather than failing the whole request, so an\n * owner correcting a blood group is never blocked by a name they cannot change.\n *\n * Nullable fields (`dob`, `bloodGroup`, `address`, `assignedTrainerId`) accept\n * `null` to CLEAR a value, which `undefined` cannot express.\n */\nexport const updateMemberBodySchema = createMemberBodySchema\n .omit({\n initialPlan: true,\n dob: true,\n bloodGroup: true,\n address: true,\n assignedTrainerId: true,\n })\n .partial()\n .extend({\n dob: isoDateSchema.nullish(),\n bloodGroup: bloodGroupSchema.nullish(),\n address: addressSchema.nullish(),\n assignedTrainerId: objectIdSchema.nullish(),\n /** Last four digits only — the full number is never stored. */\n aadhaarLast4: z\n .string()\n .trim()\n .regex(/^\\d{4}$/, 'Enter the last four digits of the Aadhaar number')\n .nullish(),\n });\nexport type UpdateMemberBody = z.infer<typeof updateMemberBodySchema>;\n\n// ─── Invite & claim ──────────────────────────────────────────────────────────\n\n/**\n * The invite a gym hands to a new member.\n *\n * GymMonk never mints credentials for anyone: central auth is the SSOT for\n * identity, and an account there is shared across products. So adding a member\n * creates a gym record only, plus an unguessable invite code. The member\n * registers/logs in themselves through central auth (exactly as in jansathi) and\n * then CLAIMS the record. The owner shares `url` over WhatsApp or shows the QR.\n */\nexport const memberInviteSchema = z.object({\n /** Single-use, unguessable. Regenerating an invite invalidates the old one. */\n code: z.string(),\n /** Absolute claim URL the owner shares (also encoded into the QR). */\n url: z.string(),\n /** The address the member MUST register with for the claim to succeed. */\n email: z.string(),\n /** WhatsApp number to share on, when the gym recorded one. */\n phone: z.string().nullable(),\n expiresAt: isoDateTimeSchema,\n});\nexport type MemberInvite = z.infer<typeof memberInviteSchema>;\n\n/** Result of adding a member: the gym record + the invite to hand over. */\nexport const provisionResultSchema = z.object({\n /** The new member record (NOT a central-auth user — none is created). */\n enrolmentId: objectIdSchema,\n code: z.string(),\n invite: memberInviteSchema,\n /**\n * The membership created from `initialPlan`, or `null`.\n *\n * Null means one of two DIFFERENT things, and the caller can tell them apart\n * because it knows whether it sent `initialPlan`: no plan was chosen, or the\n * chosen plan could not be assigned. Adding a member never fails over the\n * second case — the person is on the roster either way — so this is how the\n * owner finds out the plan still needs assigning rather than assuming it took.\n */\n membership: membershipSchema.nullable(),\n});\nexport type ProvisionResult = z.infer<typeof provisionResultSchema>;\n\n/**\n * What the claim screen shows BEFORE the member authenticates, so they know\n * which address to register with. Public (the code is the bearer secret), and\n * deliberately minimal — gym name, member code, and the expected email.\n */\nexport const invitePreviewSchema = z.object({\n gymName: z.string(),\n gymMemberCode: gymMemberCodeSchema,\n /** Shown verbatim: the member must know exactly which address to use. */\n email: z.string(),\n expiresAt: isoDateTimeSchema,\n /** True once claimed / expired, so the screen can explain why it failed. */\n claimed: z.boolean(),\n expired: z.boolean(),\n});\nexport type InvitePreview = z.infer<typeof invitePreviewSchema>;\n\n/**\n * Claim an invite as the authenticated caller. The server links the record only\n * when the code is valid AND the caller's central-auth email matches the address\n * the invite was issued to.\n */\nexport const claimInviteBodySchema = z.object({\n code: z.string().trim().min(1),\n});\nexport type ClaimInviteBody = z.infer<typeof claimInviteBodySchema>;\n\n// ─── Mutations ───────────────────────────────────────────────────────────────\n\nexport const setMemberStatusBodySchema = z.object({ active: z.boolean() });\nexport type SetMemberStatusBody = z.infer<typeof setMemberStatusBodySchema>;\n\nexport const assignTrainerBodySchema = z.object({\n trainerId: objectIdSchema.nullable(),\n});\nexport type AssignTrainerBody = z.infer<typeof assignTrainerBodySchema>;\n\nexport const assignWorkoutPlanBodySchema = z.object({\n planId: objectIdSchema.nullable(),\n});\nexport type AssignWorkoutPlanBody = z.infer<typeof assignWorkoutPlanBodySchema>;\n\n/** Remove a member from the gym — echoes the member code to confirm. */\nexport const deleteMemberBodySchema = z.object({\n confirmationCode: z.string().trim().min(1),\n});\nexport type DeleteMemberBody = z.infer<typeof deleteMemberBodySchema>;\n"]}
|