This commit is contained in:
Timo Knuth
2025-10-15 00:03:05 +02:00
parent bccf771ffc
commit cd3ee5fc8f
15 changed files with 1096 additions and 186 deletions

View File

@@ -2,13 +2,15 @@
import React, { useState, useEffect } from 'react';
import Link from 'next/link';
import { useSession } from 'next-auth/react';
import { useRouter, useSearchParams } from 'next/navigation';
import { StatsGrid } from '@/components/dashboard/StatsGrid';
import { QRCodeCard } from '@/components/dashboard/QRCodeCard';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card';
import { Button } from '@/components/ui/Button';
import { Badge } from '@/components/ui/Badge';
import { useTranslation } from '@/hooks/useTranslation';
import { showToast } from '@/components/ui/Toast';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/Dialog';
interface QRCodeData {
id: string;
@@ -24,10 +26,13 @@ interface QRCodeData {
export default function DashboardPage() {
const { t } = useTranslation();
const { data: session } = useSession();
const router = useRouter();
const searchParams = useSearchParams();
const [qrCodes, setQrCodes] = useState<QRCodeData[]>([]);
const [loading, setLoading] = useState(true);
const [userPlan, setUserPlan] = useState<string>('FREE');
const [showUpgradeDialog, setShowUpgradeDialog] = useState(false);
const [upgradedPlan, setUpgradedPlan] = useState<string>('');
const [stats, setStats] = useState({
totalScans: 0,
activeQRCodes: 0,
@@ -118,6 +123,35 @@ export default function DashboardPage() {
},
];
// Check for successful payment and verify session
useEffect(() => {
const success = searchParams.get('success');
if (success === 'true') {
const verifySession = async () => {
try {
const response = await fetch('/api/stripe/verify-session', {
method: 'POST',
});
if (response.ok) {
const data = await response.json();
setUserPlan(data.plan);
setUpgradedPlan(data.plan);
setShowUpgradeDialog(true);
// Remove success parameter from URL
router.replace('/dashboard');
} else {
console.error('Failed to verify session:', await response.text());
}
} catch (error) {
console.error('Error verifying session:', error);
}
};
verifySession();
}
}, [searchParams, router]);
useEffect(() => {
// Load real QR codes and user plan from API
const fetchData = async () => {
@@ -148,13 +182,11 @@ export default function DashboardPage() {
});
}
// Fetch user plan
if (session?.user?.email) {
const userResponse = await fetch('/api/user/plan');
if (userResponse.ok) {
const userData = await userResponse.json();
setUserPlan(userData.plan || 'FREE');
}
// Fetch user plan (using cookie-based auth, no session needed)
const userResponse = await fetch('/api/user/plan');
if (userResponse.ok) {
const userData = await userResponse.json();
setUserPlan(userData.plan || 'FREE');
}
} catch (error) {
console.error('Error fetching data:', error);
@@ -170,7 +202,7 @@ export default function DashboardPage() {
};
fetchData();
}, [session]);
}, []);
const handleEdit = (id: string) => {
console.log('Edit QR:', id);
@@ -200,16 +232,8 @@ export default function DashboardPage() {
};
const getPlanEmoji = (plan: string) => {
switch (plan) {
case 'FREE':
return '🟢';
case 'PRO':
return '🔵';
case 'BUSINESS':
return '🟣';
default:
return '⚪';
}
// No emojis anymore
return '';
};
return (
@@ -222,7 +246,7 @@ export default function DashboardPage() {
</div>
<div className="flex items-center space-x-3">
<Badge variant={getPlanBadgeColor(userPlan)} className="text-lg px-4 py-2">
{getPlanEmoji(userPlan)} {userPlan} Plan
{userPlan} Plan
</Badge>
{userPlan === 'FREE' && (
<Link href="/pricing">
@@ -302,6 +326,89 @@ export default function DashboardPage() {
))}
</div>
</div>
{/* Upgrade Success Dialog */}
<Dialog open={showUpgradeDialog} onOpenChange={setShowUpgradeDialog}>
<DialogContent>
<DialogHeader>
<DialogTitle className="text-2xl text-center">
Upgrade erfolgreich!
</DialogTitle>
<DialogDescription className="text-center text-base pt-4">
Willkommen im <strong>{upgradedPlan} Plan</strong>! Ihr Konto wurde erfolgreich aktualisiert.
</DialogDescription>
</DialogHeader>
<div className="py-6 space-y-4">
<div className="bg-gradient-to-r from-blue-50 to-indigo-50 p-6 rounded-lg border border-blue-200">
<h3 className="font-semibold text-gray-900 mb-3">Ihre neuen Features:</h3>
<ul className="space-y-2 text-sm text-gray-700">
{upgradedPlan === 'PRO' && (
<>
<li className="flex items-start">
<span className="text-green-600 mr-2"></span>
<span>50 dynamische QR-Codes</span>
</li>
<li className="flex items-start">
<span className="text-green-600 mr-2"></span>
<span>Branding (Logo, Farben anpassen)</span>
</li>
<li className="flex items-start">
<span className="text-green-600 mr-2"></span>
<span>Detaillierte Analytics</span>
</li>
<li className="flex items-start">
<span className="text-green-600 mr-2"></span>
<span>CSV-Export</span>
</li>
<li className="flex items-start">
<span className="text-green-600 mr-2"></span>
<span>Passwortschutz für QR-Codes</span>
</li>
</>
)}
{upgradedPlan === 'BUSINESS' && (
<>
<li className="flex items-start">
<span className="text-green-600 mr-2"></span>
<span>500 dynamische QR-Codes</span>
</li>
<li className="flex items-start">
<span className="text-green-600 mr-2"></span>
<span>Team-Zugänge (bis zu 3 User)</span>
</li>
<li className="flex items-start">
<span className="text-green-600 mr-2"></span>
<span>Benutzerdefinierte Domains</span>
</li>
<li className="flex items-start">
<span className="text-green-600 mr-2"></span>
<span>White-Label</span>
</li>
<li className="flex items-start">
<span className="text-green-600 mr-2"></span>
<span>Prioritäts-Support</span>
</li>
</>
)}
</ul>
</div>
</div>
<DialogFooter>
<Button
variant="primary"
onClick={() => {
setShowUpgradeDialog(false);
router.push('/create');
}}
className="w-full"
>
Ersten QR-Code erstellen
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
);
}