mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-07-31 06:20:14 +02:00
Is paid user checks
This commit is contained in:
@@ -21,6 +21,7 @@ import { AICourseModuleView } from './AICourseModuleView';
|
|||||||
import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';
|
import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';
|
||||||
import { AILimitsPopup } from './AILimitsPopup';
|
import { AILimitsPopup } from './AILimitsPopup';
|
||||||
import { RegenerateOutline } from './RegenerateOutline';
|
import { RegenerateOutline } from './RegenerateOutline';
|
||||||
|
import { useIsPaidUser } from '../../queries/billing';
|
||||||
|
|
||||||
type AICourseContentProps = {
|
type AICourseContentProps = {
|
||||||
courseSlug?: string;
|
courseSlug?: string;
|
||||||
@@ -41,6 +42,8 @@ export function AICourseContent(props: AICourseContentProps) {
|
|||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||||
const [viewMode, setViewMode] = useState<'module' | 'full'>('full');
|
const [viewMode, setViewMode] = useState<'module' | 'full'>('full');
|
||||||
|
|
||||||
|
const { isPaidUser } = useIsPaidUser();
|
||||||
|
|
||||||
const { data: aiCourseProgress } = useQuery(
|
const { data: aiCourseProgress } = useQuery(
|
||||||
getAiCourseProgressOptions({ aiCourseSlug: courseSlug || '' }),
|
getAiCourseProgressOptions({ aiCourseSlug: courseSlug || '' }),
|
||||||
queryClient,
|
queryClient,
|
||||||
@@ -162,12 +165,14 @@ export function AICourseContent(props: AICourseContentProps) {
|
|||||||
|
|
||||||
{isLimitReached && (
|
{isLimitReached && (
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<button
|
{!isPaidUser && (
|
||||||
onClick={() => setShowUpgradeModal(true)}
|
<button
|
||||||
className="rounded-md bg-yellow-400 px-6 py-2 text-sm font-medium text-black hover:bg-yellow-500"
|
onClick={() => setShowUpgradeModal(true)}
|
||||||
>
|
className="rounded-md bg-yellow-400 px-6 py-2 text-sm font-medium text-black hover:bg-yellow-500"
|
||||||
Upgrade to remove Limits
|
>
|
||||||
</button>
|
Upgrade to remove Limits
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
<p className="mt-4 text-sm text-black">
|
<p className="mt-4 text-sm text-black">
|
||||||
<a href="/ai-tutor" className="underline underline-offset-2">
|
<a href="/ai-tutor" className="underline underline-offset-2">
|
||||||
|
@@ -25,6 +25,7 @@ import {
|
|||||||
import { queryClient } from '../../stores/query-client';
|
import { queryClient } from '../../stores/query-client';
|
||||||
import { AICourseFollowUp } from './AICourseFollowUp';
|
import { AICourseFollowUp } from './AICourseFollowUp';
|
||||||
import './AICourseFollowUp.css';
|
import './AICourseFollowUp.css';
|
||||||
|
import { useIsPaidUser } from '../../queries/billing';
|
||||||
|
|
||||||
type AICourseModuleViewProps = {
|
type AICourseModuleViewProps = {
|
||||||
courseSlug: string;
|
courseSlug: string;
|
||||||
@@ -72,6 +73,8 @@ export function AICourseModuleView(props: AICourseModuleViewProps) {
|
|||||||
const lessonId = `${slugify(currentModuleTitle)}__${slugify(currentLessonTitle)}`;
|
const lessonId = `${slugify(currentModuleTitle)}__${slugify(currentLessonTitle)}`;
|
||||||
const isLessonDone = aiCourseProgress?.done.includes(lessonId);
|
const isLessonDone = aiCourseProgress?.done.includes(lessonId);
|
||||||
|
|
||||||
|
const { isPaidUser } = useIsPaidUser();
|
||||||
|
|
||||||
const abortController = useMemo(
|
const abortController = useMemo(
|
||||||
() => new AbortController(),
|
() => new AbortController(),
|
||||||
[activeModuleIndex, activeLessonIndex],
|
[activeModuleIndex, activeLessonIndex],
|
||||||
@@ -124,36 +127,41 @@ export function AICourseModuleView(props: AICourseModuleViewProps) {
|
|||||||
removeAuthToken();
|
removeAuthToken();
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const reader = response.body?.getReader();
|
|
||||||
|
|
||||||
if (!reader) {
|
|
||||||
setIsLoading(false);
|
|
||||||
setError('Something went wrong');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsLoading(false);
|
if (!response.body) {
|
||||||
setIsGenerating(true);
|
setIsLoading(false);
|
||||||
await readStream(reader, {
|
setError('No response body received');
|
||||||
onStream: async (result) => {
|
return;
|
||||||
if (abortController.signal.aborted) {
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setLessonHtml(markdownToHtml(result, false));
|
try {
|
||||||
},
|
const reader = response.body.getReader();
|
||||||
onStreamEnd: async (result) => {
|
setIsLoading(false);
|
||||||
if (abortController.signal.aborted) {
|
setIsGenerating(true);
|
||||||
return;
|
await readStream(reader, {
|
||||||
}
|
onStream: async (result) => {
|
||||||
|
if (abortController.signal.aborted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setLessonHtml(await markdownToHtmlWithHighlighting(result));
|
setLessonHtml(markdownToHtml(result, false));
|
||||||
queryClient.invalidateQueries(getAiCourseLimitOptions());
|
},
|
||||||
setIsGenerating(false);
|
onStreamEnd: async (result) => {
|
||||||
},
|
if (abortController.signal.aborted) {
|
||||||
});
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLessonHtml(await markdownToHtmlWithHighlighting(result));
|
||||||
|
queryClient.invalidateQueries(getAiCourseLimitOptions());
|
||||||
|
setIsGenerating(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
setError(e instanceof Error ? e.message : 'Something went wrong');
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const { mutate: toggleDone, isPending: isTogglingDone } = useMutation(
|
const { mutate: toggleDone, isPending: isTogglingDone } = useMutation(
|
||||||
@@ -273,18 +281,21 @@ export function AICourseModuleView(props: AICourseModuleViewProps) {
|
|||||||
Limit reached
|
Limit reached
|
||||||
</h2>
|
</h2>
|
||||||
<p className="my-3 text-red-600">
|
<p className="my-3 text-red-600">
|
||||||
You have reached the AI usage limit for today. Please upgrade
|
You have reached the AI usage limit for today.
|
||||||
your account to continue.
|
{!isPaidUser && <>Please upgrade your account to continue.</>}
|
||||||
|
{isPaidUser && <>Please wait until tomorrow to continue.</>}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<button
|
{!isPaidUser && (
|
||||||
onClick={() => {
|
<button
|
||||||
onUpgrade();
|
onClick={() => {
|
||||||
}}
|
onUpgrade();
|
||||||
className="rounded-full bg-red-600 px-4 py-1 text-white hover:bg-red-700"
|
}}
|
||||||
>
|
className="rounded-full bg-red-600 px-4 py-1 text-white hover:bg-red-700"
|
||||||
Upgrade Account
|
>
|
||||||
</button>
|
Upgrade Account
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<p className="text-red-600">{error}</p>
|
<p className="text-red-600">{error}</p>
|
||||||
|
Reference in New Issue
Block a user