← back to Dear Bubbe Admin
frontend/src/components/Login.js
205 lines
import React, { useState } from 'react'
const Login = ({ onLogin, error }) => {
const [credentials, setCredentials] = useState({
username: '',
password: ''
})
const [loading, setLoading] = useState(false)
const [localError, setLocalError] = useState('')
const handleSubmit = async (e) => {
e.preventDefault()
if (!credentials.username || !credentials.password) {
setLocalError('Please enter both username and password')
return
}
setLoading(true)
setLocalError('')
try {
const result = await onLogin(credentials)
if (!result.success) {
setLocalError(result.error || 'Login failed')
}
} catch (err) {
setLocalError('Login failed. Please try again.')
} finally {
setLoading(false)
}
}
const handleChange = (e) => {
setCredentials({
...credentials,
[e.target.name]: e.target.value
})
// Clear errors when user starts typing
if (localError) setLocalError('')
if (error && e.target.value) setLocalError('')
}
return (
<div style={{
minHeight: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
padding: '20px'
}}>
<div style={{
background: 'white',
padding: '40px',
borderRadius: '12px',
boxShadow: '0 20px 40px rgba(0, 0, 0, 0.1)',
width: '100%',
maxWidth: '400px'
}}>
<div style={{ textAlign: 'center', marginBottom: '32px' }}>
<h1 style={{
fontSize: '28px',
fontWeight: '700',
color: '#1e293b',
margin: '0 0 8px 0'
}}>
Dear Bubbe Admin
</h1>
<p style={{
color: '#64748b',
fontSize: '16px',
margin: 0
}}>
Real-time Monitoring & Alert System
</p>
</div>
<form onSubmit={handleSubmit}>
<div style={{ marginBottom: '20px' }}>
<label style={{
display: 'block',
marginBottom: '6px',
fontWeight: '500',
color: '#374151'
}}>
Username
</label>
<input
type="text"
name="username"
value={credentials.username}
onChange={handleChange}
style={{
width: '100%',
padding: '12px 16px',
border: '1px solid #d1d5db',
borderRadius: '6px',
fontSize: '16px',
boxSizing: 'border-box'
}}
placeholder="Enter your username"
disabled={loading}
/>
</div>
<div style={{ marginBottom: '24px' }}>
<label style={{
display: 'block',
marginBottom: '6px',
fontWeight: '500',
color: '#374151'
}}>
Password
</label>
<input
type="password"
name="password"
value={credentials.password}
onChange={handleChange}
style={{
width: '100%',
padding: '12px 16px',
border: '1px solid #d1d5db',
borderRadius: '6px',
fontSize: '16px',
boxSizing: 'border-box'
}}
placeholder="Enter your password"
disabled={loading}
/>
</div>
{(localError || error) && (
<div style={{
background: '#fef2f2',
color: '#dc2626',
padding: '12px 16px',
borderRadius: '6px',
marginBottom: '20px',
fontSize: '14px',
border: '1px solid #fecaca'
}}>
{localError || error}
</div>
)}
<button
type="submit"
disabled={loading}
style={{
width: '100%',
padding: '12px 16px',
background: loading ? '#9ca3af' : '#3b82f6',
color: 'white',
border: 'none',
borderRadius: '6px',
fontSize: '16px',
fontWeight: '500',
cursor: loading ? 'not-allowed' : 'pointer',
transition: 'background-color 0.2s',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
>
{loading ? (
<>
<div className="loading-spinner" style={{ marginRight: '8px' }}></div>
Signing in...
</>
) : (
'Sign In'
)}
</button>
</form>
<div style={{
marginTop: '24px',
padding: '16px',
background: '#f8fafc',
borderRadius: '6px',
fontSize: '14px',
color: '#64748b'
}}>
<strong>Demo Credentials:</strong><br />
Username: admin<br />
Password: password
</div>
<div style={{
marginTop: '24px',
textAlign: 'center',
fontSize: '12px',
color: '#9ca3af'
}}>
🔒 Secure access to monitor Dear Bubbe AI system
</div>
</div>
</div>
)
}
export default Login