Updates to AI usage

feat/ai-roadmap
Kamran Ahmed 3 weeks ago
parent 2b5d75fea6
commit 21e4602881
  1. 1
      src/components/GenerateCourse/AICourseContent.tsx
  2. 31
      src/components/GenerateCourse/AICourseFollowUpPopover.tsx
  3. 2
      src/components/GenerateCourse/AICourseLesson.tsx
  4. 1
      src/components/GenerateCourse/AICourseLimit.tsx
  5. 28
      src/components/GenerateCourse/AICourseRoadmapView.tsx

@ -435,6 +435,7 @@ export function AICourseContent(props: AICourseContentProps) {
setActiveLessonIndex={setActiveLessonIndex}
setViewMode={setViewMode}
setExpandedModules={setExpandedModules}
onUpgradeClick={() => setShowUpgradeModal(true)}
/>
)}

@ -2,8 +2,7 @@ import { useQuery } from '@tanstack/react-query';
import {
BookOpen,
Bot,
Code,
Globe, Hammer,
Hammer,
HelpCircle,
LockIcon,
Send,
@ -22,6 +21,7 @@ import {
} from '../../lib/markdown';
import { getAiCourseLimitOptions } from '../../queries/ai-course';
import { queryClient } from '../../stores/query-client';
import { billingDetailsOptions } from '../../queries/billing';
export type AllowedAIChatRole = 'user' | 'assistant';
export type AIChatHistoryType = {
@ -70,7 +70,11 @@ export function AICourseFollowUpPopover(props: AICourseFollowUpPopoverProps) {
queryClient,
);
const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =
useQuery(billingDetailsOptions(), queryClient);
const isLimitExceeded = (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);
const isPaidUser = userBillingDetails?.status === 'active';
const handleChatSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
@ -247,15 +251,20 @@ export function AICourseFollowUpPopover(props: AICourseFollowUpPopoverProps) {
{isLimitExceeded && (
<div className="absolute inset-0 flex items-center justify-center gap-2 bg-black text-white">
<LockIcon className="size-4 cursor-not-allowed" strokeWidth={2.5} />
<p className="cursor-not-allowed">Limit reached for today</p>
<button
onClick={() => {
onUpgradeClick();
}}
className="rounded-md bg-white px-2 py-1 text-xs font-medium text-black hover:bg-gray-300"
>
Upgrade for more
</button>
<p className="cursor-not-allowed">
Limit reached for today
{isPaidUser ? '. Please wait until tomorrow.' : ''}
</p>
{!isPaidUser && (
<button
onClick={() => {
onUpgradeClick();
}}
className="rounded-md bg-white px-2 py-1 text-xs font-medium text-black hover:bg-gray-300"
>
Upgrade for more
</button>
)}
</div>
)}
<TextareaAutosize

@ -290,7 +290,7 @@ export function AICourseLesson(props: AICourseLessonProps) {
<p className="my-3 text-red-600">
You have reached the AI usage limit for today.
{!isPaidUser && <>Please upgrade your account to continue.</>}
{isPaidUser && <>Please wait until tomorrow to continue.</>}
{isPaidUser && <>&nbsp;Please wait until tomorrow to continue.</>}
</p>
{!isPaidUser && (

@ -32,7 +32,6 @@ export function AICourseLimit(props: AICourseLimitProps) {
const totalPercentage = getPercentage(used, limit);
// has consumed 85% of the limit
const isNearLimit = used >= limit * 0.85;
const isPaidUser = userBillingDetails.status === 'active';
return (

@ -17,9 +17,11 @@ import {
} from 'react';
import type { AICourseViewMode } from './AICourseContent';
import { replaceChildren } from '../../lib/dom';
import { Loader2Icon } from 'lucide-react';
import { ErrorIcon } from '../ReactIcons/ErrorIcon';
import { Frown, Loader2Icon } from 'lucide-react';
import { renderTopicProgress } from '../../lib/resource-progress';
import { queryClient } from '../../stores/query-client';
import { useQuery } from '@tanstack/react-query';
import { billingDetailsOptions } from '../../queries/billing';
export type AICourseRoadmapViewProps = {
done: string[];
@ -27,6 +29,7 @@ export type AICourseRoadmapViewProps = {
setActiveModuleIndex: (index: number) => void;
setActiveLessonIndex: (index: number) => void;
setViewMode: (mode: AICourseViewMode) => void;
onUpgradeClick: () => void;
setExpandedModules: Dispatch<SetStateAction<Record<number, boolean>>>;
};
@ -38,6 +41,7 @@ export function AICourseRoadmapView(props: AICourseRoadmapViewProps) {
setActiveLessonIndex,
setViewMode,
setExpandedModules,
onUpgradeClick,
} = props;
const containerEl = useRef<HTMLDivElement>(null);
@ -47,6 +51,11 @@ export function AICourseRoadmapView(props: AICourseRoadmapViewProps) {
const [isGenerating, setIsGenerating] = useState(false);
const [error, setError] = useState<string | null>(null);
const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =
useQuery(billingDetailsOptions(), queryClient);
const isPaidUser = userBillingDetails?.status === 'active';
const generateAICourseRoadmap = async (courseSlug: string) => {
try {
const response = await fetch(
@ -179,7 +188,7 @@ export function AICourseRoadmapView(props: AICourseRoadmapViewProps) {
);
return (
<div className="relative mx-auto min-h-[200px] rounded-xl border border-gray-200 bg-white shadow-sm lg:max-w-7xl">
<div className="relative mx-auto min-h-[500px] rounded-xl border border-gray-200 bg-white shadow-sm lg:max-w-7xl">
{isLoading && (
<div className="absolute inset-0 flex h-full w-full items-center justify-center">
<Loader2Icon className="h-10 w-10 animate-spin stroke-[3px]" />
@ -188,10 +197,19 @@ export function AICourseRoadmapView(props: AICourseRoadmapViewProps) {
{error && !isLoading && !isGenerating && (
<div className="absolute inset-0 flex h-full w-full flex-col items-center justify-center">
<ErrorIcon additionalClasses="h-10 w-10" />
<p className="mx-auto mt-4 max-w-sm text-balance text-center text-sm text-gray-500">
<Frown className="size-20 text-red-500" />
<p className="mx-auto mt-5 max-w-[250px] text-balance text-center text-base text-red-500">
{error || 'Something went wrong'}
</p>
{!isPaidUser && (error || '')?.includes('limit') && (
<button
onClick={onUpgradeClick}
className="mt-5 rounded-full bg-red-600 px-4 py-1 text-white hover:bg-red-700"
>
Upgrade Account
</button>
)}
</div>
)}

Loading…
Cancel
Save