![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/lavocat.ca/private_html/src/components/payments/ |
'use client';
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import { toast } from 'react-hot-toast';
import {
DollarSign,
CreditCard,
TrendingUp,
AlertCircle,
CheckCircle,
Clock,
Plus,
Eye
} from 'lucide-react';
interface PaymentWidgetProps {
userId: string;
userRole: string;
compact?: boolean;
}
interface PaymentSummary {
totalSpent: number;
thisMonthSpent: number;
pendingPayments: number;
overdueInvoices: number;
recentPayments: Array<{
id: string;
amount: number;
status: string;
description: string;
createdAt: string;
}>;
}
const PaymentWidget: React.FC<PaymentWidgetProps> = ({ userId, userRole, compact = false }) => {
const router = useRouter();
const [summary, setSummary] = useState<PaymentSummary | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchPaymentSummary();
}, [userId]);
const fetchPaymentSummary = async () => {
try {
setLoading(true);
const response = await fetch('/api/user/financial-summary');
if (response.ok) {
const data = await response.json();
setSummary({
totalSpent: data.totalSpent || 0,
thisMonthSpent: data.thisMonthSpent || 0,
pendingPayments: data.pendingPayments || 0,
overdueInvoices: data.overdueInvoices || 0,
recentPayments: []
});
}
} catch (error) {
console.error('Error fetching payment summary:', error);
} finally {
setLoading(false);
}
};
const formatCurrency = (amount: number, currency: string = 'CAD') => {
return new Intl.NumberFormat('en-CA', {
style: 'currency',
currency: currency
}).format(amount);
};
const getStatusIcon = (status: string) => {
switch (status.toLowerCase()) {
case 'completed':
return <CheckCircle className="h-4 w-4 text-green-500" />;
case 'pending':
return <Clock className="h-4 w-4 text-yellow-500" />;
case 'failed':
return <AlertCircle className="h-4 w-4 text-red-500" />;
default:
return <Clock className="h-4 w-4 text-gray-500" />;
}
};
if (loading) {
return (
<div className="bg-white rounded-lg shadow p-4">
<div className="animate-pulse">
<div className="h-4 bg-gray-200 rounded w-1/3 mb-2"></div>
<div className="h-8 bg-gray-200 rounded w-1/2 mb-4"></div>
<div className="space-y-2">
<div className="h-3 bg-gray-200 rounded"></div>
<div className="h-3 bg-gray-200 rounded w-2/3"></div>
</div>
</div>
</div>
);
}
if (compact) {
return (
<div className="bg-white rounded-lg shadow p-4">
<div className="flex items-center justify-between mb-3">
<h3 className="text-lg font-semibold text-gray-900 flex items-center">
<DollarSign className="h-5 w-5 text-green-600 mr-2" />
Payments
</h3>
<button
onClick={() => router.push('/user/payments')}
className="text-sm text-blue-600 hover:text-blue-800"
>
View All
</button>
</div>
<div className="grid grid-cols-2 gap-4 mb-4">
<div className="text-center">
<div className="text-2xl font-bold text-gray-900">
{formatCurrency(summary?.totalSpent || 0)}
</div>
<div className="text-xs text-gray-500">Total Spent</div>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-gray-900">
{formatCurrency(summary?.thisMonthSpent || 0)}
</div>
<div className="text-xs text-gray-500">This Month</div>
</div>
</div>
<div className="space-y-2">
{(summary?.pendingPayments ?? 0) > 0 && (
<div className="flex items-center justify-between text-sm">
<span className="text-yellow-600">Pending Payments</span>
<span className="font-medium">{summary?.pendingPayments ?? 0}</span>
</div>
)}
{(summary?.overdueInvoices ?? 0) > 0 && (
<div className="flex items-center justify-between text-sm">
<span className="text-red-600">Overdue Invoices</span>
<span className="font-medium">{summary?.overdueInvoices ?? 0}</span>
</div>
)}
</div>
<div className="mt-4 flex space-x-2">
<button
onClick={() => router.push('/user/payments')}
className="flex-1 bg-blue-600 text-white text-sm py-2 px-3 rounded-md hover:bg-blue-700 transition-colors"
>
<Eye className="h-4 w-4 mr-1" />
View Payments
</button>
<button
onClick={() => router.push('/user/subscription')}
className="flex-1 bg-green-600 text-white text-sm py-2 px-3 rounded-md hover:bg-green-700 transition-colors"
>
<CreditCard className="h-4 w-4 mr-1" />
Subscription
</button>
</div>
</div>
);
}
return (
<div className="bg-white rounded-lg shadow">
<div className="p-6">
<div className="flex items-center justify-between mb-6">
<h3 className="text-xl font-semibold text-gray-900 flex items-center">
<DollarSign className="h-6 w-6 text-green-600 mr-2" />
Payment Overview
</h3>
<button
onClick={() => router.push('/user/payments')}
className="text-sm text-blue-600 hover:text-blue-800 font-medium"
>
View All Payments →
</button>
</div>
{/* Summary Cards */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
<div className="bg-gradient-to-r from-green-50 to-green-100 rounded-lg p-4">
<div className="flex items-center">
<DollarSign className="h-8 w-8 text-green-600" />
<div className="ml-3">
<p className="text-sm font-medium text-green-800">Total Spent</p>
<p className="text-2xl font-bold text-green-900">
{formatCurrency(summary?.totalSpent || 0)}
</p>
</div>
</div>
</div>
<div className="bg-gradient-to-r from-blue-50 to-blue-100 rounded-lg p-4">
<div className="flex items-center">
<TrendingUp className="h-8 w-8 text-blue-600" />
<div className="ml-3">
<p className="text-sm font-medium text-blue-800">This Month</p>
<p className="text-2xl font-bold text-blue-900">
{formatCurrency(summary?.thisMonthSpent || 0)}
</p>
</div>
</div>
</div>
<div className="bg-gradient-to-r from-yellow-50 to-yellow-100 rounded-lg p-4">
<div className="flex items-center">
<Clock className="h-8 w-8 text-yellow-600" />
<div className="ml-3">
<p className="text-sm font-medium text-yellow-800">Pending</p>
<p className="text-2xl font-bold text-yellow-900">
{summary?.pendingPayments || 0}
</p>
</div>
</div>
</div>
<div className="bg-gradient-to-r from-red-50 to-red-100 rounded-lg p-4">
<div className="flex items-center">
<AlertCircle className="h-8 w-8 text-red-600" />
<div className="ml-3">
<p className="text-sm font-medium text-red-800">Overdue</p>
<p className="text-2xl font-bold text-red-900">
{summary?.overdueInvoices || 0}
</p>
</div>
</div>
</div>
</div>
{/* Quick Actions */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
<button
onClick={() => router.push('/user/payments')}
className="flex items-center p-4 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors"
>
<Eye className="h-6 w-6 text-blue-600 mr-3" />
<div className="text-left">
<p className="font-medium text-gray-900">View Payments</p>
<p className="text-sm text-gray-500">See all transactions</p>
</div>
</button>
<button
onClick={() => router.push('/user/subscription')}
className="flex items-center p-4 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors"
>
<CreditCard className="h-6 w-6 text-green-600 mr-3" />
<div className="text-left">
<p className="font-medium text-gray-900">Subscription</p>
<p className="text-sm text-gray-500">Manage your plan</p>
</div>
</button>
<button
onClick={() => router.push('/user/payments?tab=methods')}
className="flex items-center p-4 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors"
>
<Plus className="h-6 w-6 text-purple-600 mr-3" />
<div className="text-left">
<p className="font-medium text-gray-900">Payment Methods</p>
<p className="text-sm text-gray-500">Add or update cards</p>
</div>
</button>
</div>
{/* Alerts */}
{((summary?.pendingPayments ?? 0) > 0 || (summary?.overdueInvoices ?? 0) > 0) && (
<div className="space-y-3">
{(summary?.pendingPayments ?? 0) > 0 && (
<div className="flex items-center p-3 bg-yellow-50 border border-yellow-200 rounded-lg">
<Clock className="h-5 w-5 text-yellow-600 mr-3" />
<div className="flex-1">
<p className="text-sm font-medium text-yellow-800">
{summary?.pendingPayments ?? 0} pending payment{(summary?.pendingPayments ?? 0) > 1 ? 's' : ''}
</p>
<p className="text-xs text-yellow-600">
Review and complete pending transactions
</p>
</div>
<button
onClick={() => router.push('/user/payments?status=pending')}
className="text-sm text-yellow-800 hover:text-yellow-900 font-medium"
>
View
</button>
</div>
)}
{(summary?.overdueInvoices ?? 0) > 0 && (
<div className="flex items-center p-3 bg-red-50 border border-red-200 rounded-lg">
<AlertCircle className="h-5 w-5 text-red-600 mr-3" />
<div className="flex-1">
<p className="text-sm font-medium text-red-800">
{summary?.overdueInvoices ?? 0} overdue invoice{(summary?.overdueInvoices ?? 0) > 1 ? 's' : ''}
</p>
<p className="text-xs text-red-600">
Please review and settle overdue amounts
</p>
</div>
<button
onClick={() => router.push('/user/payments?status=overdue')}
className="text-sm text-red-800 hover:text-red-900 font-medium"
>
View
</button>
</div>
)}
</div>
)}
</div>
</div>
);
};
export default PaymentWidget;