diff --git a/backend/src/main.rs b/backend/src/main.rs index a821d7c..3862ac6 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -123,6 +123,37 @@ async fn add_opinion( result } +#[patch("/opinion", data = "")] +async fn remove_opinion( + token: auth::Token, + user_list: &rocket::State>>, + game_list: &rocket::State>>, + req: proto_utils::Proto, +) -> Option { + let mut users = user_list.lock().await; + let games = game_list.lock().await; + let mut result = None; + + if let Some(user) = users.iter_mut().find(|u| u.person.name == token.username) { + let req = req.into_inner(); + + if let Some(existing) = user + .person + .opinion + .iter() + .position(|o| o.title == req.game_title) + { + user.person.opinion.remove(existing); + } + result = Some(user.person.clone()); + } + + if result.is_some() { + save_state(&games, &users); + } + result +} + mod cached_option; use cached_option::CachedOption; @@ -280,6 +311,7 @@ async fn main() -> Result<(), std::io::Error> { get_game, get_games, add_opinion, + remove_opinion, add_game, get_game_thumbnail ], diff --git a/frontend/items.ts b/frontend/items.ts index bb86e81..78fbf8a 100644 --- a/frontend/items.ts +++ b/frontend/items.ts @@ -112,6 +112,10 @@ export interface AddOpinionRequest { wouldPlay: boolean; } +export interface RemoveOpinionRequest { + gameTitle: string; +} + function createBasePerson(): Person { return { name: "", opinion: [] }; } @@ -1151,6 +1155,64 @@ export const AddOpinionRequest: MessageFns = { }, }; +function createBaseRemoveOpinionRequest(): RemoveOpinionRequest { + return { gameTitle: "" }; +} + +export const RemoveOpinionRequest: MessageFns = { + encode(message: RemoveOpinionRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { + if (message.gameTitle !== "") { + writer.uint32(10).string(message.gameTitle); + } + return writer; + }, + + decode(input: BinaryReader | Uint8Array, length?: number): RemoveOpinionRequest { + const reader = input instanceof BinaryReader ? input : new BinaryReader(input); + const end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseRemoveOpinionRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + if (tag !== 10) { + break; + } + + message.gameTitle = reader.string(); + continue; + } + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skip(tag & 7); + } + return message; + }, + + fromJSON(object: any): RemoveOpinionRequest { + return { gameTitle: isSet(object.gameTitle) ? globalThis.String(object.gameTitle) : "" }; + }, + + toJSON(message: RemoveOpinionRequest): unknown { + const obj: any = {}; + if (message.gameTitle !== "") { + obj.gameTitle = message.gameTitle; + } + return obj; + }, + + create, I>>(base?: I): RemoveOpinionRequest { + return RemoveOpinionRequest.fromPartial(base ?? ({} as any)); + }, + fromPartial, I>>(object: I): RemoveOpinionRequest { + const message = createBaseRemoveOpinionRequest(); + message.gameTitle = object.gameTitle ?? ""; + return message; + }, +}; + /** Authentication service */ export interface AuthService { Login(request: LoginRequest): Promise; diff --git a/frontend/src/GameList.tsx b/frontend/src/GameList.tsx index b7367d1..8b64f06 100644 --- a/frontend/src/GameList.tsx +++ b/frontend/src/GameList.tsx @@ -6,6 +6,7 @@ import { Person as PersonProto, Opinion, AddOpinionRequest, + RemoveOpinionRequest, } from "../items"; import { Link } from "react-router-dom"; import { apiFetch, get_auth_status } from "./api"; @@ -458,7 +459,33 @@ export function GameList() {
    {games.map((game) => { const opinion = opinions.find((op) => op.title === game.title); - function handleOpinion(title: string, wouldPlay: boolean): void { + function handleOpinion(title: string, number: number): void { + if (number == 2) { + apiFetch("/api/opinion", { + method: "PATCH", + headers: { + "Content-Type": "application/octet-stream", + }, + body: RemoveOpinionRequest.encode( + AddOpinionRequest.create({ + gameTitle: title, + }) + ).finish(), + }) + .then((res) => res.arrayBuffer()) + .then((resBuffer) => { + const response = PersonProto.decode( + new Uint8Array(resBuffer) + ); + + setOpinions(response.opinion); + }) + .catch((err) => { + console.error(err); + }); + return; + } + const wouldPlay = number == 1; apiFetch(`/api/opinion`, { method: "POST", headers: { @@ -496,6 +523,7 @@ export function GameList() { display: "flex", justifyContent: "space-between", alignItems: "center", + height: "50%", borderColor: opinion ? opinion.wouldPlay ? "#4caf50" // would play (green) @@ -525,7 +553,7 @@ export function GameList() { }} > +