larxius commited on
Commit
45302ea
·
verified ·
1 Parent(s): 4e2e25e

Update frontend/src/pages/SuperAdminLogin.jsx

Browse files
Files changed (1) hide show
  1. frontend/src/pages/SuperAdminLogin.jsx +104 -104
frontend/src/pages/SuperAdminLogin.jsx CHANGED
@@ -1,104 +1,104 @@
1
- import React, { useState } from 'react';
2
- import { useNavigate } from 'react-router-dom';
3
- import { useAuth } from '../components/AuthContext';
4
-
5
- export const SuperAdminLogin = () => {
6
- const [adminPassword, setAdminPassword] = useState('');
7
- const [adminError, setAdminError] = useState('');
8
- const [showPassword, setShowPassword] = useState(false);
9
- const [isLoading, setIsLoading] = useState(false);
10
- const navigate = useNavigate();
11
- const { login } = useAuth();
12
-
13
- const handleAdminAccess = async (e) => {
14
- e.preventDefault();
15
- setIsLoading(true);
16
- setAdminError('');
17
- try {
18
- const res = await fetch('/api/auth/login', {
19
- method: 'POST',
20
- headers: { 'Content-Type': 'application/json' },
21
- body: JSON.stringify({ email: 'superadmin@gmail.com', password: adminPassword })
22
- });
23
- const data = await res.json();
24
- if (res.ok) {
25
- login(data.access_token || data.token, data.refresh_token, data.user);
26
- sessionStorage.setItem('superAdminAuth', 'true');
27
- navigate('/super-admin');
28
- } else {
29
- setAdminError(data.message || 'Incorrect password');
30
- }
31
- } catch {
32
- setAdminError('Could not connect to API');
33
- } finally {
34
- setIsLoading(false);
35
- }
36
- };
37
-
38
- return (
39
- <div className="bg-surface text-on-surface font-body-md min-h-screen flex items-center justify-center selection:bg-primary/10 relative overflow-hidden">
40
- {/* Background aesthetics */}
41
- <div className="absolute top-0 left-1/2 -translate-x-1/2 w-full max-w-container-max h-full -z-10 pointer-events-none opacity-50">
42
- <div className="absolute top-[-100px] left-[10%] w-[500px] h-[500px] bg-[radial-gradient(circle,rgba(0,74,198,0.07)_0%,transparent_70%)] rounded-full blur-3xl"></div>
43
- <div className="absolute bottom-[-100px] right-[10%] w-[500px] h-[500px] bg-[radial-gradient(circle,rgba(37,99,235,0.05)_0%,transparent_70%)] rounded-full blur-3xl"></div>
44
- </div>
45
-
46
- <div className="bg-surface-container-lowest p-2xl rounded-3xl w-full max-w-md border border-outline-variant shadow-2xl animate-fade-in mx-gutter relative">
47
- <div className="flex justify-center mb-xl">
48
- <div className="w-16 h-16 flex items-center justify-center">
49
- <img src="/logo.png" alt="LarShield Logo" className="w-full h-full object-contain" />
50
- </div>
51
- </div>
52
-
53
- <div className="text-center mb-xl">
54
- <h1 className="font-headline-lg text-on-surface font-extrabold mb-sm text-[28px] tracking-tight brand-gradient">Global Management</h1>
55
- <p className="text-on-surface-variant text-[14px] leading-relaxed">Enter the master password to access LarShield Global Management.</p>
56
- </div>
57
-
58
- <form onSubmit={handleAdminAccess} className="flex flex-col gap-lg">
59
- <div className="flex flex-col gap-xs">
60
- <div className="relative w-full">
61
- <input
62
- type={showPassword ? "text" : "password"}
63
- value={adminPassword}
64
- onChange={(e) => setAdminPassword(e.target.value)}
65
- placeholder="Master Password"
66
- autoFocus
67
- className="w-full border border-outline-variant rounded-xl py-md pl-lg pr-12 focus:ring-2 focus:ring-primary focus:border-primary bg-surface-container text-on-surface text-[15px] outline-none transition-all"
68
- />
69
- <button
70
- type="button"
71
- onClick={() => setShowPassword(!showPassword)}
72
- className="absolute right-3 top-1/2 -translate-y-1/2 text-on-surface-variant hover:text-primary transition-colors bg-transparent border-0 cursor-pointer flex items-center justify-center p-1"
73
- aria-label={showPassword ? "Hide password" : "Show password"}
74
- >
75
- <span className="material-symbols-outlined text-[20px]">
76
- {showPassword ? 'visibility_off' : 'visibility'}
77
- </span>
78
- </button>
79
- </div>
80
- {adminError && <p className="text-error font-semibold text-[13px] mt-1 text-center">{adminError}</p>}
81
- </div>
82
-
83
- <button
84
- type="submit"
85
- disabled={isLoading || !adminPassword}
86
- className="w-full bg-primary text-white py-md rounded-xl font-bold hover:brightness-110 active:scale-[0.98] transition-all border-0 cursor-pointer text-[15px] shadow-lg shadow-primary/20 flex items-center justify-center disabled:opacity-70 disabled:cursor-not-allowed"
87
- >
88
- {isLoading ? (
89
- <span className="material-symbols-outlined animate-spin text-[20px]">sync</span>
90
- ) : (
91
- 'Authenticate'
92
- )}
93
- </button>
94
- </form>
95
-
96
- <div className="mt-xl text-center">
97
- <button onClick={() => navigate('/')} className="text-on-surface-variant hover:text-primary transition-colors text-[13px] font-semibold bg-transparent border-0 cursor-pointer">
98
- ← Return to Public Site
99
- </button>
100
- </div>
101
- </div>
102
- </div>
103
- );
104
- };
 
1
+ import { useState } from 'react';
2
+ import { useNavigate } from 'react-router-dom';
3
+ import { useAuth } from '../components/AuthContext';
4
+
5
+ export const SuperAdminLogin = () => {
6
+ const [adminPassword, setAdminPassword] = useState('');
7
+ const [adminError, setAdminError] = useState('');
8
+ const [showPassword, setShowPassword] = useState(false);
9
+ const [isLoading, setIsLoading] = useState(false);
10
+ const navigate = useNavigate();
11
+ const { login } = useAuth();
12
+
13
+ const handleAdminAccess = async (e) => {
14
+ e.preventDefault();
15
+ setIsLoading(true);
16
+ setAdminError('');
17
+ try {
18
+ const res = await fetch('/api/auth/login', {
19
+ method: 'POST',
20
+ headers: { 'Content-Type': 'application/json' },
21
+ body: JSON.stringify({ email: 'superadmin@gmail.com', password: adminPassword })
22
+ });
23
+ const data = await res.json();
24
+ if (res.ok) {
25
+ login(data.access_token || data.token, data.refresh_token, data.user);
26
+ sessionStorage.setItem('superAdminAuth', 'true');
27
+ navigate('/super-admin');
28
+ } else {
29
+ setAdminError(data.message || 'Incorrect password');
30
+ }
31
+ } catch {
32
+ setAdminError('Could not connect to API');
33
+ } finally {
34
+ setIsLoading(false);
35
+ }
36
+ };
37
+
38
+ return (
39
+ <div className="bg-surface text-on-surface font-body-md min-h-screen flex items-center justify-center selection:bg-primary/10 relative overflow-hidden">
40
+ {/* Background aesthetics */}
41
+ <div className="absolute top-0 left-1/2 -translate-x-1/2 w-full max-w-container-max h-full -z-10 pointer-events-none opacity-50">
42
+ <div className="absolute top-[-100px] left-[10%] w-[500px] h-[500px] bg-[radial-gradient(circle,rgba(0,74,198,0.07)_0%,transparent_70%)] rounded-full blur-3xl"></div>
43
+ <div className="absolute bottom-[-100px] right-[10%] w-[500px] h-[500px] bg-[radial-gradient(circle,rgba(37,99,235,0.05)_0%,transparent_70%)] rounded-full blur-3xl"></div>
44
+ </div>
45
+
46
+ <div className="bg-surface-container-lowest p-2xl rounded-3xl w-full max-w-md border border-outline-variant shadow-2xl animate-fade-in mx-gutter relative">
47
+ <div className="flex justify-center mb-xl">
48
+ <div className="w-16 h-16 flex items-center justify-center">
49
+ <img src="/logo.png" alt="LarShield Logo" className="w-full h-full object-contain" />
50
+ </div>
51
+ </div>
52
+
53
+ <div className="text-center mb-xl">
54
+ <h1 className="font-headline-lg text-on-surface font-extrabold mb-sm text-[28px] tracking-tight brand-gradient">Global Management</h1>
55
+ <p className="text-on-surface-variant text-[14px] leading-relaxed">Enter the master password to access LarShield Global Management.</p>
56
+ </div>
57
+
58
+ <form onSubmit={handleAdminAccess} className="flex flex-col gap-lg">
59
+ <div className="flex flex-col gap-xs">
60
+ <div className="relative w-full">
61
+ <input
62
+ type={showPassword ? "text" : "password"}
63
+ value={adminPassword}
64
+ onChange={(e) => setAdminPassword(e.target.value)}
65
+ placeholder="Master Password"
66
+ autoFocus
67
+ className="w-full border border-outline-variant rounded-xl py-md pl-lg pr-12 focus:ring-2 focus:ring-primary focus:border-primary bg-surface-container text-on-surface text-[15px] outline-none transition-all"
68
+ />
69
+ <button
70
+ type="button"
71
+ onClick={() => setShowPassword(!showPassword)}
72
+ className="absolute right-3 top-1/2 -translate-y-1/2 text-on-surface-variant hover:text-primary transition-colors bg-transparent border-0 cursor-pointer flex items-center justify-center p-1"
73
+ aria-label={showPassword ? "Hide password" : "Show password"}
74
+ >
75
+ <span className="material-symbols-outlined text-[20px]">
76
+ {showPassword ? 'visibility_off' : 'visibility'}
77
+ </span>
78
+ </button>
79
+ </div>
80
+ {adminError && <p className="text-error font-semibold text-[13px] mt-1 text-center">{adminError}</p>}
81
+ </div>
82
+
83
+ <button
84
+ type="submit"
85
+ disabled={isLoading || !adminPassword}
86
+ className="w-full bg-primary text-white py-md rounded-xl font-bold hover:brightness-110 active:scale-[0.98] transition-all border-0 cursor-pointer text-[15px] shadow-lg shadow-primary/20 flex items-center justify-center disabled:opacity-70 disabled:cursor-not-allowed"
87
+ >
88
+ {isLoading ? (
89
+ <span className="material-symbols-outlined animate-spin text-[20px]">sync</span>
90
+ ) : (
91
+ 'Authenticate'
92
+ )}
93
+ </button>
94
+ </form>
95
+
96
+ <div className="mt-xl text-center">
97
+ <button onClick={() => navigate('/')} className="text-on-surface-variant hover:text-primary transition-colors text-[13px] font-semibold bg-transparent border-0 cursor-pointer">
98
+ ← Return to Public Site
99
+ </button>
100
+ </div>
101
+ </div>
102
+ </div>
103
+ );
104
+ };