feat: Add functionality to remove a user's game opinion via a new API endpoint and UI button.
This commit is contained in:
parent
5bb70768e3
commit
0ac633bd34
@ -123,6 +123,37 @@ async fn add_opinion(
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[patch("/opinion", data = "<req>")]
|
||||||
|
async fn remove_opinion(
|
||||||
|
token: auth::Token,
|
||||||
|
user_list: &rocket::State<Mutex<Vec<User>>>,
|
||||||
|
game_list: &rocket::State<Mutex<Vec<Game>>>,
|
||||||
|
req: proto_utils::Proto<items::RemoveOpinionRequest>,
|
||||||
|
) -> Option<items::Person> {
|
||||||
|
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;
|
mod cached_option;
|
||||||
use cached_option::CachedOption;
|
use cached_option::CachedOption;
|
||||||
|
|
||||||
@ -280,6 +311,7 @@ async fn main() -> Result<(), std::io::Error> {
|
|||||||
get_game,
|
get_game,
|
||||||
get_games,
|
get_games,
|
||||||
add_opinion,
|
add_opinion,
|
||||||
|
remove_opinion,
|
||||||
add_game,
|
add_game,
|
||||||
get_game_thumbnail
|
get_game_thumbnail
|
||||||
],
|
],
|
||||||
|
|||||||
@ -112,6 +112,10 @@ export interface AddOpinionRequest {
|
|||||||
wouldPlay: boolean;
|
wouldPlay: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RemoveOpinionRequest {
|
||||||
|
gameTitle: string;
|
||||||
|
}
|
||||||
|
|
||||||
function createBasePerson(): Person {
|
function createBasePerson(): Person {
|
||||||
return { name: "", opinion: [] };
|
return { name: "", opinion: [] };
|
||||||
}
|
}
|
||||||
@ -1151,6 +1155,64 @@ export const AddOpinionRequest: MessageFns<AddOpinionRequest> = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function createBaseRemoveOpinionRequest(): RemoveOpinionRequest {
|
||||||
|
return { gameTitle: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RemoveOpinionRequest: MessageFns<RemoveOpinionRequest> = {
|
||||||
|
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 extends Exact<DeepPartial<RemoveOpinionRequest>, I>>(base?: I): RemoveOpinionRequest {
|
||||||
|
return RemoveOpinionRequest.fromPartial(base ?? ({} as any));
|
||||||
|
},
|
||||||
|
fromPartial<I extends Exact<DeepPartial<RemoveOpinionRequest>, I>>(object: I): RemoveOpinionRequest {
|
||||||
|
const message = createBaseRemoveOpinionRequest();
|
||||||
|
message.gameTitle = object.gameTitle ?? "";
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/** Authentication service */
|
/** Authentication service */
|
||||||
export interface AuthService {
|
export interface AuthService {
|
||||||
Login(request: LoginRequest): Promise<LoginResponse>;
|
Login(request: LoginRequest): Promise<LoginResponse>;
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import {
|
|||||||
Person as PersonProto,
|
Person as PersonProto,
|
||||||
Opinion,
|
Opinion,
|
||||||
AddOpinionRequest,
|
AddOpinionRequest,
|
||||||
|
RemoveOpinionRequest,
|
||||||
} from "../items";
|
} from "../items";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { apiFetch, get_auth_status } from "./api";
|
import { apiFetch, get_auth_status } from "./api";
|
||||||
@ -458,7 +459,33 @@ export function GameList() {
|
|||||||
<ul className="grid-container">
|
<ul className="grid-container">
|
||||||
{games.map((game) => {
|
{games.map((game) => {
|
||||||
const opinion = opinions.find((op) => op.title === game.title);
|
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`, {
|
apiFetch(`/api/opinion`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
@ -496,6 +523,7 @@ export function GameList() {
|
|||||||
display: "flex",
|
display: "flex",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
|
height: "50%",
|
||||||
borderColor: opinion
|
borderColor: opinion
|
||||||
? opinion.wouldPlay
|
? opinion.wouldPlay
|
||||||
? "#4caf50" // would play (green)
|
? "#4caf50" // would play (green)
|
||||||
@ -525,7 +553,7 @@ export function GameList() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleOpinion(game.title, true)}
|
onClick={() => handleOpinion(game.title, 1)}
|
||||||
style={{
|
style={{
|
||||||
width: "50%",
|
width: "50%",
|
||||||
borderColor: "#4caf50",
|
borderColor: "#4caf50",
|
||||||
@ -534,7 +562,16 @@ export function GameList() {
|
|||||||
Would Play
|
Would Play
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleOpinion(game.title, false)}
|
onClick={() => handleOpinion(game.title, 2)}
|
||||||
|
style={{
|
||||||
|
width: "50%",
|
||||||
|
borderColor: "#ffff00",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Neutral
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => handleOpinion(game.title, 0)}
|
||||||
style={{
|
style={{
|
||||||
width: "50%",
|
width: "50%",
|
||||||
borderColor: "#f44336",
|
borderColor: "#f44336",
|
||||||
|
|||||||
@ -72,6 +72,8 @@ message AddOpinionRequest {
|
|||||||
bool would_play = 2;
|
bool would_play = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message RemoveOpinionRequest { string game_title = 1; }
|
||||||
|
|
||||||
service MainService {
|
service MainService {
|
||||||
rpc GetGame(GameRequest) returns (Game);
|
rpc GetGame(GameRequest) returns (Game);
|
||||||
rpc GetGames(GetGamesRequest) returns (GameList);
|
rpc GetGames(GetGamesRequest) returns (GameList);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user