diff --git a/frontend/api/config.ts b/frontend/api/config.ts index a48150b..68c107d 100644 --- a/frontend/api/config.ts +++ b/frontend/api/config.ts @@ -1,4 +1,5 @@ import axios from "axios"; +import Cookies from "js-cookie"; const axiosInstance = axios.create({ baseURL: process.env.NEXT_PUBLIC_BACKEND_URL || "http://localhost:8000", @@ -9,7 +10,7 @@ const axiosInstance = axios.create({ axiosInstance.interceptors.request.use( (config) => { - const token = localStorage.getItem("token"); + const token = Cookies.get("token"); if (token) { config.headers.Authorization = `Bearer ${token}`; } @@ -20,9 +21,7 @@ axiosInstance.interceptors.request.use( axiosInstance.interceptors.response.use( (response) => response, - (error) => { - return Promise.reject(error); - } + (error) => Promise.reject(error) ); export default axiosInstance; diff --git a/frontend/api/user.ts b/frontend/api/user.ts new file mode 100644 index 0000000..50b5669 --- /dev/null +++ b/frontend/api/user.ts @@ -0,0 +1,22 @@ +import axios from "axios"; +import axiosInstance from "./config"; +import { User } from "@/types"; + +export interface UserDataOutput { + user: User; +} + +/** + * Fetches the data for the authenticated user. + */ +export async function fetchUserMe(): Promise { + try { + const response = await axiosInstance.get("/user/me"); + return response.data; + } catch (error: any) { + if (axios.isAxiosError(error)) { + throw new Error(error.response?.data?.message || "Failed to fetch user data."); + } + throw error; + } +} diff --git a/frontend/components/sidebar/app-sidebar.tsx b/frontend/components/sidebar/app-sidebar.tsx index a2a1186..5faacd1 100644 --- a/frontend/components/sidebar/app-sidebar.tsx +++ b/frontend/components/sidebar/app-sidebar.tsx @@ -19,12 +19,14 @@ import { NavProjects } from "./nav-projects"; import { NavUser } from "./nav-user"; import { TeamSwitcher } from "./team-switcher"; import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarRail } from "@/components/ui/sidebar"; +import { useEffect } from "react"; +import { fetchUserMe } from "@/api/user"; const data = { user: { name: "shadcn", email: "m@example.com", - avatar: "/avatars/shadcn.jpg", + avatar: "/avatars/avatar.webp", }, teams: [ { @@ -134,6 +136,31 @@ const data = { }; export function AppSidebar({ ...props }: React.ComponentProps) { + const [user, setUser] = React.useState<{ name: string; email: string; avatar: string }>({ + name: "", + email: "", + avatar: "/avatars/avatar.webp", + }); + const [loading, setLoading] = React.useState(true); + const [error, setError] = React.useState(""); + + useEffect(() => { + async function getUser() { + try { + const data = await fetchUserMe(); + let to_set = user; + to_set.name = data.user.UUID; + to_set.email = data.user.Email; + setUser(to_set); + } catch (err: any) { + setError(err.message); + } finally { + setLoading(false); + } + } + getUser(); + }, []); + return ( @@ -143,9 +170,7 @@ export function AppSidebar({ ...props }: React.ComponentProps) { - - - + {loading ? "Loading..." : error ? error : } ); diff --git a/frontend/public/avatars/avatar.webp b/frontend/public/avatars/avatar.webp new file mode 100644 index 0000000..20f5a9e Binary files /dev/null and b/frontend/public/avatars/avatar.webp differ diff --git a/frontend/types.ts b/frontend/types.ts index 98fc9b1..c409b3f 100644 --- a/frontend/types.ts +++ b/frontend/types.ts @@ -25,3 +25,14 @@ export interface Farm { type: string; createdAt: Date; } + +export interface User { + ID: number; + UUID: string; + Username: string; + Password: string; + Email: string; + CreatedAt: string; + UpdatedAt: string; + IsActive: boolean; +}