gymmonk-schema 0.9.0 → 0.12.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 (41) hide show
  1. package/dist/center.d.ts +49 -6
  2. package/dist/center.d.ts.map +1 -1
  3. package/dist/center.js +59 -6
  4. package/dist/center.js.map +1 -1
  5. package/dist/gym-registration.d.ts +187 -0
  6. package/dist/gym-registration.d.ts.map +1 -0
  7. package/dist/gym-registration.js +37 -0
  8. package/dist/gym-registration.js.map +1 -0
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +2 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/member-profile.d.ts +1 -1
  14. package/dist/member-profile.d.ts.map +1 -1
  15. package/dist/member-profile.js +10 -1
  16. package/dist/member-profile.js.map +1 -1
  17. package/dist/member.d.ts +8 -0
  18. package/dist/member.d.ts.map +1 -1
  19. package/dist/member.js +35 -0
  20. package/dist/member.js.map +1 -1
  21. package/dist/membership-plan.d.ts +28 -0
  22. package/dist/membership-plan.d.ts.map +1 -1
  23. package/dist/membership-plan.js +32 -1
  24. package/dist/membership-plan.js.map +1 -1
  25. package/dist/messages.d.ts +31 -2
  26. package/dist/messages.d.ts.map +1 -1
  27. package/dist/messages.js +33 -2
  28. package/dist/messages.js.map +1 -1
  29. package/dist/onboarding-form.d.ts +23 -151
  30. package/dist/onboarding-form.d.ts.map +1 -1
  31. package/dist/onboarding-form.js +28 -99
  32. package/dist/onboarding-form.js.map +1 -1
  33. package/dist/onboarding.d.ts +26 -319
  34. package/dist/onboarding.d.ts.map +1 -1
  35. package/dist/onboarding.js +30 -63
  36. package/dist/onboarding.js.map +1 -1
  37. package/dist/organisation.d.ts +134 -0
  38. package/dist/organisation.d.ts.map +1 -1
  39. package/dist/organisation.js +57 -1
  40. package/dist/organisation.js.map +1 -1
  41. package/package.json +1 -1
package/dist/center.d.ts CHANGED
@@ -343,21 +343,64 @@ export declare const centerSchema: z.ZodObject<{
343
343
  updatedAt: z.ZodISODateTime;
344
344
  }, z.core.$strip>;
345
345
  export type Center = z.infer<typeof centerSchema>;
346
- /** A lightweight public directory result for the "find your gym" step. */
346
+ /** A lightweight public directory result for the "find a gym" screen. */
347
347
  export declare const nearbyGymSchema: z.ZodObject<{
348
348
  id: z.ZodString;
349
349
  code: z.ZodString;
350
350
  name: z.ZodString;
351
351
  area: z.ZodString;
352
- distanceKm: z.ZodNumber;
352
+ district: z.ZodNullable<z.ZodString>;
353
+ state: z.ZodNullable<z.ZodString>;
354
+ distanceKm: z.ZodNullable<z.ZodNumber>;
353
355
  memberCount: z.ZodOptional<z.ZodNumber>;
354
356
  }, z.core.$strip>;
355
357
  export type NearbyGym = z.infer<typeof nearbyGymSchema>;
356
- /** Query params for the nearby-gyms search. */
357
- export declare const nearbyGymsQuerySchema: z.ZodObject<{
358
+ /**
359
+ * The gym directory has THREE ways in, and they differ in how far they reach.
360
+ *
361
+ * `code` exact public gym id — matches anywhere in the country, because
362
+ * a member holding the id already knows which gym they mean and
363
+ * may well be joining one in another state.
364
+ * `q` name search — deliberately narrowed to ONE STATE. Gym names
365
+ * repeat heavily ("Fitness First"), so a nationwide name search
366
+ * returns a list nobody can pick from.
367
+ * `districtId` browse — the gyms around them, nearest first when they share
368
+ * their position.
369
+ *
370
+ * `stateId` / `districtId` are master-area ids (`area.ts`), matched against the
371
+ * address `ancestry` array every center stores.
372
+ */
373
+ export declare const GYM_SEARCH_MAX_RESULTS = 20;
374
+ export declare const gymSearchQuerySchema: z.ZodObject<{
375
+ code: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
376
+ q: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
377
+ stateId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
378
+ districtId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
358
379
  lat: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
359
380
  lng: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
360
- q: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
381
+ limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
382
+ }, z.core.$strip>;
383
+ export type GymSearchQuery = z.infer<typeof gymSearchQuerySchema>;
384
+ /**
385
+ * The directory response.
386
+ *
387
+ * `truncated` says the district holds more gyms than were returned, which is
388
+ * what the screen turns into "showing the 20 nearest — enter a gym id if yours
389
+ * is not here" rather than letting the member assume their gym is absent.
390
+ */
391
+ export declare const gymSearchResultSchema: z.ZodObject<{
392
+ items: z.ZodArray<z.ZodObject<{
393
+ id: z.ZodString;
394
+ code: z.ZodString;
395
+ name: z.ZodString;
396
+ area: z.ZodString;
397
+ district: z.ZodNullable<z.ZodString>;
398
+ state: z.ZodNullable<z.ZodString>;
399
+ distanceKm: z.ZodNullable<z.ZodNumber>;
400
+ memberCount: z.ZodOptional<z.ZodNumber>;
401
+ }, z.core.$strip>>;
402
+ total: z.ZodNumber;
403
+ truncated: z.ZodBoolean;
361
404
  }, z.core.$strip>;
362
- export type NearbyGymsQuery = z.infer<typeof nearbyGymsQuerySchema>;
405
+ export type GymSearchResult = z.infer<typeof gymSearchResultSchema>;
363
406
  //# sourceMappingURL=center.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"center.d.ts","sourceRoot":"","sources":["../src/center.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,yDAAyD;AACzD,eAAO,MAAM,YAAY,8IAaf,CAAC;AACX,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;EAAuB,CAAC;AACrD,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAI1D,eAAO,MAAM,kBAAkB;;;EAAiC,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;;GAGG;AACH,eAAO,MAAM,aAAa,aAGwB,CAAC;AACnD,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAIpD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAcjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAmC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAItE,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAqBvB,CAAC;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAIlD,0EAA0E;AAC1E,eAAO,MAAM,eAAe;;;;;;;iBAO1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,+CAA+C;AAC/C,eAAO,MAAM,qBAAqB;;;;iBAIhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
1
+ {"version":3,"file":"center.d.ts","sourceRoot":"","sources":["../src/center.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,yDAAyD;AACzD,eAAO,MAAM,YAAY,8IAaf,CAAC;AACX,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;EAAuB,CAAC;AACrD,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAI1D,eAAO,MAAM,kBAAkB;;;EAAiC,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;;GAGG;AACH,eAAO,MAAM,aAAa,aAGwB,CAAC;AACnD,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAIpD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAcjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAmC,CAAC;AACvE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAItE,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAqBvB,CAAC;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAIlD,yEAAyE;AACzE,eAAO,MAAM,eAAe;;;;;;;;;iBAkB1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,eAAO,MAAM,oBAAoB;;;;;;;;iBAmB7B,CAAC;AACL,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;iBAIhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
package/dist/center.js CHANGED
@@ -77,20 +77,73 @@ export const centerSchema = z.object({
77
77
  createdAt: isoDateTimeSchema,
78
78
  updatedAt: isoDateTimeSchema,
79
79
  });
80
- // ─── Nearby / directory card ─────────────────────────────────────────────────
81
- /** A lightweight public directory result for the "find your gym" step. */
80
+ // ─── Gym directory (member "find a gym") ─────────────────────────────────────
81
+ /** A lightweight public directory result for the "find a gym" screen. */
82
82
  export const nearbyGymSchema = z.object({
83
83
  id: objectIdSchema,
84
84
  code: gymCodeSchema,
85
85
  name: z.string(),
86
+ /** The narrowest place name we hold (locality → district → state). */
86
87
  area: z.string(),
87
- distanceKm: z.number().nonnegative(),
88
+ district: z.string().nullable(),
89
+ state: z.string().nullable(),
90
+ /**
91
+ * Kilometres from the coordinates the caller supplied.
92
+ *
93
+ * NULL, not 0, when it cannot be computed — the caller sent no position, or
94
+ * the gym's address carries no coordinates. Zero is a real distance ("you are
95
+ * standing in it") and using it as the unknown value put every un-geocoded
96
+ * gym at the top of a nearest-first list.
97
+ */
98
+ distanceKm: z.number().nonnegative().nullable(),
88
99
  memberCount: z.number().int().nonnegative().optional(),
89
100
  });
90
- /** Query params for the nearby-gyms search. */
91
- export const nearbyGymsQuerySchema = z.object({
101
+ /**
102
+ * The gym directory has THREE ways in, and they differ in how far they reach.
103
+ *
104
+ * `code` exact public gym id — matches anywhere in the country, because
105
+ * a member holding the id already knows which gym they mean and
106
+ * may well be joining one in another state.
107
+ * `q` name search — deliberately narrowed to ONE STATE. Gym names
108
+ * repeat heavily ("Fitness First"), so a nationwide name search
109
+ * returns a list nobody can pick from.
110
+ * `districtId` browse — the gyms around them, nearest first when they share
111
+ * their position.
112
+ *
113
+ * `stateId` / `districtId` are master-area ids (`area.ts`), matched against the
114
+ * address `ancestry` array every center stores.
115
+ */
116
+ export const GYM_SEARCH_MAX_RESULTS = 20;
117
+ export const gymSearchQuerySchema = z
118
+ .object({
119
+ /** Exact public gym id, e.g. `GYM-2025-001`. Unscoped by geography. */
120
+ code: optionalTrimmedString(40),
121
+ /** Name fragment. Requires `stateId`. */
122
+ q: optionalTrimmedString(120),
123
+ stateId: optionalTrimmedString(40),
124
+ districtId: optionalTrimmedString(40),
92
125
  lat: z.coerce.number().min(-90).max(90).optional(),
93
126
  lng: z.coerce.number().min(-180).max(180).optional(),
94
- q: optionalTrimmedString(120),
127
+ limit: z.coerce.number().int().min(1).max(GYM_SEARCH_MAX_RESULTS).default(GYM_SEARCH_MAX_RESULTS),
128
+ })
129
+ .refine((v) => !v.q || Boolean(v.stateId), {
130
+ message: 'Pick a state to search gyms by name',
131
+ path: ['stateId'],
132
+ })
133
+ .refine((v) => Boolean(v.code || v.q || v.stateId || v.districtId), {
134
+ message: 'Enter a gym id, or pick where to look',
135
+ path: ['stateId'],
136
+ });
137
+ /**
138
+ * The directory response.
139
+ *
140
+ * `truncated` says the district holds more gyms than were returned, which is
141
+ * what the screen turns into "showing the 20 nearest — enter a gym id if yours
142
+ * is not here" rather than letting the member assume their gym is absent.
143
+ */
144
+ export const gymSearchResultSchema = z.object({
145
+ items: z.array(nearbyGymSchema),
146
+ total: z.number().int().nonnegative(),
147
+ truncated: z.boolean(),
95
148
  });
96
149
  //# sourceMappingURL=center.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"center.js","sourceRoot":"","sources":["../src/center.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gymmonk-schema — Center (branch)\n * ================================\n * A physical gym location belonging to an organisation. Carries the public gym\n * code members use to join, opening hours, equipment scope, and contact info.\n * v1 memberships are single-center, so a Center is the unit a member joins.\n *\n * @module gymmonk-schema/center\n */\n\nimport { z } from 'zod';\nimport {\n isoDateTimeSchema,\n objectIdSchema,\n optionalEmailSchema,\n optionalPhoneSchema,\n optionalTrimmedString,\n phoneSchema,\n} from './common.js';\nimport { addressSchema, weeklyHoursSchema } from './shared.js';\n\n// ─── Center type ─────────────────────────────────────────────────────────────\n\n/** The activity types a center offers (multi-select). */\nexport const CENTER_TYPES = [\n 'gym',\n 'crossfit',\n 'yoga',\n 'pilates',\n 'zumba',\n 'cardio',\n 'strength',\n 'mma',\n 'boxing',\n 'swimming',\n 'aerobics',\n 'personal-training',\n] as const;\nexport const centerTypeSchema = z.enum(CENTER_TYPES);\nexport type CenterType = z.infer<typeof centerTypeSchema>;\n\n// ─── Status ──────────────────────────────────────────────────────────────────\n\nexport const centerStatusSchema = z.enum(['active', 'inactive']);\nexport type CenterStatus = z.infer<typeof centerStatusSchema>;\n\n/**\n * The public gym code a member enters at onboarding to join, `GYM-YYYY-NNN`.\n * Server-generated and unique; never accepted in a create body.\n */\nexport const gymCodeSchema = z\n .string()\n .trim()\n .regex(/^GYM-\\d{4}-\\d{3,}$/, 'Invalid gym code');\nexport type GymCode = z.infer<typeof gymCodeSchema>;\n\n// ─── Create / update bodies ──────────────────────────────────────────────────\n\nexport const createCenterBodySchema = z.object({\n name: z.string().trim().min(1, 'Center name is required').max(160),\n description: optionalTrimmedString(2000),\n types: z.array(centerTypeSchema).min(1, 'Pick at least one type'),\n address: addressSchema,\n /** Usable floor area in square feet. */\n floorAreaSqft: z.number().int().min(0).max(1_000_000).optional(),\n primaryPhone: phoneSchema,\n secondaryPhone: optionalPhoneSchema,\n email: optionalEmailSchema,\n website: optionalTrimmedString(200),\n hours: weeklyHoursSchema,\n /** Uploaded gallery image URLs. */\n photos: z.array(z.string().trim().max(2000)).max(20).default([]),\n});\nexport type CreateCenterBody = z.infer<typeof createCenterBodySchema>;\n\nexport const updateCenterBodySchema = createCenterBodySchema.partial();\nexport type UpdateCenterBody = z.infer<typeof updateCenterBodySchema>;\n\n// ─── Entity (API response) ───────────────────────────────────────────────────\n\nexport const centerSchema = z.object({\n id: objectIdSchema,\n organisationId: objectIdSchema,\n /** Public join code, `GYM-YYYY-NNN`. */\n code: gymCodeSchema,\n name: z.string(),\n description: z.string().nullable(),\n types: z.array(centerTypeSchema),\n address: addressSchema,\n floorAreaSqft: z.number().int().nullable(),\n primaryPhone: z.string(),\n secondaryPhone: z.string().nullable(),\n email: z.string().nullable(),\n website: z.string().nullable(),\n hours: weeklyHoursSchema,\n photos: z.array(z.string()),\n status: centerStatusSchema,\n /** Denormalised active-member count for roster headers. */\n memberCount: z.number().int().nonnegative(),\n createdAt: isoDateTimeSchema,\n updatedAt: isoDateTimeSchema,\n});\nexport type Center = z.infer<typeof centerSchema>;\n\n// ─── Nearby / directory card ─────────────────────────────────────────────────\n\n/** A lightweight public directory result for the \"find your gym\" step. */\nexport const nearbyGymSchema = z.object({\n id: objectIdSchema,\n code: gymCodeSchema,\n name: z.string(),\n area: z.string(),\n distanceKm: z.number().nonnegative(),\n memberCount: z.number().int().nonnegative().optional(),\n});\nexport type NearbyGym = z.infer<typeof nearbyGymSchema>;\n\n/** Query params for the nearby-gyms search. */\nexport const nearbyGymsQuerySchema = z.object({\n lat: z.coerce.number().min(-90).max(90).optional(),\n lng: z.coerce.number().min(-180).max(180).optional(),\n q: optionalTrimmedString(120),\n});\nexport type NearbyGymsQuery = z.infer<typeof nearbyGymsQuerySchema>;\n"]}
1
+ {"version":3,"file":"center.js","sourceRoot":"","sources":["../src/center.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gymmonk-schema — Center (branch)\n * ================================\n * A physical gym location belonging to an organisation. Carries the public gym\n * code members use to join, opening hours, equipment scope, and contact info.\n * v1 memberships are single-center, so a Center is the unit a member joins.\n *\n * @module gymmonk-schema/center\n */\n\nimport { z } from 'zod';\nimport {\n isoDateTimeSchema,\n objectIdSchema,\n optionalEmailSchema,\n optionalPhoneSchema,\n optionalTrimmedString,\n phoneSchema,\n} from './common.js';\nimport { addressSchema, weeklyHoursSchema } from './shared.js';\n\n// ─── Center type ─────────────────────────────────────────────────────────────\n\n/** The activity types a center offers (multi-select). */\nexport const CENTER_TYPES = [\n 'gym',\n 'crossfit',\n 'yoga',\n 'pilates',\n 'zumba',\n 'cardio',\n 'strength',\n 'mma',\n 'boxing',\n 'swimming',\n 'aerobics',\n 'personal-training',\n] as const;\nexport const centerTypeSchema = z.enum(CENTER_TYPES);\nexport type CenterType = z.infer<typeof centerTypeSchema>;\n\n// ─── Status ──────────────────────────────────────────────────────────────────\n\nexport const centerStatusSchema = z.enum(['active', 'inactive']);\nexport type CenterStatus = z.infer<typeof centerStatusSchema>;\n\n/**\n * The public gym code a member enters at onboarding to join, `GYM-YYYY-NNN`.\n * Server-generated and unique; never accepted in a create body.\n */\nexport const gymCodeSchema = z\n .string()\n .trim()\n .regex(/^GYM-\\d{4}-\\d{3,}$/, 'Invalid gym code');\nexport type GymCode = z.infer<typeof gymCodeSchema>;\n\n// ─── Create / update bodies ──────────────────────────────────────────────────\n\nexport const createCenterBodySchema = z.object({\n name: z.string().trim().min(1, 'Center name is required').max(160),\n description: optionalTrimmedString(2000),\n types: z.array(centerTypeSchema).min(1, 'Pick at least one type'),\n address: addressSchema,\n /** Usable floor area in square feet. */\n floorAreaSqft: z.number().int().min(0).max(1_000_000).optional(),\n primaryPhone: phoneSchema,\n secondaryPhone: optionalPhoneSchema,\n email: optionalEmailSchema,\n website: optionalTrimmedString(200),\n hours: weeklyHoursSchema,\n /** Uploaded gallery image URLs. */\n photos: z.array(z.string().trim().max(2000)).max(20).default([]),\n});\nexport type CreateCenterBody = z.infer<typeof createCenterBodySchema>;\n\nexport const updateCenterBodySchema = createCenterBodySchema.partial();\nexport type UpdateCenterBody = z.infer<typeof updateCenterBodySchema>;\n\n// ─── Entity (API response) ───────────────────────────────────────────────────\n\nexport const centerSchema = z.object({\n id: objectIdSchema,\n organisationId: objectIdSchema,\n /** Public join code, `GYM-YYYY-NNN`. */\n code: gymCodeSchema,\n name: z.string(),\n description: z.string().nullable(),\n types: z.array(centerTypeSchema),\n address: addressSchema,\n floorAreaSqft: z.number().int().nullable(),\n primaryPhone: z.string(),\n secondaryPhone: z.string().nullable(),\n email: z.string().nullable(),\n website: z.string().nullable(),\n hours: weeklyHoursSchema,\n photos: z.array(z.string()),\n status: centerStatusSchema,\n /** Denormalised active-member count for roster headers. */\n memberCount: z.number().int().nonnegative(),\n createdAt: isoDateTimeSchema,\n updatedAt: isoDateTimeSchema,\n});\nexport type Center = z.infer<typeof centerSchema>;\n\n// ─── Gym directory (member \"find a gym\") ─────────────────────────────────────\n\n/** A lightweight public directory result for the \"find a gym\" screen. */\nexport const nearbyGymSchema = z.object({\n id: objectIdSchema,\n code: gymCodeSchema,\n name: z.string(),\n /** The narrowest place name we hold (locality → district → state). */\n area: z.string(),\n district: z.string().nullable(),\n state: z.string().nullable(),\n /**\n * Kilometres from the coordinates the caller supplied.\n *\n * NULL, not 0, when it cannot be computed — the caller sent no position, or\n * the gym's address carries no coordinates. Zero is a real distance (\"you are\n * standing in it\") and using it as the unknown value put every un-geocoded\n * gym at the top of a nearest-first list.\n */\n distanceKm: z.number().nonnegative().nullable(),\n memberCount: z.number().int().nonnegative().optional(),\n});\nexport type NearbyGym = z.infer<typeof nearbyGymSchema>;\n\n/**\n * The gym directory has THREE ways in, and they differ in how far they reach.\n *\n * `code` exact public gym id — matches anywhere in the country, because\n * a member holding the id already knows which gym they mean and\n * may well be joining one in another state.\n * `q` name search — deliberately narrowed to ONE STATE. Gym names\n * repeat heavily (\"Fitness First\"), so a nationwide name search\n * returns a list nobody can pick from.\n * `districtId` browse — the gyms around them, nearest first when they share\n * their position.\n *\n * `stateId` / `districtId` are master-area ids (`area.ts`), matched against the\n * address `ancestry` array every center stores.\n */\nexport const GYM_SEARCH_MAX_RESULTS = 20;\n\nexport const gymSearchQuerySchema = z\n .object({\n /** Exact public gym id, e.g. `GYM-2025-001`. Unscoped by geography. */\n code: optionalTrimmedString(40),\n /** Name fragment. Requires `stateId`. */\n q: optionalTrimmedString(120),\n stateId: optionalTrimmedString(40),\n districtId: optionalTrimmedString(40),\n lat: z.coerce.number().min(-90).max(90).optional(),\n lng: z.coerce.number().min(-180).max(180).optional(),\n limit: z.coerce.number().int().min(1).max(GYM_SEARCH_MAX_RESULTS).default(GYM_SEARCH_MAX_RESULTS),\n })\n .refine((v) => !v.q || Boolean(v.stateId), {\n message: 'Pick a state to search gyms by name',\n path: ['stateId'],\n })\n .refine((v) => Boolean(v.code || v.q || v.stateId || v.districtId), {\n message: 'Enter a gym id, or pick where to look',\n path: ['stateId'],\n });\nexport type GymSearchQuery = z.infer<typeof gymSearchQuerySchema>;\n\n/**\n * The directory response.\n *\n * `truncated` says the district holds more gyms than were returned, which is\n * what the screen turns into \"showing the 20 nearest — enter a gym id if yours\n * is not here\" rather than letting the member assume their gym is absent.\n */\nexport const gymSearchResultSchema = z.object({\n items: z.array(nearbyGymSchema),\n total: z.number().int().nonnegative(),\n truncated: z.boolean(),\n});\nexport type GymSearchResult = z.infer<typeof gymSearchResultSchema>;\n"]}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * gymmonk-schema — Gym registration
3
+ * =================================
4
+ * "List your gym on GymMonk" — the payload a signed-in MEMBER submits to create
5
+ * the business they run.
6
+ *
7
+ * This used to be owner onboarding, a fork taken before the user had seen
8
+ * anything. It is now an ordinary action taken from the Me tab by somebody who
9
+ * already has an account, and that changes what it has to ask for:
10
+ *
11
+ * - NO personal details. Name, gender, date of birth, phone and photo were
12
+ * all captured at onboarding. Asking again would be asking the same person
13
+ * the same questions twice and then having two answers to keep in step.
14
+ * - NO automatic membership of their own gym. Owning a gym and training at
15
+ * one are separate things — an owner keeps the single member identity they
16
+ * registered with, and is free to be a paying member of somebody else's gym.
17
+ *
18
+ * The submitted organisation starts `pending` and is invisible in the member
19
+ * gym directory until a superadmin or platform manager approves it
20
+ * (`organisationApprovalStatusSchema`).
21
+ *
22
+ * @module gymmonk-schema/gym-registration
23
+ */
24
+ import { z } from 'zod';
25
+ /** The SaaS plan the owner selects at the final registration step. */
26
+ export declare const gymPlanSelectionSchema: z.ZodObject<{
27
+ planId: z.ZodString;
28
+ tenureId: z.ZodNullable<z.ZodString>;
29
+ }, z.core.$strip>;
30
+ export type GymPlanSelection = z.infer<typeof gymPlanSelectionSchema>;
31
+ export declare const gymRegistrationBodySchema: z.ZodObject<{
32
+ organisation: z.ZodObject<{
33
+ name: z.ZodString;
34
+ description: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
35
+ address: z.ZodObject<{
36
+ country: z.ZodObject<{
37
+ id: z.ZodString;
38
+ name: z.ZodString;
39
+ }, z.core.$strip>;
40
+ state: z.ZodObject<{
41
+ id: z.ZodString;
42
+ name: z.ZodString;
43
+ }, z.core.$strip>;
44
+ district: z.ZodOptional<z.ZodObject<{
45
+ id: z.ZodString;
46
+ name: z.ZodString;
47
+ }, z.core.$strip>>;
48
+ locality: z.ZodOptional<z.ZodObject<{
49
+ id: z.ZodString;
50
+ name: z.ZodString;
51
+ type: z.ZodEnum<{
52
+ SUB_DISTRICT: "SUB_DISTRICT";
53
+ BLOCK: "BLOCK";
54
+ GRAM_PANCHAYAT: "GRAM_PANCHAYAT";
55
+ VILLAGE: "VILLAGE";
56
+ HAMLET: "HAMLET";
57
+ URBAN_BODY: "URBAN_BODY";
58
+ URBAN_WARD: "URBAN_WARD";
59
+ LOCALITY: "LOCALITY";
60
+ }>;
61
+ }, z.core.$strip>>;
62
+ line1: z.ZodString;
63
+ landmark: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
64
+ pincode: z.ZodString;
65
+ ancestry: z.ZodDefault<z.ZodArray<z.ZodString>>;
66
+ coords: z.ZodOptional<z.ZodObject<{
67
+ lat: z.ZodNumber;
68
+ lng: z.ZodNumber;
69
+ source: z.ZodString;
70
+ }, z.core.$strip>>;
71
+ }, z.core.$strip>;
72
+ gstNumber: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
73
+ registrationNumber: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
74
+ website: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
75
+ socials: z.ZodObject<{
76
+ jansathi: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
77
+ youtube: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
78
+ instagram: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
79
+ facebook: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
80
+ }, z.core.$strip>;
81
+ numberOfCenters: z.ZodNumber;
82
+ }, z.core.$strip>;
83
+ center: z.ZodObject<{
84
+ name: z.ZodString;
85
+ description: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
86
+ types: z.ZodArray<z.ZodEnum<{
87
+ cardio: "cardio";
88
+ strength: "strength";
89
+ yoga: "yoga";
90
+ crossfit: "crossfit";
91
+ gym: "gym";
92
+ pilates: "pilates";
93
+ zumba: "zumba";
94
+ mma: "mma";
95
+ boxing: "boxing";
96
+ swimming: "swimming";
97
+ aerobics: "aerobics";
98
+ "personal-training": "personal-training";
99
+ }>>;
100
+ address: z.ZodObject<{
101
+ country: z.ZodObject<{
102
+ id: z.ZodString;
103
+ name: z.ZodString;
104
+ }, z.core.$strip>;
105
+ state: z.ZodObject<{
106
+ id: z.ZodString;
107
+ name: z.ZodString;
108
+ }, z.core.$strip>;
109
+ district: z.ZodOptional<z.ZodObject<{
110
+ id: z.ZodString;
111
+ name: z.ZodString;
112
+ }, z.core.$strip>>;
113
+ locality: z.ZodOptional<z.ZodObject<{
114
+ id: z.ZodString;
115
+ name: z.ZodString;
116
+ type: z.ZodEnum<{
117
+ SUB_DISTRICT: "SUB_DISTRICT";
118
+ BLOCK: "BLOCK";
119
+ GRAM_PANCHAYAT: "GRAM_PANCHAYAT";
120
+ VILLAGE: "VILLAGE";
121
+ HAMLET: "HAMLET";
122
+ URBAN_BODY: "URBAN_BODY";
123
+ URBAN_WARD: "URBAN_WARD";
124
+ LOCALITY: "LOCALITY";
125
+ }>;
126
+ }, z.core.$strip>>;
127
+ line1: z.ZodString;
128
+ landmark: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
129
+ pincode: z.ZodString;
130
+ ancestry: z.ZodDefault<z.ZodArray<z.ZodString>>;
131
+ coords: z.ZodOptional<z.ZodObject<{
132
+ lat: z.ZodNumber;
133
+ lng: z.ZodNumber;
134
+ source: z.ZodString;
135
+ }, z.core.$strip>>;
136
+ }, z.core.$strip>;
137
+ floorAreaSqft: z.ZodOptional<z.ZodNumber>;
138
+ primaryPhone: z.ZodString;
139
+ secondaryPhone: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
140
+ email: z.ZodPreprocess<z.ZodOptional<z.ZodEmail>>;
141
+ website: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
142
+ hours: z.ZodObject<{
143
+ mon: z.ZodObject<{
144
+ open: z.ZodBoolean;
145
+ from: z.ZodString;
146
+ to: z.ZodString;
147
+ }, z.core.$strip>;
148
+ tue: z.ZodObject<{
149
+ open: z.ZodBoolean;
150
+ from: z.ZodString;
151
+ to: z.ZodString;
152
+ }, z.core.$strip>;
153
+ wed: z.ZodObject<{
154
+ open: z.ZodBoolean;
155
+ from: z.ZodString;
156
+ to: z.ZodString;
157
+ }, z.core.$strip>;
158
+ thu: z.ZodObject<{
159
+ open: z.ZodBoolean;
160
+ from: z.ZodString;
161
+ to: z.ZodString;
162
+ }, z.core.$strip>;
163
+ fri: z.ZodObject<{
164
+ open: z.ZodBoolean;
165
+ from: z.ZodString;
166
+ to: z.ZodString;
167
+ }, z.core.$strip>;
168
+ sat: z.ZodObject<{
169
+ open: z.ZodBoolean;
170
+ from: z.ZodString;
171
+ to: z.ZodString;
172
+ }, z.core.$strip>;
173
+ sun: z.ZodObject<{
174
+ open: z.ZodBoolean;
175
+ from: z.ZodString;
176
+ to: z.ZodString;
177
+ }, z.core.$strip>;
178
+ }, z.core.$strip>;
179
+ photos: z.ZodDefault<z.ZodArray<z.ZodString>>;
180
+ }, z.core.$strip>;
181
+ subscription: z.ZodObject<{
182
+ planId: z.ZodString;
183
+ tenureId: z.ZodNullable<z.ZodString>;
184
+ }, z.core.$strip>;
185
+ }, z.core.$strip>;
186
+ export type GymRegistrationBody = z.infer<typeof gymRegistrationBodySchema>;
187
+ //# sourceMappingURL=gym-registration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gym-registration.d.ts","sourceRoot":"","sources":["../src/gym-registration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,sEAAsE;AACtE,eAAO,MAAM,sBAAsB;;;iBAGjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAIpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * gymmonk-schema — Gym registration
3
+ * =================================
4
+ * "List your gym on GymMonk" — the payload a signed-in MEMBER submits to create
5
+ * the business they run.
6
+ *
7
+ * This used to be owner onboarding, a fork taken before the user had seen
8
+ * anything. It is now an ordinary action taken from the Me tab by somebody who
9
+ * already has an account, and that changes what it has to ask for:
10
+ *
11
+ * - NO personal details. Name, gender, date of birth, phone and photo were
12
+ * all captured at onboarding. Asking again would be asking the same person
13
+ * the same questions twice and then having two answers to keep in step.
14
+ * - NO automatic membership of their own gym. Owning a gym and training at
15
+ * one are separate things — an owner keeps the single member identity they
16
+ * registered with, and is free to be a paying member of somebody else's gym.
17
+ *
18
+ * The submitted organisation starts `pending` and is invisible in the member
19
+ * gym directory until a superadmin or platform manager approves it
20
+ * (`organisationApprovalStatusSchema`).
21
+ *
22
+ * @module gymmonk-schema/gym-registration
23
+ */
24
+ import { z } from 'zod';
25
+ import { createCenterBodySchema } from './center.js';
26
+ import { createOrganisationBodySchema } from './organisation.js';
27
+ /** The SaaS plan the owner selects at the final registration step. */
28
+ export const gymPlanSelectionSchema = z.object({
29
+ planId: z.string().trim().min(1),
30
+ tenureId: z.string().trim().min(1).nullable(),
31
+ });
32
+ export const gymRegistrationBodySchema = z.object({
33
+ organisation: createOrganisationBodySchema,
34
+ center: createCenterBodySchema,
35
+ subscription: gymPlanSelectionSchema,
36
+ });
37
+ //# sourceMappingURL=gym-registration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gym-registration.js","sourceRoot":"","sources":["../src/gym-registration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AAEjE,sEAAsE;AACtE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC9C,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,YAAY,EAAE,4BAA4B;IAC1C,MAAM,EAAE,sBAAsB;IAC9B,YAAY,EAAE,sBAAsB;CACrC,CAAC,CAAC","sourcesContent":["/**\n * gymmonk-schema — Gym registration\n * =================================\n * \"List your gym on GymMonk\" — the payload a signed-in MEMBER submits to create\n * the business they run.\n *\n * This used to be owner onboarding, a fork taken before the user had seen\n * anything. It is now an ordinary action taken from the Me tab by somebody who\n * already has an account, and that changes what it has to ask for:\n *\n * - NO personal details. Name, gender, date of birth, phone and photo were\n * all captured at onboarding. Asking again would be asking the same person\n * the same questions twice and then having two answers to keep in step.\n * - NO automatic membership of their own gym. Owning a gym and training at\n * one are separate things — an owner keeps the single member identity they\n * registered with, and is free to be a paying member of somebody else's gym.\n *\n * The submitted organisation starts `pending` and is invisible in the member\n * gym directory until a superadmin or platform manager approves it\n * (`organisationApprovalStatusSchema`).\n *\n * @module gymmonk-schema/gym-registration\n */\n\nimport { z } from 'zod';\nimport { createCenterBodySchema } from './center.js';\nimport { createOrganisationBodySchema } from './organisation.js';\n\n/** The SaaS plan the owner selects at the final registration step. */\nexport const gymPlanSelectionSchema = z.object({\n planId: z.string().trim().min(1),\n tenureId: z.string().trim().min(1).nullable(),\n});\nexport type GymPlanSelection = z.infer<typeof gymPlanSelectionSchema>;\n\nexport const gymRegistrationBodySchema = z.object({\n organisation: createOrganisationBodySchema,\n center: createCenterBodySchema,\n subscription: gymPlanSelectionSchema,\n});\nexport type GymRegistrationBody = z.infer<typeof gymRegistrationBodySchema>;\n"]}
package/dist/index.d.ts CHANGED
@@ -18,6 +18,7 @@ export * from './equipment.js';
18
18
  export * from './exercise.js';
19
19
  export * from './feedback.js';
20
20
  export * from './file.js';
21
+ export * from './gym-registration.js';
21
22
  export * from './home.js';
22
23
  export * from './insights.js';
23
24
  export * from './member.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAElC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAE5B,cAAc,eAAe,CAAC;AAE9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAE/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAE9B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAE9B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAEhC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AAExC,cAAc,eAAe,CAAC;AAE9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAEhC,cAAc,sBAAsB,CAAC;AAErC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAElC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAE5B,cAAc,eAAe,CAAC;AAE9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAE/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAE9B,cAAc,WAAW,CAAC;AAE1B,cAAc,uBAAuB,CAAC;AACtC,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAE9B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAEhC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AAExC,cAAc,eAAe,CAAC;AAE9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAEhC,cAAc,sBAAsB,CAAC;AAErC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -24,6 +24,8 @@ export * from './exercise.js';
24
24
  export * from './feedback.js';
25
25
  // ─── Uploads ─────────────────────────────────────────────────────────────────
26
26
  export * from './file.js';
27
+ // ─── "List your gym" — a member registers the business they run ──────────────
28
+ export * from './gym-registration.js';
27
29
  export * from './home.js';
28
30
  export * from './insights.js';
29
31
  // ─── People ──────────────────────────────────────────────────────────────────
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,gFAAgF;AAChF,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,6EAA6E;AAC7E,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,gFAAgF;AAChF,cAAc,eAAe,CAAC;AAC9B,gFAAgF;AAChF,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,gFAAgF;AAChF,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,gFAAgF;AAChF,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,gFAAgF;AAChF,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,gFAAgF;AAChF,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,gFAAgF;AAChF,cAAc,eAAe,CAAC;AAC9B,gFAAgF;AAChF,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,gFAAgF;AAChF,cAAc,sBAAsB,CAAC;AACrC,gFAAgF;AAChF,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC","sourcesContent":["/**\n * gymmonk-schema — Public API\n * ===========================\n * Shared Zod schemas, enums and domain types for GymMonk (fitness SaaS).\n * Single source of truth (SSOT) for data shapes, TypeScript types and\n * validation, consumed by both gymmonk-backend and gymmonk-web-client.\n *\n * Every domain module is re-exported through this barrel. Import names are\n * globally unique across modules, so `export *` composes without collisions.\n */\n\n// ─── Owner desk-entry FORM validation (client-side working shapes) ───────────\nexport * from './add-person-form.js';\nexport * from './announcement.js';\n// ─── Location master data (the address picker's lookup API) ───────────────\nexport * from './area.js';\nexport * from './center.js';\n// ─── Check-in QR (poster payload shared by owner, member and backend) ────────\nexport * from './check-in.js';\n// ─── Foundation ──────────────────────────────────────────────────────────────\nexport * from './common.js';\nexport * from './equipment.js';\n// ─── Training ────────────────────────────────────────────────────────────────\nexport * from './exercise.js';\nexport * from './feedback.js';\n// ─── Uploads ─────────────────────────────────────────────────────────────────\nexport * from './file.js';\nexport * from './home.js';\nexport * from './insights.js';\n// ─── People ──────────────────────────────────────────────────────────────────\nexport * from './member.js';\nexport * from './member-profile.js';\nexport * from './membership.js';\n// ─── Membership ──────────────────────────────────────────────────────────────\nexport * from './membership-plan.js';\nexport * from './membership-request.js';\n// ─── API result messages + error codes ───────────────────────────────────────\nexport * from './messages.js';\n// ─── Engagement & analytics ──────────────────────────────────────────────────\nexport * from './notification.js';\nexport * from './onboarding.js';\n// ─── Onboarding wizard FORM validation (client-side working shapes) ──────────\nexport * from './onboarding-form.js';\n// ─── Gym structure & onboarding ──────────────────────────────────────────────\nexport * from './organisation.js';\nexport * from './owner-profile.js';\nexport * from './pricing.js';\nexport * from './session.js';\nexport * from './shared.js';\nexport * from './staff.js';\nexport * from './subscription.js';\nexport * from './user.js';\nexport * from './workout-plan.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,gFAAgF;AAChF,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,6EAA6E;AAC7E,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,gFAAgF;AAChF,cAAc,eAAe,CAAC;AAC9B,gFAAgF;AAChF,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,gFAAgF;AAChF,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,gFAAgF;AAChF,cAAc,WAAW,CAAC;AAC1B,gFAAgF;AAChF,cAAc,uBAAuB,CAAC;AACtC,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,gFAAgF;AAChF,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,gFAAgF;AAChF,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,gFAAgF;AAChF,cAAc,eAAe,CAAC;AAC9B,gFAAgF;AAChF,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,gFAAgF;AAChF,cAAc,sBAAsB,CAAC;AACrC,gFAAgF;AAChF,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC","sourcesContent":["/**\n * gymmonk-schema — Public API\n * ===========================\n * Shared Zod schemas, enums and domain types for GymMonk (fitness SaaS).\n * Single source of truth (SSOT) for data shapes, TypeScript types and\n * validation, consumed by both gymmonk-backend and gymmonk-web-client.\n *\n * Every domain module is re-exported through this barrel. Import names are\n * globally unique across modules, so `export *` composes without collisions.\n */\n\n// ─── Owner desk-entry FORM validation (client-side working shapes) ───────────\nexport * from './add-person-form.js';\nexport * from './announcement.js';\n// ─── Location master data (the address picker's lookup API) ───────────────\nexport * from './area.js';\nexport * from './center.js';\n// ─── Check-in QR (poster payload shared by owner, member and backend) ────────\nexport * from './check-in.js';\n// ─── Foundation ──────────────────────────────────────────────────────────────\nexport * from './common.js';\nexport * from './equipment.js';\n// ─── Training ────────────────────────────────────────────────────────────────\nexport * from './exercise.js';\nexport * from './feedback.js';\n// ─── Uploads ─────────────────────────────────────────────────────────────────\nexport * from './file.js';\n// ─── \"List your gym\" — a member registers the business they run ──────────────\nexport * from './gym-registration.js';\nexport * from './home.js';\nexport * from './insights.js';\n// ─── People ──────────────────────────────────────────────────────────────────\nexport * from './member.js';\nexport * from './member-profile.js';\nexport * from './membership.js';\n// ─── Membership ──────────────────────────────────────────────────────────────\nexport * from './membership-plan.js';\nexport * from './membership-request.js';\n// ─── API result messages + error codes ───────────────────────────────────────\nexport * from './messages.js';\n// ─── Engagement & analytics ──────────────────────────────────────────────────\nexport * from './notification.js';\nexport * from './onboarding.js';\n// ─── Onboarding wizard FORM validation (client-side working shapes) ──────────\nexport * from './onboarding-form.js';\n// ─── Gym structure & onboarding ──────────────────────────────────────────────\nexport * from './organisation.js';\nexport * from './owner-profile.js';\nexport * from './pricing.js';\nexport * from './session.js';\nexport * from './shared.js';\nexport * from './staff.js';\nexport * from './subscription.js';\nexport * from './user.js';\nexport * from './workout-plan.js';\n"]}
@@ -211,7 +211,7 @@ export declare const memberProfileSchema: z.ZodObject<{
211
211
  inviteEmail: z.ZodNullable<z.ZodString>;
212
212
  invitePhone: z.ZodNullable<z.ZodString>;
213
213
  claimedAt: z.ZodNullable<z.ZodISODateTime>;
214
- centerId: z.ZodString;
214
+ centerId: z.ZodNullable<z.ZodString>;
215
215
  memberCode: z.ZodString;
216
216
  gender: z.ZodEnum<{
217
217
  male: "male";
@@ -1 +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"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwC9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC"}
@@ -81,7 +81,16 @@ export const memberProfileSchema = z.object({
81
81
  /** WhatsApp number the owner shares the invite link on. */
82
82
  invitePhone: z.string().nullable(),
83
83
  claimedAt: isoDateTimeSchema.nullable(),
84
- centerId: objectIdSchema,
84
+ /**
85
+ * The gym this member belongs to. NULL when they belong to none.
86
+ *
87
+ * Everybody signs up as a member with no gym attached and finds one
88
+ * afterwards, so "no gym yet" is the ordinary starting state, not an error.
89
+ * It is set when a gym ACCEPTS their join request (or when they claim an
90
+ * invite a gym issued them), and cleared when they leave — which is what
91
+ * makes joining somewhere else afterwards possible.
92
+ */
93
+ centerId: objectIdSchema.nullable(),
85
94
  /** Public member code within the gym, `GM-YYYY-NNNNN`. Server-generated. */
86
95
  memberCode: z.string(),
87
96
  gender: genderSchema,
@@ -1 +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"]}
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 /**\n * The gym this member belongs to. NULL when they belong to none.\n *\n * Everybody signs up as a member with no gym attached and finds one\n * afterwards, so \"no gym yet\" is the ordinary starting state, not an error.\n * It is set when a gym ACCEPTS their join request (or when they claim an\n * invite a gym issued them), and cleared when they leave — which is what\n * makes joining somewhere else afterwards possible.\n */\n centerId: objectIdSchema.nullable(),\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"]}
package/dist/member.d.ts CHANGED
@@ -27,6 +27,8 @@ export declare const memberRosterItemSchema: z.ZodObject<{
27
27
  name: z.ZodString;
28
28
  avatarUrl: z.ZodNullable<z.ZodString>;
29
29
  verified: z.ZodBoolean;
30
+ phone: z.ZodNullable<z.ZodString>;
31
+ email: z.ZodNullable<z.ZodEmail>;
30
32
  planName: z.ZodNullable<z.ZodString>;
31
33
  tier: z.ZodNullable<z.ZodEnum<{
32
34
  free: "free";
@@ -50,7 +52,13 @@ export declare const memberRosterItemSchema: z.ZodObject<{
50
52
  new: "new";
51
53
  "at-risk": "at-risk";
52
54
  }>>;
55
+ joinedAt: z.ZodISODateTime;
56
+ visits14d: z.ZodNumber;
57
+ trainerId: z.ZodNullable<z.ZodString>;
58
+ trainerName: z.ZodNullable<z.ZodString>;
53
59
  }, z.core.$strip>;
60
+ /** Trailing window the roster's attendance filters and `visits14d` are measured over. */
61
+ export declare const ATTENDANCE_WINDOW_DAYS = 14;
54
62
  export type MemberRosterItem = z.infer<typeof memberRosterItemSchema>;
55
63
  /** Header counts for the roster. */
56
64
  export declare const memberListSummarySchema: z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"member.d.ts","sourceRoot":"","sources":["../src/member.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"member.d.ts","sourceRoot":"","sources":["../src/member.ts"],"names":[],"mappings":"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"}