feat/ai-courses
Arik Chakma 1 month ago
parent bbbdb8c7fd
commit 8897e43b21
  1. 131
      src/components/GenerateCourse/AICourseFollowUp.css
  2. 13
      src/components/GenerateCourse/AICourseFollowUp.tsx
  3. 6
      src/components/GenerateCourse/AICourseFollowUpPopover.tsx
  4. 13
      src/components/GenerateCourse/AICourseModuleView.tsx
  5. 10
      src/lib/markdown.ts

@ -0,0 +1,131 @@
.prose ul li > code,
.prose ol li > code,
p code,
a > code,
strong > code,
em > code,
h1 > code,
h2 > code,
h3 > code {
background: #ebebeb !important;
color: currentColor !important;
font-size: 14px;
font-weight: normal !important;
}
.course-ai-content.course-content.prose ul li > code,
.course-ai-content.course-content.prose ol li > code,
.course-ai-content.course-content.prose p code,
.course-ai-content.course-content.prose a > code,
.course-ai-content.course-content.prose strong > code,
.course-ai-content.course-content.prose em > code,
.course-ai-content.course-content.prose h1 > code,
.course-ai-content.course-content.prose h2 > code,
.course-ai-content.course-content.prose h3 > code,
.course-notes-content.prose ul li > code,
.course-notes-content.prose ol li > code,
.course-notes-content.prose p code,
.course-notes-content.prose a > code,
.course-notes-content.prose strong > code,
.course-notes-content.prose em > code,
.course-notes-content.prose h1 > code,
.course-notes-content.prose h2 > code,
.course-notes-content.prose h3 > code {
font-size: 12px !important;
}
.course-ai-content pre {
-ms-overflow-style: none;
scrollbar-width: none;
}
.course-ai-content pre::-webkit-scrollbar {
display: none;
}
.course-ai-content pre,
.course-notes-content pre {
overflow: scroll;
font-size: 15px;
margin: 10px 0;
}
.prose ul li > code:before,
p > code:before,
.prose ul li > code:after,
.prose ol li > code:before,
p > code:before,
.prose ol li > code:after,
.course-content h1 > code:after,
.course-content h1 > code:before,
.course-content h2 > code:after,
.course-content h2 > code:before,
.course-content h3 > code:after,
.course-content h3 > code:before,
.course-content h4 > code:after,
.course-content h4 > code:before,
p > code:after,
a > code:after,
a > code:before {
content: '' !important;
}
.course-content.prose ul li > code,
.course-content.prose ol li > code,
.course-content p code,
.course-content a > code,
.course-content strong > code,
.course-content em > code,
.course-content h1 > code,
.course-content h2 > code,
.course-content h3 > code,
.course-content table code {
background: #f4f4f5 !important;
border: 1px solid #282a36 !important;
color: #282a36 !important;
padding: 2px 4px;
border-radius: 5px;
font-size: 16px !important;
white-space: pre;
font-weight: normal;
}
.course-content blockquote {
font-style: normal;
}
.course-content.prose blockquote h1,
.course-content.prose blockquote h2,
.course-content.prose blockquote h3,
.course-content.prose blockquote h4 {
font-style: normal;
margin-bottom: 8px;
}
.course-content.prose ul li > code:before,
.course-content p > code:before,
.course-content.prose ul li > code:after,
.course-content p > code:after,
.course-content h2 > code:after,
.course-content h2 > code:before,
.course-content table code:before,
.course-content table code:after,
.course-content a > code:after,
.course-content a > code:before,
.course-content h2 code:after,
.course-content h2 code:before,
.course-content h2 code:after,
.course-content h2 code:before {
content: '' !important;
}
.course-content table {
border-collapse: collapse;
border: 1px solid black;
border-radius: 5px;
}
.course-content table td,
.course-content table th {
padding: 5px 10px;
}

@ -17,7 +17,14 @@ export function AICourseFollowUp(props: AICourseFollowUpProps) {
const [isOpen, setIsOpen] = useState(false);
const [courseAIChatHistory, setCourseAIChatHistory] = useState<
AIChatHistoryType[]
>([]);
>([
{
role: 'assistant',
content:
'Hey, I am your AI instructor. Here are some examples of what you can ask me about 🤖',
isDefault: true,
},
]);
return (
<div className="relative">
@ -47,6 +54,10 @@ export function AICourseFollowUp(props: AICourseFollowUpProps) {
}}
/>
)}
{isOpen && (
<div className="pointer-events-none fixed inset-0 z-50 bg-black/50" />
)}
</div>
);
}

@ -182,7 +182,7 @@ export function AICourseFollowUpPopover(props: AICourseFollowUpPopoverProps) {
return (
<div
className="absolute bottom-0 left-0 z-10 flex h-[400px] w-full flex-col overflow-hidden rounded-lg border border-gray-200 bg-white shadow"
className="absolute bottom-0 left-0 z-[99] flex h-[500px] w-full flex-col overflow-hidden rounded-lg border border-gray-200 bg-white shadow"
ref={containerRef}
>
<div className="flex items-center justify-between gap-2 border-b border-gray-200 px-4 py-2 text-sm">
@ -256,7 +256,7 @@ function AIChatCard(props: AIChatCardProps) {
const { role, content } = props;
const html = useMemo(() => {
return markdownToHtml(content);
return markdownToHtml(content, false);
}, [content]);
return (
@ -278,7 +278,7 @@ function AIChatCard(props: AIChatCardProps) {
<Bot className="size-4 stroke-[2.5]" />
</div>
<div
className="course-content course-ai-content prose prose-sm mt-0.5 max-w-full grow overflow-hidden text-sm"
className="course-content course-ai-content prose prose-sm mt-0.5 max-w-full overflow-hidden text-sm"
dangerouslySetInnerHTML={{ __html: html }}
/>
</div>

@ -1,10 +1,5 @@
import {
CheckIcon,
ChevronLeft,
ChevronRight,
Loader2Icon,
LockIcon,
} from 'lucide-react';
import './AICourseFollowUp.css';
import { CheckIcon, ChevronLeft, ChevronRight, Loader2Icon, LockIcon } from 'lucide-react';
import { cn } from '../../lib/classname';
import { useEffect, useMemo, useState } from 'react';
import { isLoggedIn, removeAuthToken } from '../../lib/jwt';
@ -213,7 +208,7 @@ export function AICourseModuleView(props: AICourseModuleViewProps) {
{!error && isLoggedIn() && (
<div
className="prose max-w-none"
className="course-content prose prose-lg mt-8 text-black prose-headings:mb-3 prose-headings:mt-8 prose-blockquote:font-normal prose-pre:rounded-2xl prose-pre:text-lg prose-li:my-1 prose-thead:border-zinc-800 prose-tr:border-zinc-800"
dangerouslySetInnerHTML={{ __html: lessonHtml }}
/>
)}
@ -268,7 +263,7 @@ export function AICourseModuleView(props: AICourseModuleViewProps) {
</div>
</div>
{!isGenerating && (
{!isGenerating && !isLoading && (
<AICourseFollowUp
courseSlug={courseSlug}
moduleTitle={currentModuleTitle}

@ -17,13 +17,13 @@ export function replaceVariables(
});
}
const md = new MarkdownIt({
html: true,
linkify: true,
});
export function markdownToHtml(markdown: string, isInline = true): string {
try {
const md = new MarkdownIt({
html: true,
linkify: true,
});
// Solution to open links in new tab in markdown
// otherwise default behaviour is to open in same tab
//

Loading…
Cancel
Save