import React, { useState, useEffect } from 'react'; import { Award, Search, Filter, Download, Eye, Calendar, User, BookOpen } from 'lucide-react'; import toast from 'react-hot-toast'; interface Certificate { id: number; certificateNumber: string; issuedAt: string; completionDate: string; grade: string; score: number; course: { id: number; title: string; description: string; level: string; category: string; }; user: { id: number; firstName: string; lastName: string; email: string; avatar?: string; }; } interface CertificateStats { totalCertificates: number; thisMonthCertificates: number; thisYearCertificates: number; averageScore: number; } const VendorCertificates: React.FC = () => { const [certificates, setCertificates] = useState([]); const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); const [search, setSearch] = useState(''); const [selectedCourse, setSelectedCourse] = useState('all'); const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [courses, setCourses] = useState>([]); useEffect(() => { fetchCertificates(); fetchCertificateStats(); fetchCourses(); }, [currentPage, search, selectedCourse]); const fetchCertificates = async () => { try { setLoading(true); const token = localStorage.getItem('accessToken'); const params = new URLSearchParams({ page: currentPage.toString(), limit: '10' }); if (search) params.append('search', search); if (selectedCourse !== 'all') params.append('courseId', selectedCourse); const response = await fetch(`${process.env.REACT_APP_API_URL || 'http://localhost:5000/api'}/training-new/vendor/certificates?${params}`, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }); if (response.ok) { const data = await response.json(); setCertificates(data.data.certificates || []); setTotalPages(data.data.totalPages || 1); } else { toast.error('Failed to fetch certificates'); } } catch (error) { console.error('Error fetching certificates:', error); toast.error('Failed to fetch certificates'); } finally { setLoading(false); } }; const fetchCertificateStats = async () => { try { const token = localStorage.getItem('accessToken'); const response = await fetch(`${process.env.REACT_APP_API_URL || 'http://localhost:5000/api'}/training-new/vendor/certificates/stats`, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }); if (response.ok) { const data = await response.json(); setStats(data.data); } } catch (error) { console.error('Error fetching certificate stats:', error); } }; const fetchCourses = async () => { try { const token = localStorage.getItem('accessToken'); const response = await fetch(`${process.env.REACT_APP_API_URL || 'http://localhost:5000/api'}/training-new/courses`, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }); if (response.ok) { const data = await response.json(); setCourses(data.data.courses || []); } } catch (error) { console.error('Error fetching courses:', error); } }; const handlePageChange = (page: number) => { setCurrentPage(page); }; const handleSearch = (e: React.FormEvent) => { e.preventDefault(); setCurrentPage(1); }; const handleCourseFilter = (courseId: string) => { setSelectedCourse(courseId); setCurrentPage(1); }; const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }); }; const getGradeColor = (grade: string) => { switch (grade) { case 'Pass': return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'; case 'Merit': return 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200'; case 'Distinction': return 'bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200'; default: return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200'; } }; const getLevelColor = (level: string) => { switch (level) { case 'Beginner': return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'; case 'Intermediate': return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200'; case 'Advanced': return 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200'; default: return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200'; } }; if (loading && certificates.length === 0) { return (
); } return (
{/* Header */}

Certificates Issued

Track all certificates issued to your resellers

{/* Stats Cards */} {stats && (

Total Certificates

{stats.totalCertificates}

This Month

{stats.thisMonthCertificates}

This Year

{stats.thisYearCertificates}

Average Score

{stats.averageScore}%

)} {/* Filters and Search */}
setSearch(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-primary-500" />
{/* Certificates Table */}
{certificates.map((certificate) => ( ))}
Reseller Course Certificate Grade & Score Issued Date Actions
{certificate.user.avatar ? ( {`${certificate.user.firstName} ) : ( {certificate.user.firstName.charAt(0)}{certificate.user.lastName.charAt(0)} )}
{certificate.user.firstName} {certificate.user.lastName}
{certificate.user.email}
{certificate.course.title}
{certificate.course.level} {certificate.course.category}
{certificate.certificateNumber}
{certificate.grade} {certificate.score}%
{formatDate(certificate.issuedAt)}
{certificates.length === 0 && !loading && (

No certificates issued yet

Certificates will appear here once resellers complete your courses

)}
{/* Pagination */} {totalPages > 1 && (
Page {currentPage} of {totalPages}
)}
); }; export default VendorCertificates;