ajout plan byok, plus correction d'affichage et navigation

This commit is contained in:
2026-03-05 14:04:07 +01:00
parent d004281e05
commit d8ffc61b17
13 changed files with 336 additions and 45 deletions

View File

@@ -54,6 +54,8 @@ export async function GET() {
dailyWordGoal: user.dailyWordGoal,
writingStreak: user.writingStreak,
lastWriteDate: user.lastWriteDate,
customApiProvider: user.customApiProvider,
customApiKey: user.customApiKey,
createdAt: user.createdAt,
totalWords,
});
@@ -78,6 +80,12 @@ export async function PUT(request: NextRequest) {
if (body.dailyWordGoal !== undefined) data.dailyWordGoal = body.dailyWordGoal;
if (body.writingStreak !== undefined) data.writingStreak = body.writingStreak;
if (body.lastWriteDate !== undefined) data.lastWriteDate = body.lastWriteDate ? new Date(body.lastWriteDate) : null;
if (body.customApiProvider !== undefined) data.customApiProvider = body.customApiProvider;
if (body.customApiKey !== undefined) data.customApiKey = body.customApiKey;
if (body.planId !== undefined) {
data.planId = body.planId;
data.plan = body.planId; // legacy sync
}
const updated = await prisma.user.update({
where: { id: session.user.id },

View File

@@ -1,15 +1,67 @@
'use client';
import Checkout from '@/components/Checkout';
import { useRouter } from 'next/navigation';
import { useRouter, useSearchParams } from 'next/navigation';
import { useEffect, useState, Suspense } from 'react';
export default function CheckoutPage() {
function CheckoutContent() {
const router = useRouter();
const searchParams = useSearchParams();
const planId = searchParams.get('plan') || 'pro';
const [plan, setPlan] = useState<{ id: string, displayName: string, price: number } | null>(null);
useEffect(() => {
fetch('/api/plans', { cache: 'no-store' })
.then(res => res.json())
.then(data => {
const found = data.find((p: any) => p.id === planId);
if (found) {
setPlan(found);
} else {
setPlan(data.find((p: any) => p.id === 'pro') || { id: 'pro', displayName: 'Auteur Pro', price: 12.00 });
}
})
.catch(err => {
console.error(err);
setPlan({ id: 'pro', displayName: 'Auteur Pro', price: 12.00 });
});
}, [planId]);
const handleComplete = async () => {
if (plan) {
try {
await fetch('/api/user/profile', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ planId: plan.id })
});
// Force a full reload to update user context in providers
window.location.href = '/dashboard';
} catch (err) {
console.error('Failed to update plan', err);
router.push('/dashboard');
}
} else {
router.push('/dashboard');
}
};
if (!plan) return <div className="min-h-screen bg-[#eef2ff] flex items-center justify-center p-8">Chargement...</div>;
return (
<Checkout
onComplete={() => router.push('/dashboard')}
plan={plan}
onComplete={handleComplete}
onCancel={() => router.push('/pricing')}
/>
);
}
export default function CheckoutPage() {
return (
<Suspense fallback={<div className="min-h-screen bg-[#eef2ff] flex items-center justify-center p-8">Chargement...</div>}>
<CheckoutContent />
</Suspense>
);
}

View File

@@ -31,7 +31,7 @@ export default function PricingPage() {
isLoading={isLoading}
currentPlan={user?.subscription.plan || 'free'}
onBack={() => router.push(user ? '/dashboard' : '/')}
onSelectPlan={() => router.push(user ? '/checkout' : '/login')}
onSelectPlan={(id) => router.push(user ? `/checkout?plan=${id}` : '/login')}
/>
);
}