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