'use client' import { useState } from 'react' import { useForm } from 'react-hook-form' import { zodResolver } from '@hookform/resolvers/zod' import { z } from 'zod' import { useAuth } from '@/contexts/AuthContext' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Badge } from '@/components/ui/badge' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { BalanceDisplay, TransactionHistory } from '@/components/balance' import { Separator } from '@/components/ui/separator' import { AlertCircle, Save, Plus, Wallet, CreditCard, Download, Eye, Server, FileText, Activity, X, Settings, Database, Cloud, Lock, LogIn, User, } from 'lucide-react' import { useProfileData } from '@/hooks/useProfileData' import { Skeleton } from '@/components/ui/skeleton' import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from '@/components/ui/dialog' const ProfileUpdateSchema = z.object({ name: z.string().min(1, 'Name is required'), email: z.string().email('Invalid email format'), phone: z.string().optional(), }) const PasswordChangeSchema = z .object({ currentPassword: z.string().min(1, 'Current password is required'), newPassword: z.string().min(6, 'Password must be at least 6 characters'), confirmPassword: z.string().min(6, 'Password confirmation is required'), }) .refine((data) => data.newPassword === data.confirmPassword, { message: "Passwords don't match", path: ['confirmPassword'], }) type ProfileUpdateData = z.infer type PasswordChangeData = z.infer interface ProfileSettingsProps { activeTab?: string onTabChange?: (tab: string) => void } export function ProfileSettings({ activeTab = 'profile', onTabChange }: ProfileSettingsProps) { const { user, logout } = useAuth() const { profileStats, isLoading } = useProfileData() const [isUpdating, setIsUpdating] = useState(false) const [isChangingPassword, setIsChangingPassword] = useState(false) const [updateMessage, setUpdateMessage] = useState<{ type: 'success' | 'error' text: string } | null>(null) const [passwordMessage, setPasswordMessage] = useState<{ type: 'success' | 'error' text: string } | null>(null) // Add Balance Modal State const [isBalanceModalOpen, setIsBalanceModalOpen] = useState(false) const [selectedCurrency, setSelectedCurrency] = useState<'INR' | 'USD'>('INR') const [selectedAmount, setSelectedAmount] = useState(null) const [customAmount, setCustomAmount] = useState('') const [balanceError, setBalanceError] = useState('') const [isProcessingPayment, setIsProcessingPayment] = useState(false) // Billing Details Modal State const [isBillingModalOpen, setIsBillingModalOpen] = useState(false) const [selectedBilling, setSelectedBilling] = useState(null) const profileForm = useForm({ resolver: zodResolver(ProfileUpdateSchema), defaultValues: { name: user?.name || '', email: user?.email || '', phone: '', }, }) const passwordForm = useForm({ resolver: zodResolver(PasswordChangeSchema), }) const onProfileSubmit = async (data: ProfileUpdateData) => { try { setIsUpdating(true) setUpdateMessage(null) const response = await fetch('/api/user/profile', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }) const result = await response.json() if (result.success) { setUpdateMessage({ type: 'success', text: 'Profile updated successfully!' }) // Refresh user data window.location.reload() } else { setUpdateMessage({ type: 'error', text: result.error?.message || 'Failed to update profile', }) } } catch (error) { setUpdateMessage({ type: 'error', text: 'An error occurred while updating your profile' }) } finally { setIsUpdating(false) } } const onPasswordSubmit = async (data: PasswordChangeData) => { try { setIsChangingPassword(true) setPasswordMessage(null) const response = await fetch('/api/user/change-password', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ currentPassword: data.currentPassword, newPassword: data.newPassword, }), }) const result = await response.json() if (result.success) { setPasswordMessage({ type: 'success', text: 'Password changed successfully!' }) passwordForm.reset() } else { setPasswordMessage({ type: 'error', text: result.error?.message || 'Failed to change password', }) } } catch (error) { setPasswordMessage({ type: 'error', text: 'An error occurred while changing your password' }) } finally { setIsChangingPassword(false) } } const handleDeleteAccount = async () => { if ( window.confirm('Are you sure you want to delete your account? This action cannot be undone.') ) { try { const response = await fetch('/api/user/delete', { method: 'DELETE', }) if (response.ok) { await logout() } else { alert('Failed to delete account. Please try again.') } } catch (error) { alert('An error occurred while deleting your account.') } } } // Add Balance Modal Functions const amountOptions = { INR: [100, 500, 1000, 2000, 5000, 10000], USD: [2, 10, 20, 50, 100, 200], } const handleOpenBalanceModal = () => { setIsBalanceModalOpen(true) setSelectedAmount(null) setCustomAmount('') setBalanceError('') } const handleCloseBalanceModal = () => { setIsBalanceModalOpen(false) setSelectedAmount(null) setCustomAmount('') setBalanceError('') } const handleCurrencyChange = (currency: 'INR' | 'USD') => { setSelectedCurrency(currency) setSelectedAmount(null) setCustomAmount('') setBalanceError('') } const handleAmountSelect = (amount: number) => { setSelectedAmount(amount) setCustomAmount(amount.toString()) setBalanceError('') } const handleCustomAmountChange = (value: string) => { // Only allow numbers const cleanValue = value.replace(/[^0-9]/g, '') setCustomAmount(cleanValue) setSelectedAmount(null) setBalanceError('') } const validateAmount = () => { if (!customAmount) { setBalanceError('Please enter an amount') return false } const amount = parseFloat(customAmount) if (isNaN(amount) || amount <= 0) { setBalanceError('Please enter a valid amount') return false } // Validate amount limits (matching API validation) const minAmount = selectedCurrency === 'INR' ? 100 : 2 const maxAmount = selectedCurrency === 'INR' ? 100000 : 1500 if (amount < minAmount) { setBalanceError(`Minimum amount is ${selectedCurrency === 'INR' ? '₹' : '$'}${minAmount}`) return false } if (amount > maxAmount) { setBalanceError(`Maximum amount is ${selectedCurrency === 'INR' ? '₹' : '$'}${maxAmount}`) return false } setBalanceError('') return true } const handleSubmitBalance = async () => { if (!validateAmount()) return setIsProcessingPayment(true) try { const amount = parseFloat(customAmount) // Call Add Balance API const response = await fetch('/api/balance/add', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ amount, currency: selectedCurrency, }), }) const result = await response.json() if (!response.ok) { throw new Error(result.message || 'Failed to initiate payment') } if (result.success) { // Close modal before redirecting to payment gateway handleCloseBalanceModal() // Create and submit PayU form automatically const form = document.createElement('form') form.method = 'POST' form.action = result.payment_url // Add all PayU form fields Object.entries(result.form_data).forEach(([key, value]) => { const input = document.createElement('input') input.type = 'hidden' input.name = key input.value = value as string form.appendChild(input) }) // Append form to body and submit document.body.appendChild(form) form.submit() // Remove form after submission document.body.removeChild(form) } else { throw new Error(result.message || 'Payment initiation failed') } } catch (error) { console.error('Payment error:', error) const errorMessage = error instanceof Error ? error.message : 'Failed to initiate payment. Please try again.' setBalanceError(errorMessage) } finally { setIsProcessingPayment(false) } } // Billing Details Modal Functions const handleViewBilling = (billing: any) => { setSelectedBilling(billing) setIsBillingModalOpen(true) } const getServiceIcon = (serviceType: string) => { const iconMap: Record = { hosting: Server, kubernetes: Cloud, database: Database, domain: Server, vps: Server, cloud: Cloud, } const IconComponent = iconMap[serviceType.toLowerCase()] || Server return } const getStatusColor = (status: string) => { switch (status.toLowerCase()) { case 'paid': return 'default' case 'pending': return 'secondary' case 'failed': return 'destructive' default: return 'secondary' } } if (!user) return null return ( <> Profile Balance Billing Services Security Danger Zone Profile Information Update your profile information and email address.
{updateMessage && (
{updateMessage.text}
)}
{profileForm.formState.errors.name && (

{profileForm.formState.errors.name.message}

)}
{profileForm.formState.errors.email && (

{profileForm.formState.errors.email.message}

)}
{profileForm.formState.errors.phone && (

{profileForm.formState.errors.phone.message}

)}

Your unique identifier in our system

Account Balance Manage your account funds and transactions.

Current Balance

{isLoading ? ( ) : (
//

// ₹ // {profileStats?.balance?.toLocaleString('en-IN', { // minimumFractionDigits: 2, // }) || '1,250.00'} //

)}
Transaction History View all your transactions and balance changes
Billing History View and manage your billing information and invoices.
{[ { id: 'INV-001', service: 'VPS Hosting Plan', amount: '599.00', date: 'Dec 15, 2024', dueDate: 'Dec 15, 2024', status: 'paid', serviceType: 'hosting', billingCycle: 'Monthly', description: 'VPS hosting service with 4GB RAM, 2 vCPUs, and 80GB SSD storage', }, { id: 'INV-002', service: 'Kubernetes Cluster', amount: '299.00', date: 'Dec 5, 2024', dueDate: 'Dec 5, 2024', status: 'paid', serviceType: 'kubernetes', billingCycle: 'Monthly', description: 'Managed Kubernetes cluster with 3 nodes and load balancer', }, { id: 'INV-003', service: 'Domain Registration', amount: '199.00', date: 'Nov 28, 2024', dueDate: 'Dec 5, 2024', status: 'pending', serviceType: 'domain', billingCycle: 'Annual', description: 'Domain registration for .com domain with DNS management', }, ].map((invoice) => (
{getServiceIcon(invoice.serviceType)}

{invoice.service}

ID: {invoice.id}

₹{invoice.amount}

{invoice.date}

{invoice.status.charAt(0).toUpperCase() + invoice.status.slice(1)}
{invoice.status === 'pending' && ( )}
))}
Active Services Manage your active hosting services and configurations.
{(() => { const activeServices = [ { name: 'VPS Hosting Plan', id: 'VPS-001', serviceId: 'vps_12345', billingId: 'bill_67890', clusterId: null, startDate: 'Dec 15, 2024', nextBilling: 'Jan 15, 2025', status: 'active', type: 'hosting', }, { name: 'Kubernetes Cluster', id: 'K8S-001', serviceId: 'k8s_54321', billingId: 'bill_98765', clusterId: 'cluster_abc123', startDate: 'Dec 5, 2024', nextBilling: 'Jan 5, 2025', status: 'active', type: 'kubernetes', }, { name: 'Database Service', id: 'DB-001', serviceId: 'db_11111', billingId: 'bill_22222', clusterId: null, startDate: 'Nov 20, 2024', nextBilling: 'Dec 20, 2024', status: 'active', type: 'database', }, ] return activeServices.length > 0 ? ( activeServices.map((service) => (
{getServiceIcon(service.type)}

{service.name}

Service ID: {service.serviceId}

Started: {service.startDate}

Next billing: {service.nextBilling}

Active
{service.type === 'kubernetes' && service.clusterId && ( )} {service.type === 'hosting' && service.billingId && ( )}
)) ) : (

No Active Services

You don't have any active services at the moment

) })()}
Change Password {user.provider === 'local' ? 'Update your password to keep your account secure.' : `You're signed in with ${user.provider}. Password changes are not available for OAuth accounts.`} {user.provider === 'local' ? (
{passwordMessage && (
{passwordMessage.text}
)}
{passwordForm.formState.errors.currentPassword && (

{passwordForm.formState.errors.currentPassword.message}

)}
{passwordForm.formState.errors.newPassword && (

{passwordForm.formState.errors.newPassword.message}

)}
{passwordForm.formState.errors.confirmPassword && (

{passwordForm.formState.errors.confirmPassword.message}

)}
) : (
Password management is handled by your OAuth provider ({user.provider}).
)}
Security Activity Recent account activity and login history.
{(() => { const securityActivities = [ { action: 'Successful login', date: 'Today at 10:30 AM', ip: '192.168.1.1', location: 'New York, US', icon: 'login', type: 'success', }, { action: 'Profile updated', date: '2 days ago', ip: '192.168.1.1', location: 'New York, US', icon: 'user', type: 'info', }, { action: 'Password changed', date: '3 days ago', ip: '192.168.1.1', location: 'New York, US', icon: 'lock', type: 'success', }, { action: 'Failed login attempt', date: '1 week ago', ip: '203.0.113.1', location: 'Unknown', icon: 'warning', type: 'warning', }, { action: 'Account accessed', date: '2 weeks ago', ip: '192.168.1.2', location: 'Boston, US', icon: 'login', type: 'info', }, { action: 'Email verification', date: '3 weeks ago', ip: '192.168.1.1', location: 'New York, US', icon: 'user', type: 'success', }, ] return securityActivities.map((activity, index) => (
{activity.icon === 'lock' && ( )} {activity.icon === 'login' && ( )} {activity.icon === 'user' && ( )} {activity.icon === 'warning' && ( )}

{activity.action}

{activity.date}

{activity.location}

{activity.ip}

)) })()}
Danger Zone These actions are irreversible. Please proceed with caution.

Export Account Data

Download all your data in a portable format. This includes your profile information, billing history, and service configurations.

Delete Account

Once you delete your account, there is no going back. This will permanently delete your account and all associated data including active services.

{/* Add Balance Modal */} Add Balance Choose an amount or enter a custom amount to add to your balance {balanceError &&
{balanceError}
}
{/* Currency Selection */}
{/* Amount Selection */}
{amountOptions[selectedCurrency].map((amount) => ( ))}
{/* Custom Amount Input */}
You've selected {selectedCurrency === 'INR' ? '₹' : '$'} handleCustomAmountChange(e.target.value)} className="text-lg font-bold text-center border-0 bg-transparent p-0 focus:ring-0" /> to top up your balance.
{/* Modal Actions */}
{/* Billing Details Modal */} Billing Details Invoice and billing information {selectedBilling && (

Invoice #{selectedBilling.id}

{selectedBilling.status.charAt(0).toUpperCase() + selectedBilling.status.slice(1)}

Date Created

{selectedBilling.date}

Due Date

{selectedBilling.dueDate}

Service

{selectedBilling.service}

Amount

₹{selectedBilling.amount}

Billing Cycle

{selectedBilling.billingCycle}

{selectedBilling.description && (

Description

{selectedBilling.description}

)} {selectedBilling.status === 'pending' && (
)} {selectedBilling.status === 'paid' && (
)}
)}
) }