From e21e3ab33156c11f67781ec19385838532223a23 Mon Sep 17 00:00:00 2001 From: Arik Chakma Date: Tue, 4 Mar 2025 19:15:39 +0600 Subject: [PATCH] feat: usage limit --- .../GenerateCourse/AICourseContent.tsx | 3 + .../GenerateCourse/AICourseLimit.tsx | 102 ++++++++++++++++++ .../GenerateCourse/AICourseModuleView.tsx | 6 +- .../GenerateCourse/GenerateAICourse.tsx | 3 + src/lib/markdown.ts | 1 - src/queries/ai-course.ts | 19 ++++ 6 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 src/components/GenerateCourse/AICourseLimit.tsx diff --git a/src/components/GenerateCourse/AICourseContent.tsx b/src/components/GenerateCourse/AICourseContent.tsx index 21bce4eee..9ff4a393d 100644 --- a/src/components/GenerateCourse/AICourseContent.tsx +++ b/src/components/GenerateCourse/AICourseContent.tsx @@ -17,6 +17,7 @@ import { AICourseModuleList } from './AICourseModuleList'; import { AICourseModuleView } from './AICourseModuleView'; import { slugify } from '../../lib/slugger'; import { CheckIcon } from '../ReactIcons/CheckIcon'; +import { AICourseLimit } from './AICourseLimit'; type AICourseContentProps = { courseSlug?: string; @@ -137,6 +138,8 @@ export function AICourseContent(props: AICourseContentProps) {
+ + {viewMode === 'module' && ( + + {isOpen && ( +
+
+
+
+ + {courseUsed} of {courseLimit} courses used +
+ +
+
+ +
+
+ + {lessonUsed} of {lessonLimit} lessons used +
+ +
+
+
+ +
+ + Limit resets every 24 hours +
+
+ )} +
+ ); +} diff --git a/src/components/GenerateCourse/AICourseModuleView.tsx b/src/components/GenerateCourse/AICourseModuleView.tsx index dc144aba5..8f670d76c 100644 --- a/src/components/GenerateCourse/AICourseModuleView.tsx +++ b/src/components/GenerateCourse/AICourseModuleView.tsx @@ -11,7 +11,10 @@ import { useMutation, useQuery } from '@tanstack/react-query'; import { queryClient } from '../../stores/query-client'; import { httpPost } from '../../lib/query-http'; import { slugify } from '../../lib/slugger'; -import { getAiCourseProgressOptions } from '../../queries/ai-course'; +import { + getAiCourseLimitOptions, + getAiCourseProgressOptions, +} from '../../queries/ai-course'; type AICourseModuleViewProps = { courseSlug: string; @@ -133,6 +136,7 @@ export function AICourseModuleView(props: AICourseModuleViewProps) { } setLessonHtml(await markdownToHtmlWithHighlighting(result)); + queryClient.invalidateQueries(getAiCourseLimitOptions()); setIsGenerating(false); }, }); diff --git a/src/components/GenerateCourse/GenerateAICourse.tsx b/src/components/GenerateCourse/GenerateAICourse.tsx index 310dc8ad1..3afa6a30f 100644 --- a/src/components/GenerateCourse/GenerateAICourse.tsx +++ b/src/components/GenerateCourse/GenerateAICourse.tsx @@ -5,6 +5,8 @@ import { showLoginPopup } from '../../lib/popup'; import { generateAiCourseStructure, type AiCourse } from '../../lib/ai'; import { readAICourseStream } from '../../helper/read-stream'; import { AICourseContent } from './AICourseContent'; +import { queryClient } from '../../stores/query-client'; +import { getAiCourseLimitOptions } from '../../queries/ai-course'; type GenerateAICourseProps = {}; @@ -144,6 +146,7 @@ export function GenerateAICourse(props: GenerateAICourseProps) { .replace(COURSE_ID_REGEX, '') .replace(COURSE_SLUG_REGEX, ''); setIsLoading(false); + queryClient.invalidateQueries(getAiCourseLimitOptions()); }, }); } catch (error: any) { diff --git a/src/lib/markdown.ts b/src/lib/markdown.ts index 2858d8c56..721cb6492 100644 --- a/src/lib/markdown.ts +++ b/src/lib/markdown.ts @@ -91,7 +91,6 @@ export async function markdownToHtmlWithHighlighting(markdown: string) { return self.renderToken(tokens, idx, options); }; - // @ts-ignore markdownItAsync.renderer.rules.link_open = function ( tokens, idx, diff --git a/src/queries/ai-course.ts b/src/queries/ai-course.ts index b3c789fbd..0c8067fcf 100644 --- a/src/queries/ai-course.ts +++ b/src/queries/ai-course.ts @@ -65,3 +65,22 @@ export function getAiCourseOptions(params: GetAICourseParams) { }, }; } + +type GetAICourseLimitParams = {}; + +type GetAICourseLimitResponse = { + used: number; + limit: number; + lessonUsed: number; + lessonLimit: number; +}; + +export function getAiCourseLimitOptions() { + return { + queryKey: ['ai-course-limit'], + queryFn: () => { + return httpGet(`/v1-get-ai-course-limit`); + }, + enabled: !!isLoggedIn(), + }; +}