Topic AI changes

feat/topic-chat
Kamran Ahmed 1 week ago
parent 9b382fdd71
commit dbcff8d406
  1. 1
      src/components/CustomRoadmap/CustomRoadmap.tsx
  2. 5
      src/components/TopicDetail/TopicDetail.tsx
  3. 18
      src/components/TopicDetail/TopicDetailsTabs.tsx
  4. 1
      src/pages/[roadmapId]/index.astro
  5. 1
      src/pages/best-practices/[bestPracticeId]/index.astro

@ -118,6 +118,7 @@ export function CustomRoadmap(props: CustomRoadmapProps) {
resourceId={roadmap!._id} resourceId={roadmap!._id}
resourceTitle={roadmap!.title} resourceTitle={roadmap!.title}
resourceType="roadmap" resourceType="roadmap"
renderer='editor'
isEmbed={isEmbed} isEmbed={isEmbed}
canSubmitContribution={false} canSubmitContribution={false}
/> />

@ -25,7 +25,7 @@ import { Ban, FileText, HeartHandshake, Star, X } from 'lucide-react';
import { getUrlParams, parseUrl } from '../../lib/browser'; import { getUrlParams, parseUrl } from '../../lib/browser';
import { Spinner } from '../ReactIcons/Spinner'; import { Spinner } from '../ReactIcons/Spinner';
import { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx'; import { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx';
import { resourceTitleFromId } from '../../lib/roadmap.ts'; import { resourceTitleFromId, type AllowedRoadmapRenderer } from '../../lib/roadmap.ts';
import { lockBodyScroll } from '../../lib/dom.ts'; import { lockBodyScroll } from '../../lib/dom.ts';
import { TopicDetailLink } from './TopicDetailLink.tsx'; import { TopicDetailLink } from './TopicDetailLink.tsx';
import { ResourceListSeparator } from './ResourceListSeparator.tsx'; import { ResourceListSeparator } from './ResourceListSeparator.tsx';
@ -44,6 +44,7 @@ type TopicDetailProps = {
resourceId?: string; resourceId?: string;
resourceTitle?: string; resourceTitle?: string;
resourceType?: ResourceType; resourceType?: ResourceType;
renderer?: AllowedRoadmapRenderer;
isEmbed?: boolean; isEmbed?: boolean;
canSubmitContribution: boolean; canSubmitContribution: boolean;
@ -93,6 +94,7 @@ export function TopicDetail(props: TopicDetailProps) {
canSubmitContribution, canSubmitContribution,
resourceId: defaultResourceId, resourceId: defaultResourceId,
isEmbed = false, isEmbed = false,
renderer = 'balsamiq',
resourceTitle, resourceTitle,
} = props; } = props;
@ -397,6 +399,7 @@ export function TopicDetail(props: TopicDetailProps) {
<TopicDetailsTabs <TopicDetailsTabs
activeTab={activeTab} activeTab={activeTab}
setActiveTab={setActiveTab} setActiveTab={setActiveTab}
hasAITutor={renderer === 'editor'}
/> />
)} )}
<div <div

@ -5,10 +5,11 @@ export type AllowedTopicDetailsTabs = 'content' | 'ai';
type TopicDetailsTabsProps = { type TopicDetailsTabsProps = {
activeTab: AllowedTopicDetailsTabs; activeTab: AllowedTopicDetailsTabs;
setActiveTab: (tab: AllowedTopicDetailsTabs) => void; setActiveTab: (tab: AllowedTopicDetailsTabs) => void;
hasAITutor?: boolean;
}; };
export function TopicDetailsTabs(props: TopicDetailsTabsProps) { export function TopicDetailsTabs(props: TopicDetailsTabsProps) {
const { activeTab, setActiveTab } = props; const { activeTab, setActiveTab, hasAITutor = true } = props;
return ( return (
<div className="flex w-max gap-1.5"> <div className="flex w-max gap-1.5">
@ -23,6 +24,7 @@ export function TopicDetailsTabs(props: TopicDetailsTabsProps) {
icon={WandSparkles} icon={WandSparkles}
label="AI Tutor" label="AI Tutor"
isNew={true} isNew={true}
isDisabled={!hasAITutor}
onClick={() => setActiveTab('ai')} onClick={() => setActiveTab('ai')}
/> />
</div> </div>
@ -34,27 +36,33 @@ type TopicDetailsTabProps = {
icon: LucideIcon; icon: LucideIcon;
label: string; label: string;
isNew?: boolean; isNew?: boolean;
isDisabled?: boolean;
onClick: () => void; onClick: () => void;
}; };
function TopicDetailsTab(props: TopicDetailsTabProps) { function TopicDetailsTab(props: TopicDetailsTabProps) {
const { isActive, icon: Icon, label, isNew, onClick } = props; const { isActive, icon: Icon, label, isNew, isDisabled, onClick } = props;
return ( return (
<button <button
className="flex items-center gap-2 rounded-md border border-gray-300 px-2 py-1 text-sm text-gray-500 hover:border-gray-400 data-[state=active]:border-black data-[state=active]:bg-black data-[state=active]:text-white" className="flex select-none disabled:pointer-events-none items-center gap-2 rounded-md border border-gray-300 px-2 py-1 text-sm text-gray-500 hover:border-gray-400 data-[state=active]:border-black data-[state=active]:bg-black data-[state=active]:text-white"
data-state={isActive ? 'active' : 'inactive'} data-state={isActive ? 'active' : 'inactive'}
onClick={onClick} onClick={onClick}
disabled={isActive} disabled={isDisabled}
type="button" type="button"
> >
<Icon className="h-4 w-4" /> <Icon className="h-4 w-4" />
<span className="hidden sm:block">{label}</span> <span className="hidden sm:block">{label}</span>
{isNew && ( {isNew && !isDisabled && (
<span className="hidden rounded-sm bg-yellow-400 px-1 text-xs text-black sm:block"> <span className="hidden rounded-sm bg-yellow-400 px-1 text-xs text-black sm:block">
New New
</span> </span>
)} )}
{isDisabled && (
<span className="hidden rounded-sm bg-gray-400 px-1 text-xs text-white sm:block">
Soon
</span>
)}
</button> </button>
); );
} }

@ -102,6 +102,7 @@ const courses = roadmapData.courses || [];
resourceTitle={roadmapData.title} resourceTitle={roadmapData.title}
resourceId={roadmapId} resourceId={roadmapId}
resourceType='roadmap' resourceType='roadmap'
renderer={roadmapData.renderer}
client:idle client:idle
canSubmitContribution={true} canSubmitContribution={true}
/> />

@ -108,6 +108,7 @@ const ogImageUrl = getOpenGraphImageUrl({
resourceId={bestPracticeId} resourceId={bestPracticeId}
resourceTitle={bestPracticeData.title} resourceTitle={bestPracticeData.title}
resourceType='best-practice' resourceType='best-practice'
renderer={'balsamiq'}
client:idle client:idle
canSubmitContribution={true} canSubmitContribution={true}
/> />

Loading…
Cancel
Save