@gymspace/sdk 1.9.1 → 1.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +523 -34
- package/dist/index.d.ts +523 -34
- package/dist/index.js +521 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +513 -25
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +167 -0
- package/src/models/auth.ts +15 -4
- package/src/models/clients.ts +2 -0
- package/src/models/contracts.ts +85 -1
- package/src/models/credits.ts +1 -5
- package/src/models/dashboard.ts +10 -0
- package/src/models/gyms.ts +20 -0
- package/src/models/index.ts +1 -0
- package/src/models/members.ts +133 -0
- package/src/models/membership-plans.ts +3 -0
- package/src/resources/auth.ts +56 -2
- package/src/resources/check-ins.ts +35 -0
- package/src/resources/clients.ts +58 -1
- package/src/resources/contracts.ts +54 -0
- package/src/resources/dashboard.ts +10 -0
- package/src/resources/index.ts +2 -0
- package/src/resources/members.ts +59 -0
- package/src/resources/receivables.ts +111 -0
- package/src/sdk.ts +48 -0
- package/src/types.ts +3 -5
- package/dist/.tsbuildinfo +0 -1
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -18,7 +18,14 @@ export class ApiClient {
|
|
|
18
18
|
private axiosInstance: AxiosInstance;
|
|
19
19
|
private config: GymSpaceConfig;
|
|
20
20
|
private refreshToken: string | null = null;
|
|
21
|
+
private rememberMe: boolean | null = null;
|
|
21
22
|
private onTokenRefreshed?: (accessToken: string, refreshToken?: string) => void;
|
|
23
|
+
private onAuthFailure?: (error: AuthenticationError) => void;
|
|
24
|
+
private isRefreshing = false;
|
|
25
|
+
private failedRequestsQueue: Array<{
|
|
26
|
+
resolve: (token: string) => void;
|
|
27
|
+
reject: (error: Error) => void;
|
|
28
|
+
}> = [];
|
|
22
29
|
|
|
23
30
|
public getAccessToken(): string | null {
|
|
24
31
|
return this.config.apiKey || null;
|
|
@@ -109,6 +116,104 @@ export class ApiClient {
|
|
|
109
116
|
return response;
|
|
110
117
|
},
|
|
111
118
|
async (error: AxiosError) => {
|
|
119
|
+
// Handle 401 with automatic token refresh
|
|
120
|
+
if (error.response?.status === 401) {
|
|
121
|
+
const originalRequest = error.config;
|
|
122
|
+
|
|
123
|
+
// Skip auth requests (login, refresh endpoints)
|
|
124
|
+
if ((originalRequest as any)?.skipAuth) {
|
|
125
|
+
throw this.handleError(error);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// If already refreshing, queue this request
|
|
129
|
+
if (this.isRefreshing && this.refreshToken) {
|
|
130
|
+
return new Promise((resolve, reject) => {
|
|
131
|
+
this.failedRequestsQueue.push({
|
|
132
|
+
resolve: (token: string) => {
|
|
133
|
+
// Retry with new token
|
|
134
|
+
if (originalRequest) {
|
|
135
|
+
originalRequest.headers['Authorization'] = `Bearer ${token}`;
|
|
136
|
+
this.axiosInstance.request(originalRequest).then(resolve).catch(reject);
|
|
137
|
+
} else {
|
|
138
|
+
reject(error);
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
reject: (err: Error) => {
|
|
142
|
+
reject(err);
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Start refresh process
|
|
149
|
+
if (this.refreshToken) {
|
|
150
|
+
this.isRefreshing = true;
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
console.log('Access token expired, attempting refresh...');
|
|
154
|
+
|
|
155
|
+
// Call the member refresh endpoint directly
|
|
156
|
+
const response = await axios.post(
|
|
157
|
+
`${this.config.baseURL}/auth/members/refresh`,
|
|
158
|
+
{ refresh_token: this.refreshToken },
|
|
159
|
+
{ headers: { 'Content-Type': 'application/json' } },
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const { accessToken: newAccessToken, refreshToken: newRefreshToken } = response.data;
|
|
163
|
+
|
|
164
|
+
console.log('Token refresh successful');
|
|
165
|
+
|
|
166
|
+
// Update SDK state
|
|
167
|
+
this.setAuthToken(newAccessToken);
|
|
168
|
+
if (newRefreshToken) {
|
|
169
|
+
this.setRefreshToken(newRefreshToken);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Notify listeners
|
|
173
|
+
if (this.onTokenRefreshed) {
|
|
174
|
+
this.onTokenRefreshed(newAccessToken, newRefreshToken);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Process queued requests
|
|
178
|
+
this.failedRequestsQueue.forEach((request) => {
|
|
179
|
+
request.resolve(newAccessToken);
|
|
180
|
+
});
|
|
181
|
+
this.failedRequestsQueue = [];
|
|
182
|
+
|
|
183
|
+
// Retry original request
|
|
184
|
+
if (originalRequest) {
|
|
185
|
+
originalRequest.headers['Authorization'] = `Bearer ${newAccessToken}`;
|
|
186
|
+
return this.axiosInstance.request(originalRequest);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
throw error;
|
|
190
|
+
} catch (refreshError: any) {
|
|
191
|
+
console.error('Token refresh failed:', refreshError.message);
|
|
192
|
+
|
|
193
|
+
// Reject queued requests
|
|
194
|
+
this.failedRequestsQueue.forEach((request) => {
|
|
195
|
+
request.reject(refreshError);
|
|
196
|
+
});
|
|
197
|
+
this.failedRequestsQueue = [];
|
|
198
|
+
|
|
199
|
+
// Clear auth on refresh failure
|
|
200
|
+
this.clearAuth();
|
|
201
|
+
|
|
202
|
+
const authError = new AuthenticationError(
|
|
203
|
+
refreshError.response?.data?.message || 'Token refresh failed',
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
if (this.onAuthFailure) {
|
|
207
|
+
this.onAuthFailure(authError);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
throw authError;
|
|
211
|
+
} finally {
|
|
212
|
+
this.isRefreshing = false;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
112
217
|
throw this.handleError(error);
|
|
113
218
|
},
|
|
114
219
|
);
|
|
@@ -167,6 +272,10 @@ export class ApiClient {
|
|
|
167
272
|
headers['X-Gym-Id'] = options.gymId;
|
|
168
273
|
}
|
|
169
274
|
|
|
275
|
+
if (options?.gymContextMode) {
|
|
276
|
+
headers['X-Gym-Context-Mode'] = options.gymContextMode;
|
|
277
|
+
}
|
|
278
|
+
|
|
170
279
|
return { headers };
|
|
171
280
|
}
|
|
172
281
|
|
|
@@ -228,6 +337,20 @@ export class ApiClient {
|
|
|
228
337
|
return this.refreshToken;
|
|
229
338
|
}
|
|
230
339
|
|
|
340
|
+
/**
|
|
341
|
+
* Set rememberMe preference from login response
|
|
342
|
+
*/
|
|
343
|
+
setRememberMe(value: boolean): void {
|
|
344
|
+
this.rememberMe = value;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Get rememberMe preference
|
|
349
|
+
*/
|
|
350
|
+
getRememberMe(): boolean | null {
|
|
351
|
+
return this.rememberMe;
|
|
352
|
+
}
|
|
353
|
+
|
|
231
354
|
/**
|
|
232
355
|
* Set callback for when tokens are refreshed by backend
|
|
233
356
|
*/
|
|
@@ -242,6 +365,13 @@ export class ApiClient {
|
|
|
242
365
|
return this.onTokenRefreshed;
|
|
243
366
|
}
|
|
244
367
|
|
|
368
|
+
/**
|
|
369
|
+
* Set callback for when authentication fails irrecoverably
|
|
370
|
+
*/
|
|
371
|
+
setOnAuthFailure(callback: (error: AuthenticationError) => void): void {
|
|
372
|
+
this.onAuthFailure = callback;
|
|
373
|
+
}
|
|
374
|
+
|
|
245
375
|
setGymId(gymId: string): void {
|
|
246
376
|
this.axiosInstance.defaults.headers.common['X-Gym-Id'] = gymId;
|
|
247
377
|
}
|
|
@@ -249,6 +379,7 @@ export class ApiClient {
|
|
|
249
379
|
clearAuth(): void {
|
|
250
380
|
delete this.config.apiKey;
|
|
251
381
|
this.refreshToken = null;
|
|
382
|
+
this.rememberMe = null;
|
|
252
383
|
delete this.axiosInstance.defaults.headers.common['Authorization'];
|
|
253
384
|
delete this.axiosInstance.defaults.headers.common['X-Gym-Id'];
|
|
254
385
|
}
|
|
@@ -256,4 +387,40 @@ export class ApiClient {
|
|
|
256
387
|
getBaseUrl(): string {
|
|
257
388
|
return this.config.baseURL;
|
|
258
389
|
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Get config for creating scoped SDK instances
|
|
393
|
+
* Exposes minimal config needed without exposing internal structure
|
|
394
|
+
*/
|
|
395
|
+
getConfigForScoped(): {
|
|
396
|
+
baseURL: string;
|
|
397
|
+
apiKey?: string;
|
|
398
|
+
refreshToken?: string;
|
|
399
|
+
headers?: Record<string, string>;
|
|
400
|
+
} {
|
|
401
|
+
return {
|
|
402
|
+
baseURL: this.config.baseURL,
|
|
403
|
+
apiKey: this.config.apiKey,
|
|
404
|
+
refreshToken: this.refreshToken,
|
|
405
|
+
headers: this.config.headers,
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Get axios instance defaults for scoped SDK
|
|
411
|
+
*/
|
|
412
|
+
getAxiosDefaults(): Record<string, unknown> {
|
|
413
|
+
return { ...this.axiosInstance.defaults.headers.common };
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Set common headers on axios instance (for scoped SDK setup)
|
|
418
|
+
*/
|
|
419
|
+
setCommonHeaders(headers: Record<string, string>): void {
|
|
420
|
+
Object.entries(headers).forEach(([key, value]) => {
|
|
421
|
+
if (value !== undefined) {
|
|
422
|
+
this.axiosInstance.defaults.headers.common[key] = value;
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
}
|
|
259
426
|
}
|
package/src/models/auth.ts
CHANGED
|
@@ -15,6 +15,7 @@ export interface RegisterOwnerDto {
|
|
|
15
15
|
export interface LoginDto {
|
|
16
16
|
email: string;
|
|
17
17
|
password: string;
|
|
18
|
+
rememberMe?: boolean;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export interface LoginResponseDto {
|
|
@@ -119,9 +120,7 @@ export interface CollaboratorRoleDto {
|
|
|
119
120
|
gymName: string;
|
|
120
121
|
}
|
|
121
122
|
|
|
122
|
-
export interface
|
|
123
|
-
accessToken: string;
|
|
124
|
-
refreshToken?: string;
|
|
123
|
+
export interface CurrentSessionBase {
|
|
125
124
|
user: {
|
|
126
125
|
id: string;
|
|
127
126
|
email: string;
|
|
@@ -178,4 +177,16 @@ export interface CurrentSessionResponse {
|
|
|
178
177
|
permissions: string[];
|
|
179
178
|
collaborator?: CollaboratorRoleDto;
|
|
180
179
|
isAuthenticated: boolean;
|
|
181
|
-
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export type CurrentSessionResponse = CurrentSessionBase & {
|
|
183
|
+
access_token: string;
|
|
184
|
+
refresh_token?: string;
|
|
185
|
+
accessToken?: string;
|
|
186
|
+
refreshToken?: string;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
export type CurrentSessionResponseLegacy = CurrentSessionBase & {
|
|
190
|
+
accessToken: string;
|
|
191
|
+
refreshToken?: string;
|
|
192
|
+
};
|
package/src/models/clients.ts
CHANGED
package/src/models/contracts.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ContractStatus, CancellationReason, SuspensionType } from '@gymspace/shared';
|
|
1
|
+
import { ContractStatus, ContractInstallmentStatus, CancellationReason, SuspensionType } from '@gymspace/shared';
|
|
2
2
|
import { PaginationQueryDto } from '../types';
|
|
3
3
|
|
|
4
4
|
export interface CreateContractDto {
|
|
@@ -12,6 +12,19 @@ export interface CreateContractDto {
|
|
|
12
12
|
customPrice?: number;
|
|
13
13
|
receiptIds?: string[];
|
|
14
14
|
metadata?: Record<string, any>;
|
|
15
|
+
paymentPlan?: ContractPaymentPlanInput;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ContractInstallmentScheduleDto {
|
|
19
|
+
dueDate: string;
|
|
20
|
+
amount: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ContractPaymentPlanInput {
|
|
24
|
+
installmentsCount?: number;
|
|
25
|
+
downPaymentAmount?: number;
|
|
26
|
+
firstDueDate?: string;
|
|
27
|
+
schedule?: ContractInstallmentScheduleDto[];
|
|
15
28
|
}
|
|
16
29
|
|
|
17
30
|
export interface RenewContractDto {
|
|
@@ -93,6 +106,7 @@ export interface Contract {
|
|
|
93
106
|
contractDocumentId?: string | null;
|
|
94
107
|
paymentReceiptIds?: string[] | null;
|
|
95
108
|
receiptIds?: string[];
|
|
109
|
+
accessGymIds?: string[];
|
|
96
110
|
metadata?: Record<string, any>;
|
|
97
111
|
createdByUserId?: string;
|
|
98
112
|
updatedByUserId?: string | null;
|
|
@@ -156,6 +170,76 @@ export interface Contract {
|
|
|
156
170
|
};
|
|
157
171
|
}
|
|
158
172
|
|
|
173
|
+
export interface ContractInstallment {
|
|
174
|
+
id: string;
|
|
175
|
+
contractId: string;
|
|
176
|
+
paymentPlanId: string;
|
|
177
|
+
installmentNumber: number;
|
|
178
|
+
dueDate: string;
|
|
179
|
+
amount: string;
|
|
180
|
+
paidAmount: string;
|
|
181
|
+
status: ContractInstallmentStatus;
|
|
182
|
+
paidAt?: string | null;
|
|
183
|
+
lastReminderAt?: string | null;
|
|
184
|
+
createdAt: string;
|
|
185
|
+
updatedAt: string;
|
|
186
|
+
deletedAt?: string | null;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export interface ContractPayment {
|
|
190
|
+
id: string;
|
|
191
|
+
contractId: string;
|
|
192
|
+
installmentId?: string | null;
|
|
193
|
+
paymentMethodId: string;
|
|
194
|
+
amount: string;
|
|
195
|
+
paidAt: string;
|
|
196
|
+
receiptIds?: string[];
|
|
197
|
+
notes?: string | null;
|
|
198
|
+
createdByUserId: string;
|
|
199
|
+
createdAt: string;
|
|
200
|
+
updatedAt: string;
|
|
201
|
+
deletedAt?: string | null;
|
|
202
|
+
paymentMethod?: {
|
|
203
|
+
id: string;
|
|
204
|
+
name: string;
|
|
205
|
+
};
|
|
206
|
+
installment?: {
|
|
207
|
+
id: string;
|
|
208
|
+
installmentNumber: number;
|
|
209
|
+
dueDate: string;
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export interface ContractInstallmentsResponse {
|
|
214
|
+
contractId: string;
|
|
215
|
+
totalAmount: number;
|
|
216
|
+
totalPaid: number;
|
|
217
|
+
outstandingAmount: number;
|
|
218
|
+
nextDueDate?: string | null;
|
|
219
|
+
installments: ContractInstallment[];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface ContractPaymentsResponse {
|
|
223
|
+
contractId: string;
|
|
224
|
+
totalPaid: number;
|
|
225
|
+
payments: ContractPayment[];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export interface RegisterContractPaymentDto {
|
|
229
|
+
amount: number;
|
|
230
|
+
paymentMethodId: string;
|
|
231
|
+
paidAt?: string;
|
|
232
|
+
receiptIds?: string[];
|
|
233
|
+
notes?: string;
|
|
234
|
+
installmentId?: string;
|
|
235
|
+
applyMode?: 'oldest_due' | 'installment';
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export interface RegisterContractPaymentResponse {
|
|
239
|
+
success: boolean;
|
|
240
|
+
payments: ContractPayment[];
|
|
241
|
+
}
|
|
242
|
+
|
|
159
243
|
export interface GetContractsParams extends PaginationQueryDto {
|
|
160
244
|
status?: ContractStatus;
|
|
161
245
|
clientName?: string;
|
package/src/models/credits.ts
CHANGED
package/src/models/dashboard.ts
CHANGED
|
@@ -29,12 +29,22 @@ export interface SalesRevenue {
|
|
|
29
29
|
|
|
30
30
|
export interface Debts {
|
|
31
31
|
totalDebt: number;
|
|
32
|
+
salesDebt?: number;
|
|
33
|
+
contractsDebt?: number;
|
|
32
34
|
clientsWithDebt: number;
|
|
33
35
|
averageDebt: number;
|
|
34
36
|
startDate: string;
|
|
35
37
|
endDate: string;
|
|
36
38
|
}
|
|
37
39
|
|
|
40
|
+
export interface Collections {
|
|
41
|
+
totalCollected: number;
|
|
42
|
+
salesCollected: number;
|
|
43
|
+
contractsCollected: number;
|
|
44
|
+
startDate: string;
|
|
45
|
+
endDate: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
38
48
|
export interface CheckIns {
|
|
39
49
|
totalCheckIns: number;
|
|
40
50
|
uniqueClients: number;
|
package/src/models/gyms.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { TemplateCode } from '@gymspace/shared';
|
|
2
|
+
|
|
1
3
|
export interface CreateGymDto {
|
|
2
4
|
name: string;
|
|
3
5
|
description?: string;
|
|
@@ -59,6 +61,15 @@ export interface ContractSettings {
|
|
|
59
61
|
expiringSoonDays?: number;
|
|
60
62
|
gracePeriodDays?: number;
|
|
61
63
|
enableExpirationNotifications?: boolean;
|
|
64
|
+
installmentsEnabled?: boolean;
|
|
65
|
+
defaultInstallmentsCount?: number;
|
|
66
|
+
defaultDownPaymentAmount?: number;
|
|
67
|
+
allowContractInstallmentOverride?: boolean;
|
|
68
|
+
allowReminderOverride?: boolean;
|
|
69
|
+
reminderDaysBeforeDue?: number[];
|
|
70
|
+
reminderDaysAfterDue?: number[];
|
|
71
|
+
reminderTemplateCode?: TemplateCode;
|
|
72
|
+
debtAccessPolicy?: 'allow_always' | 'block_overdue';
|
|
62
73
|
}
|
|
63
74
|
|
|
64
75
|
/**
|
|
@@ -77,6 +88,15 @@ export interface UpdateGymContractSettingsDto {
|
|
|
77
88
|
expiringSoonDays?: number;
|
|
78
89
|
gracePeriodDays?: number;
|
|
79
90
|
enableExpirationNotifications?: boolean;
|
|
91
|
+
installmentsEnabled?: boolean;
|
|
92
|
+
defaultInstallmentsCount?: number;
|
|
93
|
+
defaultDownPaymentAmount?: number;
|
|
94
|
+
allowContractInstallmentOverride?: boolean;
|
|
95
|
+
allowReminderOverride?: boolean;
|
|
96
|
+
reminderDaysBeforeDue?: number[];
|
|
97
|
+
reminderDaysAfterDue?: number[];
|
|
98
|
+
reminderTemplateCode?: TemplateCode;
|
|
99
|
+
debtAccessPolicy?: 'allow_always' | 'block_overdue';
|
|
80
100
|
}
|
|
81
101
|
|
|
82
102
|
export interface Gym {
|
package/src/models/index.ts
CHANGED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// Member invite types
|
|
2
|
+
export interface CreateMemberInviteDto {
|
|
3
|
+
sendWhatsApp?: boolean;
|
|
4
|
+
customMessage?: string;
|
|
5
|
+
expiresInHours?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface MemberInvite {
|
|
9
|
+
id: string;
|
|
10
|
+
token: string;
|
|
11
|
+
code: string;
|
|
12
|
+
status: 'pending' | 'used' | 'expired';
|
|
13
|
+
expiresAt: string;
|
|
14
|
+
usedAt?: string;
|
|
15
|
+
createdAt: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface MemberInviteResponse {
|
|
19
|
+
invite: MemberInvite;
|
|
20
|
+
whatsappSent?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface MemberInviteValidationResponse {
|
|
24
|
+
valid: boolean;
|
|
25
|
+
status: 'pending' | 'used' | 'expired';
|
|
26
|
+
gym: {
|
|
27
|
+
name: string;
|
|
28
|
+
logo?: string;
|
|
29
|
+
address?: string;
|
|
30
|
+
slug: string;
|
|
31
|
+
};
|
|
32
|
+
client: {
|
|
33
|
+
email: string;
|
|
34
|
+
name: string;
|
|
35
|
+
};
|
|
36
|
+
invite: {
|
|
37
|
+
id: string;
|
|
38
|
+
expiresAt: string;
|
|
39
|
+
status: 'pending' | 'used' | 'expired';
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Member auth types
|
|
44
|
+
export interface MemberPinLoginDto {
|
|
45
|
+
identifier: string;
|
|
46
|
+
identifierType: 'phone' | 'email' | 'document';
|
|
47
|
+
documentType?: string;
|
|
48
|
+
pin: string;
|
|
49
|
+
gymSlug?: string;
|
|
50
|
+
gymId?: string;
|
|
51
|
+
rememberMe?: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface SetPinDto {
|
|
55
|
+
token: string;
|
|
56
|
+
pin: string;
|
|
57
|
+
pinConfirm: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface MemberLoginResponse {
|
|
61
|
+
accessToken: string;
|
|
62
|
+
refreshToken: string;
|
|
63
|
+
member: MemberProfile;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Member profile types
|
|
67
|
+
export interface MemberProfile {
|
|
68
|
+
id: string;
|
|
69
|
+
gymId: string;
|
|
70
|
+
clientNumber: string;
|
|
71
|
+
name: string;
|
|
72
|
+
phone?: string;
|
|
73
|
+
email?: string;
|
|
74
|
+
documentValue?: string;
|
|
75
|
+
documentType?: string;
|
|
76
|
+
status: 'active' | 'inactive';
|
|
77
|
+
pinSet: boolean;
|
|
78
|
+
lastLoginAt?: string;
|
|
79
|
+
createdAt: string;
|
|
80
|
+
updatedAt: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Membership types
|
|
84
|
+
export interface MemberMembership {
|
|
85
|
+
contract: {
|
|
86
|
+
id: string;
|
|
87
|
+
status: string;
|
|
88
|
+
startDate: string;
|
|
89
|
+
endDate: string;
|
|
90
|
+
};
|
|
91
|
+
plan: {
|
|
92
|
+
id: string;
|
|
93
|
+
name: string;
|
|
94
|
+
description?: string;
|
|
95
|
+
};
|
|
96
|
+
status: 'active' | 'inactive' | 'suspended' | 'cancelled';
|
|
97
|
+
daysRemaining: number;
|
|
98
|
+
checkInsRemaining?: number;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Check-in types
|
|
102
|
+
export interface MemberCheckIn {
|
|
103
|
+
id: string;
|
|
104
|
+
timestamp: string;
|
|
105
|
+
createdAt: string;
|
|
106
|
+
contract?: {
|
|
107
|
+
id: string;
|
|
108
|
+
planName: string;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// QR code types
|
|
113
|
+
export interface QrTokenResponse {
|
|
114
|
+
qrToken: string;
|
|
115
|
+
expiresAt: string;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Self check-in types
|
|
119
|
+
export interface CheckInResponse {
|
|
120
|
+
success: boolean;
|
|
121
|
+
message: string;
|
|
122
|
+
checkIn: {
|
|
123
|
+
id: string;
|
|
124
|
+
gymClientId: string;
|
|
125
|
+
gymId: string;
|
|
126
|
+
timestamp: string;
|
|
127
|
+
createdAt: string;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface CheckInDto {
|
|
132
|
+
qrToken: string;
|
|
133
|
+
}
|
|
@@ -12,6 +12,7 @@ export interface CreateMembershipPlanDto {
|
|
|
12
12
|
features?: string[];
|
|
13
13
|
status?: 'active' | 'inactive' | 'archived';
|
|
14
14
|
assetsIds?: string[];
|
|
15
|
+
allowAccessToGymIds?: string[];
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export interface UpdateMembershipPlanDto {
|
|
@@ -29,6 +30,7 @@ export interface UpdateMembershipPlanDto {
|
|
|
29
30
|
status?: 'active' | 'inactive' | 'archived';
|
|
30
31
|
isActive?: boolean;
|
|
31
32
|
assetsIds?: string[];
|
|
33
|
+
allowAccessToGymIds?: string[];
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
export interface MembershipPlan {
|
|
@@ -55,6 +57,7 @@ export interface MembershipPlan {
|
|
|
55
57
|
status: 'active' | 'inactive' | 'archived';
|
|
56
58
|
isActive: boolean;
|
|
57
59
|
assetsIds?: string[];
|
|
60
|
+
allowAccessToGymIds?: string[];
|
|
58
61
|
createdAt: string;
|
|
59
62
|
updatedAt: string;
|
|
60
63
|
_count?: {
|
package/src/resources/auth.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
ResendResetCodeDto,
|
|
19
19
|
ResendResetCodeResponseDto,
|
|
20
20
|
} from '../models/auth';
|
|
21
|
+
import { MemberPinLoginDto, SetPinDto, MemberLoginResponse } from '../models/members';
|
|
21
22
|
import { SubscriptionPlan } from '../models/subscriptions';
|
|
22
23
|
import { RequestOptions } from '../types';
|
|
23
24
|
import { BaseResource } from './base';
|
|
@@ -29,8 +30,16 @@ export class AuthResource extends BaseResource {
|
|
|
29
30
|
return this.client.post(`${this.basePath}/register/owner`, data, options);
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
async login(
|
|
33
|
-
|
|
33
|
+
async login(
|
|
34
|
+
data: LoginDto,
|
|
35
|
+
options?: RequestOptions,
|
|
36
|
+
rememberMe?: boolean,
|
|
37
|
+
): Promise<LoginResponseDto> {
|
|
38
|
+
return this.client.post<LoginResponseDto>(
|
|
39
|
+
`${this.basePath}/login`,
|
|
40
|
+
{ ...data, rememberMe },
|
|
41
|
+
options,
|
|
42
|
+
);
|
|
34
43
|
}
|
|
35
44
|
|
|
36
45
|
async refreshToken(refreshToken: string, options?: RequestOptions): Promise<LoginResponseDto> {
|
|
@@ -137,4 +146,49 @@ export class AuthResource extends BaseResource {
|
|
|
137
146
|
options,
|
|
138
147
|
);
|
|
139
148
|
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Member login with PIN
|
|
152
|
+
* POST /auth/members/pin/login
|
|
153
|
+
*/
|
|
154
|
+
async memberPinLogin(
|
|
155
|
+
data: MemberPinLoginDto,
|
|
156
|
+
options?: RequestOptions,
|
|
157
|
+
): Promise<MemberLoginResponse> {
|
|
158
|
+
return this.client.post<MemberLoginResponse>(
|
|
159
|
+
`${this.basePath}/members/pin/login`,
|
|
160
|
+
data,
|
|
161
|
+
options,
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Consume member invite and set initial PIN
|
|
167
|
+
* POST /auth/members/invite/consume
|
|
168
|
+
*/
|
|
169
|
+
async consumeMemberInvite(
|
|
170
|
+
data: SetPinDto,
|
|
171
|
+
options?: RequestOptions,
|
|
172
|
+
): Promise<{ success: boolean; message: string; gymSlug?: string }> {
|
|
173
|
+
return this.client.post<{ success: boolean; message: string; gymSlug?: string }>(
|
|
174
|
+
`${this.basePath}/members/invite/consume`,
|
|
175
|
+
data,
|
|
176
|
+
options,
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Refresh member access token
|
|
182
|
+
* POST /auth/members/refresh
|
|
183
|
+
*/
|
|
184
|
+
async refreshMemberToken(
|
|
185
|
+
refreshToken: string,
|
|
186
|
+
options?: RequestOptions,
|
|
187
|
+
): Promise<MemberLoginResponse> {
|
|
188
|
+
return this.client.post<MemberLoginResponse>(
|
|
189
|
+
`${this.basePath}/members/refresh`,
|
|
190
|
+
{ refresh_token: refreshToken },
|
|
191
|
+
options,
|
|
192
|
+
);
|
|
193
|
+
}
|
|
140
194
|
}
|