···
1
1
-
import React, { useEffect } from 'react';
1
1
+
import React, { useEffect, useState } from 'react';
2
2
import { Navigate, useLocation, useNavigate } from 'react-router-dom';
3
3
import { useAuth } from '../contexts/AuthContext';
4
4
···
6
6
const { isAuthenticated, loading, session } = useAuth();
7
7
const location = useLocation();
8
8
const navigate = useNavigate();
9
9
+
const [shouldRender, setShouldRender] = useState(false);
10
10
+
const [redirectTriggered, setRedirectTriggered] = useState(false);
9
11
10
10
-
// Detailed status logging
12
12
+
// Log initial state on mount
11
13
useEffect(() => {
12
12
-
console.log('ProtectedRoute status:', {
14
14
+
console.log('ProtectedRoute mounted with auth state:', {
13
15
isAuthenticated,
14
14
-
loading,
16
16
+
loading,
15
17
hasDid: session?.did ? true : false,
16
18
path: location.pathname
17
19
});
18
18
-
}, [isAuthenticated, loading, session, location]);
19
19
-
20
20
-
// Force navigation when not authenticated and not loading
20
20
+
}, []);
21
21
+
22
22
+
// Determine if we should redirect or render children
21
23
useEffect(() => {
22
22
-
if (!loading && !isAuthenticated) {
23
23
-
console.log('ProtectedRoute: Not authenticated, redirecting via useEffect hook');
24
24
-
const redirectUrl = `/login?returnUrl=${encodeURIComponent(location.pathname + location.search)}`;
25
25
-
navigate(redirectUrl, { replace: true });
24
24
+
// Only make decision after loading completes
25
25
+
if (!loading) {
26
26
+
if (isAuthenticated) {
27
27
+
console.log('ProtectedRoute: Authentication confirmed, will render protected content');
28
28
+
setShouldRender(true);
29
29
+
} else {
30
30
+
// Only trigger redirect once to avoid infinite loops
31
31
+
if (!redirectTriggered) {
32
32
+
console.log('ProtectedRoute: Not authenticated, redirecting to login');
33
33
+
setRedirectTriggered(true);
34
34
+
35
35
+
// Prepare the redirect URL
36
36
+
const redirectUrl = `/login?returnUrl=${encodeURIComponent(location.pathname + location.search)}`;
37
37
+
38
38
+
// Try React Router navigation first
39
39
+
navigate(redirectUrl, { replace: true });
40
40
+
41
41
+
// Fallback to direct redirection after a short delay
42
42
+
// This ensures redirection happens even if React Router navigation fails
43
43
+
setTimeout(() => {
44
44
+
if (window.location.pathname !== '/login') {
45
45
+
console.log('ProtectedRoute: Fallback to direct window location redirect');
46
46
+
window.location.href = redirectUrl;
47
47
+
}
48
48
+
}, 100);
49
49
+
}
50
50
+
}
26
51
}
27
27
-
}, [isAuthenticated, loading, navigate, location]);
52
52
+
}, [isAuthenticated, loading, navigate, location, redirectTriggered]);
28
53
29
29
-
// Only show loading state when actively checking auth
54
54
+
// Show loading state while checking auth
30
55
if (loading) {
31
31
-
console.log('ProtectedRoute: Auth is still loading');
32
32
-
return <div>Checking authentication status...</div>;
33
33
-
}
34
34
-
35
35
-
// If not authenticated, redirect with Navigate component as backup
36
36
-
if (!isAuthenticated) {
37
37
-
console.log('ProtectedRoute: Not authenticated, redirecting with Navigate component');
38
38
-
return <Navigate to={`/login?returnUrl=${encodeURIComponent(location.pathname + location.search)}`} replace />;
56
56
+
return <div className="auth-loading">Checking authentication status...</div>;
39
57
}
40
58
41
41
-
console.log('ProtectedRoute: Authentication confirmed, rendering protected content');
42
42
-
return children;
59
59
+
// Render children only when explicitly set to do so
60
60
+
return shouldRender ? children : <div className="auth-redirecting">Redirecting to login...</div>;
43
61
};
44
62
45
63
export default ProtectedRoute;
···
589
589
font-weight: 500;
590
590
}
591
591
592
592
-
/* Search and quick actions container */
593
593
-
.search-filters-container {
594
594
-
display: flex;
595
595
-
gap: 1rem;
596
596
-
justify-content: center;
597
597
-
align-items: center; /* Changed from stretch to center */
598
598
-
height: 48px; /* Set a fixed height for the container */
599
599
-
}
600
600
-
601
601
-
/* Improved search input */
602
602
-
.search-container {
592
592
+
/* Renamed search classes to avoid collision with SearchBar component */
593
593
+
.resources-search-container {
594
594
+
flex-grow: 1;
595
595
+
width: 100%;
603
596
position: relative;
604
604
-
height: 100%; /* Make it fill the container height */
605
605
-
}
606
606
-
607
607
-
.search-icon {
608
608
-
position: absolute;
609
609
-
left: 12px;
610
610
-
top: 50%;
611
611
-
transform: translateY(-50%);
612
612
-
font-size: 1rem;
613
613
-
opacity: 0.6;
614
614
-
z-index: 1;
615
597
}
616
598
617
617
-
.search-input {
599
599
+
.resources-search-input {
618
600
width: 100%;
619
619
-
padding: 0 12px 0 40px; /* Adjusted padding */
601
601
+
padding: 9px 15px;
602
602
+
border: 2px solid var(--card-border);
603
603
+
border-radius: 6px;
620
604
font-size: 1rem;
621
621
-
border: 2px solid var(--card-border);
622
622
-
border-radius: 8px;
623
605
background-color: var(--navbar-bg);
624
606
color: var(--text);
625
607
transition: all 0.3s ease;
626
626
-
height: 100%; /* Make it fill the container height */
627
627
-
box-sizing: border-box; /* Include padding and border in the element's total height */
628
608
}
629
609
630
630
-
.search-input:focus {
610
610
+
.resources-search-input:hover,
611
611
+
.resources-search-input:focus {
631
612
border-color: var(--button-bg);
613
613
+
background-color: var(--background);
632
614
outline: none;
633
633
-
box-shadow: 0 0 0 3px rgba(var(--button-bg-rgb), 0.2);
615
615
+
}
616
616
+
617
617
+
/* Update the search-filters-container class to match the new search class names */
618
618
+
.search-filters-container {
619
619
+
display: flex;
620
620
+
flex-wrap: wrap;
621
621
+
gap: 15px;
622
622
+
margin-top: 10px;
623
623
+
margin-bottom: 15px;
624
624
+
justify-content: space-between;
625
625
+
align-items: center;
634
626
}
635
627
636
628
/* Quick actions */
···
428
428
</div>
429
429
430
430
<div className="search-filters-container">
431
431
-
<div className="search-container">
431
431
+
<div className="resources-search-container">
432
432
<input
433
433
type="text"
434
434
placeholder="Search resources..."
435
435
value={searchQuery}
436
436
onChange={handleSearchChange}
437
437
-
className="search-input"
437
437
+
className="resources-search-input"
438
438
aria-label="Search resources"
439
439
/>
440
440
</div>
···
128
128
// Renamed component to Verifier
129
129
function Verifier() {
130
130
// Use the main app's AuthContext
131
131
-
const { session, loading: isAuthLoading, error: authError, logout: signOut } = useAuth();
131
131
+
const { session, loading: isAuthLoading, error: authError, logout: signOut, isAuthenticated } = useAuth();
132
132
const [targetHandle, setTargetHandle] = useState('');
133
133
const [statusMessage, setStatusMessage] = useState('');
134
134
const [revokeStatusMessage, setRevokeStatusMessage] = useState('');
···
642
642
643
643
if (isAuthLoading) return <p>Loading authentication...</p>;
644
644
if (authError) return <p>Authentication Error: {authError}. <a href="/login">Please login</a>.</p>;
645
645
+
646
646
+
// Check authentication after all hooks are defined
647
647
+
if (!session) {
648
648
+
console.log('Verifier: Not authenticated, waiting for ProtectedRoute redirection');
649
649
+
// Show a brief loading message while ProtectedRoute handles redirection
650
650
+
return <p>Checking authentication status...</p>;
651
651
+
}
645
652
646
653
const isAnyOperationInProgress = isVerifying || isRevoking || isLoadingVerifications || isLoadingNetwork || isCheckingValidity;
647
654