The login page has a form. When a form is submitted, the browser has a plan of its own: it sends the form itself and loads a new page, which starts the app over. event.preventDefault() stops that, so your code can send the login through api() instead.
A sign-up form works the same way: it stops the browser, posts through api(), moves on when it worked, and keeps the server's message when it didn't:
async function handleSubmit(event) {
event.preventDefault();
try {
await api("/api/register", { method: "POST", body: { email: email, password: password } });
navigate("/login");
} catch (err) {
setError(err.message);
}
}
A login does one thing more. The server's answer, { email }, goes to setUser from useAuth(), so the header shows who is logged in at once. A wrong password makes the server answer 401: api() throws, the lines after it in the try are skipped, and the catch keeps the message. The email state is not touched, so the email stays in its field.
The check types a wrong password, then the right one:
POST /api/login {"email": "ana@example.com", "password": "mug-lover-2"} → 401 alert: Wrong email or password
POST /api/login {"email": "ana@example.com", "password": "mug-lover-1"} → 200 header: Logged in as ana@example.com
the address bar → /
Your task: in client/src/pages/LoginPage.jsx, stop the browser's own submit, post the email and password to /api/login, give the answer to setUser and go to /. On a 401, show the server's message under the button in a <p role="alert">.
Assignment
Follow the Coding Tutorial to finish the login page: the request, the user, the move to /, and the error message.
HintsetUser and navigate go right after the api line, inside the try: they run only when the login worked.
Free plan: 30 tutor messages. PRO is unlimited.
