fix bugs
This commit is contained in:
parent
8601d7ced1
commit
76281892a2
@ -3,6 +3,7 @@ use rocket::fs::FileServer;
|
|||||||
use rocket::futures::lock::Mutex;
|
use rocket::futures::lock::Mutex;
|
||||||
|
|
||||||
use backend::auth;
|
use backend::auth;
|
||||||
|
use backend::auth::AdminState;
|
||||||
use backend::items::{self, Game};
|
use backend::items::{self, Game};
|
||||||
use backend::proto_utils;
|
use backend::proto_utils;
|
||||||
use backend::store::{self, User, save_state};
|
use backend::store::{self, User, save_state};
|
||||||
@ -111,6 +112,7 @@ async fn update_game(
|
|||||||
game: proto_utils::Proto<items::Game>,
|
game: proto_utils::Proto<items::Game>,
|
||||||
) -> Option<items::Game> {
|
) -> Option<items::Game> {
|
||||||
let mut games = game_list.lock().await;
|
let mut games = game_list.lock().await;
|
||||||
|
let mut users = user_list.lock().await;
|
||||||
let mut game = game.into_inner();
|
let mut game = game.into_inner();
|
||||||
|
|
||||||
game.title = game.title.trim().to_string();
|
game.title = game.title.trim().to_string();
|
||||||
@ -125,13 +127,14 @@ async fn update_game(
|
|||||||
(g.remote_id == game.remote_id && g.source == game.source) || (g.title == game.title)
|
(g.remote_id == game.remote_id && g.source == game.source) || (g.title == game.title)
|
||||||
}) {
|
}) {
|
||||||
if existing.title != game.title {
|
if existing.title != game.title {
|
||||||
|
let old_title = existing.title.clone();
|
||||||
// Update title for every opinion
|
// Update title for every opinion
|
||||||
for person in user_list.lock().await.iter_mut() {
|
for person in users.iter_mut() {
|
||||||
let opinion = person
|
let opinion = person
|
||||||
.person
|
.person
|
||||||
.opinion
|
.opinion
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|o| o.title == existing.title);
|
.find(|o| o.title == old_title);
|
||||||
if let Some(opinion) = opinion {
|
if let Some(opinion) = opinion {
|
||||||
opinion.title = game.title.clone();
|
opinion.title = game.title.clone();
|
||||||
}
|
}
|
||||||
@ -149,7 +152,6 @@ async fn update_game(
|
|||||||
|
|
||||||
games.sort_unstable_by(|g1, g2| g1.title.cmp(&g2.title));
|
games.sort_unstable_by(|g1, g2| g1.title.cmp(&g2.title));
|
||||||
|
|
||||||
let users = user_list.lock().await;
|
|
||||||
save_state(&games, &users);
|
save_state(&games, &users);
|
||||||
|
|
||||||
r_existing
|
r_existing
|
||||||
@ -189,13 +191,16 @@ async fn refresh_state(
|
|||||||
_token: auth::AdminToken,
|
_token: auth::AdminToken,
|
||||||
game_list: &rocket::State<Mutex<Vec<Game>>>,
|
game_list: &rocket::State<Mutex<Vec<Game>>>,
|
||||||
user_list: &rocket::State<Mutex<Vec<User>>>,
|
user_list: &rocket::State<Mutex<Vec<User>>>,
|
||||||
|
admin_state: &rocket::State<AdminState>,
|
||||||
) -> items::RefreshResponse {
|
) -> items::RefreshResponse {
|
||||||
if let Some((new_games, new_users)) = store::load_state() {
|
if let Some((new_games, new_users)) = store::load_state() {
|
||||||
let mut games = game_list.lock().await;
|
let mut games = game_list.lock().await;
|
||||||
let mut users = user_list.lock().await;
|
let mut users = user_list.lock().await;
|
||||||
|
let mut admins = admin_state.admins.lock().await;
|
||||||
|
|
||||||
*games = new_games;
|
*games = new_games;
|
||||||
*users = new_users;
|
*users = new_users;
|
||||||
|
*admins = store::load_admins();
|
||||||
|
|
||||||
items::RefreshResponse {
|
items::RefreshResponse {
|
||||||
success: true,
|
success: true,
|
||||||
@ -212,12 +217,12 @@ async fn refresh_state(
|
|||||||
#[post("/opinion", data = "<req>")]
|
#[post("/opinion", data = "<req>")]
|
||||||
async fn add_opinion(
|
async fn add_opinion(
|
||||||
token: auth::Token,
|
token: auth::Token,
|
||||||
user_list: &rocket::State<Mutex<Vec<User>>>,
|
|
||||||
game_list: &rocket::State<Mutex<Vec<Game>>>,
|
game_list: &rocket::State<Mutex<Vec<Game>>>,
|
||||||
|
user_list: &rocket::State<Mutex<Vec<User>>>,
|
||||||
req: proto_utils::Proto<items::AddOpinionRequest>,
|
req: proto_utils::Proto<items::AddOpinionRequest>,
|
||||||
) -> Option<items::Person> {
|
) -> Option<items::Person> {
|
||||||
let mut users = user_list.lock().await;
|
|
||||||
let games = game_list.lock().await;
|
let games = game_list.lock().await;
|
||||||
|
let mut users = user_list.lock().await;
|
||||||
let mut result = None;
|
let mut result = None;
|
||||||
|
|
||||||
// Validate game exists
|
// Validate game exists
|
||||||
@ -261,12 +266,12 @@ async fn add_opinion(
|
|||||||
#[patch("/opinion", data = "<req>")]
|
#[patch("/opinion", data = "<req>")]
|
||||||
async fn remove_opinion(
|
async fn remove_opinion(
|
||||||
token: auth::Token,
|
token: auth::Token,
|
||||||
user_list: &rocket::State<Mutex<Vec<User>>>,
|
|
||||||
game_list: &rocket::State<Mutex<Vec<Game>>>,
|
game_list: &rocket::State<Mutex<Vec<Game>>>,
|
||||||
|
user_list: &rocket::State<Mutex<Vec<User>>>,
|
||||||
req: proto_utils::Proto<items::RemoveOpinionRequest>,
|
req: proto_utils::Proto<items::RemoveOpinionRequest>,
|
||||||
) -> Option<items::Person> {
|
) -> Option<items::Person> {
|
||||||
let mut users = user_list.lock().await;
|
|
||||||
let games = game_list.lock().await;
|
let games = game_list.lock().await;
|
||||||
|
let mut users = user_list.lock().await;
|
||||||
let mut result = None;
|
let mut result = None;
|
||||||
|
|
||||||
if let Some(user) = users
|
if let Some(user) = users
|
||||||
@ -340,9 +345,13 @@ async fn get_game_thumbnail(
|
|||||||
.json::<serde_json::Value>()
|
.json::<serde_json::Value>()
|
||||||
.await
|
.await
|
||||||
.ok()?
|
.ok()?
|
||||||
.get("universeId")?
|
.get("universeId")
|
||||||
.as_u64()
|
.and_then(|v| v.as_u64())
|
||||||
.unwrap()
|
};
|
||||||
|
|
||||||
|
let universe_id = match universe_id {
|
||||||
|
Some(id) => id,
|
||||||
|
None => return None.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let api_url = format!(
|
let api_url = format!(
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { Person, PersonList as PersonListProto } from "../items";
|
import { Person, PersonList as PersonListProto } from "../items";
|
||||||
import { Login } from "./Login";
|
import { Login } from "./Login";
|
||||||
import { PersonList } from "./PersonList";
|
import { PersonList } from "./PersonList";
|
||||||
@ -62,10 +62,21 @@ function App() {
|
|||||||
}
|
}
|
||||||
}, [theme]);
|
}, [theme]);
|
||||||
|
|
||||||
const addToast = (message: string, type: ToastType = "info") => {
|
useEffect(() => {
|
||||||
|
const handleUnauthorized = () => {
|
||||||
|
setToken("");
|
||||||
|
setPeople([]);
|
||||||
|
addToast("Session expired. Please log in again.", "info");
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener("unauthorized", handleUnauthorized);
|
||||||
|
return () => window.removeEventListener("unauthorized", handleUnauthorized);
|
||||||
|
}, [addToast]);
|
||||||
|
|
||||||
|
const addToast = useCallback((message: string, type: ToastType = "info") => {
|
||||||
const id = Date.now();
|
const id = Date.now();
|
||||||
setToasts((prev) => [...prev, { id, message, type }]);
|
setToasts((prev) => [...prev, { id, message, type }]);
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
const removeToast = (id: number) => {
|
const removeToast = (id: number) => {
|
||||||
setToasts((prev) => prev.filter((t) => t.id !== id));
|
setToasts((prev) => prev.filter((t) => t.id !== id));
|
||||||
|
|||||||
@ -67,7 +67,7 @@ export function GameDetails({ onShowToast }: Props) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (loading) return <LoadingState message="Loading game details..." />;
|
if (loading) return <LoadingState message="Loading game details..." />;
|
||||||
if (error) return <ErrorState message={error} onRetry={() => window.location.reload()} />;
|
if (error) return <ErrorState message={error} onRetry={() => navigate(0)} />;
|
||||||
if (!game) return <EmptyState icon="🎮" title="Game not found" description="This game doesn't exist or has been deleted" />;
|
if (!game) return <EmptyState icon="🎮" title="Game not found" description="This game doesn't exist or has been deleted" />;
|
||||||
|
|
||||||
const getExternalLink = () => {
|
const getExternalLink = () => {
|
||||||
|
|||||||
@ -22,7 +22,7 @@ export const apiFetch = async (
|
|||||||
if (response.status == 401) {
|
if (response.status == 401) {
|
||||||
localStorage.removeItem("token");
|
localStorage.removeItem("token");
|
||||||
localStorage.removeItem("isAdmin");
|
localStorage.removeItem("isAdmin");
|
||||||
window.location.href = "/";
|
window.dispatchEvent(new CustomEvent("unauthorized"));
|
||||||
}
|
}
|
||||||
throw new Error(`Request failed with status ${response.status}`);
|
throw new Error(`Request failed with status ${response.status}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,12 @@ export function useGameFilter(
|
|||||||
const [fetchedTitles, setFetchedTitles] = useState<string[]>([]);
|
const [fetchedTitles, setFetchedTitles] = useState<string[]>([]);
|
||||||
const metaDataRef = useRef<{ [key: string]: GameProto }>({});
|
const metaDataRef = useRef<{ [key: string]: GameProto }>({});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
metaDataRef.current = {};
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const { gameToNegative, gameToPositiveOpinion } = useMemo(() => {
|
const { gameToNegative, gameToPositiveOpinion } = useMemo(() => {
|
||||||
const gameToNegative = new Map<string, Set<string>>();
|
const gameToNegative = new Map<string, Set<string>>();
|
||||||
const gameToPositiveOpinion = new Map<string, Set<string>>();
|
const gameToPositiveOpinion = new Map<string, Set<string>>();
|
||||||
@ -108,7 +114,7 @@ export function useGameFilter(
|
|||||||
|
|
||||||
const gamesMap = useMemo(() => {
|
const gamesMap = useMemo(() => {
|
||||||
return new Map(Object.entries(metaDataRef.current));
|
return new Map(Object.entries(metaDataRef.current));
|
||||||
}, [fetchedTitles]);
|
}, []);
|
||||||
|
|
||||||
return { filteredGames, gameToPositive: gameToPositiveOpinion, games: gamesMap };
|
return { filteredGames, gameToPositive: gameToPositiveOpinion, games: gamesMap };
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user