feat: Add API to retrieve authentication status and display user game opinions with colored borders in the game list.
This commit is contained in:
parent
defcb0e0bc
commit
03de073692
@ -1,7 +1,13 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { Game, Source, GameList as GameListProto } from "../items";
|
import {
|
||||||
|
Game,
|
||||||
|
Source,
|
||||||
|
GameList as GameListProto,
|
||||||
|
Person as PersonProto,
|
||||||
|
Opinion,
|
||||||
|
} from "../items";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { apiFetch } from "./api";
|
import { apiFetch, get_auth_status } from "./api";
|
||||||
import { GameImage } from "./GameImage";
|
import { GameImage } from "./GameImage";
|
||||||
|
|
||||||
export function GameList() {
|
export function GameList() {
|
||||||
@ -14,6 +20,7 @@ export function GameList() {
|
|||||||
const [remoteId, setRemoteId] = useState(0);
|
const [remoteId, setRemoteId] = useState(0);
|
||||||
const [message, setMessage] = useState("");
|
const [message, setMessage] = useState("");
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
|
const [opinions, setOpinions] = useState<Opinion[]>([]);
|
||||||
|
|
||||||
const fetchGames = () => {
|
const fetchGames = () => {
|
||||||
apiFetch("/api/games")
|
apiFetch("/api/games")
|
||||||
@ -29,6 +36,22 @@ export function GameList() {
|
|||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
get_auth_status().then((user) => {
|
||||||
|
apiFetch(`/api/${user?.username}`)
|
||||||
|
.then((res) => res.arrayBuffer())
|
||||||
|
.then((buffer) => {
|
||||||
|
try {
|
||||||
|
const person = PersonProto.decode(new Uint8Array(buffer));
|
||||||
|
const opinions = person.opinion;
|
||||||
|
setOpinions(opinions);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to decode games:", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchGames();
|
fetchGames();
|
||||||
}, []);
|
}, []);
|
||||||
@ -365,7 +388,7 @@ export function GameList() {
|
|||||||
|
|
||||||
<div style={gridStyles}>
|
<div style={gridStyles}>
|
||||||
<div style={inputGroupStyles}>
|
<div style={inputGroupStyles}>
|
||||||
<label style={labelStyles}>Price ($)</label>
|
<label style={labelStyles}>Price (€)</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={price}
|
value={price}
|
||||||
@ -432,23 +455,31 @@ export function GameList() {
|
|||||||
<div style={{ marginTop: "3rem" }}>
|
<div style={{ marginTop: "3rem" }}>
|
||||||
<h3>Existing Games</h3>
|
<h3>Existing Games</h3>
|
||||||
<ul className="grid-container">
|
<ul className="grid-container">
|
||||||
{games.map((game) => (
|
{games.map((game) => {
|
||||||
<Link
|
const opinion = opinions.find((op) => op.title === game.title);
|
||||||
to={`/game/${encodeURIComponent(game.title)}`}
|
return (
|
||||||
key={game.title}
|
<Link
|
||||||
className="list-item"
|
to={`/game/${encodeURIComponent(game.title)}`}
|
||||||
style={{
|
key={game.title}
|
||||||
textDecoration: "none",
|
className="list-item"
|
||||||
color: "inherit",
|
style={{
|
||||||
display: "flex",
|
textDecoration: "none",
|
||||||
justifyContent: "space-between",
|
color: "inherit",
|
||||||
alignItems: "center",
|
display: "flex",
|
||||||
}}
|
justifyContent: "space-between",
|
||||||
>
|
alignItems: "center",
|
||||||
<strong>{game.title}</strong>
|
borderColor: opinion
|
||||||
<GameImage game={game.title} />
|
? opinion.wouldPlay
|
||||||
</Link>
|
? "#4caf50" // would play (green)
|
||||||
))}
|
: "#f44336" // would not play (red)
|
||||||
|
: "#191f2e", // no opinion (bg-2)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<strong>{game.title}</strong>
|
||||||
|
<GameImage game={game.title} />
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,14 +1,7 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { Link, useParams } from "react-router-dom";
|
import { Link, useParams } from "react-router-dom";
|
||||||
import {
|
import { Person, AddOpinionRequest, Game, GameList } from "../items";
|
||||||
Person,
|
import { apiFetch, get_auth_status } from "./api";
|
||||||
AddOpinionRequest,
|
|
||||||
Game,
|
|
||||||
GameList,
|
|
||||||
AuthStatusRequest,
|
|
||||||
AuthStatusResponse,
|
|
||||||
} from "../items";
|
|
||||||
import { apiFetch } from "./api";
|
|
||||||
import { GameImage } from "./GameImage";
|
import { GameImage } from "./GameImage";
|
||||||
|
|
||||||
export const PersonDetails = () => {
|
export const PersonDetails = () => {
|
||||||
@ -20,31 +13,14 @@ export const PersonDetails = () => {
|
|||||||
const [currentUser, setCurrentUser] = useState<string>("");
|
const [currentUser, setCurrentUser] = useState<string>("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const token = localStorage.getItem("token");
|
async function fetchUser() {
|
||||||
if (token) {
|
const token = localStorage.getItem("token");
|
||||||
const req = AuthStatusRequest.create({ token });
|
if (token) {
|
||||||
const buffer = AuthStatusRequest.encode(req).finish();
|
const authStatus = await get_auth_status();
|
||||||
|
setCurrentUser(authStatus?.username || "");
|
||||||
apiFetch("/auth/get_auth_status", {
|
}
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/octet-stream",
|
|
||||||
},
|
|
||||||
body: buffer,
|
|
||||||
})
|
|
||||||
.then((res) => res.arrayBuffer())
|
|
||||||
.then((buffer) => {
|
|
||||||
try {
|
|
||||||
const response = AuthStatusResponse.decode(new Uint8Array(buffer));
|
|
||||||
if (response.authenticated) {
|
|
||||||
setCurrentUser(response.username);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Failed to decode auth status:", e);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
}
|
}
|
||||||
|
fetchUser();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { AuthStatusRequest, AuthStatusResponse } from "../items";
|
||||||
|
|
||||||
export const apiFetch = async (
|
export const apiFetch = async (
|
||||||
url: string,
|
url: string,
|
||||||
options: RequestInit = {}
|
options: RequestInit = {}
|
||||||
@ -26,3 +28,24 @@ export const apiFetch = async (
|
|||||||
|
|
||||||
return response;
|
return response;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const get_auth_status = async (): Promise<AuthStatusResponse | null> => {
|
||||||
|
const token = localStorage.getItem("token") as string;
|
||||||
|
const req = AuthStatusRequest.create({ token });
|
||||||
|
const req_buffer = AuthStatusRequest.encode(req).finish();
|
||||||
|
const response = await apiFetch("/auth/get_auth_status", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/octet-stream",
|
||||||
|
},
|
||||||
|
body: req_buffer,
|
||||||
|
});
|
||||||
|
const buffer = await response.arrayBuffer();
|
||||||
|
try {
|
||||||
|
const response = AuthStatusResponse.decode(new Uint8Array(buffer));
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to decode auth status:", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user