T.ME/BIBIL_0DAY
CasperSecurity


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/public_html/src/components/payments/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.ca/public_html/src/components/payments/PaymentWidget.tsx
'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; 

CasperSecurity Mini