11"use client" ;
22
3- import React , { useState , useEffect } from 'react' ;
3+ import React , { useState , useEffect , useCallback } from 'react' ;
44import { useAuth } from '@/app/context/AuthContext' ;
55import { useRouter } from 'next/navigation' ;
66import {
@@ -92,48 +92,9 @@ const AdminProjectRequestsPage = () => {
9292 const [ currentPage , setCurrentPage ] = useState ( 1 ) ;
9393 const requestsPerPage = 10 ;
9494
95- // Function to re-verify admin access when token expires
96- const reVerifyAdminAccess = async ( ) => {
97- if ( ! user ) return ;
98-
99- try {
100- console . log ( "Re-verifying admin access for user:" , user . id ) ;
101-
102- const response = await fetch ( '/api/admin/verify' , {
103- method : 'POST' ,
104- headers : {
105- 'Content-Type' : 'application/json' ,
106- } ,
107- body : JSON . stringify ( { userId : user . id } )
108- } ) ;
109-
110- const responseData = await response . json ( ) ;
111- console . log ( "Re-verification response:" , responseData ) ;
112-
113- if ( response . ok && responseData . isAdmin ) {
114- console . log ( "Admin access re-verified successfully" ) ;
115- setAdminToken ( responseData . adminToken ) ;
116- setError ( null ) ;
117- // Retry fetching requests with the new token
118- fetchRequests ( responseData . adminToken ) ;
119- } else {
120- console . log ( "Re-verification failed:" , responseData . error ) ;
121- setError ( 'Admin session expired. Please refresh the page.' ) ;
122- setIsAdminVerified ( false ) ;
123- }
124- } catch ( error ) {
125- console . error ( 'Re-verification failed:' , error ) ;
126- setError ( 'Admin session expired. Please refresh the page.' ) ;
127- setIsAdminVerified ( false ) ;
128- }
129- } ;
130-
131- // Admin verification effect
132-
133- const fetchRequests = async ( forceToken ?: string ) => {
134- // If we have a force token, we're in the initial load after verification
135- if ( ! forceToken && ! isAdminVerified ) {
136- console . log ( "Not admin verified, skipping fetch" ) ;
95+ const fetchRequests = useCallback ( async ( ) => {
96+ if ( ! isAdminVerified || ! adminToken ) {
97+ console . log ( "Not admin verified or no token, skipping fetch" ) ;
13798 return ;
13899 }
139100
@@ -148,38 +109,16 @@ const AdminProjectRequestsPage = () => {
148109
149110 console . log ( "Fetching requests from:" , url ) ;
150111
151- // Create headers object
152- const headers : Record < string , string > = {
153- 'Content-Type' : 'application/json' ,
154- } ;
155-
156- // Use force token, admin token, or user token in that order
157- if ( forceToken ) {
158- headers [ 'Authorization' ] = `Bearer ${ forceToken } ` ;
159- console . log ( "Using force token for initial load" ) ;
160- } else if ( adminToken ) {
161- headers [ 'Authorization' ] = `Bearer ${ adminToken } ` ;
162- console . log ( "Using stored admin token:" , adminToken . substring ( 0 , 20 ) + '...' ) ;
163- } else if ( user ?. token ) {
164- headers [ 'Authorization' ] = `Bearer ${ user . token } ` ;
165- console . log ( "Using user token" ) ;
166- } else {
167- console . log ( "No token available for authorization" ) ;
168- }
169-
170- const response = await fetch ( url , { headers } ) ;
112+ const response = await fetch ( url , {
113+ headers : {
114+ 'Content-Type' : 'application/json' ,
115+ 'Authorization' : `Bearer ${ adminToken } ` ,
116+ }
117+ } ) ;
171118
172119 if ( ! response . ok ) {
173120 const errorText = await response . text ( ) ;
174121 console . error ( "Fetch requests error:" , response . status , errorText ) ;
175-
176- // If we get a 403 or 401, the token might be expired - try to re-verify admin access
177- if ( response . status === 403 || response . status === 401 ) {
178- console . log ( "Token appears to be expired or invalid, re-verifying admin access..." ) ;
179- await reVerifyAdminAccess ( ) ;
180- return ; // Exit here, reVerifyAdminAccess will call fetchRequests again if successful
181- }
182-
183122 throw new Error ( `Error: ${ response . status } - ${ errorText } ` ) ;
184123 }
185124
@@ -215,8 +154,9 @@ const AdminProjectRequestsPage = () => {
215154 } finally {
216155 setIsLoading ( false ) ;
217156 }
218- } ;
219-
157+ } , [ isAdminVerified , adminToken , filterStatus ] ) ;
158+
159+ // Separate effect for admin verification - runs only once
220160 useEffect ( ( ) => {
221161 const checkAdminAccess = async ( ) => {
222162 console . log ( "Starting admin access check" ) ;
@@ -250,10 +190,8 @@ const AdminProjectRequestsPage = () => {
250190 if ( response . ok && responseData . isAdmin ) {
251191 console . log ( "Admin access verified" ) ;
252192 setIsAdminVerified ( true ) ;
253- setAdminToken ( responseData . adminToken ) ; // Store the admin token
193+ setAdminToken ( responseData . adminToken ) ;
254194 setError ( null ) ;
255- // Start fetching requests with the token directly since state hasn't updated yet
256- fetchRequests ( responseData . adminToken ) ;
257195 } else {
258196 console . log ( "Admin access denied:" , responseData . error ) ;
259197 setError ( responseData . error || 'Access denied. Admin privileges required.' ) ;
@@ -268,8 +206,18 @@ const AdminProjectRequestsPage = () => {
268206 }
269207 } ;
270208
271- checkAdminAccess ( ) ;
272- } , [ isAuthenticated , user , router , fetchRequests ] ) ;
209+ // Only run this effect once when component mounts or when user/auth state changes
210+ if ( isAuthenticated !== null && user !== null ) {
211+ checkAdminAccess ( ) ;
212+ }
213+ } , [ isAuthenticated , user , router ] ) ; // Removed fetchRequests from dependencies
214+
215+ // Separate effect for fetching requests - runs when admin is verified and dependencies change
216+ useEffect ( ( ) => {
217+ if ( isAdminVerified && adminToken ) {
218+ fetchRequests ( ) ;
219+ }
220+ } , [ fetchRequests ] ) ; // Now safe because fetchRequests is properly memoized
273221
274222 const handleUpdateStatus = async ( status : 'accepted' | 'declined' ) => {
275223 if ( ! selectedRequest || ! user || ! isAdminVerified ) return ;
@@ -435,7 +383,7 @@ const AdminProjectRequestsPage = () => {
435383 < h1 className = "text-3xl font-bold text-white" > Admin Dashboard</ h1 >
436384 </ div >
437385 < Button
438- onClick = { ( ) => fetchRequests ( ) }
386+ onClick = { fetchRequests }
439387 className = "bg-slate-700 hover:bg-slate-600 text-white"
440388 disabled = { isLoading }
441389 >
0 commit comments