|
|
@ -1,4 +1,4 @@ |
|
|
|
import './AICourseFollowUp.css'; |
|
|
|
import { useMutation, useQuery } from '@tanstack/react-query'; |
|
|
|
import { |
|
|
|
import { |
|
|
|
CheckIcon, |
|
|
|
CheckIcon, |
|
|
|
ChevronLeft, |
|
|
|
ChevronLeft, |
|
|
@ -7,23 +7,24 @@ import { |
|
|
|
LockIcon, |
|
|
|
LockIcon, |
|
|
|
XIcon, |
|
|
|
XIcon, |
|
|
|
} from 'lucide-react'; |
|
|
|
} from 'lucide-react'; |
|
|
|
import { cn } from '../../lib/classname'; |
|
|
|
|
|
|
|
import { useEffect, useMemo, useState } from 'react'; |
|
|
|
import { useEffect, useMemo, useState } from 'react'; |
|
|
|
import { isLoggedIn, removeAuthToken } from '../../lib/jwt'; |
|
|
|
|
|
|
|
import { readAICourseLessonStream } from '../../helper/read-stream'; |
|
|
|
import { readAICourseLessonStream } from '../../helper/read-stream'; |
|
|
|
|
|
|
|
import { cn } from '../../lib/classname'; |
|
|
|
|
|
|
|
import { isLoggedIn, removeAuthToken } from '../../lib/jwt'; |
|
|
|
import { |
|
|
|
import { |
|
|
|
markdownToHtml, |
|
|
|
markdownToHtml, |
|
|
|
markdownToHtmlWithHighlighting, |
|
|
|
markdownToHtmlWithHighlighting, |
|
|
|
} from '../../lib/markdown'; |
|
|
|
} from '../../lib/markdown'; |
|
|
|
import { useMutation, useQuery } from '@tanstack/react-query'; |
|
|
|
import { httpPatch } from '../../lib/query-http'; |
|
|
|
import { queryClient } from '../../stores/query-client'; |
|
|
|
|
|
|
|
import { httpPatch, httpPost } from '../../lib/query-http'; |
|
|
|
|
|
|
|
import { slugify } from '../../lib/slugger'; |
|
|
|
import { slugify } from '../../lib/slugger'; |
|
|
|
import { |
|
|
|
import { |
|
|
|
getAiCourseLimitOptions, |
|
|
|
getAiCourseLimitOptions, |
|
|
|
getAiCourseProgressOptions, |
|
|
|
getAiCourseProgressOptions, |
|
|
|
|
|
|
|
type AICourseProgressDocument, |
|
|
|
} from '../../queries/ai-course'; |
|
|
|
} from '../../queries/ai-course'; |
|
|
|
|
|
|
|
import { queryClient } from '../../stores/query-client'; |
|
|
|
import { AICourseFollowUp } from './AICourseFollowUp'; |
|
|
|
import { AICourseFollowUp } from './AICourseFollowUp'; |
|
|
|
|
|
|
|
import './AICourseFollowUp.css'; |
|
|
|
|
|
|
|
|
|
|
|
type AICourseModuleViewProps = { |
|
|
|
type AICourseModuleViewProps = { |
|
|
|
courseSlug: string; |
|
|
|
courseSlug: string; |
|
|
@ -154,15 +155,17 @@ export function AICourseModuleView(props: AICourseModuleViewProps) { |
|
|
|
const { mutate: toggleDone, isPending: isTogglingDone } = useMutation( |
|
|
|
const { mutate: toggleDone, isPending: isTogglingDone } = useMutation( |
|
|
|
{ |
|
|
|
{ |
|
|
|
mutationFn: () => { |
|
|
|
mutationFn: () => { |
|
|
|
return httpPatch(`/v1-toggle-done-ai-lesson/${courseSlug}`, { |
|
|
|
return httpPatch<AICourseProgressDocument>( |
|
|
|
|
|
|
|
`/v1-toggle-done-ai-lesson/${courseSlug}`, |
|
|
|
|
|
|
|
{ |
|
|
|
lessonId, |
|
|
|
lessonId, |
|
|
|
}); |
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
onSuccess: () => { |
|
|
|
); |
|
|
|
queryClient.invalidateQueries( |
|
|
|
}, |
|
|
|
getAiCourseProgressOptions({ |
|
|
|
onSuccess: (data) => { |
|
|
|
aiCourseSlug: courseSlug || '', |
|
|
|
queryClient.setQueryData( |
|
|
|
}), |
|
|
|
['ai-course-progress', { aiCourseSlug: courseSlug }], |
|
|
|
|
|
|
|
data, |
|
|
|
); |
|
|
|
); |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
@ -200,26 +203,39 @@ export function AICourseModuleView(props: AICourseModuleViewProps) { |
|
|
|
{!isGenerating && !isLoading && ( |
|
|
|
{!isGenerating && !isLoading && ( |
|
|
|
<> |
|
|
|
<> |
|
|
|
<button |
|
|
|
<button |
|
|
|
disabled={isLoading} |
|
|
|
disabled={isLoading || isTogglingDone} |
|
|
|
className={cn( |
|
|
|
className={cn( |
|
|
|
'absolute right-3 top-3 flex items-center gap-1 rounded-full bg-black py-1 pl-2 pr-3 text-sm text-white hover:bg-gray-800 disabled:opacity-50', |
|
|
|
'absolute right-3 top-3 flex items-center gap-1.5 rounded-full bg-black py-1 pl-2 pr-3 text-sm text-white hover:bg-gray-800 disabled:opacity-50', |
|
|
|
isLessonDone |
|
|
|
isLessonDone |
|
|
|
? 'bg-red-500 hover:bg-red-600' |
|
|
|
? 'bg-red-500 hover:bg-red-600' |
|
|
|
: 'bg-green-500 hover:bg-green-600', |
|
|
|
: 'bg-green-500 hover:bg-green-600', |
|
|
|
)} |
|
|
|
)} |
|
|
|
onClick={() => toggleDone()} |
|
|
|
onClick={() => toggleDone()} |
|
|
|
> |
|
|
|
> |
|
|
|
|
|
|
|
{isTogglingDone ? ( |
|
|
|
|
|
|
|
<> |
|
|
|
|
|
|
|
<Loader2Icon |
|
|
|
|
|
|
|
size={16} |
|
|
|
|
|
|
|
strokeWidth={3} |
|
|
|
|
|
|
|
className="animate-spin text-white" |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
Please wait ... |
|
|
|
|
|
|
|
</> |
|
|
|
|
|
|
|
) : ( |
|
|
|
|
|
|
|
<> |
|
|
|
{isLessonDone ? ( |
|
|
|
{isLessonDone ? ( |
|
|
|
<> |
|
|
|
<> |
|
|
|
<XIcon size={16} className="mr-1" /> |
|
|
|
<XIcon size={16} /> |
|
|
|
Mark as Undone |
|
|
|
Mark as Undone |
|
|
|
</> |
|
|
|
</> |
|
|
|
) : ( |
|
|
|
) : ( |
|
|
|
<> |
|
|
|
<> |
|
|
|
<CheckIcon size={16} className="mr-1" /> |
|
|
|
<CheckIcon size={16} /> |
|
|
|
Mark as Done |
|
|
|
Mark as Done |
|
|
|
</> |
|
|
|
</> |
|
|
|
)} |
|
|
|
)} |
|
|
|
|
|
|
|
</> |
|
|
|
|
|
|
|
)} |
|
|
|
</button> |
|
|
|
</button> |
|
|
|
</> |
|
|
|
</> |
|
|
|
)} |
|
|
|
)} |
|
|
|