@orjok/commons 1.1.0 → 1.2.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/amplify.cjs +30 -5
- package/dist/amplify.cjs.map +1 -1
- package/dist/amplify.d.cts +5 -2
- package/dist/amplify.d.ts +5 -2
- package/dist/amplify.js +30 -5
- package/dist/amplify.js.map +1 -1
- package/dist/chunk-B4UJE3F4.js +529 -0
- package/dist/chunk-B4UJE3F4.js.map +1 -0
- package/dist/chunk-ODXD2WJN.cjs +529 -0
- package/dist/chunk-ODXD2WJN.cjs.map +1 -0
- package/dist/hooks.cjs +159 -12
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.cts +34 -3
- package/dist/hooks.d.ts +34 -3
- package/dist/hooks.js +148 -1
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +1930 -205
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +230 -14
- package/dist/index.d.ts +230 -14
- package/dist/index.js +1875 -150
- package/dist/index.js.map +1 -1
- package/dist/{practice-Dh2Tv80G.d.ts → notification-BoqtkNrc.d.ts} +357 -8
- package/dist/{practice-QnWtC5A7.d.cts → notification-Ctfy0m05.d.cts} +357 -8
- package/dist/{storage-DLqdJgQt.d.cts → storage-9pK8KwIM.d.cts} +4 -2
- package/dist/{storage-DLqdJgQt.d.ts → storage-9pK8KwIM.d.ts} +4 -2
- package/dist/testing.cjs +24 -3
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +7 -2
- package/dist/testing.d.ts +7 -2
- package/dist/testing.js +24 -3
- package/dist/testing.js.map +1 -1
- package/package.json +2 -1
- package/dist/chunk-DB3CMKPP.cjs +0 -165
- package/dist/chunk-DB3CMKPP.cjs.map +0 -1
- package/dist/chunk-ZDGYAVEC.js +0 -165
- package/dist/chunk-ZDGYAVEC.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -13,7 +13,24 @@
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
var _chunkODXD2WJNcjs = require('./chunk-ODXD2WJN.cjs');
|
|
17
34
|
|
|
18
35
|
// src/services/user.service.ts
|
|
19
36
|
var UserService = class {
|
|
@@ -25,11 +42,12 @@ var UserService = class {
|
|
|
25
42
|
`query GetUser($id: String!) {
|
|
26
43
|
getUser(id: $id) {
|
|
27
44
|
id fullName avatarUrl avatarConfig tier subscriptionExpiresAt
|
|
28
|
-
aiEvaluationRemaining questionCount packCount contestCount
|
|
45
|
+
aiEvaluationRemaining aiQuestionGenRemaining questionCount packCount contestCount
|
|
29
46
|
EngineeringRating MedicalRating VarsityRating BCSRating
|
|
30
47
|
sscOverallRating sscPhysicsRating sscChemistryRating sscMathRating sscBiologyRating
|
|
31
48
|
hscOverallRating hscPhysicsRating hscChemistryRating hscMathRating hscBiologyRating
|
|
32
49
|
bcsOverallRating
|
|
50
|
+
xp userLevel
|
|
33
51
|
}
|
|
34
52
|
}`,
|
|
35
53
|
{ id }
|
|
@@ -37,13 +55,16 @@ var UserService = class {
|
|
|
37
55
|
return result.data.getUser;
|
|
38
56
|
}
|
|
39
57
|
async updateAvatar(input) {
|
|
58
|
+
const updateInput = { id: input.userId };
|
|
59
|
+
if (input.avatarUrl !== void 0) updateInput.avatarUrl = input.avatarUrl;
|
|
60
|
+
if (input.avatarConfig !== void 0) updateInput.avatarConfig = input.avatarConfig;
|
|
40
61
|
const result = await this.network.mutate(
|
|
41
62
|
`mutation UpdateUser($input: UpdateUserInput!) {
|
|
42
63
|
updateUser(input: $input) {
|
|
43
64
|
id fullName avatarUrl avatarConfig
|
|
44
65
|
}
|
|
45
66
|
}`,
|
|
46
|
-
{ input:
|
|
67
|
+
{ input: updateInput }
|
|
47
68
|
);
|
|
48
69
|
return result.data.updateUser;
|
|
49
70
|
}
|
|
@@ -107,8 +128,59 @@ var UserService = class {
|
|
|
107
128
|
);
|
|
108
129
|
return result.data.listCourseEnrolledByUserIdAndCreatedAt.items;
|
|
109
130
|
}
|
|
131
|
+
async updateProfile(input) {
|
|
132
|
+
const result = await this.network.mutate(
|
|
133
|
+
`mutation UpdateUserProfile($input: UpdateUserInput!) {
|
|
134
|
+
updateUser(input: $input) {
|
|
135
|
+
id fullName avatarUrl avatarConfig tier subscriptionExpiresAt
|
|
136
|
+
aiEvaluationRemaining aiQuestionGenRemaining questionCount packCount contestCount
|
|
137
|
+
xp userLevel
|
|
138
|
+
}
|
|
139
|
+
}`,
|
|
140
|
+
{ input }
|
|
141
|
+
);
|
|
142
|
+
return result.data.updateUser;
|
|
143
|
+
}
|
|
144
|
+
async list(input = {}) {
|
|
145
|
+
const result = await this.network.query(
|
|
146
|
+
`query ListUsers($limit: Int, $nextToken: String, $filter: ModelUserFilterInput) {
|
|
147
|
+
listUsers(limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
148
|
+
items {
|
|
149
|
+
id fullName avatarUrl avatarConfig tier subscriptionExpiresAt
|
|
150
|
+
aiEvaluationRemaining aiQuestionGenRemaining questionCount packCount contestCount
|
|
151
|
+
xp userLevel
|
|
152
|
+
}
|
|
153
|
+
nextToken
|
|
154
|
+
}
|
|
155
|
+
}`,
|
|
156
|
+
{ limit: _nullishCoalesce(input.limit, () => ( 20)), nextToken: input.nextToken, filter: input.filter }
|
|
157
|
+
);
|
|
158
|
+
return result.data.listUsers;
|
|
159
|
+
}
|
|
110
160
|
};
|
|
111
161
|
|
|
162
|
+
// src/utils/pagination.ts
|
|
163
|
+
async function paginateWithAccumulator(fetchPage, targetLimit = 12, initialNextToken, maxIterations = 10) {
|
|
164
|
+
const accumulated = [];
|
|
165
|
+
let currentNextToken = initialNextToken;
|
|
166
|
+
let iterations = 0;
|
|
167
|
+
while (accumulated.length < targetLimit && iterations < maxIterations) {
|
|
168
|
+
iterations++;
|
|
169
|
+
const remaining = targetLimit - accumulated.length;
|
|
170
|
+
const response = await fetchPage(remaining, currentNextToken);
|
|
171
|
+
const items = _optionalChain([response, 'optionalAccess', _2 => _2.items]) || [];
|
|
172
|
+
accumulated.push(...items);
|
|
173
|
+
currentNextToken = _optionalChain([response, 'optionalAccess', _3 => _3.nextToken]);
|
|
174
|
+
if (!currentNextToken || accumulated.length >= targetLimit) {
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
items: accumulated.slice(0, targetLimit),
|
|
180
|
+
nextToken: _nullishCoalesce(currentNextToken, () => ( null))
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
112
184
|
// src/services/question.service.ts
|
|
113
185
|
var QuestionService = class {
|
|
114
186
|
constructor(network) {
|
|
@@ -116,8 +188,8 @@ var QuestionService = class {
|
|
|
116
188
|
}
|
|
117
189
|
async create(input) {
|
|
118
190
|
const result = await this.network.mutate(
|
|
119
|
-
`mutation CreateQuestion($question: String!, $answer: String!, $options: String!, $language: String!, $level: String!, $difficulty: String!, $type: String, $explanation: String, $tags: String, $imagePayload: String, $optionsImagesPayload: String, $packId: ID, $order: Int, $contestId: ID, $subjectId: ID, $chapterId: ID, $topicId: ID, $extra: String, $markingInstructions: String) {
|
|
120
|
-
createQuestion(question: $question, answer: $answer, options: $options, language: $language, level: $level, difficulty: $difficulty, type: $type, explanation: $explanation, tags: $tags, imagePayload: $imagePayload, optionsImagesPayload: $optionsImagesPayload, packId: $packId, order: $order, contestId: $contestId, subjectId: $subjectId, chapterId: $chapterId, topicId: $topicId, extra: $extra, markingInstructions: $markingInstructions) {
|
|
191
|
+
`mutation CreateQuestion($question: String!, $answer: String!, $options: String!, $language: String!, $level: String!, $publicExam: String, $difficulty: String!, $type: String, $explanation: String, $tags: String, $imagePayload: String, $optionsImagesPayload: String, $packId: ID, $order: Int, $contestId: ID, $subjectId: ID, $chapterId: ID, $topicId: ID, $extra: String, $markingInstructions: String) {
|
|
192
|
+
createQuestion(question: $question, answer: $answer, options: $options, language: $language, level: $level, publicExam: $publicExam, difficulty: $difficulty, type: $type, explanation: $explanation, tags: $tags, imagePayload: $imagePayload, optionsImagesPayload: $optionsImagesPayload, packId: $packId, order: $order, contestId: $contestId, subjectId: $subjectId, chapterId: $chapterId, topicId: $topicId, extra: $extra, markingInstructions: $markingInstructions) {
|
|
121
193
|
status questionId
|
|
122
194
|
}
|
|
123
195
|
}`,
|
|
@@ -129,7 +201,7 @@ var QuestionService = class {
|
|
|
129
201
|
const result = await this.network.query(
|
|
130
202
|
`query GetQuestion($id: String!) {
|
|
131
203
|
getQuestionObject(id: $id) {
|
|
132
|
-
id question imageUrl language level difficulty type voteCount
|
|
204
|
+
id question imageUrl language level publicExam difficulty type voteCount
|
|
133
205
|
verificationStatus owner packId subjectId chapterId topicId order createdAt
|
|
134
206
|
options { items { id content } }
|
|
135
207
|
tags { items { id tagId } }
|
|
@@ -143,7 +215,7 @@ var QuestionService = class {
|
|
|
143
215
|
const result = await this.network.query(
|
|
144
216
|
`query GetFullQuestion($id: String!) {
|
|
145
217
|
getQuestionObject(id: $id) {
|
|
146
|
-
id question answer explanation extra imageUrl language level difficulty type
|
|
218
|
+
id question answer explanation extra imageUrl language level publicExam difficulty type
|
|
147
219
|
markingInstructions voteCount verificationStatus owner packId
|
|
148
220
|
subjectId chapterId topicId order createdAt
|
|
149
221
|
options { items { id content } }
|
|
@@ -174,14 +246,14 @@ var QuestionService = class {
|
|
|
174
246
|
}`,
|
|
175
247
|
{ packId, order: { eq: order } }
|
|
176
248
|
);
|
|
177
|
-
return _nullishCoalesce(_optionalChain([result, 'access',
|
|
249
|
+
return _nullishCoalesce(_optionalChain([result, 'access', _4 => _4.data, 'access', _5 => _5.listQuestionObjectByPackIdAndOrder, 'access', _6 => _6.items, 'access', _7 => _7[0], 'optionalAccess', _8 => _8.id]), () => ( null));
|
|
178
250
|
}
|
|
179
251
|
async listByPack(packId, limit = 200, sortDirection = "ASC", nextToken) {
|
|
180
252
|
const result = await this.network.query(
|
|
181
253
|
`query ListQuestionsByPack($packId: ID!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String) {
|
|
182
254
|
listQuestionObjectByPackIdAndOrder(packId: $packId, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken) {
|
|
183
255
|
items {
|
|
184
|
-
id question answer explanation extra imageUrl language level difficulty type
|
|
256
|
+
id question answer explanation extra imageUrl language level publicExam difficulty type
|
|
185
257
|
markingInstructions voteCount owner packId subjectId chapterId topicId order createdAt
|
|
186
258
|
options { items { id content } }
|
|
187
259
|
tags { items { id tagId } }
|
|
@@ -197,7 +269,7 @@ var QuestionService = class {
|
|
|
197
269
|
const result = await this.network.mutate(
|
|
198
270
|
`mutation UpdateQuestion($input: UpdateQuestionObjectInput!) {
|
|
199
271
|
updateQuestionObject(input: $input) {
|
|
200
|
-
id question answer explanation extra imageUrl language level difficulty type
|
|
272
|
+
id question answer explanation extra imageUrl language level publicExam difficulty type
|
|
201
273
|
markingInstructions voteCount owner packId subjectId chapterId topicId order createdAt
|
|
202
274
|
options { items { id content } }
|
|
203
275
|
}
|
|
@@ -297,70 +369,288 @@ var QuestionService = class {
|
|
|
297
369
|
return result.data.addQuestionTag;
|
|
298
370
|
}
|
|
299
371
|
async listBySubject(input) {
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
372
|
+
const hasLanguage = Boolean(input.language && input.language !== "All" && input.language !== "Any");
|
|
373
|
+
const hasDifficulty = Boolean(input.difficulty && input.difficulty !== "All");
|
|
374
|
+
const filter = {};
|
|
375
|
+
if (input.publicExam) {
|
|
376
|
+
filter.publicExam = { eq: input.publicExam };
|
|
377
|
+
}
|
|
378
|
+
if (input.questionType && input.questionType !== "Both") {
|
|
379
|
+
filter.type = { eq: input.questionType };
|
|
380
|
+
}
|
|
381
|
+
const targetLimit = _nullishCoalesce(input.limit, () => ( 12));
|
|
382
|
+
const executeQuery = async (pageLimit, nextToken) => {
|
|
383
|
+
if (hasLanguage) {
|
|
384
|
+
const rangeKey = hasDifficulty ? `${input.language}#${input.difficulty}#` : `${input.language}#`;
|
|
385
|
+
const variables = {
|
|
386
|
+
subjectId: input.id,
|
|
387
|
+
language_difficulty_createdAt: { beginsWith: rangeKey },
|
|
388
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
389
|
+
limit: pageLimit,
|
|
390
|
+
nextToken,
|
|
391
|
+
...Object.keys(filter).length > 0 ? { filter } : {}
|
|
392
|
+
};
|
|
393
|
+
const result = await this.network.query(
|
|
394
|
+
`query ListQuestionsBySubjectAndLangDiff($subjectId: String!, $language_difficulty_createdAt: ModelStringKeyConditionInput, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelQuestionObjectFilterInput) {
|
|
395
|
+
listQuestionObjectBySubjectIdAndLanguage_difficulty_createdAt(subjectId: $subjectId, language_difficulty_createdAt: $language_difficulty_createdAt, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
396
|
+
items {
|
|
397
|
+
id question imageUrl language level publicExam difficulty type voteCount
|
|
398
|
+
verificationStatus owner packId subjectId chapterId topicId createdAt
|
|
399
|
+
options { items { id content } }
|
|
400
|
+
}
|
|
401
|
+
nextToken
|
|
402
|
+
}
|
|
403
|
+
}`,
|
|
404
|
+
variables
|
|
405
|
+
);
|
|
406
|
+
return result.data.listQuestionObjectBySubjectIdAndLanguage_difficulty_createdAt;
|
|
407
|
+
} else {
|
|
408
|
+
const queryFilter = { ...filter };
|
|
409
|
+
if (hasDifficulty) {
|
|
410
|
+
queryFilter.difficulty = { eq: input.difficulty };
|
|
315
411
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
412
|
+
const variables = {
|
|
413
|
+
subjectId: input.id,
|
|
414
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
415
|
+
limit: pageLimit,
|
|
416
|
+
nextToken,
|
|
417
|
+
...Object.keys(queryFilter).length > 0 ? { filter: queryFilter } : {}
|
|
418
|
+
};
|
|
419
|
+
const result = await this.network.query(
|
|
420
|
+
`query ListQuestionsBySubject($subjectId: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelQuestionObjectFilterInput) {
|
|
421
|
+
listQuestionObjectBySubjectIdAndCreatedAt(subjectId: $subjectId, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
422
|
+
items {
|
|
423
|
+
id question imageUrl language level publicExam difficulty type voteCount
|
|
424
|
+
verificationStatus owner packId subjectId chapterId topicId createdAt
|
|
425
|
+
options { items { id content } }
|
|
426
|
+
}
|
|
427
|
+
nextToken
|
|
428
|
+
}
|
|
429
|
+
}`,
|
|
430
|
+
variables
|
|
431
|
+
);
|
|
432
|
+
return result.data.listQuestionObjectBySubjectIdAndCreatedAt;
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
const hasPostFilter = hasLanguage ? Object.keys(filter).length > 0 : Object.keys(filter).length > 0 || hasDifficulty;
|
|
436
|
+
if (!hasPostFilter) {
|
|
437
|
+
return executeQuery(targetLimit, input.nextToken);
|
|
438
|
+
}
|
|
439
|
+
return paginateWithAccumulator(executeQuery, targetLimit, input.nextToken);
|
|
320
440
|
}
|
|
321
441
|
async listByChapter(input) {
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
442
|
+
const hasLanguage = Boolean(input.language && input.language !== "All" && input.language !== "Any");
|
|
443
|
+
const hasDifficulty = Boolean(input.difficulty && input.difficulty !== "All");
|
|
444
|
+
const filter = {};
|
|
445
|
+
if (input.publicExam) {
|
|
446
|
+
filter.publicExam = { eq: input.publicExam };
|
|
447
|
+
}
|
|
448
|
+
if (input.questionType && input.questionType !== "Both") {
|
|
449
|
+
filter.type = { eq: input.questionType };
|
|
450
|
+
}
|
|
451
|
+
const targetLimit = _nullishCoalesce(input.limit, () => ( 12));
|
|
452
|
+
const executeQuery = async (pageLimit, nextToken) => {
|
|
453
|
+
if (hasLanguage) {
|
|
454
|
+
const rangeKey = hasDifficulty ? `${input.language}#${input.difficulty}#` : `${input.language}#`;
|
|
455
|
+
const variables = {
|
|
456
|
+
chapterId: input.id,
|
|
457
|
+
language_difficulty_createdAt: { beginsWith: rangeKey },
|
|
458
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
459
|
+
limit: pageLimit,
|
|
460
|
+
nextToken,
|
|
461
|
+
...Object.keys(filter).length > 0 ? { filter } : {}
|
|
462
|
+
};
|
|
463
|
+
const result = await this.network.query(
|
|
464
|
+
`query ListQuestionsByChapterAndLangDiff($chapterId: String!, $language_difficulty_createdAt: ModelStringKeyConditionInput, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelQuestionObjectFilterInput) {
|
|
465
|
+
listQuestionObjectByChapterIdAndLanguage_difficulty_createdAt(chapterId: $chapterId, language_difficulty_createdAt: $language_difficulty_createdAt, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
466
|
+
items {
|
|
467
|
+
id question imageUrl language level publicExam difficulty type voteCount
|
|
468
|
+
verificationStatus owner packId subjectId chapterId topicId createdAt
|
|
469
|
+
options { items { id content } }
|
|
470
|
+
}
|
|
471
|
+
nextToken
|
|
472
|
+
}
|
|
473
|
+
}`,
|
|
474
|
+
variables
|
|
475
|
+
);
|
|
476
|
+
return result.data.listQuestionObjectByChapterIdAndLanguage_difficulty_createdAt;
|
|
477
|
+
} else {
|
|
478
|
+
const queryFilter = { ...filter };
|
|
479
|
+
if (hasDifficulty) {
|
|
480
|
+
queryFilter.difficulty = { eq: input.difficulty };
|
|
337
481
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
482
|
+
const variables = {
|
|
483
|
+
chapterId: input.id,
|
|
484
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
485
|
+
limit: pageLimit,
|
|
486
|
+
nextToken,
|
|
487
|
+
...Object.keys(queryFilter).length > 0 ? { filter: queryFilter } : {}
|
|
488
|
+
};
|
|
489
|
+
const result = await this.network.query(
|
|
490
|
+
`query ListQuestionsByChapter($chapterId: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelQuestionObjectFilterInput) {
|
|
491
|
+
listQuestionObjectByChapterIdAndCreatedAt(chapterId: $chapterId, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
492
|
+
items {
|
|
493
|
+
id question imageUrl language level publicExam difficulty type voteCount
|
|
494
|
+
verificationStatus owner packId subjectId chapterId topicId createdAt
|
|
495
|
+
options { items { id content } }
|
|
496
|
+
}
|
|
497
|
+
nextToken
|
|
498
|
+
}
|
|
499
|
+
}`,
|
|
500
|
+
variables
|
|
501
|
+
);
|
|
502
|
+
return result.data.listQuestionObjectByChapterIdAndCreatedAt;
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
const hasPostFilter = hasLanguage ? Object.keys(filter).length > 0 : Object.keys(filter).length > 0 || hasDifficulty;
|
|
506
|
+
if (!hasPostFilter) {
|
|
507
|
+
return executeQuery(targetLimit, input.nextToken);
|
|
508
|
+
}
|
|
509
|
+
return paginateWithAccumulator(executeQuery, targetLimit, input.nextToken);
|
|
342
510
|
}
|
|
343
511
|
async listByTopic(input) {
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
512
|
+
const hasLanguage = Boolean(input.language && input.language !== "All" && input.language !== "Any");
|
|
513
|
+
const hasDifficulty = Boolean(input.difficulty && input.difficulty !== "All");
|
|
514
|
+
const filter = {};
|
|
515
|
+
if (input.publicExam) {
|
|
516
|
+
filter.publicExam = { eq: input.publicExam };
|
|
517
|
+
}
|
|
518
|
+
if (input.questionType && input.questionType !== "Both") {
|
|
519
|
+
filter.type = { eq: input.questionType };
|
|
520
|
+
}
|
|
521
|
+
const targetLimit = _nullishCoalesce(input.limit, () => ( 12));
|
|
522
|
+
const executeQuery = async (pageLimit, nextToken) => {
|
|
523
|
+
if (hasLanguage) {
|
|
524
|
+
const rangeKey = hasDifficulty ? `${input.language}#${input.difficulty}#` : `${input.language}#`;
|
|
525
|
+
const variables = {
|
|
526
|
+
topicId: input.id,
|
|
527
|
+
language_difficulty_createdAt: { beginsWith: rangeKey },
|
|
528
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
529
|
+
limit: pageLimit,
|
|
530
|
+
nextToken,
|
|
531
|
+
...Object.keys(filter).length > 0 ? { filter } : {}
|
|
532
|
+
};
|
|
533
|
+
const result = await this.network.query(
|
|
534
|
+
`query ListQuestionsByTopicAndLangDiff($topicId: String!, $language_difficulty_createdAt: ModelStringKeyConditionInput, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelQuestionObjectFilterInput) {
|
|
535
|
+
listQuestionObjectByTopicIdAndLanguage_difficulty_createdAt(topicId: $topicId, language_difficulty_createdAt: $language_difficulty_createdAt, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
536
|
+
items {
|
|
537
|
+
id question imageUrl language level publicExam difficulty type voteCount
|
|
538
|
+
verificationStatus owner packId subjectId chapterId topicId createdAt
|
|
539
|
+
options { items { id content } }
|
|
540
|
+
}
|
|
541
|
+
nextToken
|
|
542
|
+
}
|
|
543
|
+
}`,
|
|
544
|
+
variables
|
|
545
|
+
);
|
|
546
|
+
return result.data.listQuestionObjectByTopicIdAndLanguage_difficulty_createdAt;
|
|
547
|
+
} else {
|
|
548
|
+
const queryFilter = { ...filter };
|
|
549
|
+
if (hasDifficulty) {
|
|
550
|
+
queryFilter.difficulty = { eq: input.difficulty };
|
|
551
|
+
}
|
|
552
|
+
const variables = {
|
|
553
|
+
topicId: input.id,
|
|
554
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
555
|
+
limit: pageLimit,
|
|
556
|
+
nextToken,
|
|
557
|
+
...Object.keys(queryFilter).length > 0 ? { filter: queryFilter } : {}
|
|
558
|
+
};
|
|
559
|
+
const result = await this.network.query(
|
|
560
|
+
`query ListQuestionsByTopic($topicId: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelQuestionObjectFilterInput) {
|
|
561
|
+
listQuestionObjectByTopicIdAndCreatedAt(topicId: $topicId, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
562
|
+
items {
|
|
563
|
+
id question imageUrl language level publicExam difficulty type voteCount
|
|
564
|
+
verificationStatus owner packId subjectId chapterId topicId createdAt
|
|
565
|
+
options { items { id content } }
|
|
566
|
+
}
|
|
567
|
+
nextToken
|
|
568
|
+
}
|
|
569
|
+
}`,
|
|
570
|
+
variables
|
|
571
|
+
);
|
|
572
|
+
return result.data.listQuestionObjectByTopicIdAndCreatedAt;
|
|
573
|
+
}
|
|
349
574
|
};
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
575
|
+
const hasPostFilter = hasLanguage ? Object.keys(filter).length > 0 : Object.keys(filter).length > 0 || hasDifficulty;
|
|
576
|
+
if (!hasPostFilter) {
|
|
577
|
+
return executeQuery(targetLimit, input.nextToken);
|
|
578
|
+
}
|
|
579
|
+
return paginateWithAccumulator(executeQuery, targetLimit, input.nextToken);
|
|
580
|
+
}
|
|
581
|
+
async listByPublicExam(input) {
|
|
582
|
+
const hasLanguage = Boolean(input.language && input.language !== "All" && input.language !== "Any");
|
|
583
|
+
const hasDifficulty = Boolean(input.difficulty && input.difficulty !== "All");
|
|
584
|
+
const filter = {};
|
|
585
|
+
if (input.questionType && input.questionType !== "Both") {
|
|
586
|
+
filter.type = { eq: input.questionType };
|
|
587
|
+
}
|
|
588
|
+
const targetLimit = _nullishCoalesce(input.limit, () => ( 12));
|
|
589
|
+
const executeQuery = async (pageLimit, nextToken) => {
|
|
590
|
+
if (hasLanguage) {
|
|
591
|
+
const rangeKey = hasDifficulty ? `${input.language}#${input.difficulty}#` : `${input.language}#`;
|
|
592
|
+
const variables2 = {
|
|
593
|
+
publicExam: input.publicExam,
|
|
594
|
+
language_difficulty_createdAt: { beginsWith: rangeKey },
|
|
595
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
596
|
+
limit: pageLimit,
|
|
597
|
+
nextToken,
|
|
598
|
+
...Object.keys(filter).length > 0 ? { filter } : {}
|
|
599
|
+
};
|
|
600
|
+
try {
|
|
601
|
+
const result2 = await this.network.query(
|
|
602
|
+
`query ListQuestionsByPublicExamAndLangDiff($publicExam: String!, $language_difficulty_createdAt: ModelStringKeyConditionInput, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelQuestionObjectFilterInput) {
|
|
603
|
+
listQuestionObjectByPublicExamAndLanguage_difficulty_createdAt(publicExam: $publicExam, language_difficulty_createdAt: $language_difficulty_createdAt, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
604
|
+
items {
|
|
605
|
+
id question imageUrl language level publicExam difficulty type voteCount
|
|
606
|
+
verificationStatus owner packId subjectId chapterId topicId createdAt
|
|
607
|
+
options { items { id content } }
|
|
608
|
+
}
|
|
609
|
+
nextToken
|
|
610
|
+
}
|
|
611
|
+
}`,
|
|
612
|
+
variables2
|
|
613
|
+
);
|
|
614
|
+
if (_optionalChain([result2, 'access', _9 => _9.data, 'optionalAccess', _10 => _10.listQuestionObjectByPublicExamAndLanguage_difficulty_createdAt])) {
|
|
615
|
+
return result2.data.listQuestionObjectByPublicExamAndLanguage_difficulty_createdAt;
|
|
357
616
|
}
|
|
358
|
-
|
|
617
|
+
} catch (e2) {
|
|
359
618
|
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
619
|
+
}
|
|
620
|
+
const fallbackFilter = { ...filter };
|
|
621
|
+
if (hasLanguage) {
|
|
622
|
+
fallbackFilter.language = { eq: input.language };
|
|
623
|
+
}
|
|
624
|
+
if (hasDifficulty) {
|
|
625
|
+
fallbackFilter.difficulty = { eq: input.difficulty };
|
|
626
|
+
}
|
|
627
|
+
const variables = {
|
|
628
|
+
publicExam: input.publicExam,
|
|
629
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
630
|
+
limit: pageLimit,
|
|
631
|
+
nextToken,
|
|
632
|
+
...Object.keys(fallbackFilter).length > 0 ? { filter: fallbackFilter } : {}
|
|
633
|
+
};
|
|
634
|
+
const result = await this.network.query(
|
|
635
|
+
`query ListQuestionsByPublicExam($publicExam: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelQuestionObjectFilterInput) {
|
|
636
|
+
listQuestionObjectByPublicExamAndCreatedAt(publicExam: $publicExam, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
637
|
+
items {
|
|
638
|
+
id question imageUrl language level publicExam difficulty type voteCount
|
|
639
|
+
verificationStatus owner packId subjectId chapterId topicId createdAt
|
|
640
|
+
options { items { id content } }
|
|
641
|
+
}
|
|
642
|
+
nextToken
|
|
643
|
+
}
|
|
644
|
+
}`,
|
|
645
|
+
variables
|
|
646
|
+
);
|
|
647
|
+
return result.data.listQuestionObjectByPublicExamAndCreatedAt;
|
|
648
|
+
};
|
|
649
|
+
const hasPostFilter = hasLanguage ? Object.keys(filter).length > 0 : Object.keys(filter).length > 0 || hasLanguage || hasDifficulty;
|
|
650
|
+
if (!hasPostFilter) {
|
|
651
|
+
return executeQuery(targetLimit, input.nextToken);
|
|
652
|
+
}
|
|
653
|
+
return paginateWithAccumulator(executeQuery, targetLimit, input.nextToken);
|
|
364
654
|
}
|
|
365
655
|
async listByRandomHash(input) {
|
|
366
656
|
const compositeKey = [input.language, input.difficulty].filter(Boolean).join("_");
|
|
@@ -374,7 +664,7 @@ var QuestionService = class {
|
|
|
374
664
|
`query ListByRandomHash($subjectId: String!, $language_difficulty_randomHash: ModelStringKeyConditionInput, $sortDirection: ModelSortDirection, $limit: Int) {
|
|
375
665
|
listQuestionObjectBySubjectIdAndLanguage_difficulty_randomHash(subjectId: $subjectId, language_difficulty_randomHash: $language_difficulty_randomHash, sortDirection: $sortDirection, limit: $limit) {
|
|
376
666
|
items {
|
|
377
|
-
id question imageUrl language level difficulty type voteCount
|
|
667
|
+
id question imageUrl language level publicExam difficulty type voteCount
|
|
378
668
|
verificationStatus owner packId subjectId chapterId topicId createdAt
|
|
379
669
|
options { items { id content } }
|
|
380
670
|
}
|
|
@@ -385,6 +675,76 @@ var QuestionService = class {
|
|
|
385
675
|
);
|
|
386
676
|
return result.data.listQuestionObjectBySubjectIdAndLanguage_difficulty_randomHash;
|
|
387
677
|
}
|
|
678
|
+
async listByLevel(input) {
|
|
679
|
+
const hasLanguage = Boolean(input.language && input.language !== "All" && input.language !== "Any");
|
|
680
|
+
const hasDifficulty = Boolean(input.difficulty && input.difficulty !== "All");
|
|
681
|
+
const filter = {};
|
|
682
|
+
if (input.publicExam) {
|
|
683
|
+
filter.publicExam = { eq: input.publicExam };
|
|
684
|
+
}
|
|
685
|
+
if (input.questionType && input.questionType !== "Both") {
|
|
686
|
+
filter.type = { eq: input.questionType };
|
|
687
|
+
}
|
|
688
|
+
const targetLimit = _nullishCoalesce(input.limit, () => ( 12));
|
|
689
|
+
const executeQuery = async (pageLimit, nextToken) => {
|
|
690
|
+
if (hasLanguage) {
|
|
691
|
+
const rangeKey = hasDifficulty ? `${input.language}#${input.difficulty}#` : `${input.language}#`;
|
|
692
|
+
const variables = {
|
|
693
|
+
level: input.level,
|
|
694
|
+
language_difficulty_createdAt: { beginsWith: rangeKey },
|
|
695
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
696
|
+
limit: pageLimit,
|
|
697
|
+
nextToken,
|
|
698
|
+
...Object.keys(filter).length > 0 ? { filter } : {}
|
|
699
|
+
};
|
|
700
|
+
const result = await this.network.query(
|
|
701
|
+
`query ListQuestionsByLevelAndLangDiff($level: String!, $language_difficulty_createdAt: ModelStringKeyConditionInput, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelQuestionObjectFilterInput) {
|
|
702
|
+
listQuestionObjectByLevelAndLanguage_difficulty_createdAt(level: $level, language_difficulty_createdAt: $language_difficulty_createdAt, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
703
|
+
items {
|
|
704
|
+
id question imageUrl language level publicExam difficulty type voteCount
|
|
705
|
+
verificationStatus owner packId subjectId chapterId topicId createdAt
|
|
706
|
+
options { items { id content } }
|
|
707
|
+
}
|
|
708
|
+
nextToken
|
|
709
|
+
}
|
|
710
|
+
}`,
|
|
711
|
+
variables
|
|
712
|
+
);
|
|
713
|
+
return result.data.listQuestionObjectByLevelAndLanguage_difficulty_createdAt;
|
|
714
|
+
} else {
|
|
715
|
+
const queryFilter = { ...filter };
|
|
716
|
+
if (hasDifficulty) {
|
|
717
|
+
queryFilter.difficulty = { eq: input.difficulty };
|
|
718
|
+
}
|
|
719
|
+
const variables = {
|
|
720
|
+
level: input.level,
|
|
721
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
722
|
+
limit: pageLimit,
|
|
723
|
+
nextToken,
|
|
724
|
+
...Object.keys(queryFilter).length > 0 ? { filter: queryFilter } : {}
|
|
725
|
+
};
|
|
726
|
+
const result = await this.network.query(
|
|
727
|
+
`query ListQuestionsByLevel($level: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelQuestionObjectFilterInput) {
|
|
728
|
+
listQuestionObjectByLevelAndCreatedAt(level: $level, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
729
|
+
items {
|
|
730
|
+
id question imageUrl language level publicExam difficulty type voteCount
|
|
731
|
+
verificationStatus owner packId subjectId chapterId topicId createdAt
|
|
732
|
+
options { items { id content } }
|
|
733
|
+
}
|
|
734
|
+
nextToken
|
|
735
|
+
}
|
|
736
|
+
}`,
|
|
737
|
+
variables
|
|
738
|
+
);
|
|
739
|
+
return result.data.listQuestionObjectByLevelAndCreatedAt;
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
const hasPostFilter = hasLanguage ? Object.keys(filter).length > 0 : Object.keys(filter).length > 0 || hasDifficulty;
|
|
743
|
+
if (!hasPostFilter) {
|
|
744
|
+
return executeQuery(targetLimit, input.nextToken);
|
|
745
|
+
}
|
|
746
|
+
return paginateWithAccumulator(executeQuery, targetLimit, input.nextToken);
|
|
747
|
+
}
|
|
388
748
|
};
|
|
389
749
|
|
|
390
750
|
// src/services/pack.service.ts
|
|
@@ -394,8 +754,8 @@ var PackService = class {
|
|
|
394
754
|
}
|
|
395
755
|
async create(input) {
|
|
396
756
|
const result = await this.network.mutate(
|
|
397
|
-
`mutation CreatePack($name: String!, $level: String!, $language: String!, $difficulty: String!, $automaticNumbering: Boolean, $subjectId: ID, $chapterId: ID, $topicId: ID) {
|
|
398
|
-
createPackObject(name: $name, level: $level, language: $language, difficulty: $difficulty, automaticNumbering: $automaticNumbering, subjectId: $subjectId, chapterId: $chapterId, topicId: $topicId) {
|
|
757
|
+
`mutation CreatePack($name: String!, $level: String!, $publicExam: String, $language: String!, $difficulty: String!, $automaticNumbering: Boolean, $subjectId: ID, $chapterId: ID, $topicId: ID) {
|
|
758
|
+
createPackObject(name: $name, level: $level, publicExam: $publicExam, language: $language, difficulty: $difficulty, automaticNumbering: $automaticNumbering, subjectId: $subjectId, chapterId: $chapterId, topicId: $topicId) {
|
|
399
759
|
status id
|
|
400
760
|
}
|
|
401
761
|
}`,
|
|
@@ -407,7 +767,7 @@ var PackService = class {
|
|
|
407
767
|
const result = await this.network.query(
|
|
408
768
|
`query GetPack($id: ID!) {
|
|
409
769
|
getPack(id: $id) {
|
|
410
|
-
id name language level difficulty questionCount automaticNumbering
|
|
770
|
+
id name language level publicExam difficulty questionCount automaticNumbering
|
|
411
771
|
owner subjectId chapterId topicId packGroupId verificationStatus createdAt
|
|
412
772
|
tags { items { id tagId } }
|
|
413
773
|
user { id fullName avatarUrl }
|
|
@@ -421,13 +781,13 @@ var PackService = class {
|
|
|
421
781
|
const result = await this.network.query(
|
|
422
782
|
`query GetFullPack($id: ID!) {
|
|
423
783
|
getPack(id: $id) {
|
|
424
|
-
id name language level difficulty questionCount automaticNumbering
|
|
784
|
+
id name language level publicExam difficulty questionCount automaticNumbering
|
|
425
785
|
owner subjectId chapterId topicId packGroupId verificationStatus createdAt
|
|
426
786
|
tags { items { id tagId } }
|
|
427
787
|
user { id fullName avatarUrl }
|
|
428
788
|
questions(sortDirection: ASC, limit: 200) {
|
|
429
789
|
items {
|
|
430
|
-
id question answer explanation extra imageUrl language level difficulty type
|
|
790
|
+
id question answer explanation extra imageUrl language level publicExam difficulty type
|
|
431
791
|
markingInstructions voteCount owner order createdAt
|
|
432
792
|
options { items { id content } }
|
|
433
793
|
tags { items { id tagId } }
|
|
@@ -440,6 +800,11 @@ var PackService = class {
|
|
|
440
800
|
const pack = result.data.getPack;
|
|
441
801
|
if (pack && pack.questions && Array.isArray(pack.questions.items)) {
|
|
442
802
|
pack.questions.items.sort((a, b) => {
|
|
803
|
+
const isWrittenA = a.type === "WRITTEN" ? 1 : 0;
|
|
804
|
+
const isWrittenB = b.type === "WRITTEN" ? 1 : 0;
|
|
805
|
+
if (isWrittenA !== isWrittenB) {
|
|
806
|
+
return isWrittenA - isWrittenB;
|
|
807
|
+
}
|
|
443
808
|
const orderA = typeof a.order === "number" ? a.order : a.order ? Number(a.order) : 0;
|
|
444
809
|
const orderB = typeof b.order === "number" ? b.order : b.order ? Number(b.order) : 0;
|
|
445
810
|
if (orderA !== orderB) {
|
|
@@ -458,7 +823,7 @@ var PackService = class {
|
|
|
458
823
|
const result = await this.network.mutate(
|
|
459
824
|
`mutation UpdatePack($input: UpdatePackInput!) {
|
|
460
825
|
updatePack(input: $input) {
|
|
461
|
-
id name language level difficulty questionCount automaticNumbering
|
|
826
|
+
id name language level publicExam difficulty questionCount automaticNumbering
|
|
462
827
|
owner subjectId chapterId topicId verificationStatus createdAt
|
|
463
828
|
}
|
|
464
829
|
}`,
|
|
@@ -468,12 +833,15 @@ var PackService = class {
|
|
|
468
833
|
}
|
|
469
834
|
async delete(id) {
|
|
470
835
|
const result = await this.network.mutate(
|
|
471
|
-
`mutation
|
|
472
|
-
|
|
836
|
+
`mutation DeletePackCascade($packId: ID!) {
|
|
837
|
+
deletePackCascade(packId: $packId) { status }
|
|
473
838
|
}`,
|
|
474
|
-
{
|
|
839
|
+
{ packId: id }
|
|
475
840
|
);
|
|
476
|
-
|
|
841
|
+
if (_optionalChain([result, 'access', _11 => _11.data, 'access', _12 => _12.deletePackCascade, 'optionalAccess', _13 => _13.status]) === "success") {
|
|
842
|
+
return { id };
|
|
843
|
+
}
|
|
844
|
+
return null;
|
|
477
845
|
}
|
|
478
846
|
async verify(id, userId) {
|
|
479
847
|
const result = await this.network.mutate(
|
|
@@ -493,7 +861,27 @@ var PackService = class {
|
|
|
493
861
|
);
|
|
494
862
|
return result.data.createPackReport;
|
|
495
863
|
}
|
|
496
|
-
async submitExam(packId, selectedOptions) {
|
|
864
|
+
async submitExam(packId, selectedOptions, options) {
|
|
865
|
+
if (_optionalChain([options, 'optionalAccess', _14 => _14.functionUrl])) {
|
|
866
|
+
try {
|
|
867
|
+
const headers = { "Content-Type": "application/json" };
|
|
868
|
+
if (options.authToken) {
|
|
869
|
+
headers["Authorization"] = `Bearer ${options.authToken}`;
|
|
870
|
+
}
|
|
871
|
+
const response = await fetch(options.functionUrl, {
|
|
872
|
+
method: "POST",
|
|
873
|
+
headers,
|
|
874
|
+
body: JSON.stringify({ packId, selectedOptions: JSON.stringify(selectedOptions) })
|
|
875
|
+
});
|
|
876
|
+
if (response.ok) {
|
|
877
|
+
const data = await response.json();
|
|
878
|
+
return data;
|
|
879
|
+
}
|
|
880
|
+
console.warn(`[PackService] Function URL failed with status ${response.status}, falling back to GraphQL...`);
|
|
881
|
+
} catch (err) {
|
|
882
|
+
console.warn("[PackService] Function URL fetch error, falling back to GraphQL...", err);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
497
885
|
const result = await this.network.mutate(
|
|
498
886
|
`mutation SubmitPackExam($packId: ID!, $selectedOptions: String!) {
|
|
499
887
|
submitPackExam(packId: $packId, selectedOptions: $selectedOptions) {
|
|
@@ -510,7 +898,7 @@ var PackService = class {
|
|
|
510
898
|
listPackExamResultsByOwnerAndCreatedAt(owner: $owner, sortDirection: $sortDirection, nextToken: $nextToken) {
|
|
511
899
|
items {
|
|
512
900
|
id packId selectedOptions aiEvaluations owner createdAt
|
|
513
|
-
pack { id name language level difficulty questionCount }
|
|
901
|
+
pack { id name language level publicExam difficulty questionCount }
|
|
514
902
|
}
|
|
515
903
|
nextToken
|
|
516
904
|
}
|
|
@@ -524,7 +912,7 @@ var PackService = class {
|
|
|
524
912
|
`query GetPackExamResult($id: ID!) {
|
|
525
913
|
getPackExamResults(id: $id) {
|
|
526
914
|
id packId selectedOptions aiEvaluations owner createdAt
|
|
527
|
-
pack { id name language level difficulty questionCount }
|
|
915
|
+
pack { id name language level publicExam difficulty questionCount }
|
|
528
916
|
}
|
|
529
917
|
}`,
|
|
530
918
|
{ id: resultId }
|
|
@@ -532,79 +920,462 @@ var PackService = class {
|
|
|
532
920
|
return result.data.getPackExamResults;
|
|
533
921
|
}
|
|
534
922
|
async listBySubject(input) {
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
923
|
+
const hasLanguage = Boolean(input.language && input.language !== "All" && input.language !== "Any");
|
|
924
|
+
const hasDifficulty = Boolean(input.difficulty && input.difficulty !== "All");
|
|
925
|
+
const filter = {};
|
|
926
|
+
if (input.publicExam) {
|
|
927
|
+
filter.publicExam = { eq: input.publicExam };
|
|
928
|
+
}
|
|
929
|
+
const targetLimit = _nullishCoalesce(input.limit, () => ( 12));
|
|
930
|
+
const executeQuery = async (pageLimit, nextToken) => {
|
|
931
|
+
if (hasLanguage) {
|
|
932
|
+
const rangeKey = hasDifficulty ? `${input.language}#${input.difficulty}#` : `${input.language}#`;
|
|
933
|
+
const variables = {
|
|
934
|
+
subjectId: input.id,
|
|
935
|
+
language_difficulty_createdAt: { beginsWith: rangeKey },
|
|
936
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
937
|
+
limit: pageLimit,
|
|
938
|
+
nextToken,
|
|
939
|
+
...Object.keys(filter).length > 0 ? { filter } : {}
|
|
940
|
+
};
|
|
941
|
+
const result = await this.network.query(
|
|
942
|
+
`query ListPacksBySubjectAndLangDiff($subjectId: String!, $language_difficulty_createdAt: ModelStringKeyConditionInput, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelPackFilterInput) {
|
|
943
|
+
listPackBySubjectIdAndLanguage_difficulty_createdAt(subjectId: $subjectId, language_difficulty_createdAt: $language_difficulty_createdAt, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
944
|
+
items {
|
|
945
|
+
id name language level publicExam difficulty questionCount owner createdAt verificationStatus subjectId chapterId topicId
|
|
946
|
+
tags { items { id tagId } }
|
|
947
|
+
}
|
|
948
|
+
nextToken
|
|
949
|
+
}
|
|
950
|
+
}`,
|
|
951
|
+
variables
|
|
952
|
+
);
|
|
953
|
+
return result.data.listPackBySubjectIdAndLanguage_difficulty_createdAt;
|
|
954
|
+
} else {
|
|
955
|
+
const queryFilter = { ...filter };
|
|
956
|
+
if (hasDifficulty) {
|
|
957
|
+
queryFilter.difficulty = { eq: input.difficulty };
|
|
543
958
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
959
|
+
const variables = {
|
|
960
|
+
subjectId: input.id,
|
|
961
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
962
|
+
limit: pageLimit,
|
|
963
|
+
nextToken,
|
|
964
|
+
...Object.keys(queryFilter).length > 0 ? { filter: queryFilter } : {}
|
|
965
|
+
};
|
|
966
|
+
const result = await this.network.query(
|
|
967
|
+
`query ListPacksBySubject($subjectId: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelPackFilterInput) {
|
|
968
|
+
listPackBySubjectIdAndCreatedAt(subjectId: $subjectId, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
969
|
+
items {
|
|
970
|
+
id name language level publicExam difficulty questionCount owner createdAt verificationStatus subjectId chapterId topicId
|
|
971
|
+
tags { items { id tagId } }
|
|
972
|
+
}
|
|
973
|
+
nextToken
|
|
974
|
+
}
|
|
975
|
+
}`,
|
|
976
|
+
variables
|
|
977
|
+
);
|
|
978
|
+
return result.data.listPackBySubjectIdAndCreatedAt;
|
|
979
|
+
}
|
|
980
|
+
};
|
|
981
|
+
const hasPostFilter = hasLanguage ? Object.keys(filter).length > 0 : Object.keys(filter).length > 0 || hasDifficulty;
|
|
982
|
+
if (!hasPostFilter) {
|
|
983
|
+
return executeQuery(targetLimit, input.nextToken);
|
|
984
|
+
}
|
|
985
|
+
return paginateWithAccumulator(executeQuery, targetLimit, input.nextToken);
|
|
548
986
|
}
|
|
549
987
|
async listByChapter(input) {
|
|
550
|
-
const
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
988
|
+
const hasLanguage = Boolean(input.language && input.language !== "All" && input.language !== "Any");
|
|
989
|
+
const hasDifficulty = Boolean(input.difficulty && input.difficulty !== "All");
|
|
990
|
+
const filter = {};
|
|
991
|
+
if (input.publicExam) {
|
|
992
|
+
filter.publicExam = { eq: input.publicExam };
|
|
993
|
+
}
|
|
994
|
+
const targetLimit = _nullishCoalesce(input.limit, () => ( 12));
|
|
995
|
+
const executeQuery = async (pageLimit, nextToken) => {
|
|
996
|
+
if (hasLanguage) {
|
|
997
|
+
const rangeKey = hasDifficulty ? `${input.language}#${input.difficulty}#` : `${input.language}#`;
|
|
998
|
+
const variables = {
|
|
999
|
+
chapterId: input.id,
|
|
1000
|
+
language_difficulty_createdAt: { beginsWith: rangeKey },
|
|
1001
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
1002
|
+
limit: pageLimit,
|
|
1003
|
+
nextToken,
|
|
1004
|
+
...Object.keys(filter).length > 0 ? { filter } : {}
|
|
1005
|
+
};
|
|
1006
|
+
const result = await this.network.query(
|
|
1007
|
+
`query ListPacksByChapterAndLangDiff($chapterId: String!, $language_difficulty_createdAt: ModelStringKeyConditionInput, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelPackFilterInput) {
|
|
1008
|
+
listPackByChapterIdAndLanguage_difficulty_createdAt(chapterId: $chapterId, language_difficulty_createdAt: $language_difficulty_createdAt, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
1009
|
+
items {
|
|
1010
|
+
id name language level publicExam difficulty questionCount owner createdAt verificationStatus subjectId chapterId topicId
|
|
1011
|
+
tags { items { id tagId } }
|
|
1012
|
+
}
|
|
1013
|
+
nextToken
|
|
1014
|
+
}
|
|
1015
|
+
}`,
|
|
1016
|
+
variables
|
|
1017
|
+
);
|
|
1018
|
+
return result.data.listPackByChapterIdAndLanguage_difficulty_createdAt;
|
|
1019
|
+
} else {
|
|
1020
|
+
const queryFilter = { ...filter };
|
|
1021
|
+
if (hasDifficulty) {
|
|
1022
|
+
queryFilter.difficulty = { eq: input.difficulty };
|
|
558
1023
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
1024
|
+
const variables = {
|
|
1025
|
+
chapterId: input.id,
|
|
1026
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
1027
|
+
limit: pageLimit,
|
|
1028
|
+
nextToken,
|
|
1029
|
+
...Object.keys(queryFilter).length > 0 ? { filter: queryFilter } : {}
|
|
1030
|
+
};
|
|
1031
|
+
const result = await this.network.query(
|
|
1032
|
+
`query ListPacksByChapter($chapterId: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelPackFilterInput) {
|
|
1033
|
+
listPackByChapterIdAndCreatedAt(chapterId: $chapterId, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
1034
|
+
items {
|
|
1035
|
+
id name language level publicExam difficulty questionCount owner createdAt verificationStatus subjectId chapterId topicId
|
|
1036
|
+
tags { items { id tagId } }
|
|
1037
|
+
}
|
|
1038
|
+
nextToken
|
|
1039
|
+
}
|
|
1040
|
+
}`,
|
|
1041
|
+
variables
|
|
1042
|
+
);
|
|
1043
|
+
return result.data.listPackByChapterIdAndCreatedAt;
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
const hasPostFilter = hasLanguage ? Object.keys(filter).length > 0 : Object.keys(filter).length > 0 || hasDifficulty;
|
|
1047
|
+
if (!hasPostFilter) {
|
|
1048
|
+
return executeQuery(targetLimit, input.nextToken);
|
|
1049
|
+
}
|
|
1050
|
+
return paginateWithAccumulator(executeQuery, targetLimit, input.nextToken);
|
|
563
1051
|
}
|
|
564
1052
|
async listByTopic(input) {
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
1053
|
+
const hasLanguage = Boolean(input.language && input.language !== "All" && input.language !== "Any");
|
|
1054
|
+
const hasDifficulty = Boolean(input.difficulty && input.difficulty !== "All");
|
|
1055
|
+
const filter = {};
|
|
1056
|
+
if (input.publicExam) {
|
|
1057
|
+
filter.publicExam = { eq: input.publicExam };
|
|
1058
|
+
}
|
|
1059
|
+
const targetLimit = _nullishCoalesce(input.limit, () => ( 12));
|
|
1060
|
+
const executeQuery = async (pageLimit, nextToken) => {
|
|
1061
|
+
if (hasLanguage) {
|
|
1062
|
+
const rangeKey = hasDifficulty ? `${input.language}#${input.difficulty}#` : `${input.language}#`;
|
|
1063
|
+
const variables = {
|
|
1064
|
+
topicId: input.id,
|
|
1065
|
+
language_difficulty_createdAt: { beginsWith: rangeKey },
|
|
1066
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
1067
|
+
limit: pageLimit,
|
|
1068
|
+
nextToken,
|
|
1069
|
+
...Object.keys(filter).length > 0 ? { filter } : {}
|
|
1070
|
+
};
|
|
1071
|
+
const result = await this.network.query(
|
|
1072
|
+
`query ListPacksByTopicAndLangDiff($topicId: String!, $language_difficulty_createdAt: ModelStringKeyConditionInput, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelPackFilterInput) {
|
|
1073
|
+
listPackByTopicIdAndLanguage_difficulty_createdAt(topicId: $topicId, language_difficulty_createdAt: $language_difficulty_createdAt, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
1074
|
+
items {
|
|
1075
|
+
id name language level publicExam difficulty questionCount owner createdAt verificationStatus subjectId chapterId topicId
|
|
1076
|
+
tags { items { id tagId } }
|
|
1077
|
+
}
|
|
1078
|
+
nextToken
|
|
1079
|
+
}
|
|
1080
|
+
}`,
|
|
1081
|
+
variables
|
|
1082
|
+
);
|
|
1083
|
+
return result.data.listPackByTopicIdAndLanguage_difficulty_createdAt;
|
|
1084
|
+
} else {
|
|
1085
|
+
const queryFilter = { ...filter };
|
|
1086
|
+
if (hasDifficulty) {
|
|
1087
|
+
queryFilter.difficulty = { eq: input.difficulty };
|
|
1088
|
+
}
|
|
1089
|
+
const variables = {
|
|
1090
|
+
topicId: input.id,
|
|
1091
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
1092
|
+
limit: pageLimit,
|
|
1093
|
+
nextToken,
|
|
1094
|
+
...Object.keys(queryFilter).length > 0 ? { filter: queryFilter } : {}
|
|
1095
|
+
};
|
|
1096
|
+
const result = await this.network.query(
|
|
1097
|
+
`query ListPacksByTopic($topicId: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelPackFilterInput) {
|
|
1098
|
+
listPackByTopicIdAndCreatedAt(topicId: $topicId, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
1099
|
+
items {
|
|
1100
|
+
id name language level publicExam difficulty questionCount owner createdAt verificationStatus subjectId chapterId topicId
|
|
1101
|
+
tags { items { id tagId } }
|
|
1102
|
+
}
|
|
1103
|
+
nextToken
|
|
1104
|
+
}
|
|
1105
|
+
}`,
|
|
1106
|
+
variables
|
|
1107
|
+
);
|
|
1108
|
+
return result.data.listPackByTopicIdAndCreatedAt;
|
|
1109
|
+
}
|
|
1110
|
+
};
|
|
1111
|
+
const hasPostFilter = hasLanguage ? Object.keys(filter).length > 0 : Object.keys(filter).length > 0 || hasDifficulty;
|
|
1112
|
+
if (!hasPostFilter) {
|
|
1113
|
+
return executeQuery(targetLimit, input.nextToken);
|
|
1114
|
+
}
|
|
1115
|
+
return paginateWithAccumulator(executeQuery, targetLimit, input.nextToken);
|
|
1116
|
+
}
|
|
1117
|
+
async listByPublicExam(input) {
|
|
1118
|
+
const hasLanguage = Boolean(input.language && input.language !== "All" && input.language !== "Any");
|
|
1119
|
+
const hasDifficulty = Boolean(input.difficulty && input.difficulty !== "All");
|
|
1120
|
+
const filter = {};
|
|
1121
|
+
const targetLimit = _nullishCoalesce(input.limit, () => ( 12));
|
|
1122
|
+
const executeQuery = async (pageLimit, nextToken) => {
|
|
1123
|
+
if (hasLanguage) {
|
|
1124
|
+
const rangeKey = hasDifficulty ? `${input.language}#${input.difficulty}#` : `${input.language}#`;
|
|
1125
|
+
const variables = {
|
|
1126
|
+
publicExam: input.publicExam,
|
|
1127
|
+
language_difficulty_createdAt: { beginsWith: rangeKey },
|
|
1128
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
1129
|
+
limit: pageLimit,
|
|
1130
|
+
nextToken,
|
|
1131
|
+
...Object.keys(filter).length > 0 ? { filter } : {}
|
|
1132
|
+
};
|
|
1133
|
+
try {
|
|
1134
|
+
const result2 = await this.network.query(
|
|
1135
|
+
`query ListPacksByPublicExamAndLangDiff($publicExam: String!, $language_difficulty_createdAt: ModelStringKeyConditionInput, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelPackFilterInput) {
|
|
1136
|
+
listPackByPublicExamAndLanguage_difficulty_createdAt(publicExam: $publicExam, language_difficulty_createdAt: $language_difficulty_createdAt, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
1137
|
+
items {
|
|
1138
|
+
id name language level publicExam difficulty questionCount owner createdAt verificationStatus subjectId chapterId topicId
|
|
1139
|
+
tags { items { id tagId } }
|
|
1140
|
+
}
|
|
1141
|
+
nextToken
|
|
1142
|
+
}
|
|
1143
|
+
}`,
|
|
1144
|
+
variables
|
|
1145
|
+
);
|
|
1146
|
+
if (_optionalChain([result2, 'access', _15 => _15.data, 'optionalAccess', _16 => _16.listPackByPublicExamAndLanguage_difficulty_createdAt])) {
|
|
1147
|
+
return result2.data.listPackByPublicExamAndLanguage_difficulty_createdAt;
|
|
571
1148
|
}
|
|
572
|
-
|
|
1149
|
+
} catch (e3) {
|
|
573
1150
|
}
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
1151
|
+
}
|
|
1152
|
+
const fallbackFilter = { ...filter };
|
|
1153
|
+
if (hasLanguage) {
|
|
1154
|
+
fallbackFilter.language = { eq: input.language };
|
|
1155
|
+
}
|
|
1156
|
+
if (hasDifficulty) {
|
|
1157
|
+
fallbackFilter.difficulty = { eq: input.difficulty };
|
|
1158
|
+
}
|
|
1159
|
+
try {
|
|
1160
|
+
const variables = {
|
|
1161
|
+
publicExam: input.publicExam,
|
|
1162
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
1163
|
+
limit: pageLimit,
|
|
1164
|
+
nextToken,
|
|
1165
|
+
...Object.keys(fallbackFilter).length > 0 ? { filter: fallbackFilter } : {}
|
|
1166
|
+
};
|
|
1167
|
+
const result2 = await this.network.query(
|
|
1168
|
+
`query ListPacksByPublicExam($publicExam: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelPackFilterInput) {
|
|
1169
|
+
listPackByPublicExamAndCreatedAt(publicExam: $publicExam, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
1170
|
+
items {
|
|
1171
|
+
id name language level publicExam difficulty questionCount owner createdAt verificationStatus subjectId chapterId topicId
|
|
1172
|
+
tags { items { id tagId } }
|
|
1173
|
+
}
|
|
1174
|
+
nextToken
|
|
1175
|
+
}
|
|
1176
|
+
}`,
|
|
1177
|
+
variables
|
|
1178
|
+
);
|
|
1179
|
+
if (_optionalChain([result2, 'access', _17 => _17.data, 'optionalAccess', _18 => _18.listPackByPublicExamAndCreatedAt])) {
|
|
1180
|
+
return result2.data.listPackByPublicExamAndCreatedAt;
|
|
1181
|
+
}
|
|
1182
|
+
} catch (e4) {
|
|
1183
|
+
}
|
|
1184
|
+
const scanFilter = {
|
|
1185
|
+
publicExam: { eq: input.publicExam },
|
|
1186
|
+
...fallbackFilter
|
|
1187
|
+
};
|
|
1188
|
+
const result = await this.network.query(
|
|
1189
|
+
`query ListPacksFallback($filter: ModelPackFilterInput, $limit: Int, $nextToken: String) {
|
|
1190
|
+
listPacks(filter: $filter, limit: $limit, nextToken: $nextToken) {
|
|
1191
|
+
items {
|
|
1192
|
+
id name language level publicExam difficulty questionCount owner createdAt verificationStatus subjectId chapterId topicId
|
|
1193
|
+
tags { items { id tagId } }
|
|
586
1194
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
1195
|
+
nextToken
|
|
1196
|
+
}
|
|
1197
|
+
}`,
|
|
1198
|
+
{ filter: scanFilter, limit: pageLimit, nextToken }
|
|
1199
|
+
);
|
|
1200
|
+
return result.data.listPacks;
|
|
1201
|
+
};
|
|
1202
|
+
const hasPostFilter = hasLanguage ? Object.keys(filter).length > 0 : Object.keys(filter).length > 0 || hasLanguage || hasDifficulty;
|
|
1203
|
+
if (!hasPostFilter) {
|
|
1204
|
+
return executeQuery(targetLimit, input.nextToken);
|
|
1205
|
+
}
|
|
1206
|
+
return paginateWithAccumulator(executeQuery, targetLimit, input.nextToken);
|
|
1207
|
+
}
|
|
1208
|
+
async listByLevel(input) {
|
|
1209
|
+
const hasLanguage = Boolean(input.language && input.language !== "All" && input.language !== "Any");
|
|
1210
|
+
const hasDifficulty = Boolean(input.difficulty && input.difficulty !== "All");
|
|
1211
|
+
const filter = {};
|
|
1212
|
+
if (input.publicExam) {
|
|
1213
|
+
filter.publicExam = { eq: input.publicExam };
|
|
1214
|
+
}
|
|
1215
|
+
const targetLimit = _nullishCoalesce(input.limit, () => ( 12));
|
|
1216
|
+
const executeQuery = async (pageLimit, nextToken) => {
|
|
1217
|
+
if (hasLanguage) {
|
|
1218
|
+
const rangeKey = hasDifficulty ? `${input.language}#${input.difficulty}#` : `${input.language}#`;
|
|
1219
|
+
const variables = {
|
|
1220
|
+
level: input.level,
|
|
1221
|
+
language_difficulty_createdAt: { beginsWith: rangeKey },
|
|
1222
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
1223
|
+
limit: pageLimit,
|
|
1224
|
+
nextToken,
|
|
1225
|
+
...Object.keys(filter).length > 0 ? { filter } : {}
|
|
1226
|
+
};
|
|
1227
|
+
const result = await this.network.query(
|
|
1228
|
+
`query ListPacksByLevelAndLangDiff($level: String!, $language_difficulty_createdAt: ModelStringKeyConditionInput, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelPackFilterInput) {
|
|
1229
|
+
listPackByLevelAndLanguage_difficulty_createdAt(level: $level, language_difficulty_createdAt: $language_difficulty_createdAt, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
1230
|
+
items {
|
|
1231
|
+
id name language level publicExam difficulty questionCount owner createdAt verificationStatus subjectId chapterId topicId
|
|
1232
|
+
tags { items { id tagId } }
|
|
1233
|
+
}
|
|
1234
|
+
nextToken
|
|
590
1235
|
}
|
|
591
1236
|
}`,
|
|
592
|
-
|
|
1237
|
+
variables
|
|
1238
|
+
);
|
|
1239
|
+
return result.data.listPackByLevelAndLanguage_difficulty_createdAt;
|
|
1240
|
+
} else {
|
|
1241
|
+
const queryFilter = { ...filter };
|
|
1242
|
+
if (hasDifficulty) {
|
|
1243
|
+
queryFilter.difficulty = { eq: input.difficulty };
|
|
1244
|
+
}
|
|
1245
|
+
const variables = {
|
|
1246
|
+
level: input.level,
|
|
1247
|
+
sortDirection: _nullishCoalesce(input.sortDirection, () => ( "DESC")),
|
|
1248
|
+
limit: pageLimit,
|
|
1249
|
+
nextToken,
|
|
1250
|
+
...Object.keys(queryFilter).length > 0 ? { filter: queryFilter } : {}
|
|
1251
|
+
};
|
|
1252
|
+
const result = await this.network.query(
|
|
1253
|
+
`query ListPacksByLevel($level: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String, $filter: ModelPackFilterInput) {
|
|
1254
|
+
listPackByLevelAndCreatedAt(level: $level, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
1255
|
+
items {
|
|
1256
|
+
id name language level publicExam difficulty questionCount owner createdAt verificationStatus subjectId chapterId topicId
|
|
1257
|
+
tags { items { id tagId } }
|
|
1258
|
+
}
|
|
1259
|
+
nextToken
|
|
1260
|
+
}
|
|
1261
|
+
}`,
|
|
1262
|
+
variables
|
|
1263
|
+
);
|
|
1264
|
+
return result.data.listPackByLevelAndCreatedAt;
|
|
1265
|
+
}
|
|
1266
|
+
};
|
|
1267
|
+
const hasPostFilter = hasLanguage ? Object.keys(filter).length > 0 : Object.keys(filter).length > 0 || hasDifficulty;
|
|
1268
|
+
if (!hasPostFilter) {
|
|
1269
|
+
return executeQuery(targetLimit, input.nextToken);
|
|
1270
|
+
}
|
|
1271
|
+
return paginateWithAccumulator(executeQuery, targetLimit, input.nextToken);
|
|
1272
|
+
}
|
|
1273
|
+
async createGroup(input) {
|
|
1274
|
+
const typeLevel = input.type && input.level ? `${input.type}_${input.level}` : void 0;
|
|
1275
|
+
const mutationInput = {
|
|
1276
|
+
name: input.name,
|
|
1277
|
+
description: input.description,
|
|
1278
|
+
imageUrl: input.imageUrl,
|
|
1279
|
+
type: input.type,
|
|
1280
|
+
level: input.level,
|
|
1281
|
+
typeLevel,
|
|
1282
|
+
order: input.order
|
|
1283
|
+
};
|
|
1284
|
+
const result = await this.network.mutate(
|
|
1285
|
+
`mutation CreatePackGroup($input: CreatePackGroupInput!) {
|
|
1286
|
+
createPackGroup(input: $input) {
|
|
1287
|
+
id name description imageUrl type level typeLevel packCount order
|
|
1288
|
+
}
|
|
1289
|
+
}`,
|
|
1290
|
+
{ input: mutationInput }
|
|
1291
|
+
);
|
|
1292
|
+
const created = result.data.createPackGroup;
|
|
1293
|
+
if (created && input.packIds && input.packIds.length > 0) {
|
|
1294
|
+
await Promise.all(
|
|
1295
|
+
input.packIds.map((pId) => this.update(pId, { packGroupId: created.id }))
|
|
1296
|
+
);
|
|
1297
|
+
}
|
|
1298
|
+
return created;
|
|
1299
|
+
}
|
|
1300
|
+
async deleteGroup(id) {
|
|
1301
|
+
const result = await this.network.mutate(
|
|
1302
|
+
`mutation DeletePackGroup($input: DeletePackGroupInput!) {
|
|
1303
|
+
deletePackGroup(input: $input) {
|
|
1304
|
+
id
|
|
1305
|
+
}
|
|
1306
|
+
}`,
|
|
1307
|
+
{ input: { id } }
|
|
593
1308
|
);
|
|
594
|
-
return result.data
|
|
1309
|
+
return result.data.deletePackGroup;
|
|
1310
|
+
}
|
|
1311
|
+
async listGroups(typeOrInput, level) {
|
|
1312
|
+
let type;
|
|
1313
|
+
let targetLevel;
|
|
1314
|
+
let limit;
|
|
1315
|
+
let nextToken;
|
|
1316
|
+
let sortDirection = "ASC";
|
|
1317
|
+
const isLegacyCall = typeof typeOrInput === "string";
|
|
1318
|
+
if (isLegacyCall) {
|
|
1319
|
+
type = typeOrInput;
|
|
1320
|
+
targetLevel = level;
|
|
1321
|
+
} else {
|
|
1322
|
+
type = _nullishCoalesce(typeOrInput.type, () => ( "QB"));
|
|
1323
|
+
targetLevel = typeOrInput.level;
|
|
1324
|
+
limit = typeOrInput.limit;
|
|
1325
|
+
nextToken = typeOrInput.nextToken;
|
|
1326
|
+
sortDirection = _nullishCoalesce(typeOrInput.sortDirection, () => ( "ASC"));
|
|
1327
|
+
}
|
|
1328
|
+
const queryField = targetLevel ? "listPackGroupByTypeLevelAndOrder" : "listPackGroupByTypeAndOrder";
|
|
1329
|
+
const variables = isLegacyCall ? targetLevel ? { typeLevel: `${type}_${targetLevel}`, sortDirection } : { type, sortDirection } : targetLevel ? { typeLevel: `${type}_${targetLevel}`, sortDirection, limit: _nullishCoalesce(limit, () => ( 20)), nextToken } : { type, sortDirection, limit: _nullishCoalesce(limit, () => ( 20)), nextToken };
|
|
1330
|
+
const queryString = isLegacyCall ? targetLevel ? `query ListPackGroups($typeLevel: String!, $sortDirection: ModelSortDirection) {
|
|
1331
|
+
listPackGroupByTypeLevelAndOrder(typeLevel: $typeLevel, sortDirection: $sortDirection) {
|
|
1332
|
+
items { id name description imageUrl type level typeLevel packCount order }
|
|
1333
|
+
}
|
|
1334
|
+
}` : `query ListPackGroups($type: String!, $sortDirection: ModelSortDirection) {
|
|
1335
|
+
listPackGroupByTypeAndOrder(type: $type, sortDirection: $sortDirection) {
|
|
1336
|
+
items { id name description imageUrl type level typeLevel packCount order }
|
|
1337
|
+
}
|
|
1338
|
+
}` : targetLevel ? `query ListPackGroupsByLevel($typeLevel: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String) {
|
|
1339
|
+
listPackGroupByTypeLevelAndOrder(typeLevel: $typeLevel, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken) {
|
|
1340
|
+
items { id name description imageUrl type level typeLevel packCount order }
|
|
1341
|
+
nextToken
|
|
1342
|
+
}
|
|
1343
|
+
}` : `query ListPackGroupsByType($type: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String) {
|
|
1344
|
+
listPackGroupByTypeAndOrder(type: $type, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken) {
|
|
1345
|
+
items { id name description imageUrl type level typeLevel packCount order }
|
|
1346
|
+
nextToken
|
|
1347
|
+
}
|
|
1348
|
+
}`;
|
|
1349
|
+
const result = await this.network.query(queryString, variables);
|
|
1350
|
+
const paginated = result.data[queryField];
|
|
1351
|
+
return isLegacyCall ? paginated.items : paginated;
|
|
595
1352
|
}
|
|
596
1353
|
async getGroup(id) {
|
|
597
1354
|
const result = await this.network.query(
|
|
598
1355
|
`query GetPackGroup($id: ID!) {
|
|
599
1356
|
getPackGroup(id: $id) {
|
|
600
1357
|
id name description imageUrl type level typeLevel packCount order
|
|
601
|
-
packs { items { id name language level difficulty questionCount owner createdAt verificationStatus } }
|
|
1358
|
+
packs { items { id name language level publicExam difficulty questionCount owner createdAt verificationStatus } }
|
|
602
1359
|
}
|
|
603
1360
|
}`,
|
|
604
1361
|
{ id }
|
|
605
1362
|
);
|
|
606
1363
|
return result.data.getPackGroup;
|
|
607
1364
|
}
|
|
1365
|
+
async list(input) {
|
|
1366
|
+
const result = await this.network.query(
|
|
1367
|
+
`query ListPacks($limit: Int, $nextToken: String) {
|
|
1368
|
+
listPacks(limit: $limit, nextToken: $nextToken) {
|
|
1369
|
+
items {
|
|
1370
|
+
id name language level publicExam difficulty questionCount owner createdAt verificationStatus packGroupId
|
|
1371
|
+
}
|
|
1372
|
+
nextToken
|
|
1373
|
+
}
|
|
1374
|
+
}`,
|
|
1375
|
+
{ limit: _nullishCoalesce(_optionalChain([input, 'optionalAccess', _19 => _19.limit]), () => ( 20)), nextToken: _optionalChain([input, 'optionalAccess', _20 => _20.nextToken]) }
|
|
1376
|
+
);
|
|
1377
|
+
return result.data.listPacks;
|
|
1378
|
+
}
|
|
608
1379
|
};
|
|
609
1380
|
|
|
610
1381
|
// src/services/contest.service.ts
|
|
@@ -641,7 +1412,7 @@ var ContestService = class {
|
|
|
641
1412
|
`query GetContestName($id: ID!) { getContest(id: $id) { name } }`,
|
|
642
1413
|
{ id }
|
|
643
1414
|
);
|
|
644
|
-
return _nullishCoalesce(_optionalChain([result, 'access',
|
|
1415
|
+
return _nullishCoalesce(_optionalChain([result, 'access', _21 => _21.data, 'access', _22 => _22.getContest, 'optionalAccess', _23 => _23.name]), () => ( null));
|
|
645
1416
|
}
|
|
646
1417
|
async list(nextToken, level) {
|
|
647
1418
|
const variables = level ? { level, sortDirection: "DESC", nextToken } : { globalPk: "ALL", sortDirection: "DESC", nextToken };
|
|
@@ -962,6 +1733,28 @@ var CourseService = class {
|
|
|
962
1733
|
);
|
|
963
1734
|
return result.data.publishCourseLiveExamResults;
|
|
964
1735
|
}
|
|
1736
|
+
async uploadCourseItem(input) {
|
|
1737
|
+
const signed = await this.getSignedURL({
|
|
1738
|
+
courseId: input.courseId,
|
|
1739
|
+
fileName: input.fileName,
|
|
1740
|
+
fileType: input.fileType,
|
|
1741
|
+
parentId: _nullishCoalesce(input.parentId, () => ( void 0))
|
|
1742
|
+
});
|
|
1743
|
+
if (signed && signed.signedURL && input.fileData) {
|
|
1744
|
+
await fetch(signed.signedURL, {
|
|
1745
|
+
method: "PUT",
|
|
1746
|
+
body: input.fileData,
|
|
1747
|
+
headers: { "Content-Type": input.fileType }
|
|
1748
|
+
});
|
|
1749
|
+
}
|
|
1750
|
+
return this.createItem({
|
|
1751
|
+
courseId: input.courseId,
|
|
1752
|
+
name: input.itemName || input.fileName,
|
|
1753
|
+
order: input.itemOrder,
|
|
1754
|
+
type: "file",
|
|
1755
|
+
parentId: _nullishCoalesce(input.parentId, () => ( void 0))
|
|
1756
|
+
});
|
|
1757
|
+
}
|
|
965
1758
|
};
|
|
966
1759
|
|
|
967
1760
|
// src/services/curriculum.service.ts
|
|
@@ -1029,6 +1822,67 @@ var CurriculumService = class {
|
|
|
1029
1822
|
);
|
|
1030
1823
|
return result.data.listTopicByChapterId.items;
|
|
1031
1824
|
}
|
|
1825
|
+
async recalculateQuestionCounts() {
|
|
1826
|
+
let nextToken = null;
|
|
1827
|
+
const counts = {};
|
|
1828
|
+
do {
|
|
1829
|
+
const res = await this.network.query(
|
|
1830
|
+
`query ListQuestionsForRecalc($nextToken: String) {
|
|
1831
|
+
listQuestionObjects(limit: 1000, nextToken: $nextToken) {
|
|
1832
|
+
items { id subjectId chapterId topicId }
|
|
1833
|
+
nextToken
|
|
1834
|
+
}
|
|
1835
|
+
}`,
|
|
1836
|
+
{ nextToken }
|
|
1837
|
+
);
|
|
1838
|
+
const items = _optionalChain([res, 'access', _24 => _24.data, 'optionalAccess', _25 => _25.listQuestionObjects, 'optionalAccess', _26 => _26.items]) || [];
|
|
1839
|
+
for (const q of items) {
|
|
1840
|
+
if (q.subjectId) counts[q.subjectId] = (counts[q.subjectId] || 0) + 1;
|
|
1841
|
+
}
|
|
1842
|
+
nextToken = _nullishCoalesce(_optionalChain([res, 'access', _27 => _27.data, 'optionalAccess', _28 => _28.listQuestionObjects, 'optionalAccess', _29 => _29.nextToken]), () => ( null));
|
|
1843
|
+
} while (nextToken);
|
|
1844
|
+
const [hscSubjects, sscSubjects] = await Promise.all([
|
|
1845
|
+
this.getSubjects("HSC").catch(() => []),
|
|
1846
|
+
this.getSubjects("SSC").catch(() => [])
|
|
1847
|
+
]);
|
|
1848
|
+
const allSubjects = [...hscSubjects, ...sscSubjects];
|
|
1849
|
+
for (const s of allSubjects) {
|
|
1850
|
+
await this.network.mutate(
|
|
1851
|
+
`mutation UpdateSubjectCount($input: UpdateSubjectInput!) {
|
|
1852
|
+
updateSubject(input: $input) { id }
|
|
1853
|
+
}`,
|
|
1854
|
+
{ input: { id: s.id, questionCount: counts[s.id] || 0 } }
|
|
1855
|
+
);
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
async recalculateCreatorStats() {
|
|
1859
|
+
let nextToken = null;
|
|
1860
|
+
const userQuestionCounts = {};
|
|
1861
|
+
do {
|
|
1862
|
+
const res = await this.network.query(
|
|
1863
|
+
`query ListQuestionsForCreatorStats($nextToken: String) {
|
|
1864
|
+
listQuestionObjects(limit: 1000, nextToken: $nextToken) {
|
|
1865
|
+
items { id owner }
|
|
1866
|
+
nextToken
|
|
1867
|
+
}
|
|
1868
|
+
}`,
|
|
1869
|
+
{ nextToken }
|
|
1870
|
+
);
|
|
1871
|
+
const items = _optionalChain([res, 'access', _30 => _30.data, 'optionalAccess', _31 => _31.listQuestionObjects, 'optionalAccess', _32 => _32.items]) || [];
|
|
1872
|
+
for (const q of items) {
|
|
1873
|
+
if (q.owner) userQuestionCounts[q.owner] = (userQuestionCounts[q.owner] || 0) + 1;
|
|
1874
|
+
}
|
|
1875
|
+
nextToken = _nullishCoalesce(_optionalChain([res, 'access', _33 => _33.data, 'optionalAccess', _34 => _34.listQuestionObjects, 'optionalAccess', _35 => _35.nextToken]), () => ( null));
|
|
1876
|
+
} while (nextToken);
|
|
1877
|
+
for (const [userId, count] of Object.entries(userQuestionCounts)) {
|
|
1878
|
+
await this.network.mutate(
|
|
1879
|
+
`mutation UpdateCreatorStats($input: UpdateUserInput!) {
|
|
1880
|
+
updateUser(input: $input) { id }
|
|
1881
|
+
}`,
|
|
1882
|
+
{ input: { id: userId, questionCount: count } }
|
|
1883
|
+
);
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1032
1886
|
};
|
|
1033
1887
|
|
|
1034
1888
|
// src/services/media.service.ts
|
|
@@ -1053,7 +1907,7 @@ var MediaService = class {
|
|
|
1053
1907
|
JSON.stringify(result.errors, null, 2)
|
|
1054
1908
|
);
|
|
1055
1909
|
}
|
|
1056
|
-
const response = _optionalChain([result, 'access',
|
|
1910
|
+
const response = _optionalChain([result, 'access', _36 => _36.data, 'optionalAccess', _37 => _37.uploadImage]);
|
|
1057
1911
|
if (!response) {
|
|
1058
1912
|
console.error(`[MediaService.uploadImage] No uploadImage object returned in GraphQL response for questionId "${questionId}". Full result:`, result);
|
|
1059
1913
|
} else if (response.status === "Error" || response.status === "error" || !response.imageUrl) {
|
|
@@ -1141,7 +1995,7 @@ var ProgressService = class {
|
|
|
1141
1995
|
}`,
|
|
1142
1996
|
variables
|
|
1143
1997
|
);
|
|
1144
|
-
return _optionalChain([result, 'access',
|
|
1998
|
+
return _optionalChain([result, 'access', _38 => _38.data, 'optionalAccess', _39 => _39.trackPracticeProgress]) || { status: "success" };
|
|
1145
1999
|
}
|
|
1146
2000
|
async getSubjectProgress(userId) {
|
|
1147
2001
|
try {
|
|
@@ -1153,7 +2007,7 @@ var ProgressService = class {
|
|
|
1153
2007
|
}`,
|
|
1154
2008
|
{ userId }
|
|
1155
2009
|
);
|
|
1156
|
-
return _optionalChain([result, 'access',
|
|
2010
|
+
return _optionalChain([result, 'access', _40 => _40.data, 'optionalAccess', _41 => _41.listUserSubjectProgressByUserIdAndSubjectId, 'optionalAccess', _42 => _42.items]) || _optionalChain([result, 'access', _43 => _43.data, 'optionalAccess', _44 => _44.listUserSubjectProgressesByUserIdAndSubjectId, 'optionalAccess', _45 => _45.items]) || [];
|
|
1157
2011
|
} catch (e) {
|
|
1158
2012
|
console.error("Error fetching subject progress:", e);
|
|
1159
2013
|
return [];
|
|
@@ -1169,7 +2023,7 @@ var ProgressService = class {
|
|
|
1169
2023
|
}`,
|
|
1170
2024
|
{ userId }
|
|
1171
2025
|
);
|
|
1172
|
-
return _optionalChain([result, 'access',
|
|
2026
|
+
return _optionalChain([result, 'access', _46 => _46.data, 'optionalAccess', _47 => _47.listUserChapterProgressByUserIdAndChapterId, 'optionalAccess', _48 => _48.items]) || _optionalChain([result, 'access', _49 => _49.data, 'optionalAccess', _50 => _50.listUserChapterProgressesByUserIdAndChapterId, 'optionalAccess', _51 => _51.items]) || [];
|
|
1173
2027
|
} catch (e) {
|
|
1174
2028
|
console.error("Error fetching chapter progress:", e);
|
|
1175
2029
|
return [];
|
|
@@ -1185,7 +2039,7 @@ var ProgressService = class {
|
|
|
1185
2039
|
}`,
|
|
1186
2040
|
{ userId }
|
|
1187
2041
|
);
|
|
1188
|
-
return _optionalChain([result, 'access',
|
|
2042
|
+
return _optionalChain([result, 'access', _52 => _52.data, 'optionalAccess', _53 => _53.listUserTopicProgressByUserIdAndTopicId, 'optionalAccess', _54 => _54.items]) || _optionalChain([result, 'access', _55 => _55.data, 'optionalAccess', _56 => _56.listUserTopicProgressesByUserIdAndTopicId, 'optionalAccess', _57 => _57.items]) || [];
|
|
1189
2043
|
} catch (e) {
|
|
1190
2044
|
console.error("Error fetching topic progress:", e);
|
|
1191
2045
|
return [];
|
|
@@ -1201,13 +2055,13 @@ var ProgressService = class {
|
|
|
1201
2055
|
}`,
|
|
1202
2056
|
{ filter: { userId: { eq: userId } } }
|
|
1203
2057
|
);
|
|
1204
|
-
return _optionalChain([result, 'access',
|
|
2058
|
+
return _optionalChain([result, 'access', _58 => _58.data, 'optionalAccess', _59 => _59.listUserTopicMetrics, 'optionalAccess', _60 => _60.items]) || [];
|
|
1205
2059
|
} catch (e) {
|
|
1206
2060
|
console.error("Error fetching topic metrics:", e);
|
|
1207
2061
|
return [];
|
|
1208
2062
|
}
|
|
1209
2063
|
}
|
|
1210
|
-
async getMistakenQuestions(userId) {
|
|
2064
|
+
async getMistakenQuestions(userId, status = "MISTAKE") {
|
|
1211
2065
|
try {
|
|
1212
2066
|
const result = await this.network.query(
|
|
1213
2067
|
`query ListMistakes($userId: String!, $filter: ModelQuestionTrackingFilterInput) {
|
|
@@ -1215,14 +2069,17 @@ var ProgressService = class {
|
|
|
1215
2069
|
items { id userId questionId subjectId chapterId topicId status attempts }
|
|
1216
2070
|
}
|
|
1217
2071
|
}`,
|
|
1218
|
-
{ userId, filter: { status: { eq:
|
|
2072
|
+
{ userId, filter: { status: { eq: status } } }
|
|
1219
2073
|
);
|
|
1220
|
-
return _optionalChain([result, 'access',
|
|
2074
|
+
return _optionalChain([result, 'access', _61 => _61.data, 'optionalAccess', _62 => _62.listQuestionTrackingByUserIdAndQuestionId, 'optionalAccess', _63 => _63.items]) || _optionalChain([result, 'access', _64 => _64.data, 'optionalAccess', _65 => _65.listQuestionTrackingsByUserIdAndQuestionId, 'optionalAccess', _66 => _66.items]) || _optionalChain([result, 'access', _67 => _67.data, 'optionalAccess', _68 => _68.listQuestionTrackings, 'optionalAccess', _69 => _69.items]) || [];
|
|
1221
2075
|
} catch (e) {
|
|
1222
2076
|
console.error("Error fetching mistaken questions:", e);
|
|
1223
2077
|
return [];
|
|
1224
2078
|
}
|
|
1225
2079
|
}
|
|
2080
|
+
async getCorrectedQuestions(userId) {
|
|
2081
|
+
return this.getMistakenQuestions(userId, "CORRECTED");
|
|
2082
|
+
}
|
|
1226
2083
|
};
|
|
1227
2084
|
|
|
1228
2085
|
// src/services/ai.service.ts
|
|
@@ -1230,7 +2087,27 @@ var AIService = class {
|
|
|
1230
2087
|
constructor(network) {
|
|
1231
2088
|
this.network = network;
|
|
1232
2089
|
}
|
|
1233
|
-
async evaluateWrittenAnswer(input) {
|
|
2090
|
+
async evaluateWrittenAnswer(input, options) {
|
|
2091
|
+
if (_optionalChain([options, 'optionalAccess', _70 => _70.functionUrl])) {
|
|
2092
|
+
try {
|
|
2093
|
+
const headers = { "Content-Type": "application/json" };
|
|
2094
|
+
if (options.authToken) {
|
|
2095
|
+
headers["Authorization"] = `Bearer ${options.authToken}`;
|
|
2096
|
+
}
|
|
2097
|
+
const response = await fetch(options.functionUrl, {
|
|
2098
|
+
method: "POST",
|
|
2099
|
+
headers,
|
|
2100
|
+
body: JSON.stringify(input)
|
|
2101
|
+
});
|
|
2102
|
+
if (response.ok) {
|
|
2103
|
+
const data = await response.json();
|
|
2104
|
+
return data;
|
|
2105
|
+
}
|
|
2106
|
+
console.warn(`[AIService] Function URL failed with status ${response.status}, falling back to GraphQL...`);
|
|
2107
|
+
} catch (err) {
|
|
2108
|
+
console.warn("[AIService] Function URL fetch error, falling back to GraphQL...", err);
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
1234
2111
|
const result = await this.network.query(
|
|
1235
2112
|
`query EvaluateWrittenAnswer($question: String!, $userAnswer: String!, $correctAnswer: String!, $markingInstructions: String, $topicId: String, $topicName: String, $questionImageUrl: String) {
|
|
1236
2113
|
evaluateWrittenAnswer(question: $question, userAnswer: $userAnswer, correctAnswer: $correctAnswer, markingInstructions: $markingInstructions, topicId: $topicId, topicName: $topicName, questionImageUrl: $questionImageUrl) {
|
|
@@ -1280,10 +2157,256 @@ var NewsService = class {
|
|
|
1280
2157
|
}
|
|
1281
2158
|
};
|
|
1282
2159
|
|
|
2160
|
+
// src/services/notification.service.ts
|
|
2161
|
+
var NotificationService = class {
|
|
2162
|
+
constructor(network) {
|
|
2163
|
+
this.network = network;
|
|
2164
|
+
}
|
|
2165
|
+
/**
|
|
2166
|
+
* List broadcast announcements (ordered by category and createdAt).
|
|
2167
|
+
*/
|
|
2168
|
+
async listAnnouncements(limit = 20, nextToken) {
|
|
2169
|
+
const result = await this.network.query(
|
|
2170
|
+
`query ListAnnouncements($limit: Int, $nextToken: String) {
|
|
2171
|
+
listAnnouncements(limit: $limit, nextToken: $nextToken) {
|
|
2172
|
+
items {
|
|
2173
|
+
id title message senderType senderName senderAvatar category actionUrl priority createdAt updatedAt
|
|
2174
|
+
}
|
|
2175
|
+
nextToken
|
|
2176
|
+
}
|
|
2177
|
+
}`,
|
|
2178
|
+
{ limit, nextToken }
|
|
2179
|
+
);
|
|
2180
|
+
return _nullishCoalesce(result.data.listAnnouncements, () => ( { items: [], nextToken: null }));
|
|
2181
|
+
}
|
|
2182
|
+
/**
|
|
2183
|
+
* List announcements by category.
|
|
2184
|
+
*/
|
|
2185
|
+
async listAnnouncementsByCategory(category = "ANNOUNCEMENT", limit = 20, nextToken) {
|
|
2186
|
+
const result = await this.network.query(
|
|
2187
|
+
`query ListAnnouncementsByCategory($category: String!, $limit: Int, $nextToken: String, $sortDirection: ModelSortDirection) {
|
|
2188
|
+
listAnnouncementByCategoryAndCreatedAt(category: $category, limit: $limit, nextToken: $nextToken, sortDirection: $sortDirection) {
|
|
2189
|
+
items {
|
|
2190
|
+
id title message senderType senderName senderAvatar category actionUrl priority createdAt updatedAt
|
|
2191
|
+
}
|
|
2192
|
+
nextToken
|
|
2193
|
+
}
|
|
2194
|
+
}`,
|
|
2195
|
+
{ category, limit, nextToken, sortDirection: "DESC" }
|
|
2196
|
+
);
|
|
2197
|
+
return _nullishCoalesce(result.data.listAnnouncementByCategoryAndCreatedAt, () => ( {
|
|
2198
|
+
items: [],
|
|
2199
|
+
nextToken: null
|
|
2200
|
+
}));
|
|
2201
|
+
}
|
|
2202
|
+
/**
|
|
2203
|
+
* Create an announcement (Admins only).
|
|
2204
|
+
*/
|
|
2205
|
+
async createAnnouncement(input) {
|
|
2206
|
+
const result = await this.network.mutate(
|
|
2207
|
+
`mutation CreateAnnouncement($input: CreateAnnouncementInput!) {
|
|
2208
|
+
createAnnouncement(input: $input) {
|
|
2209
|
+
id title message senderType senderName senderAvatar category actionUrl priority createdAt updatedAt
|
|
2210
|
+
}
|
|
2211
|
+
}`,
|
|
2212
|
+
{
|
|
2213
|
+
input: {
|
|
2214
|
+
...input,
|
|
2215
|
+
senderType: input.senderType || "ORJOK",
|
|
2216
|
+
category: input.category || "ANNOUNCEMENT",
|
|
2217
|
+
priority: input.priority || "NORMAL"
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
);
|
|
2221
|
+
return result.data.createAnnouncement;
|
|
2222
|
+
}
|
|
2223
|
+
/**
|
|
2224
|
+
* Delete an announcement (Admins only).
|
|
2225
|
+
*/
|
|
2226
|
+
async deleteAnnouncement(id) {
|
|
2227
|
+
const result = await this.network.mutate(
|
|
2228
|
+
`mutation DeleteAnnouncement($input: DeleteAnnouncementInput!) {
|
|
2229
|
+
deleteAnnouncement(input: $input) { id }
|
|
2230
|
+
}`,
|
|
2231
|
+
{ input: { id } }
|
|
2232
|
+
);
|
|
2233
|
+
return Boolean(_optionalChain([result, 'access', _71 => _71.data, 'access', _72 => _72.deleteAnnouncement, 'optionalAccess', _73 => _73.id]));
|
|
2234
|
+
}
|
|
2235
|
+
/**
|
|
2236
|
+
* List user notifications for a specific user ID.
|
|
2237
|
+
*/
|
|
2238
|
+
async listUserNotifications(userId, limit = 20, nextToken) {
|
|
2239
|
+
const result = await this.network.query(
|
|
2240
|
+
`query ListUserNotifications($userId: ID!, $limit: Int, $nextToken: String, $sortDirection: ModelSortDirection) {
|
|
2241
|
+
listUserNotificationByUserIdAndCreatedAt(userId: $userId, limit: $limit, nextToken: $nextToken, sortDirection: $sortDirection) {
|
|
2242
|
+
items {
|
|
2243
|
+
id userId title message type senderType senderName senderAvatar actionUrl isRead readAt metadata createdAt updatedAt
|
|
2244
|
+
}
|
|
2245
|
+
nextToken
|
|
2246
|
+
}
|
|
2247
|
+
}`,
|
|
2248
|
+
{ userId, limit, nextToken, sortDirection: "DESC" }
|
|
2249
|
+
);
|
|
2250
|
+
return _nullishCoalesce(result.data.listUserNotificationByUserIdAndCreatedAt, () => ( {
|
|
2251
|
+
items: [],
|
|
2252
|
+
nextToken: null
|
|
2253
|
+
}));
|
|
2254
|
+
}
|
|
2255
|
+
/**
|
|
2256
|
+
* Create a user notification (Level up, direct message, system alert).
|
|
2257
|
+
*/
|
|
2258
|
+
async createUserNotification(input) {
|
|
2259
|
+
const result = await this.network.mutate(
|
|
2260
|
+
`mutation CreateUserNotification($input: CreateUserNotificationInput!) {
|
|
2261
|
+
createUserNotification(input: $input) {
|
|
2262
|
+
id userId title message type senderType senderName senderAvatar actionUrl isRead readAt metadata createdAt updatedAt
|
|
2263
|
+
}
|
|
2264
|
+
}`,
|
|
2265
|
+
{
|
|
2266
|
+
input: {
|
|
2267
|
+
...input,
|
|
2268
|
+
isRead: false
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
);
|
|
2272
|
+
return result.data.createUserNotification;
|
|
2273
|
+
}
|
|
2274
|
+
/**
|
|
2275
|
+
* Mark a personal notification as read.
|
|
2276
|
+
*/
|
|
2277
|
+
async markNotificationAsRead(id) {
|
|
2278
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2279
|
+
const result = await this.network.mutate(
|
|
2280
|
+
`mutation UpdateUserNotification($input: UpdateUserNotificationInput!) {
|
|
2281
|
+
updateUserNotification(input: $input) {
|
|
2282
|
+
id isRead readAt
|
|
2283
|
+
}
|
|
2284
|
+
}`,
|
|
2285
|
+
{
|
|
2286
|
+
input: {
|
|
2287
|
+
id,
|
|
2288
|
+
isRead: true,
|
|
2289
|
+
readAt: now
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
);
|
|
2293
|
+
return result.data.updateUserNotification;
|
|
2294
|
+
}
|
|
2295
|
+
/**
|
|
2296
|
+
* Delete a personal user notification.
|
|
2297
|
+
*/
|
|
2298
|
+
async deleteUserNotification(id) {
|
|
2299
|
+
const result = await this.network.mutate(
|
|
2300
|
+
`mutation DeleteUserNotification($input: DeleteUserNotificationInput!) {
|
|
2301
|
+
deleteUserNotification(input: $input) { id }
|
|
2302
|
+
}`,
|
|
2303
|
+
{ input: { id } }
|
|
2304
|
+
);
|
|
2305
|
+
return Boolean(_optionalChain([result, 'access', _74 => _74.data, 'access', _75 => _75.deleteUserNotification, 'optionalAccess', _76 => _76.id]));
|
|
2306
|
+
}
|
|
2307
|
+
/**
|
|
2308
|
+
* Update the user's lastReadAnnouncementAt timestamp in DynamoDB.
|
|
2309
|
+
*/
|
|
2310
|
+
async updateLastReadAnnouncement(userId, timestamp = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
2311
|
+
const result = await this.network.mutate(
|
|
2312
|
+
`mutation UpdateUserLastRead($input: UpdateUserInput!) {
|
|
2313
|
+
updateUser(input: $input) { id lastReadAnnouncementAt }
|
|
2314
|
+
}`,
|
|
2315
|
+
{ input: { id: userId, lastReadAnnouncementAt: timestamp } }
|
|
2316
|
+
);
|
|
2317
|
+
return Boolean(_optionalChain([result, 'access', _77 => _77.data, 'access', _78 => _78.updateUser, 'optionalAccess', _79 => _79.id]));
|
|
2318
|
+
}
|
|
2319
|
+
};
|
|
2320
|
+
|
|
2321
|
+
// src/services/subscription.service.ts
|
|
2322
|
+
var SubscriptionService = class {
|
|
2323
|
+
constructor(network) {
|
|
2324
|
+
this.network = network;
|
|
2325
|
+
}
|
|
2326
|
+
async createRequest(input) {
|
|
2327
|
+
const result = await this.network.mutate(
|
|
2328
|
+
`mutation CreateSubscriptionRequest($input: CreateSubscriptionRequestInput!) {
|
|
2329
|
+
createSubscriptionRequest(input: $input) {
|
|
2330
|
+
id userId userFullName userEmail itemType itemId itemTitle amount billingCycle paymentMethod senderPhone contactPhone trxId status aiEvals aiQuestions adminNotes processedAt processedBy createdAt updatedAt
|
|
2331
|
+
}
|
|
2332
|
+
}`,
|
|
2333
|
+
{ input }
|
|
2334
|
+
);
|
|
2335
|
+
return result.data.createSubscriptionRequest;
|
|
2336
|
+
}
|
|
2337
|
+
async getRequest(id) {
|
|
2338
|
+
const result = await this.network.query(
|
|
2339
|
+
`query GetSubscriptionRequest($id: ID!) {
|
|
2340
|
+
getSubscriptionRequest(id: $id) {
|
|
2341
|
+
id userId userFullName userEmail itemType itemId itemTitle amount billingCycle paymentMethod senderPhone contactPhone trxId status aiEvals aiQuestions adminNotes processedAt processedBy createdAt updatedAt
|
|
2342
|
+
}
|
|
2343
|
+
}`,
|
|
2344
|
+
{ id }
|
|
2345
|
+
);
|
|
2346
|
+
return result.data.getSubscriptionRequest;
|
|
2347
|
+
}
|
|
2348
|
+
async listRequests(input = {}) {
|
|
2349
|
+
const limit = _nullishCoalesce(input.limit, () => ( 20));
|
|
2350
|
+
const sortDirection = _nullishCoalesce(input.sortDirection, () => ( "DESC"));
|
|
2351
|
+
if (input.status) {
|
|
2352
|
+
const result2 = await this.network.query(
|
|
2353
|
+
`query ListSubscriptionRequestsByStatus($status: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String) {
|
|
2354
|
+
listSubscriptionRequestByStatusAndCreatedAt(status: $status, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken) {
|
|
2355
|
+
items {
|
|
2356
|
+
id userId userFullName userEmail itemType itemId itemTitle amount billingCycle paymentMethod senderPhone contactPhone trxId status aiEvals aiQuestions adminNotes processedAt processedBy createdAt updatedAt
|
|
2357
|
+
}
|
|
2358
|
+
nextToken
|
|
2359
|
+
}
|
|
2360
|
+
}`,
|
|
2361
|
+
{ status: input.status, sortDirection, limit, nextToken: input.nextToken }
|
|
2362
|
+
);
|
|
2363
|
+
return result2.data.listSubscriptionRequestByStatusAndCreatedAt;
|
|
2364
|
+
}
|
|
2365
|
+
if (input.userId) {
|
|
2366
|
+
const result2 = await this.network.query(
|
|
2367
|
+
`query ListSubscriptionRequestsByUser($userId: String!, $sortDirection: ModelSortDirection, $limit: Int, $nextToken: String) {
|
|
2368
|
+
listSubscriptionRequestByUserIdAndCreatedAt(userId: $userId, sortDirection: $sortDirection, limit: $limit, nextToken: $nextToken) {
|
|
2369
|
+
items {
|
|
2370
|
+
id userId userFullName userEmail itemType itemId itemTitle amount billingCycle paymentMethod senderPhone contactPhone trxId status aiEvals aiQuestions adminNotes processedAt processedBy createdAt updatedAt
|
|
2371
|
+
}
|
|
2372
|
+
nextToken
|
|
2373
|
+
}
|
|
2374
|
+
}`,
|
|
2375
|
+
{ userId: input.userId, sortDirection, limit, nextToken: input.nextToken }
|
|
2376
|
+
);
|
|
2377
|
+
return result2.data.listSubscriptionRequestByUserIdAndCreatedAt;
|
|
2378
|
+
}
|
|
2379
|
+
const result = await this.network.query(
|
|
2380
|
+
`query ListAllSubscriptionRequests($limit: Int, $nextToken: String, $filter: ModelSubscriptionRequestFilterInput) {
|
|
2381
|
+
listSubscriptionRequests(limit: $limit, nextToken: $nextToken, filter: $filter) {
|
|
2382
|
+
items {
|
|
2383
|
+
id userId userFullName userEmail itemType itemId itemTitle amount billingCycle paymentMethod senderPhone contactPhone trxId status aiEvals aiQuestions adminNotes processedAt processedBy createdAt updatedAt
|
|
2384
|
+
}
|
|
2385
|
+
nextToken
|
|
2386
|
+
}
|
|
2387
|
+
}`,
|
|
2388
|
+
{ limit, nextToken: input.nextToken, filter: input.filter }
|
|
2389
|
+
);
|
|
2390
|
+
return result.data.listSubscriptionRequests;
|
|
2391
|
+
}
|
|
2392
|
+
async updateRequest(input) {
|
|
2393
|
+
const result = await this.network.mutate(
|
|
2394
|
+
`mutation UpdateSubscriptionRequest($input: UpdateSubscriptionRequestInput!) {
|
|
2395
|
+
updateSubscriptionRequest(input: $input) {
|
|
2396
|
+
id userId userFullName userEmail itemType itemId itemTitle amount billingCycle paymentMethod senderPhone contactPhone trxId status aiEvals aiQuestions adminNotes processedAt processedBy createdAt updatedAt
|
|
2397
|
+
}
|
|
2398
|
+
}`,
|
|
2399
|
+
{ input }
|
|
2400
|
+
);
|
|
2401
|
+
return result.data.updateSubscriptionRequest;
|
|
2402
|
+
}
|
|
2403
|
+
};
|
|
2404
|
+
|
|
1283
2405
|
// src/client.ts
|
|
1284
2406
|
var OrjokClient = class {
|
|
1285
2407
|
constructor(config) {
|
|
1286
2408
|
this.auth = config.authProvider;
|
|
2409
|
+
this.network = config.networkProvider;
|
|
1287
2410
|
this.storage = config.storageProvider;
|
|
1288
2411
|
this.users = new UserService(config.networkProvider);
|
|
1289
2412
|
this.questions = new QuestionService(config.networkProvider);
|
|
@@ -1295,29 +2418,14 @@ var OrjokClient = class {
|
|
|
1295
2418
|
this.progress = new ProgressService(config.networkProvider);
|
|
1296
2419
|
this.ai = new AIService(config.networkProvider);
|
|
1297
2420
|
this.news = new NewsService(config.networkProvider);
|
|
2421
|
+
this.notifications = new NotificationService(config.networkProvider);
|
|
2422
|
+
this.subscriptions = new SubscriptionService(config.networkProvider);
|
|
1298
2423
|
}
|
|
1299
2424
|
};
|
|
1300
2425
|
function createOrjokClient(config) {
|
|
1301
2426
|
return new OrjokClient(config);
|
|
1302
2427
|
}
|
|
1303
2428
|
|
|
1304
|
-
// src/types/select-options.ts
|
|
1305
|
-
var levelOptions = [
|
|
1306
|
-
{ value: "SSC", label: "SSC" },
|
|
1307
|
-
{ value: "HSC+Admission", label: "HSC/Admission" },
|
|
1308
|
-
{ value: "BCS", label: "BCS" }
|
|
1309
|
-
];
|
|
1310
|
-
var languageOptions = [
|
|
1311
|
-
{ value: "Bangla", label: "Bangla" },
|
|
1312
|
-
{ value: "English", label: "English" },
|
|
1313
|
-
{ value: "Any", label: "Any" }
|
|
1314
|
-
];
|
|
1315
|
-
var difficultyOptions = [
|
|
1316
|
-
{ value: "Easy", label: "Easy" },
|
|
1317
|
-
{ value: "Medium", label: "Medium" },
|
|
1318
|
-
{ value: "Hard", label: "Hard" }
|
|
1319
|
-
];
|
|
1320
|
-
|
|
1321
2429
|
// src/logic/avatar.ts
|
|
1322
2430
|
var HAIR_COLORS = [
|
|
1323
2431
|
{ name: "Original", filter: "none", hex: "#e2e8f0", brightness: 1 },
|
|
@@ -1403,15 +2511,124 @@ function parseAvatarConfig(configStr) {
|
|
|
1403
2511
|
const parsed = JSON.parse(configStr);
|
|
1404
2512
|
return {
|
|
1405
2513
|
selections: parsed.selections || {},
|
|
1406
|
-
colors: parsed.colors || {}
|
|
2514
|
+
colors: parsed.colors || {},
|
|
2515
|
+
gender: parsed.gender
|
|
1407
2516
|
};
|
|
1408
|
-
} catch (
|
|
2517
|
+
} catch (e5) {
|
|
1409
2518
|
return { selections: {}, colors: {} };
|
|
1410
2519
|
}
|
|
1411
2520
|
}
|
|
2521
|
+
function parseAvatarConfigWithDefaults(configStr, seed) {
|
|
2522
|
+
const parsed = parseAvatarConfig(configStr);
|
|
2523
|
+
const hasSelections = Object.keys(parsed.selections).length > 0;
|
|
2524
|
+
if (!hasSelections) {
|
|
2525
|
+
return generateRandomAvatarState({ seed });
|
|
2526
|
+
}
|
|
2527
|
+
return {
|
|
2528
|
+
selections: { ...parsed.selections },
|
|
2529
|
+
colors: { ...parsed.colors },
|
|
2530
|
+
gender: parsed.gender
|
|
2531
|
+
};
|
|
2532
|
+
}
|
|
1412
2533
|
function serializeAvatarConfig(state) {
|
|
1413
2534
|
return JSON.stringify(state);
|
|
1414
2535
|
}
|
|
2536
|
+
function createSeededRandom(seedStr) {
|
|
2537
|
+
let h = 1779033703 ^ seedStr.length;
|
|
2538
|
+
for (let i = 0; i < seedStr.length; i++) {
|
|
2539
|
+
h = Math.imul(h ^ seedStr.charCodeAt(i), 3432918353);
|
|
2540
|
+
h = h << 13 | h >>> 19;
|
|
2541
|
+
}
|
|
2542
|
+
return () => {
|
|
2543
|
+
h = Math.imul(h ^ h >>> 16, 2246822507);
|
|
2544
|
+
h = Math.imul(h ^ h >>> 13, 3266489909);
|
|
2545
|
+
return ((h ^= h >>> 16) >>> 0) / 4294967296;
|
|
2546
|
+
};
|
|
2547
|
+
}
|
|
2548
|
+
function pickRandom(arr, fallback, rng = Math.random) {
|
|
2549
|
+
if (arr.length === 0) return fallback;
|
|
2550
|
+
const item = arr[Math.floor(rng() * arr.length)];
|
|
2551
|
+
return item !== void 0 ? item : fallback;
|
|
2552
|
+
}
|
|
2553
|
+
function generateRandomAvatarState(options) {
|
|
2554
|
+
const rng = _optionalChain([options, 'optionalAccess', _80 => _80.seed]) ? createSeededRandom(options.seed) : Math.random;
|
|
2555
|
+
const gender = _optionalChain([options, 'optionalAccess', _81 => _81.gender]) || (rng() > 0.5 ? "Male" : "Female");
|
|
2556
|
+
const backgrounds = ["Solid", "3 Stripes"];
|
|
2557
|
+
const skinColors = [
|
|
2558
|
+
"Light Peach",
|
|
2559
|
+
"Warm Peach",
|
|
2560
|
+
"Golden Tan",
|
|
2561
|
+
"Sand Beige",
|
|
2562
|
+
"Warm Brown",
|
|
2563
|
+
"Deep Brown"
|
|
2564
|
+
];
|
|
2565
|
+
const maleHairs = ["Clean", "Mid", "Curled", "Bald"];
|
|
2566
|
+
const femaleHairs = ["Bun", "Long", "Mid", "Short"];
|
|
2567
|
+
const clothesList = ["Tshirt", "Hoodie", "Turtleneck"];
|
|
2568
|
+
const expressions = ["Normal", "Happy", "Joyful", "Playful", "Surprised"];
|
|
2569
|
+
const eywears = ["None", "None", "None", "None", "Normal Glasses"];
|
|
2570
|
+
const headwears = ["None", "None", "None", "None", "Beanie", "HeadPhones"];
|
|
2571
|
+
const hairList = gender === "Male" ? maleHairs : femaleHairs;
|
|
2572
|
+
const bg = pickRandom(backgrounds, "Solid", rng);
|
|
2573
|
+
const skin = pickRandom(skinColors, "Light Peach", rng);
|
|
2574
|
+
const hair = pickRandom(hairList, gender === "Male" ? "Clean" : "Short", rng);
|
|
2575
|
+
const clothes = pickRandom(clothesList, "Tshirt", rng);
|
|
2576
|
+
const expression = pickRandom(expressions, "Normal", rng);
|
|
2577
|
+
const eyewear = pickRandom(eywears, "None", rng);
|
|
2578
|
+
const headwear = pickRandom(headwears, "None", rng);
|
|
2579
|
+
const hairColorPool = [
|
|
2580
|
+
"Black",
|
|
2581
|
+
"Black",
|
|
2582
|
+
"Brown",
|
|
2583
|
+
"Brown",
|
|
2584
|
+
"Blonde",
|
|
2585
|
+
"White",
|
|
2586
|
+
"Red",
|
|
2587
|
+
"Blue"
|
|
2588
|
+
];
|
|
2589
|
+
const hairColor = pickRandom(hairColorPool, "Black", rng);
|
|
2590
|
+
const clothesColorPool = [
|
|
2591
|
+
"Blue",
|
|
2592
|
+
"Red",
|
|
2593
|
+
"Green",
|
|
2594
|
+
"Orange",
|
|
2595
|
+
"Purple",
|
|
2596
|
+
"Black",
|
|
2597
|
+
"Yellow",
|
|
2598
|
+
"Pink"
|
|
2599
|
+
];
|
|
2600
|
+
const clothesColor = pickRandom(clothesColorPool, "Blue", rng);
|
|
2601
|
+
const bgColorPool = ["Blue", "Green", "Purple", "Orange", "Red", "Pink", "Original"];
|
|
2602
|
+
const bgColor = pickRandom(bgColorPool, "Blue", rng);
|
|
2603
|
+
return {
|
|
2604
|
+
selections: {
|
|
2605
|
+
Background: bg,
|
|
2606
|
+
"Hair Back": hair,
|
|
2607
|
+
"Skin Color": skin,
|
|
2608
|
+
"Clothes Back": clothes,
|
|
2609
|
+
"Clothes Front": clothes,
|
|
2610
|
+
Accessories: "None",
|
|
2611
|
+
Headwears: headwear,
|
|
2612
|
+
Eyewear: eyewear,
|
|
2613
|
+
"Facial Expression": expression,
|
|
2614
|
+
Beard: "None",
|
|
2615
|
+
"Hair Front": hair
|
|
2616
|
+
},
|
|
2617
|
+
colors: {
|
|
2618
|
+
"Background Color": bgColor,
|
|
2619
|
+
"Hair Color": hairColor,
|
|
2620
|
+
"Clothes Color": clothesColor,
|
|
2621
|
+
"Accessory Color": "Original",
|
|
2622
|
+
"Headwears Color": "Original",
|
|
2623
|
+
"Eyewear Color": "Original",
|
|
2624
|
+
"Facial Expression Color": "Original"
|
|
2625
|
+
},
|
|
2626
|
+
gender
|
|
2627
|
+
};
|
|
2628
|
+
}
|
|
2629
|
+
function generateRandomAvatarConfig(options) {
|
|
2630
|
+
return JSON.stringify(generateRandomAvatarState(options));
|
|
2631
|
+
}
|
|
1415
2632
|
|
|
1416
2633
|
// src/logic/elo.ts
|
|
1417
2634
|
var TIERS = [
|
|
@@ -1548,6 +2765,212 @@ function reorderObjectKeys(obj, oldIndex, newIndex, length) {
|
|
|
1548
2765
|
return newObj;
|
|
1549
2766
|
}
|
|
1550
2767
|
|
|
2768
|
+
// src/logic/home.ts
|
|
2769
|
+
function mapCognitoLevelToStandardLevel(cognitoLevel) {
|
|
2770
|
+
if (!cognitoLevel) return "HSC+Admission";
|
|
2771
|
+
const normalized = cognitoLevel.trim().toLowerCase();
|
|
2772
|
+
if (normalized === "class_9" || normalized === "class_10" || normalized === "ssc") {
|
|
2773
|
+
return "SSC";
|
|
2774
|
+
}
|
|
2775
|
+
if (normalized === "class_11" || normalized === "class_12" || normalized === "admission" || normalized === "hsc" || normalized === "hsc+admission") {
|
|
2776
|
+
return "HSC+Admission";
|
|
2777
|
+
}
|
|
2778
|
+
if (normalized === "bcs" || normalized === "job") {
|
|
2779
|
+
return "BCS";
|
|
2780
|
+
}
|
|
2781
|
+
return "HSC+Admission";
|
|
2782
|
+
}
|
|
2783
|
+
function getTimeOfDayGreeting(customHour, lang = "en") {
|
|
2784
|
+
const hour = customHour !== void 0 ? customHour : (/* @__PURE__ */ new Date()).getHours();
|
|
2785
|
+
if (hour >= 5 && hour < 12) {
|
|
2786
|
+
return {
|
|
2787
|
+
greeting: lang === "bn" ? "\u09B6\u09C1\u09AD \u09B8\u0995\u09BE\u09B2" : "Good morning",
|
|
2788
|
+
period: "morning"
|
|
2789
|
+
};
|
|
2790
|
+
}
|
|
2791
|
+
if (hour >= 12 && hour < 17) {
|
|
2792
|
+
return {
|
|
2793
|
+
greeting: lang === "bn" ? "\u09B6\u09C1\u09AD \u09A6\u09C1\u09AA\u09C1\u09B0" : "Good afternoon",
|
|
2794
|
+
period: "afternoon"
|
|
2795
|
+
};
|
|
2796
|
+
}
|
|
2797
|
+
if (hour >= 17 && hour < 21) {
|
|
2798
|
+
return {
|
|
2799
|
+
greeting: lang === "bn" ? "\u09B6\u09C1\u09AD \u09B8\u09A8\u09CD\u09A7\u09CD\u09AF\u09BE" : "Good evening",
|
|
2800
|
+
period: "evening"
|
|
2801
|
+
};
|
|
2802
|
+
}
|
|
2803
|
+
return {
|
|
2804
|
+
greeting: lang === "bn" ? "\u09B6\u09C1\u09AD \u09B0\u09BE\u09A4\u09CD\u09B0\u09BF" : "Good evening",
|
|
2805
|
+
period: "night"
|
|
2806
|
+
};
|
|
2807
|
+
}
|
|
2808
|
+
function getRecommendedSubjectsForLevel(level, lang = "en") {
|
|
2809
|
+
const isBn = lang === "bn";
|
|
2810
|
+
const normalizedLevel = mapCognitoLevelToStandardLevel(level);
|
|
2811
|
+
if (normalizedLevel === "SSC") {
|
|
2812
|
+
return [
|
|
2813
|
+
{
|
|
2814
|
+
id: "ssc-physics",
|
|
2815
|
+
name: isBn ? "\u09AA\u09A6\u09BE\u09B0\u09CD\u09A5\u09AC\u09BF\u099C\u09CD\u099E\u09BE\u09A8" : "Physics",
|
|
2816
|
+
iconKey: "atom",
|
|
2817
|
+
colorClass: "from-blue-500 to-indigo-600"
|
|
2818
|
+
},
|
|
2819
|
+
{
|
|
2820
|
+
id: "ssc-chemistry",
|
|
2821
|
+
name: isBn ? "\u09B0\u09B8\u09BE\u09DF\u09A8" : "Chemistry",
|
|
2822
|
+
iconKey: "flask",
|
|
2823
|
+
colorClass: "from-emerald-500 to-teal-600"
|
|
2824
|
+
},
|
|
2825
|
+
{
|
|
2826
|
+
id: "ssc-higher-math",
|
|
2827
|
+
name: isBn ? "\u0989\u099A\u09CD\u099A\u09A4\u09B0 \u0997\u09A3\u09BF\u09A4" : "Higher Math",
|
|
2828
|
+
iconKey: "math",
|
|
2829
|
+
colorClass: "from-amber-500 to-orange-600"
|
|
2830
|
+
},
|
|
2831
|
+
{
|
|
2832
|
+
id: "ssc-general-math",
|
|
2833
|
+
name: isBn ? "\u09B8\u09BE\u09A7\u09BE\u09B0\u09A3 \u0997\u09A3\u09BF\u09A4" : "General Math",
|
|
2834
|
+
iconKey: "calculator",
|
|
2835
|
+
colorClass: "from-violet-500 to-purple-600"
|
|
2836
|
+
},
|
|
2837
|
+
{
|
|
2838
|
+
id: "ssc-biology",
|
|
2839
|
+
name: isBn ? "\u099C\u09C0\u09AC\u09AC\u09BF\u099C\u09CD\u099E\u09BE\u09A8" : "Biology",
|
|
2840
|
+
iconKey: "dna",
|
|
2841
|
+
colorClass: "from-rose-500 to-pink-600"
|
|
2842
|
+
},
|
|
2843
|
+
{
|
|
2844
|
+
id: "ssc-bangla",
|
|
2845
|
+
name: isBn ? "\u09AC\u09BE\u0982\u09B2\u09BE" : "Bangla",
|
|
2846
|
+
iconKey: "book",
|
|
2847
|
+
colorClass: "from-cyan-500 to-blue-600"
|
|
2848
|
+
}
|
|
2849
|
+
];
|
|
2850
|
+
}
|
|
2851
|
+
if (normalizedLevel === "BCS") {
|
|
2852
|
+
return [
|
|
2853
|
+
{
|
|
2854
|
+
id: "bcs-bangladesh-affairs",
|
|
2855
|
+
name: isBn ? "\u09AC\u09BE\u0982\u09B2\u09BE\u09A6\u09C7\u09B6 \u09AC\u09BF\u09B7\u09DF\u09BE\u09AC\u09B2\u09C0" : "Bangladesh Affairs",
|
|
2856
|
+
iconKey: "monument",
|
|
2857
|
+
colorClass: "from-emerald-500 to-green-600"
|
|
2858
|
+
},
|
|
2859
|
+
{
|
|
2860
|
+
id: "bcs-international-affairs",
|
|
2861
|
+
name: isBn ? "\u0986\u09A8\u09CD\u09A4\u09B0\u09CD\u099C\u09BE\u09A4\u09BF\u0995 \u09AC\u09BF\u09B7\u09DF\u09BE\u09AC\u09B2\u09C0" : "International Affairs",
|
|
2862
|
+
iconKey: "world",
|
|
2863
|
+
colorClass: "from-blue-500 to-cyan-600"
|
|
2864
|
+
},
|
|
2865
|
+
{
|
|
2866
|
+
id: "bcs-bangla",
|
|
2867
|
+
name: isBn ? "\u09AC\u09BE\u0982\u09B2\u09BE \u09AD\u09BE\u09B7\u09BE \u0993 \u09B8\u09BE\u09B9\u09BF\u09A4\u09CD\u09AF" : "Bangla Literature",
|
|
2868
|
+
iconKey: "book",
|
|
2869
|
+
colorClass: "from-amber-500 to-orange-600"
|
|
2870
|
+
},
|
|
2871
|
+
{
|
|
2872
|
+
id: "bcs-english",
|
|
2873
|
+
name: isBn ? "\u0987\u0982\u09B0\u09C7\u099C\u09BF \u09AD\u09BE\u09B7\u09BE \u0993 \u09B8\u09BE\u09B9\u09BF\u09A4\u09CD\u09AF" : "English Language",
|
|
2874
|
+
iconKey: "language",
|
|
2875
|
+
colorClass: "from-violet-500 to-purple-600"
|
|
2876
|
+
},
|
|
2877
|
+
{
|
|
2878
|
+
id: "bcs-math-mental-ability",
|
|
2879
|
+
name: isBn ? "\u0997\u09BE\u09A3\u09BF\u09A4\u09BF\u0995 \u0993 \u09AE\u09BE\u09A8\u09B8\u09BF\u0995 \u09A6\u0995\u09CD\u09B7\u09A4\u09BE" : "Math & Mental Ability",
|
|
2880
|
+
iconKey: "brain",
|
|
2881
|
+
colorClass: "from-pink-500 to-rose-600"
|
|
2882
|
+
},
|
|
2883
|
+
{
|
|
2884
|
+
id: "bcs-general-science",
|
|
2885
|
+
name: isBn ? "\u09B8\u09BE\u09A7\u09BE\u09B0\u09A3 \u09AC\u09BF\u099C\u09CD\u099E\u09BE\u09A8 \u0993 \u09AA\u09CD\u09B0\u09AF\u09C1\u0995\u09CD\u09A4\u09BF" : "General Science",
|
|
2886
|
+
iconKey: "atom",
|
|
2887
|
+
colorClass: "from-teal-500 to-emerald-600"
|
|
2888
|
+
}
|
|
2889
|
+
];
|
|
2890
|
+
}
|
|
2891
|
+
return [
|
|
2892
|
+
{
|
|
2893
|
+
id: "hsc-physics",
|
|
2894
|
+
name: isBn ? "\u09AA\u09A6\u09BE\u09B0\u09CD\u09A5\u09AC\u09BF\u099C\u09CD\u099E\u09BE\u09A8" : "Physics",
|
|
2895
|
+
iconKey: "atom",
|
|
2896
|
+
colorClass: "from-blue-500 to-indigo-600"
|
|
2897
|
+
},
|
|
2898
|
+
{
|
|
2899
|
+
id: "hsc-chemistry",
|
|
2900
|
+
name: isBn ? "\u09B0\u09B8\u09BE\u09DF\u09A8" : "Chemistry",
|
|
2901
|
+
iconKey: "flask",
|
|
2902
|
+
colorClass: "from-emerald-500 to-teal-600"
|
|
2903
|
+
},
|
|
2904
|
+
{
|
|
2905
|
+
id: "hsc-higher-math",
|
|
2906
|
+
name: isBn ? "\u0989\u099A\u09CD\u099A\u09A4\u09B0 \u0997\u09A3\u09BF\u09A4" : "Higher Math",
|
|
2907
|
+
iconKey: "math",
|
|
2908
|
+
colorClass: "from-amber-500 to-orange-600"
|
|
2909
|
+
},
|
|
2910
|
+
{
|
|
2911
|
+
id: "hsc-biology",
|
|
2912
|
+
name: isBn ? "\u099C\u09C0\u09AC\u09AC\u09BF\u099C\u09CD\u099E\u09BE\u09A8" : "Biology",
|
|
2913
|
+
iconKey: "dna",
|
|
2914
|
+
colorClass: "from-rose-500 to-pink-600"
|
|
2915
|
+
},
|
|
2916
|
+
{
|
|
2917
|
+
id: "hsc-ict",
|
|
2918
|
+
name: isBn ? "\u09A4\u09A5\u09CD\u09AF \u0993 \u09AF\u09CB\u0997\u09BE\u09AF\u09CB\u0997 \u09AA\u09CD\u09B0\u09AF\u09C1\u0995\u09CD\u09A4\u09BF" : "ICT",
|
|
2919
|
+
iconKey: "device-laptop",
|
|
2920
|
+
colorClass: "from-cyan-500 to-sky-600"
|
|
2921
|
+
},
|
|
2922
|
+
{
|
|
2923
|
+
id: "hsc-bangla",
|
|
2924
|
+
name: isBn ? "\u09AC\u09BE\u0982\u09B2\u09BE" : "Bangla",
|
|
2925
|
+
iconKey: "book",
|
|
2926
|
+
colorClass: "from-violet-500 to-purple-600"
|
|
2927
|
+
}
|
|
2928
|
+
];
|
|
2929
|
+
}
|
|
2930
|
+
function calculateStreakFromDates(activityDates) {
|
|
2931
|
+
if (!activityDates || activityDates.length === 0) {
|
|
2932
|
+
return { streak: 0, isActiveToday: false };
|
|
2933
|
+
}
|
|
2934
|
+
const uniqueDateStrings = Array.from(
|
|
2935
|
+
new Set(
|
|
2936
|
+
activityDates.map((d) => {
|
|
2937
|
+
try {
|
|
2938
|
+
return new Date(d).toISOString().split("T")[0];
|
|
2939
|
+
} catch (e6) {
|
|
2940
|
+
return null;
|
|
2941
|
+
}
|
|
2942
|
+
}).filter((d) => Boolean(d))
|
|
2943
|
+
)
|
|
2944
|
+
).sort((a, b) => a > b ? -1 : 1);
|
|
2945
|
+
if (uniqueDateStrings.length === 0) {
|
|
2946
|
+
return { streak: 0, isActiveToday: false };
|
|
2947
|
+
}
|
|
2948
|
+
const todayStr = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
2949
|
+
const yesterdayDate = /* @__PURE__ */ new Date();
|
|
2950
|
+
yesterdayDate.setDate(yesterdayDate.getDate() - 1);
|
|
2951
|
+
const yesterdayStr = yesterdayDate.toISOString().split("T")[0];
|
|
2952
|
+
const latestDate = uniqueDateStrings[0];
|
|
2953
|
+
if (!latestDate) {
|
|
2954
|
+
return { streak: 0, isActiveToday: false };
|
|
2955
|
+
}
|
|
2956
|
+
const isActiveToday = latestDate === todayStr;
|
|
2957
|
+
if (latestDate !== todayStr && latestDate !== yesterdayStr) {
|
|
2958
|
+
return { streak: 0, isActiveToday: false };
|
|
2959
|
+
}
|
|
2960
|
+
let streak = 0;
|
|
2961
|
+
const checkDate = new Date(latestDate);
|
|
2962
|
+
for (const dateStr of uniqueDateStrings) {
|
|
2963
|
+
const expectedStr = checkDate.toISOString().split("T")[0];
|
|
2964
|
+
if (dateStr === expectedStr) {
|
|
2965
|
+
streak += 1;
|
|
2966
|
+
checkDate.setDate(checkDate.getDate() - 1);
|
|
2967
|
+
} else {
|
|
2968
|
+
break;
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
return { streak, isActiveToday };
|
|
2972
|
+
}
|
|
2973
|
+
|
|
1551
2974
|
// src/logic/import-export.ts
|
|
1552
2975
|
var MAX_QUESTIONS = 200;
|
|
1553
2976
|
function parseFields(parts) {
|
|
@@ -1564,50 +2987,50 @@ function parseFields(parts) {
|
|
|
1564
2987
|
let option3ImageUrl = "";
|
|
1565
2988
|
let option4ImageUrl = "";
|
|
1566
2989
|
if (parts.length >= 13) {
|
|
1567
|
-
extra = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1568
|
-
const rawDiff = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
2990
|
+
extra = _nullishCoalesce(_optionalChain([parts, 'access', _82 => _82[7], 'optionalAccess', _83 => _83.trim, 'call', _84 => _84()]), () => ( ""));
|
|
2991
|
+
const rawDiff = _nullishCoalesce(_optionalChain([parts, 'access', _85 => _85[8], 'optionalAccess', _86 => _86.trim, 'call', _87 => _87()]), () => ( ""));
|
|
1569
2992
|
if (rawDiff) {
|
|
1570
2993
|
const cap = rawDiff.charAt(0).toUpperCase() + rawDiff.slice(1).toLowerCase();
|
|
1571
2994
|
if (cap === "Easy" || cap === "Medium" || cap === "Hard") difficulty = cap;
|
|
1572
2995
|
}
|
|
1573
|
-
subjectId = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1574
|
-
chapterId = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1575
|
-
topicId = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1576
|
-
markingInstructions = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1577
|
-
if (parts.length > 13) id = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1578
|
-
if (parts.length > 14) imageUrl = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1579
|
-
if (parts.length > 15) answerImageUrl = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1580
|
-
if (parts.length > 16) option2ImageUrl = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1581
|
-
if (parts.length > 17) option3ImageUrl = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1582
|
-
if (parts.length > 18) option4ImageUrl = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
2996
|
+
subjectId = _nullishCoalesce(_optionalChain([parts, 'access', _88 => _88[9], 'optionalAccess', _89 => _89.trim, 'call', _90 => _90()]), () => ( ""));
|
|
2997
|
+
chapterId = _nullishCoalesce(_optionalChain([parts, 'access', _91 => _91[10], 'optionalAccess', _92 => _92.trim, 'call', _93 => _93()]), () => ( ""));
|
|
2998
|
+
topicId = _nullishCoalesce(_optionalChain([parts, 'access', _94 => _94[11], 'optionalAccess', _95 => _95.trim, 'call', _96 => _96()]), () => ( ""));
|
|
2999
|
+
markingInstructions = _nullishCoalesce(_optionalChain([parts, 'access', _97 => _97[12], 'optionalAccess', _98 => _98.trim, 'call', _99 => _99()]), () => ( ""));
|
|
3000
|
+
if (parts.length > 13) id = _nullishCoalesce(_optionalChain([parts, 'access', _100 => _100[13], 'optionalAccess', _101 => _101.trim, 'call', _102 => _102()]), () => ( ""));
|
|
3001
|
+
if (parts.length > 14) imageUrl = _nullishCoalesce(_optionalChain([parts, 'access', _103 => _103[14], 'optionalAccess', _104 => _104.trim, 'call', _105 => _105()]), () => ( ""));
|
|
3002
|
+
if (parts.length > 15) answerImageUrl = _nullishCoalesce(_optionalChain([parts, 'access', _106 => _106[15], 'optionalAccess', _107 => _107.trim, 'call', _108 => _108()]), () => ( ""));
|
|
3003
|
+
if (parts.length > 16) option2ImageUrl = _nullishCoalesce(_optionalChain([parts, 'access', _109 => _109[16], 'optionalAccess', _110 => _110.trim, 'call', _111 => _111()]), () => ( ""));
|
|
3004
|
+
if (parts.length > 17) option3ImageUrl = _nullishCoalesce(_optionalChain([parts, 'access', _112 => _112[17], 'optionalAccess', _113 => _113.trim, 'call', _114 => _114()]), () => ( ""));
|
|
3005
|
+
if (parts.length > 18) option4ImageUrl = _nullishCoalesce(_optionalChain([parts, 'access', _115 => _115[18], 'optionalAccess', _116 => _116.trim, 'call', _117 => _117()]), () => ( ""));
|
|
1583
3006
|
} else if (parts.length === 8) {
|
|
1584
|
-
extra = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
3007
|
+
extra = _nullishCoalesce(_optionalChain([parts, 'access', _118 => _118[7], 'optionalAccess', _119 => _119.trim, 'call', _120 => _120()]), () => ( ""));
|
|
1585
3008
|
} else if (parts.length === 9) {
|
|
1586
|
-
extra = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1587
|
-
const rawDiff = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
3009
|
+
extra = _nullishCoalesce(_optionalChain([parts, 'access', _121 => _121[7], 'optionalAccess', _122 => _122.trim, 'call', _123 => _123()]), () => ( ""));
|
|
3010
|
+
const rawDiff = _nullishCoalesce(_optionalChain([parts, 'access', _124 => _124[8], 'optionalAccess', _125 => _125.trim, 'call', _126 => _126()]), () => ( ""));
|
|
1588
3011
|
if (rawDiff) {
|
|
1589
3012
|
const cap = rawDiff.charAt(0).toUpperCase() + rawDiff.slice(1).toLowerCase();
|
|
1590
3013
|
if (cap === "Easy" || cap === "Medium" || cap === "Hard") difficulty = cap;
|
|
1591
3014
|
}
|
|
1592
3015
|
} else if (parts.length === 10) {
|
|
1593
|
-
subjectId = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1594
|
-
chapterId = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1595
|
-
topicId = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
3016
|
+
subjectId = _nullishCoalesce(_optionalChain([parts, 'access', _127 => _127[7], 'optionalAccess', _128 => _128.trim, 'call', _129 => _129()]), () => ( ""));
|
|
3017
|
+
chapterId = _nullishCoalesce(_optionalChain([parts, 'access', _130 => _130[8], 'optionalAccess', _131 => _131.trim, 'call', _132 => _132()]), () => ( ""));
|
|
3018
|
+
topicId = _nullishCoalesce(_optionalChain([parts, 'access', _133 => _133[9], 'optionalAccess', _134 => _134.trim, 'call', _135 => _135()]), () => ( ""));
|
|
1596
3019
|
} else if (parts.length === 11) {
|
|
1597
|
-
extra = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1598
|
-
subjectId = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1599
|
-
chapterId = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1600
|
-
topicId = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
3020
|
+
extra = _nullishCoalesce(_optionalChain([parts, 'access', _136 => _136[7], 'optionalAccess', _137 => _137.trim, 'call', _138 => _138()]), () => ( ""));
|
|
3021
|
+
subjectId = _nullishCoalesce(_optionalChain([parts, 'access', _139 => _139[8], 'optionalAccess', _140 => _140.trim, 'call', _141 => _141()]), () => ( ""));
|
|
3022
|
+
chapterId = _nullishCoalesce(_optionalChain([parts, 'access', _142 => _142[9], 'optionalAccess', _143 => _143.trim, 'call', _144 => _144()]), () => ( ""));
|
|
3023
|
+
topicId = _nullishCoalesce(_optionalChain([parts, 'access', _145 => _145[10], 'optionalAccess', _146 => _146.trim, 'call', _147 => _147()]), () => ( ""));
|
|
1601
3024
|
} else if (parts.length === 12) {
|
|
1602
|
-
extra = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1603
|
-
const rawDiff = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
3025
|
+
extra = _nullishCoalesce(_optionalChain([parts, 'access', _148 => _148[7], 'optionalAccess', _149 => _149.trim, 'call', _150 => _150()]), () => ( ""));
|
|
3026
|
+
const rawDiff = _nullishCoalesce(_optionalChain([parts, 'access', _151 => _151[8], 'optionalAccess', _152 => _152.trim, 'call', _153 => _153()]), () => ( ""));
|
|
1604
3027
|
if (rawDiff) {
|
|
1605
3028
|
const cap = rawDiff.charAt(0).toUpperCase() + rawDiff.slice(1).toLowerCase();
|
|
1606
3029
|
if (cap === "Easy" || cap === "Medium" || cap === "Hard") difficulty = cap;
|
|
1607
3030
|
}
|
|
1608
|
-
subjectId = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1609
|
-
chapterId = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1610
|
-
topicId = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
3031
|
+
subjectId = _nullishCoalesce(_optionalChain([parts, 'access', _154 => _154[9], 'optionalAccess', _155 => _155.trim, 'call', _156 => _156()]), () => ( ""));
|
|
3032
|
+
chapterId = _nullishCoalesce(_optionalChain([parts, 'access', _157 => _157[10], 'optionalAccess', _158 => _158.trim, 'call', _159 => _159()]), () => ( ""));
|
|
3033
|
+
topicId = _nullishCoalesce(_optionalChain([parts, 'access', _160 => _160[11], 'optionalAccess', _161 => _161.trim, 'call', _162 => _162()]), () => ( ""));
|
|
1611
3034
|
}
|
|
1612
3035
|
return {
|
|
1613
3036
|
id: id || void 0,
|
|
@@ -1626,18 +3049,18 @@ function parseFields(parts) {
|
|
|
1626
3049
|
}
|
|
1627
3050
|
function buildQuestion(parts) {
|
|
1628
3051
|
const tags = parts.length >= 7 && parts[6] ? parts[6].split(",").map((t) => t.trim()).filter(Boolean) : [];
|
|
1629
|
-
const opt2 = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1630
|
-
const opt3 = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1631
|
-
const opt4 = _nullishCoalesce(_optionalChain([parts, 'access',
|
|
3052
|
+
const opt2 = _nullishCoalesce(_optionalChain([parts, 'access', _163 => _163[2], 'optionalAccess', _164 => _164.trim, 'call', _165 => _165()]), () => ( ""));
|
|
3053
|
+
const opt3 = _nullishCoalesce(_optionalChain([parts, 'access', _166 => _166[3], 'optionalAccess', _167 => _167.trim, 'call', _168 => _168()]), () => ( ""));
|
|
3054
|
+
const opt4 = _nullishCoalesce(_optionalChain([parts, 'access', _169 => _169[4], 'optionalAccess', _170 => _170.trim, 'call', _171 => _171()]), () => ( ""));
|
|
1632
3055
|
const isWritten = parts.length < 6 || !opt2 && !opt3 && !opt4;
|
|
1633
3056
|
const extra = parseFields(parts);
|
|
1634
3057
|
return {
|
|
1635
|
-
question: _nullishCoalesce(_optionalChain([parts, 'access',
|
|
1636
|
-
answer: _nullishCoalesce(_optionalChain([parts, 'access',
|
|
3058
|
+
question: _nullishCoalesce(_optionalChain([parts, 'access', _172 => _172[0], 'optionalAccess', _173 => _173.trim, 'call', _174 => _174()]), () => ( "")),
|
|
3059
|
+
answer: _nullishCoalesce(_optionalChain([parts, 'access', _175 => _175[1], 'optionalAccess', _176 => _176.trim, 'call', _177 => _177()]), () => ( "")),
|
|
1637
3060
|
option2: opt2,
|
|
1638
3061
|
option3: opt3,
|
|
1639
3062
|
option4: opt4,
|
|
1640
|
-
explanation: _nullishCoalesce(_optionalChain([parts, 'access',
|
|
3063
|
+
explanation: _nullishCoalesce(_optionalChain([parts, 'access', _178 => _178[5], 'optionalAccess', _179 => _179.trim, 'call', _180 => _180()]), () => ( "")),
|
|
1641
3064
|
tags,
|
|
1642
3065
|
type: isWritten ? "WRITTEN" : "MCQ",
|
|
1643
3066
|
...extra
|
|
@@ -1688,9 +3111,9 @@ function formatQuestionsToText(questions, keyword, packSubjectId, packChapterId,
|
|
|
1688
3111
|
const activeSubject = q.subjectId || packSubjectId;
|
|
1689
3112
|
const activeChapter = q.chapterId || packChapterId;
|
|
1690
3113
|
const activeTopic = q.topicId || packTopicId;
|
|
1691
|
-
const subjectSlug = activeSubject ? _nullishCoalesce(_optionalChain([activeSubject, 'access',
|
|
1692
|
-
const chapterSlug = activeChapter ? _nullishCoalesce(_optionalChain([activeChapter, 'access',
|
|
1693
|
-
const topicSlug = activeTopic ? _nullishCoalesce(_optionalChain([activeTopic, 'access',
|
|
3114
|
+
const subjectSlug = activeSubject ? _nullishCoalesce(_optionalChain([activeSubject, 'access', _181 => _181.split, 'call', _182 => _182("::"), 'access', _183 => _183[0], 'optionalAccess', _184 => _184.trim, 'call', _185 => _185()]), () => ( "")) : "";
|
|
3115
|
+
const chapterSlug = activeChapter ? _nullishCoalesce(_optionalChain([activeChapter, 'access', _186 => _186.split, 'call', _187 => _187("::"), 'access', _188 => _188[0], 'optionalAccess', _189 => _189.trim, 'call', _190 => _190()]), () => ( "")) : "";
|
|
3116
|
+
const topicSlug = activeTopic ? _nullishCoalesce(_optionalChain([activeTopic, 'access', _191 => _191.split, 'call', _192 => _192("::"), 'access', _193 => _193[0], 'optionalAccess', _194 => _194.trim, 'call', _195 => _195()]), () => ( "")) : "";
|
|
1694
3117
|
const fields = [
|
|
1695
3118
|
q.question,
|
|
1696
3119
|
q.answer,
|
|
@@ -1723,9 +3146,9 @@ function formatQuestionsToCsv(questions, packSubjectId, packChapterId, packTopic
|
|
|
1723
3146
|
const activeSubject = q.subjectId || packSubjectId;
|
|
1724
3147
|
const activeChapter = q.chapterId || packChapterId;
|
|
1725
3148
|
const activeTopic = q.topicId || packTopicId;
|
|
1726
|
-
const subjectSlug = activeSubject ? _nullishCoalesce(_optionalChain([activeSubject, 'access',
|
|
1727
|
-
const chapterSlug = activeChapter ? _nullishCoalesce(_optionalChain([activeChapter, 'access',
|
|
1728
|
-
const topicSlug = activeTopic ? _nullishCoalesce(_optionalChain([activeTopic, 'access',
|
|
3149
|
+
const subjectSlug = activeSubject ? _nullishCoalesce(_optionalChain([activeSubject, 'access', _196 => _196.split, 'call', _197 => _197("::"), 'access', _198 => _198[0], 'optionalAccess', _199 => _199.trim, 'call', _200 => _200()]), () => ( "")) : "";
|
|
3150
|
+
const chapterSlug = activeChapter ? _nullishCoalesce(_optionalChain([activeChapter, 'access', _201 => _201.split, 'call', _202 => _202("::"), 'access', _203 => _203[0], 'optionalAccess', _204 => _204.trim, 'call', _205 => _205()]), () => ( "")) : "";
|
|
3151
|
+
const topicSlug = activeTopic ? _nullishCoalesce(_optionalChain([activeTopic, 'access', _206 => _206.split, 'call', _207 => _207("::"), 'access', _208 => _208[0], 'optionalAccess', _209 => _209.trim, 'call', _210 => _210()]), () => ( "")) : "";
|
|
1729
3152
|
return [
|
|
1730
3153
|
escapeCSV(q.question),
|
|
1731
3154
|
escapeCSV(q.answer),
|
|
@@ -1752,6 +3175,250 @@ function formatQuestionsToCsv(questions, packSubjectId, packChapterId, packTopic
|
|
|
1752
3175
|
${rows.join("\n")}`;
|
|
1753
3176
|
}
|
|
1754
3177
|
|
|
3178
|
+
// src/logic/subscription.ts
|
|
3179
|
+
var MANUAL_PAYMENT_CONFIG = {
|
|
3180
|
+
phoneNumber: "01323567688",
|
|
3181
|
+
accountType: "Personal",
|
|
3182
|
+
methods: ["BKASH", "ROCKET"]
|
|
3183
|
+
};
|
|
3184
|
+
var SUBSCRIPTION_PLANS = {
|
|
3185
|
+
FREE: {
|
|
3186
|
+
id: "FREE",
|
|
3187
|
+
tier: "FREE",
|
|
3188
|
+
titleKey: "upgrade.freeTitle",
|
|
3189
|
+
descKey: "upgrade.freeDesc",
|
|
3190
|
+
pricing: {
|
|
3191
|
+
monthly: 0,
|
|
3192
|
+
quarterly: 0,
|
|
3193
|
+
biannually: 0,
|
|
3194
|
+
annually: 0
|
|
3195
|
+
},
|
|
3196
|
+
aiQuotas: {
|
|
3197
|
+
monthly: { aiEvals: 0, aiQuestions: 0 },
|
|
3198
|
+
quarterly: { aiEvals: 0, aiQuestions: 0 },
|
|
3199
|
+
biannually: { aiEvals: 0, aiQuestions: 0 },
|
|
3200
|
+
annually: { aiEvals: 0, aiQuestions: 0 }
|
|
3201
|
+
}
|
|
3202
|
+
},
|
|
3203
|
+
PRO: {
|
|
3204
|
+
id: "PRO",
|
|
3205
|
+
tier: "PRO",
|
|
3206
|
+
titleKey: "upgrade.proTitle",
|
|
3207
|
+
descKey: "upgrade.proDesc",
|
|
3208
|
+
pricing: {
|
|
3209
|
+
monthly: 149,
|
|
3210
|
+
quarterly: 399,
|
|
3211
|
+
biannually: 699,
|
|
3212
|
+
annually: 999
|
|
3213
|
+
},
|
|
3214
|
+
aiQuotas: {
|
|
3215
|
+
monthly: { aiEvals: 0, aiQuestions: 0 },
|
|
3216
|
+
quarterly: { aiEvals: 0, aiQuestions: 0 },
|
|
3217
|
+
biannually: { aiEvals: 0, aiQuestions: 0 },
|
|
3218
|
+
annually: { aiEvals: 0, aiQuestions: 0 }
|
|
3219
|
+
}
|
|
3220
|
+
},
|
|
3221
|
+
PRO_AI: {
|
|
3222
|
+
id: "PRO_AI",
|
|
3223
|
+
tier: "PRO_AI",
|
|
3224
|
+
titleKey: "upgrade.aiTitle",
|
|
3225
|
+
descKey: "upgrade.aiDesc",
|
|
3226
|
+
pricing: {
|
|
3227
|
+
monthly: 349,
|
|
3228
|
+
quarterly: 899,
|
|
3229
|
+
biannually: 1599,
|
|
3230
|
+
annually: 2499
|
|
3231
|
+
},
|
|
3232
|
+
aiQuotas: {
|
|
3233
|
+
monthly: { aiEvals: 100, aiQuestions: 450 },
|
|
3234
|
+
quarterly: { aiEvals: 280, aiQuestions: 1100 },
|
|
3235
|
+
biannually: { aiEvals: 500, aiQuestions: 2e3 },
|
|
3236
|
+
annually: { aiEvals: 800, aiQuestions: 3e3 }
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3239
|
+
};
|
|
3240
|
+
var AI_EVAL_BOOSTER_PACKS = [
|
|
3241
|
+
{
|
|
3242
|
+
id: "eval_booster_starter",
|
|
3243
|
+
type: "AI_EVAL",
|
|
3244
|
+
amount: 40,
|
|
3245
|
+
price: 69,
|
|
3246
|
+
titleKey: "upgrade.boosters.evalStarterTitle",
|
|
3247
|
+
descKey: "upgrade.boosters.evalStarterDesc"
|
|
3248
|
+
},
|
|
3249
|
+
{
|
|
3250
|
+
id: "eval_booster_standard",
|
|
3251
|
+
type: "AI_EVAL",
|
|
3252
|
+
amount: 100,
|
|
3253
|
+
price: 159,
|
|
3254
|
+
titleKey: "upgrade.boosters.evalStandardTitle",
|
|
3255
|
+
descKey: "upgrade.boosters.evalStandardDesc",
|
|
3256
|
+
badgeKey: "upgrade.popular"
|
|
3257
|
+
},
|
|
3258
|
+
{
|
|
3259
|
+
id: "eval_booster_mega",
|
|
3260
|
+
type: "AI_EVAL",
|
|
3261
|
+
amount: 220,
|
|
3262
|
+
price: 349,
|
|
3263
|
+
titleKey: "upgrade.boosters.evalMegaTitle",
|
|
3264
|
+
descKey: "upgrade.boosters.evalMegaDesc",
|
|
3265
|
+
badgeKey: "upgrade.bestValue"
|
|
3266
|
+
}
|
|
3267
|
+
];
|
|
3268
|
+
var AI_QUESTION_BOOSTER_PACKS = [
|
|
3269
|
+
{
|
|
3270
|
+
id: "question_booster_drill",
|
|
3271
|
+
type: "AI_QUESTION",
|
|
3272
|
+
amount: 100,
|
|
3273
|
+
price: 39,
|
|
3274
|
+
titleKey: "upgrade.boosters.questionDrillTitle",
|
|
3275
|
+
descKey: "upgrade.boosters.questionDrillDesc"
|
|
3276
|
+
},
|
|
3277
|
+
{
|
|
3278
|
+
id: "question_booster_chapter",
|
|
3279
|
+
type: "AI_QUESTION",
|
|
3280
|
+
amount: 250,
|
|
3281
|
+
price: 99,
|
|
3282
|
+
titleKey: "upgrade.boosters.questionChapterTitle",
|
|
3283
|
+
descKey: "upgrade.boosters.questionChapterDesc",
|
|
3284
|
+
badgeKey: "upgrade.popular"
|
|
3285
|
+
},
|
|
3286
|
+
{
|
|
3287
|
+
id: "question_booster_exam",
|
|
3288
|
+
type: "AI_QUESTION",
|
|
3289
|
+
amount: 700,
|
|
3290
|
+
price: 249,
|
|
3291
|
+
titleKey: "upgrade.boosters.questionExamTitle",
|
|
3292
|
+
descKey: "upgrade.boosters.questionExamDesc",
|
|
3293
|
+
badgeKey: "upgrade.bestValue"
|
|
3294
|
+
}
|
|
3295
|
+
];
|
|
3296
|
+
function getCycleMultiplier(cycle) {
|
|
3297
|
+
switch (cycle) {
|
|
3298
|
+
case "quarterly":
|
|
3299
|
+
return 3;
|
|
3300
|
+
case "biannually":
|
|
3301
|
+
return 6;
|
|
3302
|
+
case "annually":
|
|
3303
|
+
return 12;
|
|
3304
|
+
case "monthly":
|
|
3305
|
+
default:
|
|
3306
|
+
return 1;
|
|
3307
|
+
}
|
|
3308
|
+
}
|
|
3309
|
+
function getPlanOriginalPrice(tier, cycle) {
|
|
3310
|
+
const normalizedTier = tier === "AI_ANNUAL" || tier === "AI_MONTHLY" ? "PRO_AI" : tier;
|
|
3311
|
+
const plan = SUBSCRIPTION_PLANS[normalizedTier] || SUBSCRIPTION_PLANS.FREE;
|
|
3312
|
+
const monthlyPrice = _nullishCoalesce(plan.pricing.monthly, () => ( 0));
|
|
3313
|
+
return monthlyPrice * getCycleMultiplier(cycle);
|
|
3314
|
+
}
|
|
3315
|
+
function getPlanPrice(tier, cycle) {
|
|
3316
|
+
const normalizedTier = tier === "AI_ANNUAL" || tier === "AI_MONTHLY" ? "PRO_AI" : tier;
|
|
3317
|
+
const plan = SUBSCRIPTION_PLANS[normalizedTier] || SUBSCRIPTION_PLANS.FREE;
|
|
3318
|
+
return _nullishCoalesce(plan.pricing[cycle], () => ( 0));
|
|
3319
|
+
}
|
|
3320
|
+
function getPlanMonthlyEquivalentPrice(tier, cycle) {
|
|
3321
|
+
const normalizedTier = tier === "AI_ANNUAL" || tier === "AI_MONTHLY" ? "PRO_AI" : tier;
|
|
3322
|
+
const plan = SUBSCRIPTION_PLANS[normalizedTier] || SUBSCRIPTION_PLANS.FREE;
|
|
3323
|
+
const cyclePrice = _nullishCoalesce(plan.pricing[cycle], () => ( 0));
|
|
3324
|
+
const multiplier = getCycleMultiplier(cycle);
|
|
3325
|
+
return Math.round(cyclePrice / multiplier);
|
|
3326
|
+
}
|
|
3327
|
+
function getPlanDiscountPercent(cycle) {
|
|
3328
|
+
switch (cycle) {
|
|
3329
|
+
case "quarterly":
|
|
3330
|
+
return 10;
|
|
3331
|
+
case "biannually":
|
|
3332
|
+
return 22;
|
|
3333
|
+
case "annually":
|
|
3334
|
+
return 44;
|
|
3335
|
+
case "monthly":
|
|
3336
|
+
default:
|
|
3337
|
+
return 0;
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3340
|
+
function getPlanAiQuotas(tier, cycle) {
|
|
3341
|
+
const normalizedTier = tier === "AI_ANNUAL" || tier === "AI_MONTHLY" ? "PRO_AI" : tier;
|
|
3342
|
+
const plan = SUBSCRIPTION_PLANS[normalizedTier] || SUBSCRIPTION_PLANS.FREE;
|
|
3343
|
+
return _nullishCoalesce(plan.aiQuotas[cycle], () => ( { aiEvals: 0, aiQuestions: 0 }));
|
|
3344
|
+
}
|
|
3345
|
+
function isValidBangladeshiPhone(phone) {
|
|
3346
|
+
if (!phone) return false;
|
|
3347
|
+
const cleaned = phone.replace(/[\s\-()]/g, "");
|
|
3348
|
+
const regex = /^(?:\+?88)?01[3-9]\d{8}$/;
|
|
3349
|
+
return regex.test(cleaned);
|
|
3350
|
+
}
|
|
3351
|
+
function isValidTrxId(trxId) {
|
|
3352
|
+
if (!trxId) return false;
|
|
3353
|
+
const cleaned = trxId.trim();
|
|
3354
|
+
return cleaned.length >= 4 && cleaned.length <= 40;
|
|
3355
|
+
}
|
|
3356
|
+
function hasProAccess(tier, expiresAt) {
|
|
3357
|
+
if (!tier) return false;
|
|
3358
|
+
const upper = tier.toUpperCase();
|
|
3359
|
+
const isTierPro = upper === "PRO" || upper === "PRO_AI";
|
|
3360
|
+
if (!isTierPro) return false;
|
|
3361
|
+
if (!expiresAt) return true;
|
|
3362
|
+
const expTime = new Date(expiresAt).getTime();
|
|
3363
|
+
if (isNaN(expTime)) return true;
|
|
3364
|
+
return expTime > Date.now();
|
|
3365
|
+
}
|
|
3366
|
+
function hasAiTierAccess(tier, expiresAt) {
|
|
3367
|
+
if (!tier) return false;
|
|
3368
|
+
const upper = tier.toUpperCase();
|
|
3369
|
+
const isTierAi = upper === "PRO_AI";
|
|
3370
|
+
if (!isTierAi) return false;
|
|
3371
|
+
if (!expiresAt) return true;
|
|
3372
|
+
const expTime = new Date(expiresAt).getTime();
|
|
3373
|
+
if (isNaN(expTime)) return true;
|
|
3374
|
+
return expTime > Date.now();
|
|
3375
|
+
}
|
|
3376
|
+
var FREE_DAILY_PRACTICE_LIMIT = 30;
|
|
3377
|
+
function canExportPack(tier, expiresAt, isCreator) {
|
|
3378
|
+
return Boolean(isCreator || hasProAccess(tier, expiresAt));
|
|
3379
|
+
}
|
|
3380
|
+
function canAccessMistakeVault(tier, expiresAt, isCreator) {
|
|
3381
|
+
return Boolean(isCreator || hasProAccess(tier, expiresAt));
|
|
3382
|
+
}
|
|
3383
|
+
function canWatchContestSolution(tier, expiresAt, isCreator) {
|
|
3384
|
+
return Boolean(isCreator || hasProAccess(tier, expiresAt));
|
|
3385
|
+
}
|
|
3386
|
+
function shouldTrackPracticeProgress(tier, expiresAt, isCreator) {
|
|
3387
|
+
return Boolean(isCreator || hasProAccess(tier, expiresAt));
|
|
3388
|
+
}
|
|
3389
|
+
function getDailyPracticeLimit(tier, expiresAt) {
|
|
3390
|
+
if (hasProAccess(tier, expiresAt)) return null;
|
|
3391
|
+
return FREE_DAILY_PRACTICE_LIMIT;
|
|
3392
|
+
}
|
|
3393
|
+
function checkDailyPracticeLimit(dailyCount, lastPracticeDate, tier, expiresAt, todayStr) {
|
|
3394
|
+
if (hasProAccess(tier, expiresAt)) {
|
|
3395
|
+
return {
|
|
3396
|
+
allowed: true,
|
|
3397
|
+
remaining: Infinity,
|
|
3398
|
+
currentCount: dailyCount,
|
|
3399
|
+
isUnlimited: true
|
|
3400
|
+
};
|
|
3401
|
+
}
|
|
3402
|
+
const today = todayStr || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
3403
|
+
const isSameDay = lastPracticeDate ? lastPracticeDate.startsWith(today) : false;
|
|
3404
|
+
const currentCount = isSameDay ? Number.isFinite(dailyCount) ? dailyCount : 0 : 0;
|
|
3405
|
+
const remaining = Math.max(0, FREE_DAILY_PRACTICE_LIMIT - currentCount);
|
|
3406
|
+
const allowed = currentCount < FREE_DAILY_PRACTICE_LIMIT;
|
|
3407
|
+
return {
|
|
3408
|
+
allowed,
|
|
3409
|
+
remaining,
|
|
3410
|
+
currentCount,
|
|
3411
|
+
isUnlimited: false
|
|
3412
|
+
};
|
|
3413
|
+
}
|
|
3414
|
+
function hasSufficientAiQuestionQuota(quota, requested) {
|
|
3415
|
+
if (requested <= 0) return false;
|
|
3416
|
+
return (_nullishCoalesce(quota, () => ( 0))) >= requested;
|
|
3417
|
+
}
|
|
3418
|
+
function hasSufficientAiEvalQuota(quota) {
|
|
3419
|
+
return (_nullishCoalesce(quota, () => ( 0))) > 0;
|
|
3420
|
+
}
|
|
3421
|
+
|
|
1755
3422
|
// src/navigation.ts
|
|
1756
3423
|
function getActiveTab(pathname) {
|
|
1757
3424
|
const normalized = pathname.toLowerCase();
|
|
@@ -1802,8 +3469,8 @@ function extractBilingualName(name, language) {
|
|
|
1802
3469
|
if (!match) {
|
|
1803
3470
|
return trimmed;
|
|
1804
3471
|
}
|
|
1805
|
-
const part1 = _optionalChain([match, 'access',
|
|
1806
|
-
const part2 = _optionalChain([match, 'access',
|
|
3472
|
+
const part1 = _optionalChain([match, 'access', _211 => _211[1], 'optionalAccess', _212 => _212.trim, 'call', _213 => _213()]) || "";
|
|
3473
|
+
const part2 = _optionalChain([match, 'access', _214 => _214[2], 'optionalAccess', _215 => _215.trim, 'call', _216 => _216()]) || "";
|
|
1807
3474
|
if (!part1 && !part2) return trimmed;
|
|
1808
3475
|
if (!part1) return part2;
|
|
1809
3476
|
if (!part2) return part1;
|
|
@@ -1819,7 +3486,7 @@ function extractBilingualName(name, language) {
|
|
|
1819
3486
|
banglaPart = part1;
|
|
1820
3487
|
englishPart = part2;
|
|
1821
3488
|
}
|
|
1822
|
-
const lang = _optionalChain([language, 'optionalAccess',
|
|
3489
|
+
const lang = _optionalChain([language, 'optionalAccess', _217 => _217.toLowerCase, 'call', _218 => _218()]);
|
|
1823
3490
|
if (lang === "en") {
|
|
1824
3491
|
return englishPart || banglaPart || trimmed;
|
|
1825
3492
|
}
|
|
@@ -1906,7 +3573,7 @@ function processLatexText(str) {
|
|
|
1906
3573
|
}
|
|
1907
3574
|
|
|
1908
3575
|
// src/utils/time.ts
|
|
1909
|
-
function convertToBangladeshTime(isoString) {
|
|
3576
|
+
function convertToBangladeshTime(isoString, locale = "en-GB") {
|
|
1910
3577
|
const options = {
|
|
1911
3578
|
year: "numeric",
|
|
1912
3579
|
month: "long",
|
|
@@ -1916,7 +3583,8 @@ function convertToBangladeshTime(isoString) {
|
|
|
1916
3583
|
hour12: true
|
|
1917
3584
|
};
|
|
1918
3585
|
const date = new Date(isoString);
|
|
1919
|
-
|
|
3586
|
+
const resolvedLocale = locale === "bn" ? "bn-BD" : locale;
|
|
3587
|
+
return date.toLocaleString(resolvedLocale, {
|
|
1920
3588
|
...options,
|
|
1921
3589
|
timeZone: "Asia/Dhaka"
|
|
1922
3590
|
});
|
|
@@ -1933,7 +3601,7 @@ function getDhakaNow() {
|
|
|
1933
3601
|
second: "2-digit",
|
|
1934
3602
|
hour12: false
|
|
1935
3603
|
}).formatToParts(now);
|
|
1936
|
-
const get = (type) => _nullishCoalesce(_optionalChain([parts, 'access',
|
|
3604
|
+
const get = (type) => _nullishCoalesce(_optionalChain([parts, 'access', _219 => _219.find, 'call', _220 => _220((p) => p.type === type), 'optionalAccess', _221 => _221.value]), () => ( "00"));
|
|
1937
3605
|
return /* @__PURE__ */ new Date(`${get("year")}-${get("month")}-${get("day")}T${get("hour")}:${get("minute")}:${get("second")}`);
|
|
1938
3606
|
}
|
|
1939
3607
|
function calculateTimeLeft(endTime) {
|
|
@@ -1976,7 +3644,7 @@ function getYouTubeId(url) {
|
|
|
1976
3644
|
if (!url) return null;
|
|
1977
3645
|
const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|[?&]v=)([^#&?]*).*/;
|
|
1978
3646
|
const match = url.match(regExp);
|
|
1979
|
-
return match && _optionalChain([match, 'access',
|
|
3647
|
+
return match && _optionalChain([match, 'access', _222 => _222[2], 'optionalAccess', _223 => _223.length]) === 11 ? match[2] : null;
|
|
1980
3648
|
}
|
|
1981
3649
|
|
|
1982
3650
|
// src/utils/file.ts
|
|
@@ -2008,6 +3676,63 @@ function isLanguage(value) {
|
|
|
2008
3676
|
function isDifficulty(value) {
|
|
2009
3677
|
return ["Easy", "Medium", "Hard"].includes(value);
|
|
2010
3678
|
}
|
|
3679
|
+
function normalizeLevel(value) {
|
|
3680
|
+
if (!value) return "";
|
|
3681
|
+
const clean = value.trim().replace(/\s+/g, "+");
|
|
3682
|
+
const upper = clean.toUpperCase();
|
|
3683
|
+
if (upper === "SSC" || upper.includes("CLASS_9") || upper.includes("CLASS_10")) return "SSC";
|
|
3684
|
+
if (upper === "HSC" || upper === "ADMISSION" || upper === "HSC+ADMISSION" || upper.includes("CLASS_11") || upper.includes("CLASS_12")) return "HSC+Admission";
|
|
3685
|
+
if (upper === "BCS") return "BCS";
|
|
3686
|
+
return clean;
|
|
3687
|
+
}
|
|
3688
|
+
|
|
3689
|
+
|
|
3690
|
+
|
|
3691
|
+
|
|
3692
|
+
|
|
3693
|
+
|
|
3694
|
+
|
|
3695
|
+
|
|
3696
|
+
|
|
3697
|
+
|
|
3698
|
+
|
|
3699
|
+
|
|
3700
|
+
|
|
3701
|
+
|
|
3702
|
+
|
|
3703
|
+
|
|
3704
|
+
|
|
3705
|
+
|
|
3706
|
+
|
|
3707
|
+
|
|
3708
|
+
|
|
3709
|
+
|
|
3710
|
+
|
|
3711
|
+
|
|
3712
|
+
|
|
3713
|
+
|
|
3714
|
+
|
|
3715
|
+
|
|
3716
|
+
|
|
3717
|
+
|
|
3718
|
+
|
|
3719
|
+
|
|
3720
|
+
|
|
3721
|
+
|
|
3722
|
+
|
|
3723
|
+
|
|
3724
|
+
|
|
3725
|
+
|
|
3726
|
+
|
|
3727
|
+
|
|
3728
|
+
|
|
3729
|
+
|
|
3730
|
+
|
|
3731
|
+
|
|
3732
|
+
|
|
3733
|
+
|
|
3734
|
+
|
|
3735
|
+
|
|
2011
3736
|
|
|
2012
3737
|
|
|
2013
3738
|
|
|
@@ -2085,5 +3810,5 @@ function isDifficulty(value) {
|
|
|
2085
3810
|
|
|
2086
3811
|
|
|
2087
3812
|
|
|
2088
|
-
exports.AIService = AIService; exports.CLOTHES_COLORS = CLOTHES_COLORS; exports.COLOR_HUES = COLOR_HUES; exports.ContestService = ContestService; exports.CourseService = CourseService; exports.CurriculumService = CurriculumService; exports.HAIR_COLORS = HAIR_COLORS; exports.INITIAL_AVATAR_DATA = INITIAL_AVATAR_DATA; exports.MediaService = MediaService; exports.MediaUrlCache =
|
|
3813
|
+
exports.AIService = AIService; exports.AI_EVAL_BOOSTER_PACKS = AI_EVAL_BOOSTER_PACKS; exports.AI_QUESTION_BOOSTER_PACKS = AI_QUESTION_BOOSTER_PACKS; exports.CLOTHES_COLORS = CLOTHES_COLORS; exports.COLOR_HUES = COLOR_HUES; exports.ContestService = ContestService; exports.CourseService = CourseService; exports.CurriculumService = CurriculumService; exports.FREE_DAILY_PRACTICE_LIMIT = FREE_DAILY_PRACTICE_LIMIT; exports.HAIR_COLORS = HAIR_COLORS; exports.INITIAL_AVATAR_DATA = INITIAL_AVATAR_DATA; exports.MANUAL_PAYMENT_CONFIG = MANUAL_PAYMENT_CONFIG; exports.MediaService = MediaService; exports.MediaUrlCache = _chunkODXD2WJNcjs.MediaUrlCache; exports.NewsService = NewsService; exports.NotificationService = NotificationService; exports.OrjokClient = OrjokClient; exports.PackService = PackService; exports.ProgressService = ProgressService; exports.QuestionService = QuestionService; exports.RENDER_ORDER = RENDER_ORDER; exports.SUBSCRIPTION_PLANS = SUBSCRIPTION_PLANS; exports.SubscriptionService = SubscriptionService; exports.UserService = UserService; exports.XP_REWARDS = _chunkODXD2WJNcjs.XP_REWARDS; exports.XP_TIERS = _chunkODXD2WJNcjs.XP_TIERS; exports._resetMediaUrlWarning = _chunkODXD2WJNcjs._resetMediaUrlWarning; exports.aggregateChapterMetrics = _chunkODXD2WJNcjs.aggregateChapterMetrics; exports.aggregateSubjectMetrics = _chunkODXD2WJNcjs.aggregateSubjectMetrics; exports.aggregateTopicMetrics = _chunkODXD2WJNcjs.aggregateTopicMetrics; exports.buildImageAnswer = buildImageAnswer; exports.calculateAccuracy = _chunkODXD2WJNcjs.calculateAccuracy; exports.calculateDefaultExamMinutes = calculateDefaultExamMinutes; exports.calculateExamTime = calculateExamTime; exports.calculateStreakFromDates = calculateStreakFromDates; exports.calculateTimeLeft = calculateTimeLeft; exports.calculateUnreadCount = _chunkODXD2WJNcjs.calculateUnreadCount; exports.calculateXpReward = _chunkODXD2WJNcjs.calculateXpReward; exports.canAccessMistakeVault = canAccessMistakeVault; exports.canExportPack = canExportPack; exports.canWatchContestSolution = canWatchContestSolution; exports.checkDailyPracticeLimit = checkDailyPracticeLimit; exports.computeRatingDelta = computeRatingDelta; exports.convertToBangladeshTime = convertToBangladeshTime; exports.createOrjokClient = createOrjokClient; exports.detectQuestionType = detectQuestionType; exports.difficultyOptions = _chunkODXD2WJNcjs.difficultyOptions; exports.engToBanglaNumber = engToBanglaNumber; exports.extractBilingualName = extractBilingualName; exports.filterQuestionsByMode = filterQuestionsByMode; exports.formatBDT = formatBDT; exports.formatCurriculumName = formatCurriculumName; exports.formatDate = formatDate; exports.formatExamTime = formatExamTime; exports.formatLevelUpNotification = _chunkODXD2WJNcjs.formatLevelUpNotification; exports.formatQuestionsToCsv = formatQuestionsToCsv; exports.formatQuestionsToText = formatQuestionsToText; exports.generateRandomAvatarConfig = generateRandomAvatarConfig; exports.generateRandomAvatarState = generateRandomAvatarState; exports.getActiveTab = getActiveTab; exports.getActualOptionFileName = getActualOptionFileName; exports.getAllTiers = getAllTiers; exports.getAllXpTiers = _chunkODXD2WJNcjs.getAllXpTiers; exports.getCanonicalPath = getCanonicalPath; exports.getCycleMultiplier = getCycleMultiplier; exports.getDailyPracticeLimit = getDailyPracticeLimit; exports.getDhakaNow = getDhakaNow; exports.getEloProgress = getEloProgress; exports.getEloTier = getEloTier; exports.getLevelFromXp = _chunkODXD2WJNcjs.getLevelFromXp; exports.getPlanAiQuotas = getPlanAiQuotas; exports.getPlanDiscountPercent = getPlanDiscountPercent; exports.getPlanMonthlyEquivalentPrice = getPlanMonthlyEquivalentPrice; exports.getPlanOriginalPrice = getPlanOriginalPrice; exports.getPlanPrice = getPlanPrice; exports.getPublicExamsByLevel = _chunkODXD2WJNcjs.getPublicExamsByLevel; exports.getRatingForSubject = getRatingForSubject; exports.getRecommendedSubjectsForLevel = getRecommendedSubjectsForLevel; exports.getRelativeTime = getRelativeTime; exports.getTimeOfDayGreeting = getTimeOfDayGreeting; exports.getXpForLevel = _chunkODXD2WJNcjs.getXpForLevel; exports.getXpProgress = _chunkODXD2WJNcjs.getXpProgress; exports.getXpRequiredForNextLevel = _chunkODXD2WJNcjs.getXpRequiredForNextLevel; exports.getXpTier = _chunkODXD2WJNcjs.getXpTier; exports.getYouTubeId = getYouTubeId; exports.hasAiTierAccess = hasAiTierAccess; exports.hasProAccess = hasProAccess; exports.hasSufficientAiEvalQuota = hasSufficientAiEvalQuota; exports.hasSufficientAiQuestionQuota = hasSufficientAiQuestionQuota; exports.isAuthGatedRoute = isAuthGatedRoute; exports.isCorrectAnswer = isCorrectAnswer; exports.isDifficulty = isDifficulty; exports.isDifficultyMatch = _chunkODXD2WJNcjs.isDifficultyMatch; exports.isImageAnswer = isImageAnswer; exports.isLanguage = isLanguage; exports.isLanguageMatch = _chunkODXD2WJNcjs.isLanguageMatch; exports.isQuestionLevel = isQuestionLevel; exports.isStorageKey = _chunkODXD2WJNcjs.isStorageKey; exports.isValidBangladeshiPhone = isValidBangladeshiPhone; exports.isValidMCQ = _chunkODXD2WJNcjs.isValidMCQ; exports.isValidTrxId = isValidTrxId; exports.languageOptions = _chunkODXD2WJNcjs.languageOptions; exports.levelOptions = _chunkODXD2WJNcjs.levelOptions; exports.mapCognitoLevelToStandardLevel = mapCognitoLevelToStandardLevel; exports.mergeNotificationTimeline = _chunkODXD2WJNcjs.mergeNotificationTimeline; exports.normalizeDifficulty = normalizeDifficulty; exports.normalizeLevel = normalizeLevel; exports.paginateWithAccumulator = paginateWithAccumulator; exports.parseAvatarConfig = parseAvatarConfig; exports.parseAvatarConfigWithDefaults = parseAvatarConfigWithDefaults; exports.parseCsvQuestions = parseCsvQuestions; exports.parseImageKeys = parseImageKeys; exports.parseTextQuestions = parseTextQuestions; exports.processLatexText = processLatexText; exports.publicExamOptions = _chunkODXD2WJNcjs.publicExamOptions; exports.reorderObjectKeys = reorderObjectKeys; exports.resolveMediaUrl = _chunkODXD2WJNcjs.resolveMediaUrl; exports.resolveMediaUrls = _chunkODXD2WJNcjs.resolveMediaUrls; exports.sanitizeFileName = sanitizeFileName; exports.scoreExam = scoreExam; exports.serializeAvatarConfig = serializeAvatarConfig; exports.shouldTrackPracticeProgress = shouldTrackPracticeProgress; exports.shuffle = _chunkODXD2WJNcjs.shuffle; exports.shuffleInPlace = _chunkODXD2WJNcjs.shuffleInPlace;
|
|
2089
3814
|
//# sourceMappingURL=index.cjs.map
|