1
0
mirror of https://github.com/kamranahmedse/developer-roadmap.git synced 2025-09-10 01:00:42 +02:00

feat: remove ai roadmap limit for pro user

This commit is contained in:
Arik Chakma
2025-03-31 10:54:53 +06:00
parent e5802eaeaf
commit 62cdbb0f1c
4 changed files with 42 additions and 31 deletions

View File

@@ -35,8 +35,9 @@ import {
readAIRoadmapStream,
} from '../../lib/ai.ts';
import { AITermSuggestionInput } from './AITermSuggestionInput.tsx';
import { IncreaseRoadmapLimit } from './IncreaseRoadmapLimit.tsx';
import { AuthenticationForm } from '../AuthenticationFlow/AuthenticationForm.tsx';
import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal.tsx';
import { useIsPaidUser } from '../../queries/billing.ts';
export type GetAIRoadmapLimitResponse = {
used: number;
@@ -101,6 +102,7 @@ export function GenerateRoadmap(props: GenerateRoadmapProps) {
const roadmapContainerRef = useRef<HTMLDivElement>(null);
const { isPaidUser, isLoading: isLoadingPaidUser } = useIsPaidUser();
const { rc: referralCode } = getUrlParams() as {
rc?: string;
};
@@ -472,12 +474,25 @@ export function GenerateRoadmap(props: GenerateRoadmapProps) {
}
const pageUrl = `https://roadmap.sh/ai/${roadmapSlug}`;
const canGenerateMore = roadmapLimitUsed < roadmapLimit;
const canGenerateMore = roadmapLimitUsed < roadmapLimit || isPaidUser;
const isGenerateButtonDisabled =
isLoadingResults ||
(isAuthenticatedUser &&
// if no limit,
(!roadmapLimit ||
// no roadmap term,
!roadmapTerm ||
// if limit is reached and user is not paid user,
(roadmapLimitUsed >= roadmapLimit && !isPaidUser) ||
// if roadmap term is the same as the current roadmap term,
roadmapTerm === currentRoadmap?.term ||
// if key only,
isKeyOnly));
return (
<>
{isConfiguring && (
<IncreaseRoadmapLimit
<UpgradeAccountModal
onClose={() => {
setIsConfiguring(false);
loadAIRoadmapLimit().finally(() => null);
@@ -519,7 +534,7 @@ export function GenerateRoadmap(props: GenerateRoadmapProps) {
{!isLoading && (
<div className="container flex flex-grow flex-col items-start">
<AIRoadmapAlert />
{isKeyOnly && isAuthenticatedUser && (
{isKeyOnly && isAuthenticatedUser && !isPaidUser && (
<div className="flex flex-row gap-4">
<p className={'text-left text-red-500'}>
We have hit the limit for AI roadmap generation. Please try
@@ -533,7 +548,7 @@ export function GenerateRoadmap(props: GenerateRoadmapProps) {
</p>
</div>
)}
{!isKeyOnly && isAuthenticatedUser && (
{!isKeyOnly && isAuthenticatedUser && !isPaidUser && (
<div className="mt-2 flex w-full flex-col items-start justify-between gap-2 text-sm sm:flex-row sm:items-center sm:gap-0">
<span>
<span
@@ -582,7 +597,7 @@ export function GenerateRoadmap(props: GenerateRoadmapProps) {
<button
type={'submit'}
className={cn(
'flex min-w-[127px] flex-shrink-0 items-center justify-center gap-2 rounded-md bg-black px-4 py-2 text-white',
'flex min-w-[127px] flex-shrink-0 items-center justify-center gap-2 rounded-md bg-black px-4 py-2.5 text-white',
'disabled:cursor-not-allowed disabled:opacity-50',
)}
onClick={(e) => {
@@ -591,15 +606,7 @@ export function GenerateRoadmap(props: GenerateRoadmapProps) {
showLoginPopup();
}
}}
disabled={
isLoadingResults ||
(isAuthenticatedUser &&
(!roadmapLimit ||
!roadmapTerm ||
roadmapLimitUsed >= roadmapLimit ||
roadmapTerm === currentRoadmap?.term ||
isKeyOnly))
}
disabled={isGenerateButtonDisabled}
>
{isLoadingResults && (
<>

View File

@@ -5,7 +5,8 @@ import { isLoggedIn } from '../../lib/jwt';
import { showLoginPopup } from '../../lib/popup';
import { cn } from '../../lib/classname.ts';
import { AITermSuggestionInput } from './AITermSuggestionInput.tsx';
import { IncreaseRoadmapLimit } from './IncreaseRoadmapLimit.tsx';
import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal.tsx';
import { useIsPaidUser } from '../../queries/billing.ts';
type RoadmapSearchProps = {
roadmapTerm: string;
@@ -30,6 +31,7 @@ export function RoadmapSearch(props: RoadmapSearchProps) {
isKeyOnly,
} = props;
const { isPaidUser, isLoading } = useIsPaidUser();
const canGenerateMore = limitUsed < limit;
const [isConfiguring, setIsConfiguring] = useState(false);
const [isAuthenticatedUser, setIsAuthenticatedUser] = useState(false);
@@ -44,7 +46,7 @@ export function RoadmapSearch(props: RoadmapSearchProps) {
return (
<div className="flex flex-grow flex-col items-center px-4 py-6 sm:px-6 md:my-24 lg:my-32">
{isConfiguring && (
<IncreaseRoadmapLimit
<UpgradeAccountModal
onClose={() => {
setIsConfiguring(false);
loadAIRoadmapLimit();
@@ -193,7 +195,7 @@ export function RoadmapSearch(props: RoadmapSearchProps) {
</p>
</div>
)}
{isKeyOnly && isAuthenticatedUser && (
{isKeyOnly && isAuthenticatedUser && !isPaidUser && (
<div className="mx-auto mt-12 flex max-w-[450px] flex-col items-center gap-4">
<p className={'text-center text-red-500'}>
We have hit the limit for AI roadmap generation. Please try again
@@ -222,7 +224,7 @@ export function RoadmapSearch(props: RoadmapSearchProps) {
</p>
</div>
)}
{!isKeyOnly && limit > 0 && isAuthenticatedUser && (
{!isKeyOnly && limit > 0 && isAuthenticatedUser && !isPaidUser && (
<div className="mt-12 flex flex-col items-center gap-4">
<p className="text-center text-gray-500">
You have generated{' '}
@@ -235,17 +237,15 @@ export function RoadmapSearch(props: RoadmapSearchProps) {
</span>{' '}
roadmaps today.
</p>
{isAuthenticatedUser && (
<p className="flex items-center text-sm">
<button
onClick={() => setIsConfiguring(true)}
className="rounded-xl border border-current px-2 py-0.5 text-sm text-blue-500 transition-colors hover:bg-blue-400 hover:text-white"
>
Need to generate more?{' '}
<span className="font-semibold">Click here.</span>
</button>
</p>
)}
<p className="flex items-center text-sm">
<button
onClick={() => setIsConfiguring(true)}
className="rounded-xl border border-current px-2 py-0.5 text-sm text-blue-500 transition-colors hover:bg-blue-400 hover:text-white"
>
Need to generate more?{' '}
<span className="font-semibold">Click here.</span>
</button>
</p>
</div>
)}
</div>

View File

@@ -2,6 +2,7 @@
import { aiRoadmapApi } from '../../api/ai-roadmap';
import BaseLayout from '../../layouts/BaseLayout.astro';
import { GenerateRoadmap } from '../../components/GenerateRoadmap/GenerateRoadmap';
import { CheckSubscriptionVerification } from '../../components/Billing/CheckSubscriptionVerification';
export const prerender = false;
@@ -31,4 +32,5 @@ const title = roadmap?.title || 'Roadmap AI';
isAuthenticatedUser={roadmap?.isAuthenticatedUser}
client:load
/>
<CheckSubscriptionVerification client:load />
</BaseLayout>

View File

@@ -1,8 +1,10 @@
---
import { GenerateRoadmap } from '../../components/GenerateRoadmap/GenerateRoadmap';
import BaseLayout from '../../layouts/BaseLayout.astro';
import { CheckSubscriptionVerification } from '../../components/Billing/CheckSubscriptionVerification';
---
<BaseLayout title='Roadmap AI' permalink="/ai">
<BaseLayout title='Roadmap AI' permalink='/ai'>
<GenerateRoadmap client:load />
<CheckSubscriptionVerification client:load />
</BaseLayout>