1
0
mirror of https://github.com/kamranahmedse/developer-roadmap.git synced 2025-09-08 16:20:40 +02:00
This commit is contained in:
Arik Chakma
2025-06-17 00:27:05 +06:00
parent c118ce4020
commit 1217a7afb7
7 changed files with 55 additions and 23 deletions

View File

@@ -63,7 +63,7 @@ export function AIGuideActions(props: AIGuideActionsType) {
{isOpen && ( {isOpen && (
<div className="absolute top-8 right-0 z-10 w-48 overflow-hidden rounded-md border border-gray-200 bg-white shadow-lg"> <div className="absolute top-8 right-0 z-10 w-48 overflow-hidden rounded-md border border-gray-200 bg-white shadow-lg">
<a <a
href={`/ai/guides/${guideSlug}`} href={`/ai/guide/${guideSlug}`}
className="flex w-full items-center gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70" className="flex w-full items-center gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70"
> >
<ArrowUpRightIcon className="h-3.5 w-3.5" /> <ArrowUpRightIcon className="h-3.5 w-3.5" />

View File

@@ -19,7 +19,7 @@ export function AIGuideCard(props: AIGuideCardProps) {
return ( return (
<div className="relative flex flex-grow flex-col"> <div className="relative flex flex-grow flex-col">
<a <a
href={`/ai/guides/${guide.slug}`} href={`/ai/guide/${guide.slug}`}
className="hover:border-gray-3 00 group relative flex h-full min-h-[140px] w-full flex-col overflow-hidden rounded-lg border border-gray-200 bg-white p-4 text-left transition-all hover:bg-gray-50" className="hover:border-gray-3 00 group relative flex h-full min-h-[140px] w-full flex-col overflow-hidden rounded-lg border border-gray-200 bg-white p-4 text-left transition-all hover:bg-gray-50"
> >
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">

View File

@@ -107,18 +107,20 @@ export function AIGuide(props: AIGuideProps) {
)} )}
{!guideSlug && <GenerateAIGuide onGuideSlugChange={setGuideSlug} />} {!guideSlug && <GenerateAIGuide onGuideSlugChange={setGuideSlug} />}
{!isAiGuideSuggestionsLoading && aiGuide && !isRegenerating && ( {aiGuide && !isRegenerating && (
<div className="mt-4 grid grid-cols-2 divide-x divide-gray-200 rounded-lg border border-gray-200 bg-white"> <div className="mt-4 grid grid-cols-2 divide-x divide-gray-200 rounded-lg border border-gray-200 bg-white">
<ListSuggestions <ListSuggestions
title="Related Topics" title="Related Topics"
suggestions={relatedTopics} suggestions={relatedTopics}
depth="essentials" depth="essentials"
isLoading={isAiGuideSuggestionsLoading}
/> />
<ListSuggestions <ListSuggestions
title="Dive Deeper" title="Dive Deeper"
suggestions={deepDiveTopics} suggestions={deepDiveTopics}
depth="detailed" depth="detailed"
isLoading={isAiGuideSuggestionsLoading}
/> />
</div> </div>
)} )}
@@ -128,6 +130,7 @@ export function AIGuide(props: AIGuideProps) {
isGuideLoading={!aiGuide} isGuideLoading={!aiGuide}
onUpgrade={() => setShowUpgradeModal(true)} onUpgrade={() => setShowUpgradeModal(true)}
randomQuestions={randomQuestions} randomQuestions={randomQuestions}
isQuestionsLoading={isAiGuideSuggestionsLoading}
/> />
</AITutorLayout> </AITutorLayout>
); );
@@ -137,10 +140,11 @@ type ListSuggestionsProps = {
title: string; title: string;
suggestions: string[]; suggestions: string[];
depth: string; depth: string;
isLoading: boolean;
}; };
export function ListSuggestions(props: ListSuggestionsProps) { export function ListSuggestions(props: ListSuggestionsProps) {
const { title, suggestions, depth } = props; const { title, suggestions, depth, isLoading } = props;
return ( return (
<div className="flex flex-col"> <div className="flex flex-col">
@@ -148,7 +152,17 @@ export function ListSuggestions(props: ListSuggestionsProps) {
{title} {title}
</h2> </h2>
<ul className="flex flex-col gap-1 p-1"> <ul className="flex flex-col gap-1 p-1">
{suggestions?.map((topic) => { {isLoading && (
<>
{[1, 2].map((i) => (
<div key={i} className="w-full">
<div className="h-7 w-full animate-pulse rounded-md bg-gray-200"></div>
</div>
))}
</>
)}
{!isLoading &&
suggestions?.map((topic) => {
const url = `/ai/guides?term=${encodeURIComponent(topic)}&depth=${depth}&id=&format=guide`; const url = `/ai/guides?term=${encodeURIComponent(topic)}&depth=${depth}&id=&format=guide`;
return ( return (

View File

@@ -24,11 +24,18 @@ type AIGuideChatProps = {
guideSlug?: string; guideSlug?: string;
isGuideLoading?: boolean; isGuideLoading?: boolean;
onUpgrade?: () => void; onUpgrade?: () => void;
isQuestionsLoading?: boolean;
randomQuestions?: string[]; randomQuestions?: string[];
}; };
export function AIGuideChat(props: AIGuideChatProps) { export function AIGuideChat(props: AIGuideChatProps) {
const { guideSlug, isGuideLoading, onUpgrade, randomQuestions } = props; const {
guideSlug,
isGuideLoading,
onUpgrade,
randomQuestions,
isQuestionsLoading,
} = props;
const scrollareaRef = useRef<HTMLDivElement>(null); const scrollareaRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null); const inputRef = useRef<HTMLInputElement>(null);
@@ -163,7 +170,18 @@ export function AIGuideChat(props: AIGuideChatProps) {
html="Hello, how can I help you today?" html="Hello, how can I help you today?"
isIntro isIntro
/> />
{randomQuestions && {isQuestionsLoading && (
<div className="flex flex-col gap-1">
{[1, 2, 3, 4].map((i) => (
<div
key={i}
className="h-[38px] w-full animate-pulse rounded-lg bg-gray-200"
></div>
))}
</div>
)}
{!isQuestionsLoading &&
randomQuestions &&
randomQuestions.length > 0 && randomQuestions.length > 0 &&
messages.length === 0 && ( messages.length === 0 && (
<> <>

View File

@@ -108,7 +108,7 @@ export function GenerateAIGuide(props: GenerateAIGuideProps) {
); );
onGuideSlugChange?.(guideSlug); onGuideSlugChange?.(guideSlug);
window.history.replaceState(null, '', `/ai/guides/${guideSlug}`); window.history.replaceState(null, '', `/ai/guide/${guideSlug}`);
}, },
onLoadingChange: setIsLoading, onLoadingChange: setIsLoading,
onError: setError, onError: setError,

View File

@@ -16,7 +16,7 @@ const { slug } = Astro.params as Params;
briefTitle='AI Tutor' briefTitle='AI Tutor'
description='AI Tutor' description='AI Tutor'
keywords={['ai', 'tutor', 'education', 'learning']} keywords={['ai', 'tutor', 'education', 'learning']}
canonicalUrl={`/ai/document/${slug}`} canonicalUrl={`/ai/guide/${slug}`}
> >
<AIGuide client:load guideSlug={slug} /> <AIGuide client:load guideSlug={slug} />
</SkeletonLayout> </SkeletonLayout>

View File

@@ -11,7 +11,7 @@ import SkeletonLayout from '../../../layouts/SkeletonLayout.astro';
briefTitle='AI Tutor' briefTitle='AI Tutor'
description='AI Tutor' description='AI Tutor'
keywords={['ai', 'tutor', 'education', 'learning']} keywords={['ai', 'tutor', 'education', 'learning']}
canonicalUrl='/ai/document' canonicalUrl='/ai/guide'
noIndex={true} noIndex={true}
> >
<AIGuide client:load /> <AIGuide client:load />