store token

This commit is contained in:
code002lover 2025-12-02 23:27:59 +01:00
parent 30950e6c83
commit 926926f357
4 changed files with 43 additions and 22 deletions

View File

@ -4,6 +4,7 @@ extern crate prost_build;
fn main() -> Result<(), std::io::Error> {
println!("cargo:rerun-if-changed=../protobuf/items.proto");
println!("cargo:rerun-if-changed=../frontend/src/");
let mut cfg = prost_build::Config::new();

View File

@ -5,19 +5,18 @@ import { PersonList } from "./PersonList";
import { PersonDetails } from "./PersonDetails";
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
import "./App.css";
import { apiFetch } from "./api";
function App() {
const [people, setPeople] = useState<Person[]>([]);
const [token, setToken] = useState<string>("");
const [token, setToken] = useState<string>(
localStorage.getItem("token") || ""
);
useEffect(() => {
if (!token) return;
fetch("/api", {
headers: {
Authorization: `Bearer ${token}`,
},
})
apiFetch("/api")
.then((res) => res.arrayBuffer())
.then((buffer) => {
const list = PersonListProto.decode(new Uint8Array(buffer));
@ -26,13 +25,19 @@ function App() {
.catch((err) => console.error("Failed to fetch people:", err));
}, [token]);
const handleLogin = (newToken: string) => {
setToken(newToken);
localStorage.setItem("token", newToken);
};
const handleLogout = () => {
setToken("");
setPeople([]);
localStorage.removeItem("token");
};
if (!token) {
return <Login onLogin={setToken} />;
return <Login onLogin={handleLogin} />;
}
return (
@ -55,10 +60,7 @@ function App() {
</div>
<Routes>
<Route path="/" element={<PersonList people={people} />} />
<Route
path="/person/:name"
element={<PersonDetails token={token} />}
/>
<Route path="/person/:name" element={<PersonDetails />} />
</Routes>
</div>
</BrowserRouter>

View File

@ -1,12 +1,9 @@
import { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import { Person, AddOpinionRequest } from "../items";
import { apiFetch } from "./api";
interface Props {
token: string;
}
export const PersonDetails = ({ token }: Props) => {
export const PersonDetails = () => {
const { name } = useParams<{ name: string }>();
const [person, setPerson] = useState<Person | null>(null);
const [gameTitle, setGameTitle] = useState("");
@ -14,9 +11,7 @@ export const PersonDetails = ({ token }: Props) => {
useEffect(() => {
if (name) {
fetch(`/api/${name}`, {
headers: { Authorization: `Bearer ${token}` },
})
apiFetch(`/api/${name}`)
.then((res) => res.arrayBuffer())
.then((buffer) => {
try {
@ -27,7 +22,7 @@ export const PersonDetails = ({ token }: Props) => {
})
.catch(console.error);
}
}, [name, token]);
}, [name]);
const handleAddOpinion = async () => {
if (!person) return;
@ -40,11 +35,10 @@ export const PersonDetails = ({ token }: Props) => {
const buffer = AddOpinionRequest.encode(req).finish();
try {
const res = await fetch("/api/opinion", {
const res = await apiFetch("/api/opinion", {
method: "POST",
headers: {
"Content-Type": "application/octet-stream",
Authorization: `Bearer ${token}`,
},
body: buffer,
});

24
frontend/src/api.ts Normal file
View File

@ -0,0 +1,24 @@
export const apiFetch = async (
url: string,
options: RequestInit = {}
): Promise<Response> => {
const token = localStorage.getItem("token");
const headers = new Headers(options.headers);
if (token) {
headers.set("Authorization", `Bearer ${token}`);
}
const config = {
...options,
headers,
};
const response = await fetch(url, config);
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
return response;
};