Skip to content

Commit d9f1613

Browse files
committed
feat(auth):added addadmin list admin removeadmin as well
1 parent 2797cdc commit d9f1613

File tree

8 files changed

+551
-61
lines changed

8 files changed

+551
-61
lines changed

public/sw.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/admin/addAdmin/page.tsx

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// app/admin/AddAdmin.tsx
2+
"use client";
3+
4+
import React, { useState } from 'react';
5+
import { useRouter } from 'next/navigation';
6+
import { auth, firestore } from '@/lib/firebase/config';
7+
import { doc, setDoc, getDoc } from 'firebase/firestore';
8+
9+
const AddAdmin: React.FC = () => {
10+
const [email, setEmail] = useState<string>('');
11+
const [error, setError] = useState<string | null>(null);
12+
const [success, setSuccess] = useState<string | null>(null);
13+
const [loading, setLoading] = useState<boolean>(false);
14+
const router = useRouter();
15+
16+
// Function to check if the user is an admin
17+
const checkIfUserIsAdmin = async (userEmail: string): Promise<boolean> => {
18+
const adminDoc = doc(firestore, 'adminemail', userEmail);
19+
const docSnap = await getDoc(adminDoc);
20+
return docSnap.exists();
21+
};
22+
23+
// Function to handle adding a new admin
24+
const handleAddAdmin = async () => {
25+
if (!email) {
26+
setError('Email cannot be empty');
27+
return;
28+
}
29+
30+
setLoading(true);
31+
setError(null);
32+
setSuccess(null);
33+
34+
try {
35+
const user = auth.currentUser;
36+
37+
if (user) {
38+
const isAdmin = await checkIfUserIsAdmin(user.email!);
39+
40+
if (isAdmin) {
41+
const adminData = {
42+
role: 'admin',
43+
addedBy: user.email,
44+
timestamp: new Date()
45+
};
46+
await setDoc(doc(firestore, 'adminemail', email), adminData);
47+
setSuccess('Admin added successfully!');
48+
setEmail('');
49+
} else {
50+
setError('You are not authorized to add admins.');
51+
}
52+
} else {
53+
setError('You must be logged in to add an admin.');
54+
}
55+
} catch (err: any) {
56+
console.error('Error adding admin:', err);
57+
setError('Failed to add admin: ' + err.message);
58+
} finally {
59+
setLoading(false);
60+
}
61+
};
62+
63+
return (
64+
<div className="p-4">
65+
<h2 className="text-xl font-semibold mb-4">Add New Admin</h2>
66+
{error && <p className="text-red-500">{error}</p>}
67+
{success && <p className="text-green-500">{success}</p>}
68+
{loading && <p className="text-blue-500">Loading...</p>}
69+
<input
70+
type="email"
71+
value={email}
72+
onChange={(e) => setEmail(e.target.value)}
73+
placeholder="Enter admin email"
74+
className="border border-gray-300 rounded p-2 mb-4 w-full"
75+
/>
76+
<button
77+
onClick={handleAddAdmin}
78+
className="bg-blue-600 text-white py-2 px-4 rounded"
79+
disabled={loading}
80+
>
81+
Add Admin
82+
</button>
83+
</div>
84+
);
85+
};
86+
87+
export default AddAdmin;

src/app/admin/listAdmin/page.tsx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// app/admin/AdminList.tsx
2+
"use client";
3+
4+
import React, { useState, useEffect } from 'react';
5+
import { firestore } from '@/lib/firebase/config';
6+
import { collection, getDocs } from 'firebase/firestore';
7+
8+
const AdminList: React.FC = () => {
9+
const [admins, setAdmins] = useState<any[]>([]);
10+
const [loading, setLoading] = useState<boolean>(true);
11+
const [error, setError] = useState<string | null>(null);
12+
13+
// Fetch the list of admins from Firestore
14+
const fetchAdmins = async () => {
15+
setLoading(true);
16+
setError(null);
17+
try {
18+
const adminCollection = collection(firestore, 'adminemail');
19+
const adminSnapshot = await getDocs(adminCollection);
20+
const adminList = adminSnapshot.docs.map(doc => ({
21+
id: doc.id,
22+
...doc.data()
23+
}));
24+
setAdmins(adminList);
25+
} catch (err) {
26+
console.error('Error fetching admins:', err);
27+
setError('Failed to fetch admins: ' + err.message);
28+
} finally {
29+
setLoading(false);
30+
}
31+
};
32+
33+
useEffect(() => {
34+
fetchAdmins();
35+
}, []);
36+
37+
if (loading) return <p className="text-blue-500">Loading...</p>;
38+
if (error) return <p className="text-red-500">{error}</p>;
39+
40+
return (
41+
<div className="p-4">
42+
<h2 className="text-xl font-semibold mb-4">Admin List</h2>
43+
{admins.length > 0 ? (
44+
<table className="min-w-full bg-white border border-gray-200">
45+
<thead>
46+
<tr>
47+
<th className="py-2 px-4 border-b">Email</th>
48+
<th className="py-2 px-4 border-b">Added By</th>
49+
<th className="py-2 px-4 border-b">Timestamp</th>
50+
</tr>
51+
</thead>
52+
<tbody>
53+
{admins.map(admin => (
54+
<tr key={admin.id}>
55+
<td className="py-2 px-4 border-b">{admin.id}</td>
56+
<td className="py-2 px-4 border-b">{admin.addedBy ?? 'N/A'}</td>
57+
<td className="py-2 px-4 border-b">
58+
{admin.timestamp ? new Date(admin.timestamp.toDate()).toLocaleString() : 'N/A'}
59+
</td>
60+
</tr>
61+
))}
62+
</tbody>
63+
</table>
64+
) : (
65+
<p>No admins found.</p>
66+
)}
67+
</div>
68+
);
69+
};
70+
71+
export default AdminList;

src/app/admin/removeAdmin/page.tsx

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// app/admin/RemoveAdmin.tsx
2+
"use client";
3+
4+
import React, { useState, useEffect } from 'react';
5+
import { useRouter } from 'next/navigation';
6+
import { auth, firestore } from '@/lib/firebase/config';
7+
import { doc, getDoc, deleteDoc, setDoc, collection, getDocs } from 'firebase/firestore';
8+
9+
const RemoveAdmin: React.FC = () => {
10+
const [email, setEmail] = useState<string>('');
11+
const [error, setError] = useState<string | null>(null);
12+
const [success, setSuccess] = useState<string | null>(null);
13+
const [loading, setLoading] = useState<boolean>(false);
14+
const [showRemovedAdmins, setShowRemovedAdmins] = useState<boolean>(false);
15+
const router = useRouter();
16+
17+
// Function to check if the user is an admin
18+
const checkIfUserIsAdmin = async (userEmail: string): Promise<boolean> => {
19+
const adminDoc = doc(firestore, 'adminemail', userEmail);
20+
const docSnap = await getDoc(adminDoc);
21+
return docSnap.exists();
22+
};
23+
24+
// Function to handle removing an admin
25+
const handleRemoveAdmin = async () => {
26+
if (!email) {
27+
setError('Email cannot be empty');
28+
return;
29+
}
30+
31+
setLoading(true);
32+
setError(null);
33+
setSuccess(null);
34+
35+
try {
36+
const user = auth.currentUser;
37+
38+
if (user) {
39+
const isAdmin = await checkIfUserIsAdmin(user.email!);
40+
41+
if (isAdmin) {
42+
// Remove the admin
43+
await deleteDoc(doc(firestore, 'adminemail', email));
44+
45+
// Log the removal
46+
const removedAdminData = {
47+
email: email,
48+
removedBy: user.email ?? 'N/A', // Use 'N/A' if removedBy is null
49+
timestamp: new Date() // Always set a timestamp, but you can check for missing data elsewhere
50+
};
51+
await setDoc(doc(firestore, 'removedadmin', email), removedAdminData);
52+
53+
setSuccess('Admin removed successfully!');
54+
setEmail('');
55+
} else {
56+
setError('You are not authorized to remove admins.');
57+
}
58+
} else {
59+
setError('You must be logged in to remove an admin.');
60+
}
61+
} catch (err: any) {
62+
console.error('Error removing admin:', err);
63+
setError('Failed to remove admin: ' + err.message);
64+
} finally {
65+
setLoading(false);
66+
}
67+
};
68+
69+
// Function to toggle the display of removed admins
70+
const handleToggleRemovedAdmins = () => {
71+
setShowRemovedAdmins(!showRemovedAdmins);
72+
};
73+
74+
return (
75+
<div className="p-4">
76+
<h2 className="text-xl font-semibold mb-4">Remove Admin</h2>
77+
{error && <p className="text-red-500">{error}</p>}
78+
{success && <p className="text-green-500">{success}</p>}
79+
{loading && <p className="text-blue-500">Loading...</p>}
80+
<input
81+
type="email"
82+
value={email}
83+
onChange={(e) => setEmail(e.target.value)}
84+
placeholder="Enter admin email"
85+
className="border border-gray-300 rounded p-2 mb-4 w-full"
86+
/>
87+
<button
88+
onClick={handleRemoveAdmin}
89+
className="bg-red-600 text-white py-2 px-4 rounded"
90+
disabled={loading}
91+
>
92+
Remove Admin
93+
</button>
94+
<button
95+
onClick={handleToggleRemovedAdmins}
96+
className="bg-blue-600 text-white py-2 px-4 mx-4 rounded mt-4"
97+
>
98+
{showRemovedAdmins ? 'Hide Removed Admins' : 'Show Removed Admins'}
99+
</button>
100+
{showRemovedAdmins && <RemovedAdminsList />}
101+
</div>
102+
);
103+
};
104+
105+
// Component to display the list of removed admins
106+
const RemovedAdminsList: React.FC = () => {
107+
const [removedAdmins, setRemovedAdmins] = useState<any[]>([]);
108+
const [loading, setLoading] = useState<boolean>(true);
109+
const [error, setError] = useState<string | null>(null);
110+
111+
useEffect(() => {
112+
const fetchRemovedAdmins = async () => {
113+
setLoading(true);
114+
setError(null);
115+
try {
116+
const removedAdminCollection = collection(firestore, 'removedadmin');
117+
const removedAdminSnapshot = await getDocs(removedAdminCollection);
118+
const removedAdminList = removedAdminSnapshot.docs.map(doc => ({
119+
id: doc.id,
120+
...doc.data()
121+
}));
122+
setRemovedAdmins(removedAdminList);
123+
} catch (err) {
124+
console.error('Error fetching removed admins:', err);
125+
setError('Failed to fetch removed admins: ' + err.message);
126+
} finally {
127+
setLoading(false);
128+
}
129+
};
130+
131+
fetchRemovedAdmins();
132+
}, []);
133+
134+
if (loading) return <p className="text-blue-500">Loading...</p>;
135+
if (error) return <p className="text-red-500">{error}</p>;
136+
137+
return (
138+
<div className="mt-4">
139+
<h3 className="text-lg font-semibold mb-2">Removed Admins</h3>
140+
{removedAdmins.length > 0 ? (
141+
<table className="min-w-full bg-white border border-gray-200">
142+
<thead>
143+
<tr>
144+
<th className="py-2 px-4 border-b">Email</th>
145+
<th className="py-2 px-4 border-b">Removed By</th>
146+
<th className="py-2 px-4 border-b">Timestamp</th>
147+
</tr>
148+
</thead>
149+
<tbody>
150+
{removedAdmins.map(admin => (
151+
<tr key={admin.id}>
152+
<td className="py-2 px-4 border-b">{admin.email ?? 'N/A'}</td>
153+
<td className="py-2 px-4 border-b">{admin.removedBy ?? 'N/A'}</td>
154+
<td className="py-2 px-4 border-b">
155+
{admin.timestamp ? new Date(admin.timestamp.toDate()).toLocaleString() : 'N/A'}
156+
</td>
157+
</tr>
158+
))}
159+
</tbody>
160+
</table>
161+
) : (
162+
<p>No removed admins found.</p>
163+
)}
164+
</div>
165+
166+
);
167+
};
168+
169+
export default RemoveAdmin;

0 commit comments

Comments
 (0)