@orjok/commons 1.0.2 → 1.1.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/chunk-DB3CMKPP.cjs +165 -0
- package/dist/chunk-DB3CMKPP.cjs.map +1 -0
- package/dist/chunk-ZDGYAVEC.js +165 -0
- package/dist/chunk-ZDGYAVEC.js.map +1 -0
- package/dist/hooks.cjs +492 -2
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.cts +130 -2
- package/dist/hooks.d.ts +130 -2
- package/dist/hooks.js +491 -1
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +590 -224
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +86 -14
- package/dist/index.d.ts +86 -14
- package/dist/index.js +549 -183
- package/dist/index.js.map +1 -1
- package/dist/{client-Bm9aiyTx.d.ts → practice-Dh2Tv80G.d.ts} +36 -5
- package/dist/{client-BaOC79Nc.d.cts → practice-QnWtC5A7.d.cts} +36 -5
- package/dist/testing.cjs +10 -0
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +2 -0
- package/dist/testing.d.ts +2 -0
- package/dist/testing.js +10 -0
- package/dist/testing.js.map +1 -1
- package/package.json +5 -3
package/dist/hooks.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
aggregateSubjectMetrics,
|
|
3
|
+
isDifficultyMatch,
|
|
4
|
+
isLanguageMatch,
|
|
5
|
+
isStorageKey,
|
|
6
|
+
isValidMCQ,
|
|
7
|
+
resolveMediaUrl,
|
|
8
|
+
shuffle
|
|
9
|
+
} from "./chunk-ZDGYAVEC.js";
|
|
10
|
+
|
|
1
11
|
// src/hooks/useOrjokClient.ts
|
|
2
12
|
import { createContext, useContext } from "react";
|
|
3
13
|
var OrjokContext = createContext(null);
|
|
@@ -9,8 +19,488 @@ function useOrjokClient() {
|
|
|
9
19
|
}
|
|
10
20
|
return client;
|
|
11
21
|
}
|
|
22
|
+
|
|
23
|
+
// src/hooks/useMediaUrl.ts
|
|
24
|
+
import { useQuery } from "@tanstack/react-query";
|
|
25
|
+
function useMediaUrl(key) {
|
|
26
|
+
const client = useOrjokClient();
|
|
27
|
+
const isResolvable = Boolean(key && isStorageKey(key));
|
|
28
|
+
const query = useQuery({
|
|
29
|
+
queryKey: ["media-url", key],
|
|
30
|
+
queryFn: async () => {
|
|
31
|
+
if (!key) return null;
|
|
32
|
+
return resolveMediaUrl(key, client.storage);
|
|
33
|
+
},
|
|
34
|
+
enabled: isResolvable,
|
|
35
|
+
staleTime: 50 * 60 * 1e3
|
|
36
|
+
// 50 mins
|
|
37
|
+
});
|
|
38
|
+
if (!key) {
|
|
39
|
+
return { url: null, isLoading: false };
|
|
40
|
+
}
|
|
41
|
+
if (!isStorageKey(key)) {
|
|
42
|
+
return { url: key, isLoading: false };
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
url: query.data ?? null,
|
|
46
|
+
isLoading: query.isLoading
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/hooks/useCurriculum.ts
|
|
51
|
+
import { useQuery as useQuery2 } from "@tanstack/react-query";
|
|
52
|
+
function useCurriculum({ level, subjectId, chapterId } = {}) {
|
|
53
|
+
const client = useOrjokClient();
|
|
54
|
+
const subjectsQuery = useQuery2({
|
|
55
|
+
queryKey: ["curriculum-subjects", level],
|
|
56
|
+
queryFn: () => level ? client.curriculum.getSubjects(level) : Promise.resolve([]),
|
|
57
|
+
enabled: Boolean(level)
|
|
58
|
+
});
|
|
59
|
+
const chaptersQuery = useQuery2({
|
|
60
|
+
queryKey: ["curriculum-chapters", subjectId],
|
|
61
|
+
queryFn: () => subjectId ? client.curriculum.getChapters(subjectId) : Promise.resolve([]),
|
|
62
|
+
enabled: Boolean(subjectId)
|
|
63
|
+
});
|
|
64
|
+
const topicsQuery = useQuery2({
|
|
65
|
+
queryKey: ["curriculum-topics", chapterId],
|
|
66
|
+
queryFn: () => chapterId ? client.curriculum.getTopics(chapterId) : Promise.resolve([]),
|
|
67
|
+
enabled: Boolean(chapterId)
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
subjects: subjectsQuery.data ?? [],
|
|
71
|
+
chapters: chaptersQuery.data ?? [],
|
|
72
|
+
topics: topicsQuery.data ?? [],
|
|
73
|
+
isLoadingSubjects: subjectsQuery.isLoading,
|
|
74
|
+
isLoadingChapters: chaptersQuery.isLoading,
|
|
75
|
+
isLoadingTopics: topicsQuery.isLoading
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/hooks/useQuestions.ts
|
|
80
|
+
import { useQuery as useQuery3 } from "@tanstack/react-query";
|
|
81
|
+
function useQuestions({
|
|
82
|
+
subjectId,
|
|
83
|
+
chapterId,
|
|
84
|
+
topicId,
|
|
85
|
+
language,
|
|
86
|
+
difficulty,
|
|
87
|
+
limit = 20,
|
|
88
|
+
nextToken
|
|
89
|
+
} = {}) {
|
|
90
|
+
const client = useOrjokClient();
|
|
91
|
+
const lang = language === "All" ? void 0 : language;
|
|
92
|
+
const diff = difficulty === "All" ? void 0 : difficulty;
|
|
93
|
+
const query = useQuery3({
|
|
94
|
+
queryKey: ["questions", { subjectId, chapterId, topicId, language, difficulty, limit, nextToken }],
|
|
95
|
+
queryFn: async () => {
|
|
96
|
+
if (topicId) {
|
|
97
|
+
return client.questions.listByTopic({ id: topicId, language: lang, difficulty: diff, limit, nextToken: nextToken || void 0 });
|
|
98
|
+
}
|
|
99
|
+
if (chapterId) {
|
|
100
|
+
return client.questions.listByChapter({ id: chapterId, language: lang, difficulty: diff, limit, nextToken: nextToken || void 0 });
|
|
101
|
+
}
|
|
102
|
+
if (subjectId) {
|
|
103
|
+
return client.questions.listBySubject({ id: subjectId, language: lang, difficulty: diff, limit, nextToken: nextToken || void 0 });
|
|
104
|
+
}
|
|
105
|
+
return { items: [], nextToken: null };
|
|
106
|
+
},
|
|
107
|
+
enabled: Boolean(subjectId || chapterId || topicId)
|
|
108
|
+
});
|
|
109
|
+
return {
|
|
110
|
+
questions: query.data?.items ?? [],
|
|
111
|
+
nextToken: query.data?.nextToken ?? null,
|
|
112
|
+
isLoading: query.isLoading,
|
|
113
|
+
refetch: query.refetch
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/hooks/usePacks.ts
|
|
118
|
+
import { useQuery as useQuery4 } from "@tanstack/react-query";
|
|
119
|
+
function usePacks({
|
|
120
|
+
subjectId,
|
|
121
|
+
chapterId,
|
|
122
|
+
topicId,
|
|
123
|
+
language,
|
|
124
|
+
difficulty,
|
|
125
|
+
limit = 20,
|
|
126
|
+
nextToken
|
|
127
|
+
} = {}) {
|
|
128
|
+
const client = useOrjokClient();
|
|
129
|
+
const lang = language === "All" ? void 0 : language;
|
|
130
|
+
const diff = difficulty === "All" ? void 0 : difficulty;
|
|
131
|
+
const query = useQuery4({
|
|
132
|
+
queryKey: ["packs", { subjectId, chapterId, topicId, language, difficulty, limit, nextToken }],
|
|
133
|
+
queryFn: async () => {
|
|
134
|
+
if (topicId) {
|
|
135
|
+
return client.packs.listByTopic({ id: topicId, language: lang, difficulty: diff, limit, nextToken: nextToken || void 0 });
|
|
136
|
+
}
|
|
137
|
+
if (chapterId) {
|
|
138
|
+
return client.packs.listByChapter({ id: chapterId, language: lang, difficulty: diff, limit, nextToken: nextToken || void 0 });
|
|
139
|
+
}
|
|
140
|
+
if (subjectId) {
|
|
141
|
+
return client.packs.listBySubject({ id: subjectId, language: lang, difficulty: diff, limit, nextToken: nextToken || void 0 });
|
|
142
|
+
}
|
|
143
|
+
return { items: [], nextToken: null };
|
|
144
|
+
},
|
|
145
|
+
enabled: Boolean(subjectId || chapterId || topicId)
|
|
146
|
+
});
|
|
147
|
+
return {
|
|
148
|
+
packs: query.data?.items ?? [],
|
|
149
|
+
nextToken: query.data?.nextToken ?? null,
|
|
150
|
+
isLoading: query.isLoading,
|
|
151
|
+
refetch: query.refetch
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function usePackDetail(packId) {
|
|
155
|
+
const client = useOrjokClient();
|
|
156
|
+
const query = useQuery4({
|
|
157
|
+
queryKey: ["pack-detail", packId],
|
|
158
|
+
queryFn: async () => {
|
|
159
|
+
if (!packId) return null;
|
|
160
|
+
return client.packs.getFull(packId);
|
|
161
|
+
},
|
|
162
|
+
enabled: Boolean(packId)
|
|
163
|
+
});
|
|
164
|
+
return {
|
|
165
|
+
pack: query.data ?? null,
|
|
166
|
+
questions: query.data?.questions?.items ?? [],
|
|
167
|
+
isLoading: query.isLoading,
|
|
168
|
+
refetch: query.refetch
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/hooks/useContest.ts
|
|
173
|
+
import { useQuery as useQuery5 } from "@tanstack/react-query";
|
|
174
|
+
function useContest(contestId, checkParticipation = false) {
|
|
175
|
+
const client = useOrjokClient();
|
|
176
|
+
const contestQuery = useQuery5({
|
|
177
|
+
queryKey: ["contest", contestId],
|
|
178
|
+
queryFn: async () => {
|
|
179
|
+
if (!contestId) return null;
|
|
180
|
+
return client.contests.get(contestId);
|
|
181
|
+
},
|
|
182
|
+
enabled: Boolean(contestId)
|
|
183
|
+
});
|
|
184
|
+
const partQuery = useQuery5({
|
|
185
|
+
queryKey: ["contest-participation", contestId],
|
|
186
|
+
queryFn: async () => {
|
|
187
|
+
if (!contestId || !checkParticipation) return null;
|
|
188
|
+
return client.contests.checkParticipation(contestId);
|
|
189
|
+
},
|
|
190
|
+
enabled: Boolean(contestId && checkParticipation)
|
|
191
|
+
});
|
|
192
|
+
return {
|
|
193
|
+
contest: contestQuery.data ?? null,
|
|
194
|
+
participation: partQuery.data ?? null,
|
|
195
|
+
isLoading: contestQuery.isLoading || checkParticipation && partQuery.isLoading,
|
|
196
|
+
refetch: async () => {
|
|
197
|
+
await Promise.all([contestQuery.refetch(), partQuery.refetch()]);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function useContestsList({ level, nextToken } = {}) {
|
|
202
|
+
const client = useOrjokClient();
|
|
203
|
+
const query = useQuery5({
|
|
204
|
+
queryKey: ["contests-list", level, nextToken],
|
|
205
|
+
queryFn: () => client.contests.list(nextToken, level)
|
|
206
|
+
});
|
|
207
|
+
return {
|
|
208
|
+
contests: query.data?.items ?? [],
|
|
209
|
+
nextToken: query.data?.nextToken ?? null,
|
|
210
|
+
isLoading: query.isLoading,
|
|
211
|
+
refetch: query.refetch
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// src/hooks/useCourse.ts
|
|
216
|
+
import { useQuery as useQuery6 } from "@tanstack/react-query";
|
|
217
|
+
function useCourse(courseId) {
|
|
218
|
+
const client = useOrjokClient();
|
|
219
|
+
const query = useQuery6({
|
|
220
|
+
queryKey: ["course", courseId],
|
|
221
|
+
queryFn: async () => {
|
|
222
|
+
if (!courseId) return null;
|
|
223
|
+
return client.courses.get(courseId);
|
|
224
|
+
},
|
|
225
|
+
enabled: Boolean(courseId)
|
|
226
|
+
});
|
|
227
|
+
return {
|
|
228
|
+
course: query.data ?? null,
|
|
229
|
+
isLoading: query.isLoading,
|
|
230
|
+
refetch: query.refetch
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function useCourseItems(courseId) {
|
|
234
|
+
const client = useOrjokClient();
|
|
235
|
+
const query = useQuery6({
|
|
236
|
+
queryKey: ["course-items", courseId],
|
|
237
|
+
queryFn: async () => {
|
|
238
|
+
if (!courseId) return [];
|
|
239
|
+
return client.courses.getItems(courseId);
|
|
240
|
+
},
|
|
241
|
+
enabled: Boolean(courseId)
|
|
242
|
+
});
|
|
243
|
+
return {
|
|
244
|
+
items: query.data ?? [],
|
|
245
|
+
isLoading: query.isLoading,
|
|
246
|
+
refetch: query.refetch
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
function useCourseLiveExams(courseId) {
|
|
250
|
+
const client = useOrjokClient();
|
|
251
|
+
const query = useQuery6({
|
|
252
|
+
queryKey: ["course-live-exams", courseId],
|
|
253
|
+
queryFn: async () => {
|
|
254
|
+
if (!courseId) return { items: [], nextToken: null };
|
|
255
|
+
return client.courses.getLiveExams(courseId);
|
|
256
|
+
},
|
|
257
|
+
enabled: Boolean(courseId)
|
|
258
|
+
});
|
|
259
|
+
return {
|
|
260
|
+
exams: query.data?.items ?? [],
|
|
261
|
+
isLoading: query.isLoading,
|
|
262
|
+
refetch: query.refetch
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// src/hooks/useProgress.ts
|
|
267
|
+
import { useQuery as useQuery7 } from "@tanstack/react-query";
|
|
268
|
+
function useProgress(userId) {
|
|
269
|
+
const client = useOrjokClient();
|
|
270
|
+
const subjectsQuery = useQuery7({
|
|
271
|
+
queryKey: ["user-subject-progress", userId],
|
|
272
|
+
queryFn: () => userId ? client.progress.getSubjectProgress(userId) : Promise.resolve([]),
|
|
273
|
+
enabled: Boolean(userId)
|
|
274
|
+
});
|
|
275
|
+
const chaptersQuery = useQuery7({
|
|
276
|
+
queryKey: ["user-chapter-progress", userId],
|
|
277
|
+
queryFn: () => userId ? client.progress.getChapterProgress(userId) : Promise.resolve([]),
|
|
278
|
+
enabled: Boolean(userId)
|
|
279
|
+
});
|
|
280
|
+
const topicsQuery = useQuery7({
|
|
281
|
+
queryKey: ["user-topic-progress", userId],
|
|
282
|
+
queryFn: () => userId ? client.progress.getTopicProgress(userId) : Promise.resolve([]),
|
|
283
|
+
enabled: Boolean(userId)
|
|
284
|
+
});
|
|
285
|
+
const subjectsProgress = subjectsQuery.data ?? [];
|
|
286
|
+
const chaptersProgress = chaptersQuery.data ?? [];
|
|
287
|
+
const topicsProgress = topicsQuery.data ?? [];
|
|
288
|
+
const metrics = aggregateSubjectMetrics(subjectsProgress);
|
|
289
|
+
return {
|
|
290
|
+
subjectsProgress,
|
|
291
|
+
chaptersProgress,
|
|
292
|
+
topicsProgress,
|
|
293
|
+
metrics,
|
|
294
|
+
isLoading: subjectsQuery.isLoading || chaptersQuery.isLoading || topicsQuery.isLoading,
|
|
295
|
+
refetch: async () => {
|
|
296
|
+
await Promise.all([
|
|
297
|
+
subjectsQuery.refetch(),
|
|
298
|
+
chaptersQuery.refetch(),
|
|
299
|
+
topicsQuery.refetch()
|
|
300
|
+
]);
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// src/hooks/usePractice.ts
|
|
306
|
+
import { useState, useCallback } from "react";
|
|
307
|
+
function usePractice({
|
|
308
|
+
subjectId,
|
|
309
|
+
chapterIds = [],
|
|
310
|
+
topicIds = [],
|
|
311
|
+
language = "Bangla",
|
|
312
|
+
difficulty = "All",
|
|
313
|
+
userId,
|
|
314
|
+
isCreator
|
|
315
|
+
} = {}) {
|
|
316
|
+
const client = useOrjokClient();
|
|
317
|
+
const [mode, setMode] = useState("setup");
|
|
318
|
+
const [questions, setQuestions] = useState([]);
|
|
319
|
+
const [currentIdx, setCurrentIdx] = useState(0);
|
|
320
|
+
const [selectedOption, setSelectedOption] = useState(null);
|
|
321
|
+
const [isAnswered, setIsAnswered] = useState(false);
|
|
322
|
+
const [isCorrect, setIsCorrect] = useState(null);
|
|
323
|
+
const [score, setScore] = useState(0);
|
|
324
|
+
const [totalPracticed, setTotalPracticed] = useState(0);
|
|
325
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
326
|
+
const [isValidating, setIsValidating] = useState(false);
|
|
327
|
+
const fetchQuestionsPool = useCallback(async () => {
|
|
328
|
+
const bounds = [];
|
|
329
|
+
if (topicIds.length > 0) {
|
|
330
|
+
topicIds.forEach((tId) => bounds.push({ id: tId, type: "topic" }));
|
|
331
|
+
} else if (chapterIds.length > 0) {
|
|
332
|
+
chapterIds.forEach((cId) => bounds.push({ id: cId, type: "chapter" }));
|
|
333
|
+
} else if (subjectId) {
|
|
334
|
+
bounds.push({ id: subjectId, type: "subject" });
|
|
335
|
+
}
|
|
336
|
+
if (bounds.length === 0) return [];
|
|
337
|
+
const queries = bounds.map(async (b) => {
|
|
338
|
+
try {
|
|
339
|
+
if (b.type === "topic") {
|
|
340
|
+
return await client.questions.listByTopic({ id: b.id, limit: 50 });
|
|
341
|
+
} else if (b.type === "chapter") {
|
|
342
|
+
return await client.questions.listByChapter({ id: b.id, limit: 50 });
|
|
343
|
+
} else {
|
|
344
|
+
return await client.questions.listBySubject({ id: b.id, limit: 50 });
|
|
345
|
+
}
|
|
346
|
+
} catch (e) {
|
|
347
|
+
console.error("Error fetching bounds query in practice:", b, e);
|
|
348
|
+
return { items: [] };
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
const results = await Promise.all(queries);
|
|
352
|
+
const uniqueMap = /* @__PURE__ */ new Map();
|
|
353
|
+
results.forEach((r) => {
|
|
354
|
+
(r.items || []).forEach((q) => {
|
|
355
|
+
if (q && q.id && !uniqueMap.has(q.id)) {
|
|
356
|
+
uniqueMap.set(q.id, q);
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
let list = Array.from(uniqueMap.values()).filter((q) => {
|
|
361
|
+
if (!isLanguageMatch(q.language, language)) return false;
|
|
362
|
+
if (!isDifficultyMatch(q.difficulty, difficulty)) return false;
|
|
363
|
+
return true;
|
|
364
|
+
});
|
|
365
|
+
if (list.length < 5 && subjectId && bounds.some((b) => b.type !== "subject")) {
|
|
366
|
+
try {
|
|
367
|
+
const subRes = await client.questions.listBySubject({ id: subjectId, limit: 50 });
|
|
368
|
+
(subRes.items || []).forEach((q) => {
|
|
369
|
+
if (q && q.id && !uniqueMap.has(q.id)) {
|
|
370
|
+
if (isLanguageMatch(q.language, language) && isDifficultyMatch(q.difficulty, difficulty)) {
|
|
371
|
+
list.push(q);
|
|
372
|
+
uniqueMap.set(q.id, q);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
} catch (e) {
|
|
377
|
+
console.error("Error fetching subject fallback in practice:", e);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return list.filter(isValidMCQ);
|
|
381
|
+
}, [client, subjectId, chapterIds, topicIds, language, difficulty]);
|
|
382
|
+
const startPractice = useCallback(async () => {
|
|
383
|
+
setIsLoading(true);
|
|
384
|
+
setMode("practice");
|
|
385
|
+
setCurrentIdx(0);
|
|
386
|
+
setScore(0);
|
|
387
|
+
setTotalPracticed(0);
|
|
388
|
+
setSelectedOption(null);
|
|
389
|
+
setIsAnswered(false);
|
|
390
|
+
setIsCorrect(null);
|
|
391
|
+
try {
|
|
392
|
+
const fetched = await fetchQuestionsPool();
|
|
393
|
+
setQuestions(shuffle(fetched));
|
|
394
|
+
} catch (e) {
|
|
395
|
+
console.error("Error starting practice:", e);
|
|
396
|
+
setQuestions([]);
|
|
397
|
+
} finally {
|
|
398
|
+
setIsLoading(false);
|
|
399
|
+
}
|
|
400
|
+
}, [fetchQuestionsPool]);
|
|
401
|
+
const selectOption = useCallback(
|
|
402
|
+
async (optionId) => {
|
|
403
|
+
if (isAnswered || isValidating || questions.length === 0) return;
|
|
404
|
+
setSelectedOption(optionId);
|
|
405
|
+
setIsValidating(true);
|
|
406
|
+
const currentQ = questions[currentIdx];
|
|
407
|
+
if (!currentQ) {
|
|
408
|
+
setIsValidating(false);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
try {
|
|
412
|
+
const fullQ = await client.questions.get(currentQ.id);
|
|
413
|
+
const ansVal = fullQ?.answer;
|
|
414
|
+
const rawOpts = currentQ.options;
|
|
415
|
+
const optsList = Array.isArray(rawOpts) ? rawOpts : rawOpts && typeof rawOpts === "object" && Array.isArray(rawOpts.items) ? rawOpts.items : [];
|
|
416
|
+
const chosenOpt = optsList.find((o) => o?.id === optionId);
|
|
417
|
+
const correct = Boolean(
|
|
418
|
+
ansVal && (ansVal === optionId || chosenOpt && ansVal === chosenOpt.content)
|
|
419
|
+
);
|
|
420
|
+
setIsCorrect(correct);
|
|
421
|
+
setIsAnswered(true);
|
|
422
|
+
setTotalPracticed((prev) => prev + 1);
|
|
423
|
+
if (correct) setScore((prev) => prev + 1);
|
|
424
|
+
if (userId && isCreator) {
|
|
425
|
+
void client.progress.track({
|
|
426
|
+
questionId: currentQ.id,
|
|
427
|
+
isCorrect: correct,
|
|
428
|
+
subjectId: currentQ.subjectId || subjectId,
|
|
429
|
+
chapterId: currentQ.chapterId || (chapterIds.length === 1 ? chapterIds[0] : void 0),
|
|
430
|
+
topicId: currentQ.topicId || (topicIds.length === 1 ? topicIds[0] : void 0)
|
|
431
|
+
}).catch((e) => console.error("Tracking practice progress error:", e));
|
|
432
|
+
}
|
|
433
|
+
} catch (err) {
|
|
434
|
+
console.error("Error validating option in practice:", err);
|
|
435
|
+
} finally {
|
|
436
|
+
setIsValidating(false);
|
|
437
|
+
}
|
|
438
|
+
},
|
|
439
|
+
[client, isAnswered, isValidating, questions, currentIdx, userId, isCreator, subjectId, chapterIds, topicIds]
|
|
440
|
+
);
|
|
441
|
+
const nextQuestion = useCallback(() => {
|
|
442
|
+
if (questions.length === 0) return;
|
|
443
|
+
if (currentIdx + 1 < questions.length) {
|
|
444
|
+
setCurrentIdx((prev) => prev + 1);
|
|
445
|
+
setSelectedOption(null);
|
|
446
|
+
setIsAnswered(false);
|
|
447
|
+
setIsCorrect(null);
|
|
448
|
+
} else {
|
|
449
|
+
setQuestions((prev) => shuffle(prev));
|
|
450
|
+
setCurrentIdx(0);
|
|
451
|
+
setSelectedOption(null);
|
|
452
|
+
setIsAnswered(false);
|
|
453
|
+
setIsCorrect(null);
|
|
454
|
+
}
|
|
455
|
+
}, [questions.length, currentIdx]);
|
|
456
|
+
const finishPractice = useCallback(() => {
|
|
457
|
+
setMode("summary");
|
|
458
|
+
}, []);
|
|
459
|
+
const resetPractice = useCallback(() => {
|
|
460
|
+
setMode("setup");
|
|
461
|
+
setQuestions([]);
|
|
462
|
+
setCurrentIdx(0);
|
|
463
|
+
setScore(0);
|
|
464
|
+
setTotalPracticed(0);
|
|
465
|
+
setSelectedOption(null);
|
|
466
|
+
setIsAnswered(false);
|
|
467
|
+
setIsCorrect(null);
|
|
468
|
+
}, []);
|
|
469
|
+
const accuracy = totalPracticed > 0 ? Math.round(score / totalPracticed * 100) : 0;
|
|
470
|
+
return {
|
|
471
|
+
mode,
|
|
472
|
+
questions,
|
|
473
|
+
currentIdx,
|
|
474
|
+
currentQuestion: questions[currentIdx] ?? null,
|
|
475
|
+
selectedOption,
|
|
476
|
+
isAnswered,
|
|
477
|
+
isCorrect,
|
|
478
|
+
score,
|
|
479
|
+
totalPracticed,
|
|
480
|
+
accuracy,
|
|
481
|
+
isLoading,
|
|
482
|
+
isValidating,
|
|
483
|
+
startPractice,
|
|
484
|
+
selectOption,
|
|
485
|
+
nextQuestion,
|
|
486
|
+
finishPractice,
|
|
487
|
+
resetPractice
|
|
488
|
+
};
|
|
489
|
+
}
|
|
12
490
|
export {
|
|
13
491
|
OrjokProvider,
|
|
14
|
-
|
|
492
|
+
useContest,
|
|
493
|
+
useContestsList,
|
|
494
|
+
useCourse,
|
|
495
|
+
useCourseItems,
|
|
496
|
+
useCourseLiveExams,
|
|
497
|
+
useCurriculum,
|
|
498
|
+
useMediaUrl,
|
|
499
|
+
useOrjokClient,
|
|
500
|
+
usePackDetail,
|
|
501
|
+
usePacks,
|
|
502
|
+
usePractice,
|
|
503
|
+
useProgress,
|
|
504
|
+
useQuestions
|
|
15
505
|
};
|
|
16
506
|
//# sourceMappingURL=hooks.js.map
|
package/dist/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/useOrjokClient.ts"],"sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { OrjokClient } from \"../client\";\n\nconst OrjokContext = createContext<OrjokClient | null>(null);\n\nexport const OrjokProvider = OrjokContext.Provider;\n\nexport function useOrjokClient(): OrjokClient {\n const client = useContext(OrjokContext);\n if (!client) {\n throw new Error(\"useOrjokClient must be used within an OrjokProvider\");\n }\n return client;\n}\n"],"mappings":";AAAA,SAAS,eAAe,kBAAkB;AAG1C,IAAM,eAAe,cAAkC,IAAI;AAEpD,IAAM,gBAAgB,aAAa;AAEnC,SAAS,iBAA8B;AAC5C,QAAM,SAAS,WAAW,YAAY;AACtC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AACA,SAAO;AACT;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/hooks/useOrjokClient.ts","../src/hooks/useMediaUrl.ts","../src/hooks/useCurriculum.ts","../src/hooks/useQuestions.ts","../src/hooks/usePacks.ts","../src/hooks/useContest.ts","../src/hooks/useCourse.ts","../src/hooks/useProgress.ts","../src/hooks/usePractice.ts"],"sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { OrjokClient } from \"../client\";\n\nconst OrjokContext = createContext<OrjokClient | null>(null);\n\nexport const OrjokProvider = OrjokContext.Provider;\n\nexport function useOrjokClient(): OrjokClient {\n const client = useContext(OrjokContext);\n if (!client) {\n throw new Error(\"useOrjokClient must be used within an OrjokProvider\");\n }\n return client;\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { useOrjokClient } from \"./useOrjokClient\";\nimport { isStorageKey, resolveMediaUrl } from \"../logic/media-url\";\n\nexport function useMediaUrl(key: string | null | undefined): {\n url: string | null;\n isLoading: boolean;\n} {\n const client = useOrjokClient();\n\n const isResolvable = Boolean(key && isStorageKey(key));\n\n const query = useQuery({\n queryKey: [\"media-url\", key],\n queryFn: async () => {\n if (!key) return null;\n return resolveMediaUrl(key, client.storage);\n },\n enabled: isResolvable,\n staleTime: 50 * 60 * 1000, // 50 mins\n });\n\n if (!key) {\n return { url: null, isLoading: false };\n }\n\n if (!isStorageKey(key)) {\n return { url: key, isLoading: false };\n }\n\n return {\n url: query.data ?? null,\n isLoading: query.isLoading,\n };\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { useOrjokClient } from \"./useOrjokClient\";\nimport type { Subject, Chapter, Topic } from \"../types/models\";\n\nexport interface UseCurriculumParams {\n level?: string;\n subjectId?: string;\n chapterId?: string;\n}\n\nexport function useCurriculum({ level, subjectId, chapterId }: UseCurriculumParams = {}): {\n subjects: Subject[];\n chapters: Chapter[];\n topics: Topic[];\n isLoadingSubjects: boolean;\n isLoadingChapters: boolean;\n isLoadingTopics: boolean;\n} {\n const client = useOrjokClient();\n\n const subjectsQuery = useQuery({\n queryKey: [\"curriculum-subjects\", level],\n queryFn: () => (level ? client.curriculum.getSubjects(level) : Promise.resolve([])),\n enabled: Boolean(level),\n });\n\n const chaptersQuery = useQuery({\n queryKey: [\"curriculum-chapters\", subjectId],\n queryFn: () => (subjectId ? client.curriculum.getChapters(subjectId) : Promise.resolve([])),\n enabled: Boolean(subjectId),\n });\n\n const topicsQuery = useQuery({\n queryKey: [\"curriculum-topics\", chapterId],\n queryFn: () => (chapterId ? client.curriculum.getTopics(chapterId) : Promise.resolve([])),\n enabled: Boolean(chapterId),\n });\n\n return {\n subjects: subjectsQuery.data ?? [],\n chapters: chaptersQuery.data ?? [],\n topics: topicsQuery.data ?? [],\n isLoadingSubjects: subjectsQuery.isLoading,\n isLoadingChapters: chaptersQuery.isLoading,\n isLoadingTopics: topicsQuery.isLoading,\n };\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { useOrjokClient } from \"./useOrjokClient\";\nimport type { QuestionObject } from \"../types/models\";\nimport type { Difficulty, Language } from \"../types/enums\";\n\nexport interface UseQuestionsParams {\n subjectId?: string;\n chapterId?: string;\n topicId?: string;\n language?: Language | \"All\";\n difficulty?: Difficulty | \"All\";\n limit?: number;\n nextToken?: string | null;\n}\n\nexport function useQuestions({\n subjectId,\n chapterId,\n topicId,\n language,\n difficulty,\n limit = 20,\n nextToken,\n}: UseQuestionsParams = {}): {\n questions: QuestionObject[];\n nextToken: string | null;\n isLoading: boolean;\n refetch: () => Promise<unknown>;\n} {\n const client = useOrjokClient();\n\n const lang = language === \"All\" ? undefined : language;\n const diff = difficulty === \"All\" ? undefined : difficulty;\n\n const query = useQuery({\n queryKey: [\"questions\", { subjectId, chapterId, topicId, language, difficulty, limit, nextToken }],\n queryFn: async () => {\n if (topicId) {\n return client.questions.listByTopic({ id: topicId, language: lang, difficulty: diff, limit, nextToken: nextToken || undefined });\n }\n if (chapterId) {\n return client.questions.listByChapter({ id: chapterId, language: lang, difficulty: diff, limit, nextToken: nextToken || undefined });\n }\n if (subjectId) {\n return client.questions.listBySubject({ id: subjectId, language: lang, difficulty: diff, limit, nextToken: nextToken || undefined });\n }\n return { items: [], nextToken: null };\n },\n enabled: Boolean(subjectId || chapterId || topicId),\n });\n\n return {\n questions: query.data?.items ?? [],\n nextToken: query.data?.nextToken ?? null,\n isLoading: query.isLoading,\n refetch: query.refetch,\n };\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { useOrjokClient } from \"./useOrjokClient\";\nimport type { Pack, QuestionObject } from \"../types/models\";\nimport type { Difficulty, Language } from \"../types/enums\";\n\nexport interface UsePacksParams {\n subjectId?: string;\n chapterId?: string;\n topicId?: string;\n language?: Language | \"All\";\n difficulty?: Difficulty | \"All\";\n limit?: number;\n nextToken?: string | null;\n}\n\nexport function usePacks({\n subjectId,\n chapterId,\n topicId,\n language,\n difficulty,\n limit = 20,\n nextToken,\n}: UsePacksParams = {}): {\n packs: Pack[];\n nextToken: string | null;\n isLoading: boolean;\n refetch: () => Promise<unknown>;\n} {\n const client = useOrjokClient();\n\n const lang = language === \"All\" ? undefined : language;\n const diff = difficulty === \"All\" ? undefined : difficulty;\n\n const query = useQuery({\n queryKey: [\"packs\", { subjectId, chapterId, topicId, language, difficulty, limit, nextToken }],\n queryFn: async () => {\n if (topicId) {\n return client.packs.listByTopic({ id: topicId, language: lang, difficulty: diff, limit, nextToken: nextToken || undefined });\n }\n if (chapterId) {\n return client.packs.listByChapter({ id: chapterId, language: lang, difficulty: diff, limit, nextToken: nextToken || undefined });\n }\n if (subjectId) {\n return client.packs.listBySubject({ id: subjectId, language: lang, difficulty: diff, limit, nextToken: nextToken || undefined });\n }\n return { items: [], nextToken: null };\n },\n enabled: Boolean(subjectId || chapterId || topicId),\n });\n\n return {\n packs: query.data?.items ?? [],\n nextToken: query.data?.nextToken ?? null,\n isLoading: query.isLoading,\n refetch: query.refetch,\n };\n}\n\nexport function usePackDetail(packId: string | undefined): {\n pack: Pack | null;\n questions: QuestionObject[];\n isLoading: boolean;\n refetch: () => Promise<unknown>;\n} {\n const client = useOrjokClient();\n\n const query = useQuery({\n queryKey: [\"pack-detail\", packId],\n queryFn: async () => {\n if (!packId) return null;\n return client.packs.getFull(packId);\n },\n enabled: Boolean(packId),\n });\n\n return {\n pack: query.data ?? null,\n questions: query.data?.questions?.items ?? [],\n isLoading: query.isLoading,\n refetch: query.refetch,\n };\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { useOrjokClient } from \"./useOrjokClient\";\nimport type { Contest } from \"../types/models\";\nimport type { CheckParticipationResponse } from \"../types/responses\";\n\nexport function useContest(contestId: string | undefined, checkParticipation: boolean = false): {\n contest: Contest | null;\n participation: CheckParticipationResponse | null;\n isLoading: boolean;\n refetch: () => Promise<unknown>;\n} {\n const client = useOrjokClient();\n\n const contestQuery = useQuery({\n queryKey: [\"contest\", contestId],\n queryFn: async () => {\n if (!contestId) return null;\n return client.contests.get(contestId);\n },\n enabled: Boolean(contestId),\n });\n\n const partQuery = useQuery({\n queryKey: [\"contest-participation\", contestId],\n queryFn: async () => {\n if (!contestId || !checkParticipation) return null;\n return client.contests.checkParticipation(contestId);\n },\n enabled: Boolean(contestId && checkParticipation),\n });\n\n return {\n contest: contestQuery.data ?? null,\n participation: partQuery.data ?? null,\n isLoading: contestQuery.isLoading || (checkParticipation && partQuery.isLoading),\n refetch: async () => {\n await Promise.all([contestQuery.refetch(), partQuery.refetch()]);\n },\n };\n}\n\nexport function useContestsList({ level, nextToken }: { level?: string; nextToken?: string } = {}): {\n contests: Contest[];\n nextToken: string | null;\n isLoading: boolean;\n refetch: () => Promise<unknown>;\n} {\n const client = useOrjokClient();\n\n const query = useQuery({\n queryKey: [\"contests-list\", level, nextToken],\n queryFn: () => client.contests.list(nextToken, level),\n });\n\n return {\n contests: query.data?.items ?? [],\n nextToken: query.data?.nextToken ?? null,\n isLoading: query.isLoading,\n refetch: query.refetch,\n };\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { useOrjokClient } from \"./useOrjokClient\";\nimport type { Course, CourseItem, CourseLiveExam } from \"../types/models\";\n\nexport function useCourse(courseId: string | undefined): {\n course: Course | null;\n isLoading: boolean;\n refetch: () => Promise<unknown>;\n} {\n const client = useOrjokClient();\n\n const query = useQuery({\n queryKey: [\"course\", courseId],\n queryFn: async () => {\n if (!courseId) return null;\n return client.courses.get(courseId);\n },\n enabled: Boolean(courseId),\n });\n\n return {\n course: query.data ?? null,\n isLoading: query.isLoading,\n refetch: query.refetch,\n };\n}\n\nexport function useCourseItems(courseId: string | undefined): {\n items: CourseItem[];\n isLoading: boolean;\n refetch: () => Promise<unknown>;\n} {\n const client = useOrjokClient();\n\n const query = useQuery({\n queryKey: [\"course-items\", courseId],\n queryFn: async () => {\n if (!courseId) return [];\n return client.courses.getItems(courseId);\n },\n enabled: Boolean(courseId),\n });\n\n return {\n items: query.data ?? [],\n isLoading: query.isLoading,\n refetch: query.refetch,\n };\n}\n\nexport function useCourseLiveExams(courseId: string | undefined): {\n exams: CourseLiveExam[];\n isLoading: boolean;\n refetch: () => Promise<unknown>;\n} {\n const client = useOrjokClient();\n\n const query = useQuery({\n queryKey: [\"course-live-exams\", courseId],\n queryFn: async () => {\n if (!courseId) return { items: [], nextToken: null };\n return client.courses.getLiveExams(courseId);\n },\n enabled: Boolean(courseId),\n });\n\n return {\n exams: query.data?.items ?? [],\n isLoading: query.isLoading,\n refetch: query.refetch,\n };\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { useOrjokClient } from \"./useOrjokClient\";\nimport type { UserSubjectProgress, UserChapterProgress, UserTopicProgress } from \"../types/models\";\nimport { aggregateSubjectMetrics, type PracticeMetrics } from \"../logic/practice\";\n\nexport function useProgress(userId: string | undefined): {\n subjectsProgress: UserSubjectProgress[];\n chaptersProgress: UserChapterProgress[];\n topicsProgress: UserTopicProgress[];\n metrics: PracticeMetrics;\n isLoading: boolean;\n refetch: () => Promise<unknown>;\n} {\n const client = useOrjokClient();\n\n const subjectsQuery = useQuery({\n queryKey: [\"user-subject-progress\", userId],\n queryFn: () => (userId ? client.progress.getSubjectProgress(userId) : Promise.resolve([])),\n enabled: Boolean(userId),\n });\n\n const chaptersQuery = useQuery({\n queryKey: [\"user-chapter-progress\", userId],\n queryFn: () => (userId ? client.progress.getChapterProgress(userId) : Promise.resolve([])),\n enabled: Boolean(userId),\n });\n\n const topicsQuery = useQuery({\n queryKey: [\"user-topic-progress\", userId],\n queryFn: () => (userId ? client.progress.getTopicProgress(userId) : Promise.resolve([])),\n enabled: Boolean(userId),\n });\n\n const subjectsProgress = subjectsQuery.data ?? [];\n const chaptersProgress = chaptersQuery.data ?? [];\n const topicsProgress = topicsQuery.data ?? [];\n\n const metrics = aggregateSubjectMetrics(subjectsProgress);\n\n return {\n subjectsProgress,\n chaptersProgress,\n topicsProgress,\n metrics,\n isLoading: subjectsQuery.isLoading || chaptersQuery.isLoading || topicsQuery.isLoading,\n refetch: async () => {\n await Promise.all([\n subjectsQuery.refetch(),\n chaptersQuery.refetch(),\n topicsQuery.refetch(),\n ]);\n },\n };\n}\n","import { useState, useCallback } from \"react\";\nimport { useOrjokClient } from \"./useOrjokClient\";\nimport type { QuestionObject } from \"../types/models\";\nimport { isLanguageMatch, isDifficultyMatch, isValidMCQ } from \"../logic/practice\";\nimport { shuffle } from \"../utils/shuffle\";\n\nexport type PracticeMode = \"setup\" | \"practice\" | \"summary\";\n\nexport interface ItemBounds {\n id: string;\n type: \"topic\" | \"chapter\" | \"subject\";\n}\n\nexport interface UsePracticeProps {\n subjectId?: string;\n chapterIds?: string[];\n topicIds?: string[];\n language?: string;\n difficulty?: string;\n userId?: string;\n isCreator?: boolean;\n}\n\nexport function usePractice({\n subjectId,\n chapterIds = [],\n topicIds = [],\n language = \"Bangla\",\n difficulty = \"All\",\n userId,\n isCreator,\n}: UsePracticeProps = {}) {\n const client = useOrjokClient();\n\n const [mode, setMode] = useState<PracticeMode>(\"setup\");\n const [questions, setQuestions] = useState<QuestionObject[]>([]);\n const [currentIdx, setCurrentIdx] = useState<number>(0);\n const [selectedOption, setSelectedOption] = useState<string | null>(null);\n const [isAnswered, setIsAnswered] = useState<boolean>(false);\n const [isCorrect, setIsCorrect] = useState<boolean | null>(null);\n const [score, setScore] = useState<number>(0);\n const [totalPracticed, setTotalPracticed] = useState<number>(0);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isValidating, setIsValidating] = useState<boolean>(false);\n\n const fetchQuestionsPool = useCallback(async (): Promise<QuestionObject[]> => {\n const bounds: ItemBounds[] = [];\n if (topicIds.length > 0) {\n topicIds.forEach((tId) => bounds.push({ id: tId, type: \"topic\" }));\n } else if (chapterIds.length > 0) {\n chapterIds.forEach((cId) => bounds.push({ id: cId, type: \"chapter\" }));\n } else if (subjectId) {\n bounds.push({ id: subjectId, type: \"subject\" });\n }\n\n if (bounds.length === 0) return [];\n\n const queries = bounds.map(async (b) => {\n try {\n if (b.type === \"topic\") {\n return await client.questions.listByTopic({ id: b.id, limit: 50 });\n } else if (b.type === \"chapter\") {\n return await client.questions.listByChapter({ id: b.id, limit: 50 });\n } else {\n return await client.questions.listBySubject({ id: b.id, limit: 50 });\n }\n } catch (e) {\n console.error(\"Error fetching bounds query in practice:\", b, e);\n return { items: [] };\n }\n });\n\n const results = await Promise.all(queries);\n const uniqueMap = new Map<string, QuestionObject>();\n\n results.forEach((r) => {\n (r.items || []).forEach((q) => {\n if (q && q.id && !uniqueMap.has(q.id)) {\n uniqueMap.set(q.id, q);\n }\n });\n });\n\n let list = Array.from(uniqueMap.values()).filter((q) => {\n if (!isLanguageMatch(q.language, language)) return false;\n if (!isDifficultyMatch(q.difficulty, difficulty)) return false;\n return true;\n });\n\n // Fallback to parent subject if fewer than 5 matching questions\n if (list.length < 5 && subjectId && bounds.some((b) => b.type !== \"subject\")) {\n try {\n const subRes = await client.questions.listBySubject({ id: subjectId, limit: 50 });\n (subRes.items || []).forEach((q) => {\n if (q && q.id && !uniqueMap.has(q.id)) {\n if (isLanguageMatch(q.language, language) && isDifficultyMatch(q.difficulty, difficulty)) {\n list.push(q);\n uniqueMap.set(q.id, q);\n }\n }\n });\n } catch (e) {\n console.error(\"Error fetching subject fallback in practice:\", e);\n }\n }\n\n return list.filter(isValidMCQ);\n }, [client, subjectId, chapterIds, topicIds, language, difficulty]);\n\n const startPractice = useCallback(async () => {\n setIsLoading(true);\n setMode(\"practice\");\n setCurrentIdx(0);\n setScore(0);\n setTotalPracticed(0);\n setSelectedOption(null);\n setIsAnswered(false);\n setIsCorrect(null);\n\n try {\n const fetched = await fetchQuestionsPool();\n setQuestions(shuffle(fetched));\n } catch (e) {\n console.error(\"Error starting practice:\", e);\n setQuestions([]);\n } finally {\n setIsLoading(false);\n }\n }, [fetchQuestionsPool]);\n\n const selectOption = useCallback(\n async (optionId: string) => {\n if (isAnswered || isValidating || questions.length === 0) return;\n setSelectedOption(optionId);\n setIsValidating(true);\n const currentQ = questions[currentIdx];\n if (!currentQ) {\n setIsValidating(false);\n return;\n }\n\n try {\n const fullQ = await client.questions.get(currentQ.id);\n const ansVal = fullQ?.answer;\n const rawOpts = currentQ.options as unknown;\n const optsList = Array.isArray(rawOpts)\n ? rawOpts\n : (rawOpts && typeof rawOpts === \"object\" && Array.isArray((rawOpts as { items?: unknown[] }).items))\n ? (rawOpts as { items: Array<{ id?: string; content?: string }> }).items\n : [];\n\n const chosenOpt = optsList.find((o) => o?.id === optionId);\n const correct = Boolean(\n ansVal && (ansVal === optionId || (chosenOpt && ansVal === chosenOpt.content))\n );\n\n setIsCorrect(correct);\n setIsAnswered(true);\n setTotalPracticed((prev) => prev + 1);\n if (correct) setScore((prev) => prev + 1);\n\n if (userId && isCreator) {\n void client.progress\n .track({\n questionId: currentQ.id,\n isCorrect: correct,\n subjectId: currentQ.subjectId || subjectId,\n chapterId: currentQ.chapterId || (chapterIds.length === 1 ? chapterIds[0] : undefined),\n topicId: currentQ.topicId || (topicIds.length === 1 ? topicIds[0] : undefined),\n })\n .catch((e) => console.error(\"Tracking practice progress error:\", e));\n }\n } catch (err) {\n console.error(\"Error validating option in practice:\", err);\n } finally {\n setIsValidating(false);\n }\n },\n [client, isAnswered, isValidating, questions, currentIdx, userId, isCreator, subjectId, chapterIds, topicIds]\n );\n\n const nextQuestion = useCallback(() => {\n if (questions.length === 0) return;\n if (currentIdx + 1 < questions.length) {\n setCurrentIdx((prev) => prev + 1);\n setSelectedOption(null);\n setIsAnswered(false);\n setIsCorrect(null);\n } else {\n // Seamless reshuffle and continue\n setQuestions((prev) => shuffle(prev));\n setCurrentIdx(0);\n setSelectedOption(null);\n setIsAnswered(false);\n setIsCorrect(null);\n }\n }, [questions.length, currentIdx]);\n\n const finishPractice = useCallback(() => {\n setMode(\"summary\");\n }, []);\n\n const resetPractice = useCallback(() => {\n setMode(\"setup\");\n setQuestions([]);\n setCurrentIdx(0);\n setScore(0);\n setTotalPracticed(0);\n setSelectedOption(null);\n setIsAnswered(false);\n setIsCorrect(null);\n }, []);\n\n const accuracy = totalPracticed > 0 ? Math.round((score / totalPracticed) * 100) : 0;\n\n return {\n mode,\n questions,\n currentIdx,\n currentQuestion: questions[currentIdx] ?? null,\n selectedOption,\n isAnswered,\n isCorrect,\n score,\n totalPracticed,\n accuracy,\n isLoading,\n isValidating,\n startPractice,\n selectOption,\n nextQuestion,\n finishPractice,\n resetPractice,\n };\n}\n"],"mappings":"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","names":["useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery"]}
|