@@ -2,8 +2,10 @@ import React, { useEffect, useState } from 'react';
22import { db } from '../../services/firebase' ;
33import { collection , getDocs , addDoc , deleteDoc , doc , Timestamp , query , orderBy } from 'firebase/firestore' ;
44import { Award , Plus , Trash2 , Search , X , Eye } from 'lucide-react' ;
5+ import { useAuth } from '../../context/AuthContext' ;
56
67const AdminCertificates = ( ) => {
8+ const { user, isAdmin } = useAuth ( ) ;
79 const [ certificates , setCertificates ] = useState ( [ ] ) ;
810 const [ isModalOpen , setIsModalOpen ] = useState ( false ) ;
911 const [ formData , setFormData ] = useState ( {
@@ -27,20 +29,44 @@ const AdminCertificates = () => {
2729 setCertificates ( snapshot . docs . map ( d => ( { id : d . id , ...d . data ( ) } ) ) ) ;
2830 } ;
2931
32+ // Filter by Event AND by Creator (User)
33+ // Show certificate IF:
34+ // 1. It matches the selected event filter (or All)
35+ // AND
36+ // 2. (User is Admin OR User created the certificate)
3037 const uniqueEvents = [ 'All' , ...new Set ( certificates . map ( c => c . eventname ) ) ] ;
31- const filteredCertificates = filterEvent === 'All'
32- ? certificates
33- : certificates . filter ( c => c . eventname === filterEvent ) ;
38+
39+ const filteredCertificates = certificates . filter ( c => {
40+ const eventMatch = filterEvent === 'All' || c . eventname === filterEvent ;
41+ const userMatch = isAdmin || ( c . createdBy === user ?. uid ) ;
42+ return eventMatch && userMatch ;
43+ } ) ;
3444
3545 const handleSubmit = async ( e ) => {
3646 e . preventDefault ( ) ;
47+ if ( ! user ) {
48+ alert ( "You must be logged in to issue certificates." ) ;
49+ return ;
50+ }
3751 try {
3852 await addDoc ( collection ( db , 'certificates' ) , {
3953 ...formData ,
4054 issueddate : Timestamp . fromDate ( new Date ( formData . issueddate ) ) ,
55+ createdBy : user . uid ,
56+ createdByName : user . name || user . email ,
57+ createdAt : Timestamp . now ( )
4158 } ) ;
4259 setIsModalOpen ( false ) ;
4360 fetchCertificates ( ) ;
61+ // Reset form
62+ setFormData ( {
63+ recipientname : '' ,
64+ email : '' ,
65+ eventname : '' ,
66+ certificateurl : '' ,
67+ issueddate : '' ,
68+ description : 'Successfully completed the workshop'
69+ } ) ;
4470 } catch ( error ) {
4571 console . error ( "Error issuing certificate:" , error ) ;
4672 }
@@ -84,22 +110,31 @@ const AdminCertificates = () => {
84110 </ tr >
85111 </ thead >
86112 < tbody className = "divide-y divide-gray-700" >
87- { filteredCertificates . map ( ( cert ) => (
88- < tr key = { cert . id } className = "text-gray-300 hover:bg-gray-750" >
89- < td className = "px-6 py-4" >
90- < div className = "font-medium text-white" > { cert . recipientname } </ div >
91- < div className = "text-xs text-gray-500" > { cert . email } </ div >
92- </ td >
93- < td className = "px-6 py-4" > { cert . eventname } </ td >
94- < td className = "px-6 py-4" > { cert . issueddate ?. toDate ( ) . toLocaleDateString ( ) } </ td >
95- < td className = "px-6 py-4 flex gap-3" >
96- < a href = { `/certificate/${ cert . id } ` } target = "_blank" rel = "noopener noreferrer" className = "text-blue-400 hover:text-blue-300" >
97- < Eye size = { 16 } />
98- </ a >
99- < button onClick = { ( ) => handleDelete ( cert . id ) } className = "text-red-400 hover:text-red-300" > < Trash2 size = { 16 } /> </ button >
113+ { filteredCertificates . length > 0 ? (
114+ filteredCertificates . map ( ( cert ) => (
115+ < tr key = { cert . id } className = "text-gray-300 hover:bg-gray-750" >
116+ < td className = "px-6 py-4" >
117+ < div className = "font-medium text-white" > { cert . recipientname } </ div >
118+ < div className = "text-xs text-gray-500" > { cert . email } </ div >
119+ { cert . createdByName && < div className = "text-[10px] text-gray-600" > By: { cert . createdByName } </ div > }
120+ </ td >
121+ < td className = "px-6 py-4" > { cert . eventname } </ td >
122+ < td className = "px-6 py-4" > { cert . issueddate ?. toDate ( ) . toLocaleDateString ( ) } </ td >
123+ < td className = "px-6 py-4 flex gap-3" >
124+ < a href = { `/certificate/${ cert . id } ` } target = "_blank" rel = "noopener noreferrer" className = "text-blue-400 hover:text-blue-300" >
125+ < Eye size = { 16 } />
126+ </ a >
127+ < button onClick = { ( ) => handleDelete ( cert . id ) } className = "text-red-400 hover:text-red-300" > < Trash2 size = { 16 } /> </ button >
128+ </ td >
129+ </ tr >
130+ ) )
131+ ) : (
132+ < tr >
133+ < td colSpan = "4" className = "px-6 py-8 text-center text-gray-500" >
134+ No certificates found.
100135 </ td >
101136 </ tr >
102- ) ) }
137+ ) }
103138 </ tbody >
104139 </ table >
105140 </ div >
0 commit comments