diff --git a/.gitignore b/.gitignore index f90f665..f37e688 100644 --- a/.gitignore +++ b/.gitignore @@ -141,3 +141,8 @@ vite.config.ts.timestamp-* generate-token.js **/Login.jsx +b a c k e n d / p r i s m a / p r i s m a / d e v . d b + + * . db + + \ No newline at end of file diff --git a/frontend/src/librarian/LibrarianDashboard.jsx b/frontend/src/librarian/LibrarianDashboard.jsx index eb50723..81fd63f 100644 --- a/frontend/src/librarian/LibrarianDashboard.jsx +++ b/frontend/src/librarian/LibrarianDashboard.jsx @@ -101,7 +101,7 @@ export default function LibrarianDashboard({ librarian, onLogout }) { onClick={() => setActiveTab('home')} className="mb-4 bg-gray-200 text-gray-800 px-4 py-2 rounded-lg hover:bg-gray-300 transition flex items-center gap-2" > - 返回仪表盘 + 返回 diff --git a/frontend/src/pages/Login.jsx b/frontend/src/pages/Login.jsx new file mode 100644 index 0000000..f5d725a --- /dev/null +++ b/frontend/src/pages/Login.jsx @@ -0,0 +1,56 @@ +import { useState } from 'react'; + +function Login({ onLogin }) { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [error, setError] = useState(''); + const [loading, setLoading] = useState(false); + + const handleSubmit = async (e) => { + e.preventDefault(); + setError(''); + setLoading(true); + + try { + const res = await fetch('http://localhost:3001/readers/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ email, password }) + }); + + const data = await res.json(); + + if (res.ok && data.token) { + localStorage.setItem('token', data.token); + localStorage.setItem('user', JSON.stringify(data.user)); + if (onLogin) onLogin(data.user); + window.location.href = '/'; + } else { + setError(data.message || 'Login failed'); + } + } catch (err) { + setError('Cannot connect to server'); + } finally { + setLoading(false); + } + }; + + return ( +
+

Reader Login

+
+ setEmail(e.target.value)} required style={{ width: '100%', padding: 8, margin: '10px 0' }} /> + setPassword(e.target.value)} required style={{ width: '100%', padding: 8, margin: '10px 0' }} /> + {error &&
{error}
} + +
+
+ No account? Register +
+
+ ); +} + +export default Login; \ No newline at end of file