mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2026-09-24 15:00:31 +08:00
feat: make AI courses/guides look like courses/guides
This commit is contained in:
@@ -1,11 +1,27 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { useChat } from '@ai-sdk/react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import {
|
||||
Ban,
|
||||
FileText, HeartHandshake,
|
||||
Star,
|
||||
X,
|
||||
Zap
|
||||
} from 'lucide-react';
|
||||
import { useKeydown } from '../../hooks/use-keydown';
|
||||
import { useLoadTopic } from '../../hooks/use-load-topic';
|
||||
import { useOutsideClick } from '../../hooks/use-outside-click';
|
||||
import { useToast } from '../../hooks/use-toast';
|
||||
import { useToggleTopic } from '../../hooks/use-toggle-topic';
|
||||
import { topicDetailAiChatTransport } from '../../lib/ai.ts';
|
||||
import { getUrlParams, parseUrl } from '../../lib/browser';
|
||||
import { cn } from '../../lib/classname.ts';
|
||||
import { lockBodyScroll } from '../../lib/dom.ts';
|
||||
import { httpGet } from '../../lib/http';
|
||||
import { isLoggedIn } from '../../lib/jwt';
|
||||
import { markdownToHtml, sanitizeMarkdown } from '../../lib/markdown';
|
||||
import { showLoginPopup } from '../../lib/popup';
|
||||
import type { ResourceType } from '../../lib/resource-progress';
|
||||
import {
|
||||
isTopicDone,
|
||||
@@ -13,50 +29,30 @@ import {
|
||||
renderTopicProgress,
|
||||
updateResourceProgress as updateResourceProgressApi,
|
||||
} from '../../lib/resource-progress';
|
||||
import { type AllowedRoadmapRenderer } from '../../lib/roadmap.ts';
|
||||
import { aiLimitOptions } from '../../queries/ai-course.ts';
|
||||
import { billingDetailsOptions } from '../../queries/billing.ts';
|
||||
import { roadmapTreeMappingOptions } from '../../queries/roadmap-tree.ts';
|
||||
import { pageProgressMessage } from '../../stores/page';
|
||||
import { showLoginPopup } from '../../lib/popup';
|
||||
import { useToast } from '../../hooks/use-toast';
|
||||
import { queryClient } from '../../stores/query-client.ts';
|
||||
import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal.tsx';
|
||||
import type {
|
||||
AllowedLinkTypes,
|
||||
RoadmapContentDocument,
|
||||
} from '../CustomRoadmap/CustomRoadmap';
|
||||
import { markdownToHtml, sanitizeMarkdown } from '../../lib/markdown';
|
||||
import {
|
||||
Ban,
|
||||
BookOpen,
|
||||
BookOpenIcon,
|
||||
BotIcon,
|
||||
FileText,
|
||||
FileTextIcon,
|
||||
HeartHandshake,
|
||||
Star,
|
||||
X,
|
||||
} from 'lucide-react';
|
||||
import { getUrlParams, parseUrl } from '../../lib/browser';
|
||||
import { Spinner } from '../ReactIcons/Spinner';
|
||||
import type { AIChatHistoryType } from '../GenerateCourse/AICourseLessonChat.tsx';
|
||||
import { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx';
|
||||
import { type AllowedRoadmapRenderer } from '../../lib/roadmap.ts';
|
||||
import { lockBodyScroll } from '../../lib/dom.ts';
|
||||
import { TopicDetailLink } from './TopicDetailLink.tsx';
|
||||
import { ResourceListSeparator } from './ResourceListSeparator.tsx';
|
||||
import { Spinner } from '../ReactIcons/Spinner';
|
||||
import { CreateCourseModal } from './CreateCourseModal.tsx';
|
||||
import { PaidResourceDisclaimer } from './PaidResourceDisclaimer.tsx';
|
||||
import { ResourceListSeparator } from './ResourceListSeparator.tsx';
|
||||
import { TopicDetailAI } from './TopicDetailAI.tsx';
|
||||
import { TopicDetailLink } from './TopicDetailLink.tsx';
|
||||
import {
|
||||
TopicDetailsTabs,
|
||||
type AllowedTopicDetailsTabs,
|
||||
} from './TopicDetailsTabs.tsx';
|
||||
import { TopicDetailAI } from './TopicDetailAI.tsx';
|
||||
import { cn } from '../../lib/classname.ts';
|
||||
import type { AIChatHistoryType } from '../GenerateCourse/AICourseLessonChat.tsx';
|
||||
import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal.tsx';
|
||||
import { TopicProgressButton } from './TopicProgressButton.tsx';
|
||||
import { CreateCourseModal } from './CreateCourseModal.tsx';
|
||||
import { useChat } from '@ai-sdk/react';
|
||||
import { topicDetailAiChatTransport } from '../../lib/ai.ts';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { queryClient } from '../../stores/query-client.ts';
|
||||
import { roadmapTreeMappingOptions } from '../../queries/roadmap-tree.ts';
|
||||
import { aiLimitOptions } from '../../queries/ai-course.ts';
|
||||
import { billingDetailsOptions } from '../../queries/billing.ts';
|
||||
|
||||
type PaidResourceType = {
|
||||
_id?: string;
|
||||
@@ -664,17 +660,18 @@ export function TopicDetail(props: TopicDetailProps) {
|
||||
{(hasSubjects || hasGuides) && (
|
||||
<>
|
||||
<ResourceListSeparator
|
||||
text="AI Tutor"
|
||||
text="Your personalized AI tutor"
|
||||
className="text-blue-600"
|
||||
icon={BotIcon}
|
||||
icon={Zap}
|
||||
/>
|
||||
<ul className="mt-4 ml-3 flex flex-wrap gap-1 text-sm">
|
||||
<ul className="mt-4 ml-3 flex flex-col flex-wrap gap-1 text-sm">
|
||||
{subjects.map((subject) => {
|
||||
return (
|
||||
<li key={subject}>
|
||||
<a
|
||||
key={subject}
|
||||
target="_blank"
|
||||
<TopicDetailLink
|
||||
url={`/ai/course/search?term=${subject}&src=topic`}
|
||||
type="course"
|
||||
title={subject}
|
||||
onClick={(e) => {
|
||||
if (!isLoggedIn()) {
|
||||
e.preventDefault();
|
||||
@@ -688,21 +685,17 @@ export function TopicDetail(props: TopicDetailProps) {
|
||||
return;
|
||||
}
|
||||
}}
|
||||
href={`/ai/course/search?term=${subject}&src=topic`}
|
||||
className="flex items-center gap-1.5 rounded-md border border-gray-300 bg-gray-100 px-2 py-1 hover:bg-gray-200 hover:text-black"
|
||||
>
|
||||
<BookOpenIcon className="size-3.5" />
|
||||
{subject}
|
||||
</a>
|
||||
/>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
{guides.map((guide) => {
|
||||
return (
|
||||
<li key={guide}>
|
||||
<a
|
||||
key={guide}
|
||||
target="_blank"
|
||||
<TopicDetailLink
|
||||
url={`/ai/guide/search?term=${guide}&src=topic`}
|
||||
type="article"
|
||||
title={guide}
|
||||
onClick={(e) => {
|
||||
if (!isLoggedIn()) {
|
||||
e.preventDefault();
|
||||
@@ -716,12 +709,7 @@ export function TopicDetail(props: TopicDetailProps) {
|
||||
return;
|
||||
}
|
||||
}}
|
||||
href={`/ai/guide/search?term=${guide}&src=topic`}
|
||||
className="flex items-center gap-1.5 rounded-md border border-gray-300 bg-gray-100 px-2 py-1 hover:bg-gray-200 hover:text-black"
|
||||
>
|
||||
<FileTextIcon className="size-3.5" />
|
||||
{guide}
|
||||
</a>
|
||||
/>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -48,7 +48,7 @@ function TopicLinkBadge(props: TopicLinkBadgeProps) {
|
||||
|
||||
type TopicDetailLinkProps = {
|
||||
url: string;
|
||||
onClick?: () => void;
|
||||
onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
|
||||
type: AllowedLinkTypes;
|
||||
title: string;
|
||||
isPaid?: boolean;
|
||||
|
||||
Reference in New Issue
Block a user