'use client'; import React, { useState, useEffect } from 'react'; import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card'; import { Button } from '@/components/ui/Button'; import { Badge } from '@/components/ui/Badge'; import { Input } from '@/components/ui/Input'; import { useCsrf } from '@/hooks/useCsrf'; import { showToast } from '@/components/ui/Toast'; import ChangePasswordModal from '@/components/settings/ChangePasswordModal'; type TabType = 'profile' | 'subscription' | 'whitelabel'; export default function SettingsPage() { const { fetchWithCsrf } = useCsrf(); const [activeTab, setActiveTab] = useState('profile'); const [loading, setLoading] = useState(false); const [showPasswordModal, setShowPasswordModal] = useState(false); // Profile states const [name, setName] = useState(''); const [email, setEmail] = useState(''); // Subscription states const [plan, setPlan] = useState('FREE'); const [usageStats, setUsageStats] = useState({ dynamicUsed: 0, dynamicLimit: 3, staticUsed: 0, }); // White Label Subdomain states const [subdomain, setSubdomain] = useState(''); const [savedSubdomain, setSavedSubdomain] = useState(null); const [subdomainLoading, setSubdomainLoading] = useState(false); // Load user data useEffect(() => { const fetchUserData = async () => { try { // Load from localStorage const userStr = localStorage.getItem('user'); if (userStr) { const user = JSON.parse(userStr); setName(user.name || ''); setEmail(user.email || ''); } // Fetch plan from API const planResponse = await fetch('/api/user/plan'); if (planResponse.ok) { const data = await planResponse.json(); setPlan(data.plan || 'FREE'); } // Fetch usage stats from API const statsResponse = await fetch('/api/user/stats'); if (statsResponse.ok) { const data = await statsResponse.json(); setUsageStats(data); } // Fetch subdomain const subdomainResponse = await fetch('/api/user/subdomain'); if (subdomainResponse.ok) { const data = await subdomainResponse.json(); setSavedSubdomain(data.subdomain); setSubdomain(data.subdomain || ''); } } catch (e) { console.error('Failed to load user data:', e); } }; fetchUserData(); }, []); const handleSaveProfile = async () => { setLoading(true); try { // Save to backend API const response = await fetchWithCsrf('/api/user/profile', { method: 'PATCH', body: JSON.stringify({ name }), }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Failed to update profile'); } // Update user data in localStorage const userStr = localStorage.getItem('user'); if (userStr) { const user = JSON.parse(userStr); user.name = name; localStorage.setItem('user', JSON.stringify(user)); } showToast('Profile updated successfully!', 'success'); } catch (error: any) { console.error('Error saving profile:', error); showToast(error.message || 'Failed to update profile', 'error'); } finally { setLoading(false); } }; const handleManageSubscription = async () => { setLoading(true); try { const response = await fetchWithCsrf('/api/stripe/portal', { method: 'POST', }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Failed to open subscription management'); } // Redirect to Stripe Customer Portal window.location.href = data.url; } catch (error: any) { console.error('Error opening portal:', error); showToast(error.message || 'Failed to open subscription management', 'error'); setLoading(false); } }; const handleDeleteAccount = async () => { const confirmed = window.confirm( 'Are you sure you want to delete your account? This will permanently delete all your data, including all QR codes and analytics. This action cannot be undone.' ); if (!confirmed) return; // Double confirmation for safety const doubleConfirmed = window.confirm( 'This is your last warning. Are you absolutely sure you want to permanently delete your account?' ); if (!doubleConfirmed) return; setLoading(true); try { const response = await fetchWithCsrf('/api/user/delete', { method: 'DELETE', }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Failed to delete account'); } // Clear local storage and redirect to login localStorage.clear(); showToast('Account deleted successfully', 'success'); // Redirect to home page after a short delay setTimeout(() => { window.location.href = '/'; }, 1500); } catch (error: any) { console.error('Error deleting account:', error); showToast(error.message || 'Failed to delete account', 'error'); setLoading(false); } }; const getPlanLimits = () => { switch (plan) { case 'PRO': return { dynamic: 50, price: '€9', period: 'per month' }; case 'BUSINESS': return { dynamic: 500, price: '€29', period: 'per month' }; default: return { dynamic: 3, price: '€0', period: 'forever' }; } }; const planLimits = getPlanLimits(); const usagePercentage = (usageStats.dynamicUsed / usageStats.dynamicLimit) * 100; return (

Settings

Manage your account settings and preferences

{/* Tabs */}
{/* Tab Content */} {activeTab === 'profile' && (
{/* Profile Information */} Profile Information
setName(e.target.value)} className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500" placeholder="Enter your name" />

Email cannot be changed

{/* Security */} Security

Password

Update your password to keep your account secure

{/* Account Deletion */} Delete Account

Delete your account

Permanently delete your account and all data. This action cannot be undone.

{/* Save Button */}
)} {activeTab === 'subscription' && (
{/* Current Plan */}
Current Plan {plan}
{planLimits.price} {planLimits.period}
Dynamic QR Codes {usageStats.dynamicUsed} of {usageStats.dynamicLimit} used
Static QR Codes Unlimited ∞
{plan !== 'FREE' && (
)} {plan === 'FREE' && (
)}
)} {activeTab === 'whitelabel' && (
{/* White Label Subdomain */}
White Label Subdomain FREE

Create your own branded QR code URL. Your QR codes will be accessible via your custom subdomain.

setSubdomain(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, ''))} placeholder="your-brand" className="flex-1 max-w-xs" /> .qrmaster.net
  • 3-30 characters
  • Only lowercase letters, numbers, and hyphens
  • Cannot start or end with a hyphen
{savedSubdomain && (

✅ Your white label URL is active:

https://{savedSubdomain}.qrmaster.net
)}
{savedSubdomain && ( )}
{/* How it works */} {savedSubdomain && ( How it works

Before (default)

qrmaster.net/r/your-qr

After (your brand)

{savedSubdomain}.qrmaster.net/r/your-qr

All your QR codes will work with both URLs. Share the branded version with your clients!

)}
)} {/* Change Password Modal */} setShowPasswordModal(false)} onSuccess={() => { setShowPasswordModal(false); }} />
); }