@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/hooks.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
aggregateSubjectMetrics,
|
|
3
|
+
calculateUnreadCount,
|
|
4
|
+
getPublicExamsByLevel,
|
|
3
5
|
isDifficultyMatch,
|
|
4
6
|
isLanguageMatch,
|
|
5
7
|
isStorageKey,
|
|
6
8
|
isValidMCQ,
|
|
9
|
+
mergeNotificationTimeline,
|
|
7
10
|
resolveMediaUrl,
|
|
8
11
|
shuffle
|
|
9
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-B4UJE3F4.js";
|
|
10
13
|
|
|
11
14
|
// src/hooks/useOrjokClient.ts
|
|
12
15
|
import { createContext, useContext } from "react";
|
|
@@ -487,8 +490,151 @@ function usePractice({
|
|
|
487
490
|
resetPractice
|
|
488
491
|
};
|
|
489
492
|
}
|
|
493
|
+
|
|
494
|
+
// src/hooks/useAvailablePublicExams.ts
|
|
495
|
+
import { useMemo } from "react";
|
|
496
|
+
import { useQuery as useQuery8 } from "@tanstack/react-query";
|
|
497
|
+
function useAvailablePublicExams({
|
|
498
|
+
level,
|
|
499
|
+
exploreType = "Question",
|
|
500
|
+
enabled = true,
|
|
501
|
+
client: directClient
|
|
502
|
+
} = {}) {
|
|
503
|
+
let contextClient = null;
|
|
504
|
+
try {
|
|
505
|
+
contextClient = useOrjokClient();
|
|
506
|
+
} catch {
|
|
507
|
+
}
|
|
508
|
+
const client = directClient ?? contextClient;
|
|
509
|
+
const candidateExams = useMemo(() => getPublicExamsByLevel(level), [level]);
|
|
510
|
+
const query = useQuery8({
|
|
511
|
+
queryKey: ["availablePublicExams", level, exploreType],
|
|
512
|
+
queryFn: async () => {
|
|
513
|
+
if (!client || !level || candidateExams.length === 0) return candidateExams;
|
|
514
|
+
const results = await Promise.all(
|
|
515
|
+
candidateExams.map(async (exam) => {
|
|
516
|
+
try {
|
|
517
|
+
if (exploreType === "Pack") {
|
|
518
|
+
const res = await client.packs.listByPublicExam({
|
|
519
|
+
publicExam: exam.value,
|
|
520
|
+
limit: 1
|
|
521
|
+
});
|
|
522
|
+
return (res.items?.length ?? 0) > 0 ? exam : null;
|
|
523
|
+
} else {
|
|
524
|
+
const res = await client.questions.listByPublicExam({
|
|
525
|
+
publicExam: exam.value,
|
|
526
|
+
limit: 1
|
|
527
|
+
});
|
|
528
|
+
return (res.items?.length ?? 0) > 0 ? exam : null;
|
|
529
|
+
}
|
|
530
|
+
} catch {
|
|
531
|
+
return null;
|
|
532
|
+
}
|
|
533
|
+
})
|
|
534
|
+
);
|
|
535
|
+
return results.filter((e) => e !== null);
|
|
536
|
+
},
|
|
537
|
+
enabled: Boolean(level) && enabled,
|
|
538
|
+
staleTime: 10 * 60 * 1e3,
|
|
539
|
+
gcTime: 30 * 60 * 1e3
|
|
540
|
+
});
|
|
541
|
+
if (!enabled || !level) {
|
|
542
|
+
return {
|
|
543
|
+
availableExams: candidateExams,
|
|
544
|
+
isLoading: false,
|
|
545
|
+
isSuccess: true,
|
|
546
|
+
refetch: async () => candidateExams
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
return {
|
|
550
|
+
availableExams: query.data ?? [],
|
|
551
|
+
isLoading: query.isLoading,
|
|
552
|
+
isSuccess: query.isSuccess,
|
|
553
|
+
refetch: query.refetch
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// src/hooks/useNotifications.ts
|
|
558
|
+
import { useQuery as useQuery9, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
559
|
+
function useNotifications(userId, lastReadAnnouncementAt) {
|
|
560
|
+
const client = useOrjokClient();
|
|
561
|
+
const queryClient = useQueryClient();
|
|
562
|
+
const announcementsQuery = useQuery9({
|
|
563
|
+
queryKey: ["notifications-announcements"],
|
|
564
|
+
queryFn: async () => {
|
|
565
|
+
const result = await client.notifications.listAnnouncements(50);
|
|
566
|
+
return result.items || [];
|
|
567
|
+
},
|
|
568
|
+
enabled: Boolean(userId),
|
|
569
|
+
refetchInterval: 3e4
|
|
570
|
+
// Poll every 30s
|
|
571
|
+
});
|
|
572
|
+
const userNotificationsQuery = useQuery9({
|
|
573
|
+
queryKey: ["notifications-user", userId],
|
|
574
|
+
queryFn: async () => {
|
|
575
|
+
if (!userId) return [];
|
|
576
|
+
const result = await client.notifications.listUserNotifications(userId, 50);
|
|
577
|
+
return result.items || [];
|
|
578
|
+
},
|
|
579
|
+
enabled: Boolean(userId),
|
|
580
|
+
refetchInterval: 3e4
|
|
581
|
+
});
|
|
582
|
+
const announcements = announcementsQuery.data ?? [];
|
|
583
|
+
const userNotifications = userNotificationsQuery.data ?? [];
|
|
584
|
+
const timeline = mergeNotificationTimeline({
|
|
585
|
+
announcements,
|
|
586
|
+
userNotifications,
|
|
587
|
+
lastReadAnnouncementAt
|
|
588
|
+
});
|
|
589
|
+
const unreadCount = calculateUnreadCount({
|
|
590
|
+
announcements,
|
|
591
|
+
userNotifications,
|
|
592
|
+
lastReadAnnouncementAt
|
|
593
|
+
});
|
|
594
|
+
const markAsReadMutation = useMutation({
|
|
595
|
+
mutationFn: (id) => client.notifications.markNotificationAsRead(id),
|
|
596
|
+
onSuccess: () => {
|
|
597
|
+
queryClient.invalidateQueries({ queryKey: ["notifications-user", userId] });
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
const deleteAnnouncementMutation = useMutation({
|
|
601
|
+
mutationFn: (id) => client.notifications.deleteAnnouncement(id),
|
|
602
|
+
onSuccess: () => {
|
|
603
|
+
queryClient.invalidateQueries({ queryKey: ["notifications-announcements"] });
|
|
604
|
+
}
|
|
605
|
+
});
|
|
606
|
+
const deleteUserNotificationMutation = useMutation({
|
|
607
|
+
mutationFn: (id) => client.notifications.deleteUserNotification(id),
|
|
608
|
+
onSuccess: () => {
|
|
609
|
+
queryClient.invalidateQueries({ queryKey: ["notifications-user", userId] });
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
return {
|
|
613
|
+
announcements,
|
|
614
|
+
userNotifications,
|
|
615
|
+
timeline,
|
|
616
|
+
unreadCount,
|
|
617
|
+
isLoading: announcementsQuery.isLoading || Boolean(userId) && userNotificationsQuery.isLoading,
|
|
618
|
+
refetch: async () => {
|
|
619
|
+
await Promise.all([
|
|
620
|
+
announcementsQuery.refetch(),
|
|
621
|
+
userId ? userNotificationsQuery.refetch() : Promise.resolve()
|
|
622
|
+
]);
|
|
623
|
+
},
|
|
624
|
+
markNotificationAsRead: async (id) => {
|
|
625
|
+
return markAsReadMutation.mutateAsync(id);
|
|
626
|
+
},
|
|
627
|
+
deleteAnnouncement: async (id) => {
|
|
628
|
+
return deleteAnnouncementMutation.mutateAsync(id);
|
|
629
|
+
},
|
|
630
|
+
deleteUserNotification: async (id) => {
|
|
631
|
+
return deleteUserNotificationMutation.mutateAsync(id);
|
|
632
|
+
}
|
|
633
|
+
};
|
|
634
|
+
}
|
|
490
635
|
export {
|
|
491
636
|
OrjokProvider,
|
|
637
|
+
useAvailablePublicExams,
|
|
492
638
|
useContest,
|
|
493
639
|
useContestsList,
|
|
494
640
|
useCourse,
|
|
@@ -496,6 +642,7 @@ export {
|
|
|
496
642
|
useCourseLiveExams,
|
|
497
643
|
useCurriculum,
|
|
498
644
|
useMediaUrl,
|
|
645
|
+
useNotifications,
|
|
499
646
|
useOrjokClient,
|
|
500
647
|
usePackDetail,
|
|
501
648
|
usePacks,
|
package/dist/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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"]}
|
|
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","../src/hooks/useAvailablePublicExams.ts","../src/hooks/useNotifications.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","import { useMemo } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useOrjokClient } from \"./useOrjokClient\";\nimport { getPublicExamsByLevel, type PublicExamOption } from \"../types/select-options\";\n\nimport type { OrjokClient } from \"../client\";\n\nexport interface UseAvailablePublicExamsParams {\n level?: string | null;\n exploreType?: \"Question\" | \"Pack\";\n enabled?: boolean;\n client?: OrjokClient;\n}\n\n/**\n * Hook to dynamically filter public exams by querying the GSI for existing questions or packs.\n * Caches results via React Query to keep DynamoDB RCU negligible (< 9 RCUs per cold session, 0 RCU cached).\n * Can be disabled at any time by setting `enabled: false`.\n */\nexport function useAvailablePublicExams({\n level,\n exploreType = \"Question\",\n enabled = true,\n client: directClient,\n}: UseAvailablePublicExamsParams = {}): {\n availableExams: PublicExamOption[];\n isLoading: boolean;\n isSuccess: boolean;\n refetch: () => Promise<unknown>;\n} {\n let contextClient: OrjokClient | null = null;\n try {\n contextClient = useOrjokClient();\n } catch {\n // optional fallback if outside provider\n }\n const client = directClient ?? contextClient;\n\n const candidateExams = useMemo(() => getPublicExamsByLevel(level), [level]);\n\n const query = useQuery({\n queryKey: [\"availablePublicExams\", level, exploreType],\n queryFn: async (): Promise<PublicExamOption[]> => {\n if (!client || !level || candidateExams.length === 0) return candidateExams;\n\n const results = await Promise.all(\n candidateExams.map(async (exam) => {\n try {\n if (exploreType === \"Pack\") {\n const res = await client.packs.listByPublicExam({\n publicExam: exam.value,\n limit: 1,\n });\n return (res.items?.length ?? 0) > 0 ? exam : null;\n } else {\n const res = await client.questions.listByPublicExam({\n publicExam: exam.value,\n limit: 1,\n });\n return (res.items?.length ?? 0) > 0 ? exam : null;\n }\n } catch {\n return null;\n }\n })\n );\n\n return results.filter((e): e is PublicExamOption => e !== null);\n },\n enabled: Boolean(level) && enabled,\n staleTime: 10 * 60 * 1000,\n gcTime: 30 * 60 * 1000,\n });\n\n if (!enabled || !level) {\n return {\n availableExams: candidateExams,\n isLoading: false,\n isSuccess: true,\n refetch: async () => candidateExams,\n };\n }\n\n return {\n availableExams: query.data ?? [],\n isLoading: query.isLoading,\n isSuccess: query.isSuccess,\n refetch: query.refetch,\n };\n}\n","import { useQuery, useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { useOrjokClient } from \"./useOrjokClient\";\nimport type { Announcement, UserNotification } from \"../types/models\";\nimport {\n mergeNotificationTimeline,\n calculateUnreadCount,\n type NotificationTimelineItem,\n} from \"../logic/notification\";\n\nexport type { NotificationTimelineItem };\n\nexport interface UseNotificationsResult {\n announcements: Announcement[];\n userNotifications: UserNotification[];\n timeline: NotificationTimelineItem[];\n unreadCount: number;\n isLoading: boolean;\n refetch: () => Promise<unknown>;\n markNotificationAsRead: (id: string) => Promise<unknown>;\n deleteAnnouncement: (id: string) => Promise<unknown>;\n deleteUserNotification: (id: string) => Promise<unknown>;\n}\n\nexport function useNotifications(\n userId: string | null | undefined,\n lastReadAnnouncementAt?: string | null\n): UseNotificationsResult {\n const client = useOrjokClient();\n const queryClient = useQueryClient();\n\n const announcementsQuery = useQuery({\n queryKey: [\"notifications-announcements\"],\n queryFn: async () => {\n const result = await client.notifications.listAnnouncements(50);\n return result.items || [];\n },\n enabled: Boolean(userId),\n refetchInterval: 30000, // Poll every 30s\n });\n\n const userNotificationsQuery = useQuery({\n queryKey: [\"notifications-user\", userId],\n queryFn: async () => {\n if (!userId) return [];\n const result = await client.notifications.listUserNotifications(userId, 50);\n return result.items || [];\n },\n enabled: Boolean(userId),\n refetchInterval: 30000,\n });\n\n const announcements = announcementsQuery.data ?? [];\n const userNotifications = userNotificationsQuery.data ?? [];\n\n const timeline = mergeNotificationTimeline({\n announcements,\n userNotifications,\n lastReadAnnouncementAt,\n });\n\n const unreadCount = calculateUnreadCount({\n announcements,\n userNotifications,\n lastReadAnnouncementAt,\n });\n\n const markAsReadMutation = useMutation({\n mutationFn: (id: string) => client.notifications.markNotificationAsRead(id),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [\"notifications-user\", userId] });\n },\n });\n\n const deleteAnnouncementMutation = useMutation({\n mutationFn: (id: string) => client.notifications.deleteAnnouncement(id),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [\"notifications-announcements\"] });\n },\n });\n\n const deleteUserNotificationMutation = useMutation({\n mutationFn: (id: string) => client.notifications.deleteUserNotification(id),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: [\"notifications-user\", userId] });\n },\n });\n\n return {\n announcements,\n userNotifications,\n timeline,\n unreadCount,\n isLoading: announcementsQuery.isLoading || (Boolean(userId) && userNotificationsQuery.isLoading),\n refetch: async () => {\n await Promise.all([\n announcementsQuery.refetch(),\n userId ? userNotificationsQuery.refetch() : Promise.resolve(),\n ]);\n },\n markNotificationAsRead: async (id: string) => {\n return markAsReadMutation.mutateAsync(id);\n },\n deleteAnnouncement: async (id: string) => {\n return deleteAnnouncementMutation.mutateAsync(id);\n },\n deleteUserNotification: async (id: string) => {\n return deleteUserNotificationMutation.mutateAsync(id);\n },\n };\n}\n"],"mappings":"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","names":["useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery","useQuery"]}
|