Skip to content

Commit 0ce4a02

Browse files
Fixed Certs Filtering
1 parent 270b04f commit 0ce4a02

2 files changed

Lines changed: 66 additions & 31 deletions

File tree

node_modules/.vite/deps/_metadata.json

Lines changed: 14 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/pages/admin/AdminCertificates.jsx

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import React, { useEffect, useState } from 'react';
22
import { db } from '../../services/firebase';
33
import { collection, getDocs, addDoc, deleteDoc, doc, Timestamp, query, orderBy } from 'firebase/firestore';
44
import { Award, Plus, Trash2, Search, X, Eye } from 'lucide-react';
5+
import { useAuth } from '../../context/AuthContext';
56

67
const 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

Comments
 (0)