Add static password protection to the dashboard
This commit is contained in:
+93
-5
@@ -1,18 +1,106 @@
|
|||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
|
||||||
import ConsolidatedHome from './components/ConsolidatedHome';
|
import ConsolidatedHome from './components/ConsolidatedHome';
|
||||||
import ChangeoverDetail from './components/ChangeoverDetail';
|
import ChangeoverDetail from './components/ChangeoverDetail';
|
||||||
import EventTimeline from './components/EventTimeline';
|
import EventTimeline from './components/EventTimeline';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
|
const STATIC_PASSWORD = "SOP-Monitor-99";
|
||||||
|
|
||||||
|
function ProtectedRoute({ children, isAuthenticated }) {
|
||||||
|
if (!isAuthenticated) {
|
||||||
|
return <Navigate to="/login" replace />;
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Login({ onLogin }) {
|
||||||
|
const [password, setPassword] = useState('');
|
||||||
|
const [error, setError] = useState('');
|
||||||
|
|
||||||
|
const handleSubmit = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (password === STATIC_PASSWORD) {
|
||||||
|
onLogin();
|
||||||
|
} else {
|
||||||
|
setError('Incorrect password');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="container animate-fade-in" style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh', maxWidth: '100%' }}>
|
||||||
|
<div className="glass-panel" style={{ padding: '3rem', width: '100%', maxWidth: '400px', textAlign: 'center' }}>
|
||||||
|
<h2 style={{ marginBottom: '2rem' }}>AI SOP Monitoring</h2>
|
||||||
|
<form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
placeholder="Enter Access Password"
|
||||||
|
value={password}
|
||||||
|
onChange={e => setPassword(e.target.value)}
|
||||||
|
style={{
|
||||||
|
padding: '0.75rem 1rem',
|
||||||
|
borderRadius: '8px',
|
||||||
|
border: '1px solid var(--panel-border)',
|
||||||
|
background: 'rgba(255,255,255,0.05)',
|
||||||
|
color: 'var(--text)',
|
||||||
|
fontSize: '1rem',
|
||||||
|
outline: 'none',
|
||||||
|
boxShadow: 'inset 0 2px 4px rgba(0,0,0,0.2)'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{error && <p style={{ color: '#ff6b6b', margin: 0, fontSize: '0.875rem' }}>{error}</p>}
|
||||||
|
<button type="submit" style={{
|
||||||
|
padding: '0.75rem',
|
||||||
|
background: 'var(--accent)',
|
||||||
|
color: 'white',
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: '8px',
|
||||||
|
fontSize: '1rem',
|
||||||
|
fontWeight: '600',
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: 'background 0.2s ease'
|
||||||
|
}}
|
||||||
|
onMouseEnter={(e) => e.currentTarget.style.background = '#0e705b'}
|
||||||
|
onMouseLeave={(e) => e.currentTarget.style.background = 'var(--accent)'}
|
||||||
|
>
|
||||||
|
Access Dashboard
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
const [isAuthenticated, setIsAuthenticated] = useState(() => {
|
||||||
|
return localStorage.getItem('sop_auth') === 'true';
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleLogin = () => {
|
||||||
|
setIsAuthenticated(true);
|
||||||
|
localStorage.setItem('sop_auth', 'true');
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<ConsolidatedHome />} />
|
<Route path="/login" element={<Login onLogin={handleLogin} />} />
|
||||||
<Route path="/changeover/:id" element={<ChangeoverDetail />} />
|
<Route path="/" element={
|
||||||
<Route path="/changeover/:id/timeline" element={<EventTimeline />} />
|
<ProtectedRoute isAuthenticated={isAuthenticated}>
|
||||||
|
<ConsolidatedHome />
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/changeover/:id" element={
|
||||||
|
<ProtectedRoute isAuthenticated={isAuthenticated}>
|
||||||
|
<ChangeoverDetail />
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
|
<Route path="/changeover/:id/timeline" element={
|
||||||
|
<ProtectedRoute isAuthenticated={isAuthenticated}>
|
||||||
|
<EventTimeline />
|
||||||
|
</ProtectedRoute>
|
||||||
|
} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
|||||||
Reference in New Issue
Block a user