feat: remove ai roadmap limit for pro user (#8442)

pull/8456/head
Arik Chakma 3 weeks ago committed by GitHub
parent 7a988cbbea
commit f798035f0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 37
      src/components/GenerateRoadmap/GenerateRoadmap.tsx
  2. 30
      src/components/GenerateRoadmap/RoadmapSearch.tsx
  3. 2
      src/pages/ai/[aiRoadmapSlug].astro
  4. 4
      src/pages/ai/index.astro

@ -35,8 +35,9 @@ import {
readAIRoadmapStream, readAIRoadmapStream,
} from '../../lib/ai.ts'; } from '../../lib/ai.ts';
import { AITermSuggestionInput } from './AITermSuggestionInput.tsx'; import { AITermSuggestionInput } from './AITermSuggestionInput.tsx';
import { IncreaseRoadmapLimit } from './IncreaseRoadmapLimit.tsx';
import { AuthenticationForm } from '../AuthenticationFlow/AuthenticationForm.tsx'; import { AuthenticationForm } from '../AuthenticationFlow/AuthenticationForm.tsx';
import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal.tsx';
import { useIsPaidUser } from '../../queries/billing.ts';
export type GetAIRoadmapLimitResponse = { export type GetAIRoadmapLimitResponse = {
used: number; used: number;
@ -101,6 +102,7 @@ export function GenerateRoadmap(props: GenerateRoadmapProps) {
const roadmapContainerRef = useRef<HTMLDivElement>(null); const roadmapContainerRef = useRef<HTMLDivElement>(null);
const { isPaidUser, isLoading: isLoadingPaidUser } = useIsPaidUser();
const { rc: referralCode } = getUrlParams() as { const { rc: referralCode } = getUrlParams() as {
rc?: string; rc?: string;
}; };
@ -472,12 +474,25 @@ export function GenerateRoadmap(props: GenerateRoadmapProps) {
} }
const pageUrl = `https://roadmap.sh/ai/${roadmapSlug}`; 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 ( return (
<> <>
{isConfiguring && ( {isConfiguring && (
<IncreaseRoadmapLimit <UpgradeAccountModal
onClose={() => { onClose={() => {
setIsConfiguring(false); setIsConfiguring(false);
loadAIRoadmapLimit().finally(() => null); loadAIRoadmapLimit().finally(() => null);
@ -519,7 +534,7 @@ export function GenerateRoadmap(props: GenerateRoadmapProps) {
{!isLoading && ( {!isLoading && (
<div className="container flex flex-grow flex-col items-start"> <div className="container flex flex-grow flex-col items-start">
<AIRoadmapAlert /> <AIRoadmapAlert />
{isKeyOnly && isAuthenticatedUser && ( {isKeyOnly && isAuthenticatedUser && !isPaidUser && (
<div className="flex flex-row gap-4"> <div className="flex flex-row gap-4">
<p className={'text-left text-red-500'}> <p className={'text-left text-red-500'}>
We have hit the limit for AI roadmap generation. Please try We have hit the limit for AI roadmap generation. Please try
@ -533,7 +548,7 @@ export function GenerateRoadmap(props: GenerateRoadmapProps) {
</p> </p>
</div> </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"> <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>
<span <span
@ -582,7 +597,7 @@ export function GenerateRoadmap(props: GenerateRoadmapProps) {
<button <button
type={'submit'} type={'submit'}
className={cn( 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', 'disabled:cursor-not-allowed disabled:opacity-50',
)} )}
onClick={(e) => { onClick={(e) => {
@ -591,15 +606,7 @@ export function GenerateRoadmap(props: GenerateRoadmapProps) {
showLoginPopup(); showLoginPopup();
} }
}} }}
disabled={ disabled={isGenerateButtonDisabled}
isLoadingResults ||
(isAuthenticatedUser &&
(!roadmapLimit ||
!roadmapTerm ||
roadmapLimitUsed >= roadmapLimit ||
roadmapTerm === currentRoadmap?.term ||
isKeyOnly))
}
> >
{isLoadingResults && ( {isLoadingResults && (
<> <>

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

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

@ -1,8 +1,10 @@
--- ---
import { GenerateRoadmap } from '../../components/GenerateRoadmap/GenerateRoadmap'; import { GenerateRoadmap } from '../../components/GenerateRoadmap/GenerateRoadmap';
import BaseLayout from '../../layouts/BaseLayout.astro'; 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 /> <GenerateRoadmap client:load />
<CheckSubscriptionVerification client:load />
</BaseLayout> </BaseLayout>

Loading…
Cancel
Save