'use client'; import React, { useState, useEffect } from 'react'; import Link from 'next/link'; 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 { useCsrf } from '@/hooks/useCsrf'; import { showToast } from '@/components/ui/Toast'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/Dialog'; interface QRCodeData { id: string; title: string; type: 'STATIC' | 'DYNAMIC'; contentType: string; content?: any; slug: string; createdAt: string; scans: number; style?: any; status?: 'ACTIVE' | 'INACTIVE'; } export default function DashboardPage() { const { t } = useTranslation(); const router = useRouter(); const searchParams = useSearchParams(); const { fetchWithCsrf } = useCsrf(); const [qrCodes, setQrCodes] = useState([]); const [loading, setLoading] = useState(true); const [userPlan, setUserPlan] = useState('FREE'); const [showUpgradeDialog, setShowUpgradeDialog] = useState(false); const [upgradedPlan, setUpgradedPlan] = useState(''); const [deletingAll, setDeletingAll] = useState(false); const [stats, setStats] = useState({ totalScans: 0, activeQRCodes: 0, conversionRate: 0, uniqueScans: 0, }); const [analyticsData, setAnalyticsData] = useState(null); const mockQRCodes = [ { id: '1', title: 'Support Phone', type: 'DYNAMIC' as const, contentType: 'PHONE', slug: 'support-phone-demo', status: 'ACTIVE' as const, createdAt: '2025-08-07T10:00:00Z', scans: 0, }, { id: '2', title: 'Event Details', type: 'DYNAMIC' as const, contentType: 'URL', slug: 'event-details-demo', status: 'ACTIVE' as const, createdAt: '2025-08-07T10:01:00Z', scans: 0, }, { id: '3', title: 'Product Demo', type: 'DYNAMIC' as const, contentType: 'URL', slug: 'product-demo-qr', status: 'ACTIVE' as const, createdAt: '2025-08-07T10:02:00Z', scans: 0, }, { id: '4', title: 'Company Website', type: 'DYNAMIC' as const, contentType: 'URL', slug: 'company-website-qr', status: 'ACTIVE' as const, createdAt: '2025-08-07T10:03:00Z', scans: 0, }, { id: '5', title: 'Contact Card', type: 'DYNAMIC' as const, contentType: 'VCARD', slug: 'contact-card-qr', status: 'ACTIVE' as const, createdAt: '2025-08-07T10:04:00Z', scans: 0, }, { id: '6', title: 'Event Details', type: 'DYNAMIC' as const, contentType: 'URL', slug: 'event-details-dup', status: 'ACTIVE' as const, createdAt: '2025-08-07T10:05:00Z', scans: 0, }, ]; const blogPosts = [ // NEW POSTS { title: 'How to Create a QR Code for Restaurant Menu', excerpt: 'Step-by-step guide to creating digital menu QR codes for your restaurant. Best practices for touchless menus.', readTime: '12 Min', slug: 'qr-code-restaurant-menu', }, { title: 'Free vCard QR Code Generator: Digital Business Cards', excerpt: 'Create professional vCard QR codes for digital business cards. Share contact info instantly.', readTime: '10 Min', slug: 'vcard-qr-code-generator', }, { title: 'Best QR Code Generator for Small Business', excerpt: 'Find the best QR code solution for your small business. Compare features, pricing, and use cases.', readTime: '14 Min', slug: 'qr-code-small-business', }, { title: 'QR Code Print Size Guide', excerpt: 'Complete guide to QR code print sizes. Minimum dimensions for business cards, posters, and more.', readTime: '8 Min', slug: 'qr-code-print-size-guide', }, // EXISTING POSTS { title: 'QR Code Tracking: Complete Guide 2025', excerpt: 'Learn how to track QR code scans with real-time analytics. Compare free vs paid tracking tools.', readTime: '12 Min', slug: 'qr-code-tracking-guide-2025', }, { title: 'Dynamic vs Static QR Codes: Which Should You Use?', excerpt: 'Understand the difference between static and dynamic QR codes. Pros, cons, and when to use each.', readTime: '10 Min', slug: 'dynamic-vs-static-qr-codes', }, { title: 'How to Generate Bulk QR Codes from Excel', excerpt: 'Generate hundreds of QR codes from Excel or CSV files in minutes. Step-by-step guide.', readTime: '13 Min', slug: 'bulk-qr-code-generator-excel', }, { title: 'QR Code Analytics: Track, Measure & Optimize', excerpt: 'Learn how to leverage scan analytics and dashboard insights to maximize QR code ROI.', readTime: '15 Min', slug: 'qr-code-analytics', }, ]; // Track Google OAuth login/signup useEffect(() => { const authMethod = searchParams.get('authMethod'); const isNewUser = searchParams.get('isNewUser') === 'true'; if (authMethod === 'google') { const trackGoogleAuth = async () => { try { // Fetch user data from API (cookie-based auth) const response = await fetch('/api/user'); if (!response.ok) return; const user = await response.json(); // Store in localStorage for consistency localStorage.setItem('user', JSON.stringify(user)); const { identifyUser, trackEvent } = await import('@/components/PostHogProvider'); identifyUser(user.id, { email: user.email, name: user.name, plan: user.plan || 'FREE', provider: 'google', }); trackEvent(isNewUser ? 'user_signup' : 'user_login', { method: 'google', email: user.email, isNewUser, }); // Clean up URL params router.replace('/dashboard'); } catch (error) { console.error('PostHog tracking error:', error); } }; trackGoogleAuth(); } }, [searchParams, router]); // 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 () => { try { // Fetch QR codes const qrResponse = await fetch('/api/qrs'); if (qrResponse.ok) { const data = await qrResponse.json(); setQrCodes(data); // Calculate real stats const totalScans = data.reduce((sum: number, qr: QRCodeData) => sum + (qr.scans || 0), 0); const activeQRCodes = data.filter((qr: QRCodeData) => qr.status === 'ACTIVE').length; // Calculate unique scans (absolute count) const uniqueScans = data.reduce((acc: number, qr: any) => acc + (qr.uniqueScans || 0), 0); const conversionRate = totalScans > 0 ? Math.round((uniqueScans / totalScans) * 100) : 0; setStats({ totalScans, activeQRCodes, conversionRate, uniqueScans, }); } else { // If not logged in, show zeros setQrCodes([]); setStats({ totalScans: 0, activeQRCodes: 0, conversionRate: 0, uniqueScans: 0, }); } // 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'); } // Fetch analytics data for trends (last 30 days = month comparison) const analyticsResponse = await fetch('/api/analytics/summary?range=30'); if (analyticsResponse.ok) { const analytics = await analyticsResponse.json(); setAnalyticsData(analytics); } } catch (error) { console.error('Error fetching data:', error); setQrCodes([]); setStats({ totalScans: 0, activeQRCodes: 0, conversionRate: 0, uniqueScans: 0, }); } finally { setLoading(false); } }; fetchData(); }, []); const handleEdit = (id: string) => { // Redirect to edit page router.push(`/qr/${id}/edit`); }; const handleDelete = async (id: string) => { if (!confirm('Are you sure you want to delete this QR code? This action cannot be undone.')) { return; } try { const response = await fetchWithCsrf(`/api/qrs/${id}`, { method: 'DELETE', }); if (response.ok) { // Remove from local state setQrCodes(qrCodes.filter(q => q.id !== id)); showToast('QR code deleted successfully!', 'success'); } else { throw new Error('Failed to delete'); } } catch (error) { console.error('Error deleting QR:', error); showToast('Failed to delete QR code', 'error'); } }; const handleDeleteAll = async () => { if (!confirm('Are you sure you want to delete ALL QR codes? This action cannot be undone.')) { return; } // Double confirmation if (!confirm('This will permanently delete ALL your QR codes. Are you absolutely sure?')) { return; } setDeletingAll(true); try { const response = await fetchWithCsrf('/api/qrs/delete-all', { method: 'DELETE', }); if (response.ok) { const data = await response.json(); setQrCodes([]); setStats({ totalScans: 0, activeQRCodes: 0, conversionRate: 0, uniqueScans: 0, }); showToast(`Successfully deleted ${data.deletedCount} QR code${data.deletedCount !== 1 ? 's' : ''}`, 'success'); } else { throw new Error('Failed to delete all QR codes'); } } catch (error) { console.error('Error deleting all QR codes:', error); showToast('Failed to delete QR codes', 'error'); } finally { setDeletingAll(false); } }; const getPlanBadgeColor = (plan: string) => { switch (plan) { case 'PRO': return 'info'; case 'BUSINESS': return 'warning'; default: return 'default'; } }; const getPlanEmoji = (plan: string) => { // No emojis anymore return ''; }; return (
{/* Header with Plan Badge */}

{t('dashboard.title')}

{t('dashboard.subtitle')}

{userPlan} Plan {userPlan === 'FREE' && ( )}
{/* Stats Grid */} {/* Recent QR Codes */}

{t('dashboard.recent_codes')}

{qrCodes.length > 0 && ( )}
{loading ? (
{[1, 2, 3, 4, 5, 6].map((i) => (
))}
) : (
{qrCodes.map((qr) => ( ))}
)}
{/* Blog & Resources - Horizontal Scroll */}

{t('dashboard.blog_resources')}

{blogPosts.map((post) => (
{post.readTime}
{post.title}

{post.excerpt}

Read more →
))}
{/* Upgrade Success Dialog */} Upgrade Successful! Welcome to the {upgradedPlan} Plan! Your account has been successfully upgraded.

Your New Features:

    {upgradedPlan === 'PRO' && ( <>
  • 50 Dynamic QR Codes
  • Custom Branding (Colors & Logo)
  • Detailed Analytics (Devices, Locations, Time-Series)
  • CSV Export
  • SVG/PNG Download
  • )} {upgradedPlan === 'BUSINESS' && ( <>
  • 500 Dynamic QR Codes
  • Everything from Pro
  • Bulk QR Generation (up to 1,000)
  • Priority Support
  • )}
); }