Skip to content

Commit 33befc0

Browse files
feature fix [login]: uses new login page, uses correct authentication, api interceptor updated
1 parent e7992a4 commit 33befc0

2 files changed

Lines changed: 81 additions & 62 deletions

File tree

client/src/lib/api.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import axios from "axios";
22

3-
import { clearTokens,getAccessToken } from "./auth";
4-
53
// use env URL to call API
64
const api = axios.create({ baseURL: process.env.NEXT_PUBLIC_BACKEND_URL });
75

86
// request interceptor attaches bearer token (logins & non public pages)
97
api.interceptors.request.use((config) => {
10-
const token = getAccessToken();
8+
const token = localStorage.getItem("accessToken");
119
if (token) {
1210
config.headers.Authorization = `Bearer ${token}`;
1311
}
@@ -21,8 +19,6 @@ api.interceptors.response.use(
2119
},
2220
(error) => {
2321
if (error.response?.status === 401) {
24-
clearTokens();
25-
2622
// Redirect to login page
2723
if (typeof window !== "undefined") {
2824
window.location.href = "/login";

client/src/pages/login.tsx

Lines changed: 80 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,99 @@
1+
import Link from "next/link";
12
import { useRouter } from "next/router";
23
import { useState } from "react";
34

4-
import Layout from "@/components/Layout";
5+
import { Button } from "@/components/ui/button";
6+
import {
7+
Card,
8+
CardContent,
9+
CardDescription,
10+
CardFooter,
11+
CardHeader,
12+
CardTitle,
13+
} from "@/components/ui/card";
14+
import { Input } from "@/components/ui/input";
515
import { useAuth } from "@/context/AuthContext";
16+
import api from "@/lib/api";
617

7-
export default function LoginPage() {
18+
export default function Login() {
819
const router = useRouter();
920
const { login } = useAuth();
10-
const [form, setForm] = useState({ username: "", password: "" });
21+
const [username, setUsername] = useState("");
22+
const [password, setPassword] = useState("");
1123
const [message, setMessage] = useState("");
1224

13-
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
14-
setForm({ ...form, [e.target.name]: e.target.value });
15-
};
16-
17-
const handleSubmit = async (e: React.FormEvent) => {
18-
e.preventDefault();
19-
setMessage("");
20-
25+
//function to return JWT
26+
const handleLogin = async () => {
2127
try {
22-
const res = await fetch("http://localhost:8000/api/user/login/", {
23-
method: "POST",
24-
headers: { "Content-Type": "application/json" },
25-
body: JSON.stringify(form),
28+
const res = await api.post("/user/login/", {
29+
username,
30+
password,
2631
});
27-
const data = await res.json();
32+
const { access, refresh } = res.data;
33+
login(access, refresh);
2834

29-
if (res.ok) {
30-
login(data.access, data.refresh);
31-
router.push("/");
32-
} else {
33-
setMessage(data.detail || "Login failed");
34-
}
35-
} catch (error) {
36-
// Temporary fix to commit
37-
const x = error;
38-
console.log(x);
39-
setMessage("Login failed. Please try again");
35+
// redirect based on role
36+
const me = await api.get("/user/me/");
37+
const role = me.data.profile.role;
38+
router.push(role === "manager" ? "/manager/dashboard" : "/home");
39+
} catch (err) {
40+
console.log(err);
41+
setMessage("Login failed. Please check your credentials.");
4042
}
4143
};
4244

4345
return (
44-
<Layout>
45-
<div className="mx-auto max-w-md p-4">
46-
<h1 className="mb-4 text-2xl font-bold">Login</h1>
47-
{message && <p className="mb-2 text-red-500">{message}</p>}
48-
<form onSubmit={handleSubmit} className="flex flex-col gap-2">
49-
<input
50-
name="username"
51-
placeholder="Username"
52-
value={form.username}
53-
onChange={handleChange}
54-
className="border p-2"
55-
required
56-
/>
57-
<input
58-
name="password"
59-
type="password"
60-
placeholder="Password"
61-
value={form.password}
62-
onChange={handleChange}
63-
className="border p-2"
64-
required
65-
/>
66-
<button
67-
type="submit"
68-
className="mt-2 rounded bg-green-500 p-2 text-white"
69-
>
46+
<div className="flex min-h-screen items-center justify-center bg-muted">
47+
<Card className="w-full max-w-sm">
48+
<CardHeader>
49+
<CardTitle>Login to your account</CardTitle>
50+
<CardDescription>
51+
Enter your email below to login to your account
52+
</CardDescription>
53+
<Link href={"/register"}>
54+
<Button variant="link">Sign Up</Button>
55+
</Link>
56+
</CardHeader>
57+
<CardContent>
58+
{message && (
59+
<p className="mb-4 text-center text-sm text-muted-foreground">
60+
{message}
61+
</p>
62+
)}
63+
<form>
64+
<div className="flex flex-col gap-6">
65+
<div className="grid gap-2">
66+
<Input
67+
id="username"
68+
type="username"
69+
placeholder="user-name"
70+
required
71+
onChange={(e) => setUsername(e.target.value)}
72+
/>
73+
</div>
74+
<div className="grid gap-2">
75+
<div className="flex items-center">
76+
<a
77+
href="#"
78+
className="ml-auto inline-block text-sm underline-offset-4 hover:underline"
79+
>
80+
Forgot your password?
81+
</a>
82+
</div>
83+
<Input
84+
type="password"
85+
onChange={(e) => setPassword(e.target.value)}
86+
/>
87+
</div>
88+
</div>
89+
</form>
90+
</CardContent>
91+
<CardFooter className="flex-col gap-2">
92+
<Button type="submit" className="w-full" onClick={handleLogin}>
7093
Login
71-
</button>
72-
</form>
73-
</div>
74-
</Layout>
94+
</Button>
95+
</CardFooter>
96+
</Card>
97+
</div>
7598
);
7699
}

0 commit comments

Comments
 (0)