Skip to content

Commit 369bfb5

Browse files
committed
demo auth redirect issue fixed and limit API generation daily
1 parent 8619f91 commit 369bfb5

File tree

5 files changed

+64
-11
lines changed

5 files changed

+64
-11
lines changed
836 KB
Loading

src/app/(dashboard)/api-doc-generator/generate/page.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useState, ChangeEvent, FormEvent, useEffect } from 'react';
44
import { useRouter } from 'next/navigation';
55
import Link from 'next/link';
66
import { generateDocumentation, AVAILABLE_MODELS } from '@/lib/openrouter';
7-
import { createProject, saveMdxFiles, updateProjectStatus, saveAiJob, updateAiJob } from '@/lib/docService';
7+
import { createProject, saveMdxFiles, updateProjectStatus, saveAiJob, updateAiJob, getUserDailyAiJobCount } from '@/lib/docService';
88
import { getUser } from '@/lib/supabase';
99
import FileUploader from '@/components/api-doc-generator/FileUploader';
1010

@@ -27,19 +27,23 @@ export default function GenerateDocumentationPage() {
2727
const [isLoading, setIsLoading] = useState(false);
2828
const [error, setError] = useState<string | null>(null);
2929
const [userId, setUserId] = useState<string | null>(null);
30+
const [aiJobCount, setAiJobCount] = useState<number>(0);
31+
const AI_JOB_DAILY_LIMIT = 7;
3032

31-
// Get the current user
33+
// Get the current user and AI job count
3234
useEffect(() => {
33-
async function fetchUser() {
35+
async function fetchUserAndJobCount() {
3436
const user = await getUser();
3537
if (user) {
3638
setUserId(user.id);
39+
const count = await getUserDailyAiJobCount(user.id);
40+
setAiJobCount(count);
3741
} else {
3842
// Redirect to login if user is not authenticated
3943
router.push('/login');
4044
}
4145
}
42-
fetchUser();
46+
fetchUserAndJobCount();
4347
}, [router]);
4448

4549
/**
@@ -96,6 +100,11 @@ export default function GenerateDocumentationPage() {
96100
setError('You must be logged in to generate documentation');
97101
return;
98102
}
103+
104+
if (aiJobCount >= AI_JOB_DAILY_LIMIT) {
105+
setError(`You have reached the limit of ${AI_JOB_DAILY_LIMIT} AI generations per day. Please try again tomorrow.`);
106+
return;
107+
}
99108

100109
setIsLoading(true);
101110
setError(null);
@@ -186,6 +195,9 @@ export default function GenerateDocumentationPage() {
186195
sessionStorage.setItem('generatedDocs', JSON.stringify(formattedFiles));
187196
console.log('💾 Saved formatted docs to sessionStorage');
188197

198+
// Update the AI job count after successful generation
199+
setAiJobCount(prevCount => prevCount + 1);
200+
189201
// Navigate directly to the editor instead of preview
190202
router.push('/editor');
191203
} catch (err) {
@@ -500,9 +512,9 @@ export default function GenerateDocumentationPage() {
500512
<div className="flex justify-end">
501513
<button
502514
type="submit"
503-
disabled={isLoading || !apiSpec.trim() || !userId}
515+
disabled={isLoading || !apiSpec.trim() || !userId || aiJobCount >= AI_JOB_DAILY_LIMIT}
504516
className={`inline-flex items-center justify-center px-8 py-3 text-base font-medium rounded-lg transition-all duration-200 ${
505-
isLoading || !apiSpec.trim() || !userId
517+
isLoading || !apiSpec.trim() || !userId || aiJobCount >= AI_JOB_DAILY_LIMIT
506518
? 'cursor-not-allowed bg-muted text-muted-foreground'
507519
: 'bg-primary text-primary-foreground hover:bg-primary/90 shadow-lg shadow-primary/20 hover:shadow-xl hover:shadow-primary/30'
508520
}`}
@@ -533,7 +545,12 @@ export default function GenerateDocumentationPage() {
533545
</>
534546
) : (
535547
<>
536-
<span>Generate Documentation</span>
548+
<span>
549+
{aiJobCount >= AI_JOB_DAILY_LIMIT
550+
? `Daily Limit Reached (${aiJobCount}/${AI_JOB_DAILY_LIMIT})`
551+
: `Generate Documentation (${aiJobCount}/${AI_JOB_DAILY_LIMIT})`
552+
}
553+
</span>
537554
<svg
538555
className="w-5 h-5 ml-2"
539556
fill="none"

src/app/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export const metadata: Metadata = {
2828
"One-click API documentation generator with AI enhancement and custom domain support",
2929
images: [
3030
{
31-
url: "/og-image.png",
31+
url: "/images/create-beautiful-api.png",
3232
width: 1200,
3333
height: 630,
3434
alt: "Clario API Documentation Generator",
@@ -40,7 +40,7 @@ export const metadata: Metadata = {
4040
title: "Clario | API Documentation Generator",
4141
description:
4242
"Transform your API spec into a clean, branded, shareable documentation site instantly",
43-
images: ["/og-image.png"],
43+
images: ["/images/create-beautiful-api.png"],
4444
},
4545
icons: {
4646
icon: ["/favicon_io/favicon.ico?v=4"],

src/lib/docService.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,4 +572,37 @@ export async function updateMdxFileOrder(
572572
console.error('Error updating MDX file order:', error);
573573
return false;
574574
}
575+
}
576+
577+
/**
578+
* Gets the count of AI jobs created by a user in the last 24 hours
579+
*
580+
* @param userId - User ID
581+
* @returns Number of AI jobs created today
582+
*/
583+
export async function getUserDailyAiJobCount(userId: string): Promise<number> {
584+
const oneDayAgo = new Date();
585+
oneDayAgo.setDate(oneDayAgo.getDate() - 1);
586+
587+
// First get the user's project IDs
588+
const { data: projectIds } = await supabase
589+
.from('projects')
590+
.select('id')
591+
.eq('user_id', userId);
592+
593+
if (!projectIds) return 0;
594+
595+
// Then count AI jobs for these projects
596+
const { count, error } = await supabase
597+
.from('ai_jobs')
598+
.select('*', { count: 'exact', head: true })
599+
.in('project_id', projectIds.map(p => p.id))
600+
.gte('started_at', oneDayAgo.toISOString());
601+
602+
if (error) {
603+
console.error('Error getting AI job count:', error);
604+
return 0;
605+
}
606+
607+
return count || 0;
575608
}

src/provider/auth.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,12 @@ export function AuthProvider({ children }: { children: ReactNode }) {
150150
// Create demo user in public table if needed
151151
if (data.user) {
152152
await ensureUserInPublicTable(data.user as UserData);
153+
// Set the user state immediately after successful login
154+
setUser(data.user as UserData);
155+
// Wait a brief moment to ensure auth state is properly updated
156+
await new Promise(resolve => setTimeout(resolve, 100));
157+
router.push('/dashboard');
153158
}
154-
155-
router.push('/dashboard');
156159
} catch (error) {
157160
console.error("Error signing in with demo account:", error);
158161
toast.error("Failed to sign in with demo account");

0 commit comments

Comments
 (0)