Adds a details page for a single gamenight.

This commit is contained in:
Dennis Brentjes 2022-05-29 10:28:53 +02:00
parent 2ba2026e21
commit 639405bf9f
6 changed files with 54 additions and 38 deletions

View File

@ -137,6 +137,7 @@ pub struct GamenightOutput {
#[serde(flatten)] #[serde(flatten)]
gamenight: Gamenight, gamenight: Gamenight,
game_list: Vec<Game>, game_list: Vec<Game>,
participants: Vec<User>,
} }
#[get("/gamenights")] #[get("/gamenights")]
@ -150,12 +151,15 @@ pub async fn gamenights(conn: DbConn, _user: User) -> ApiResponseVariant {
let game_results : Result<Vec<GamenightOutput>, DatabaseError> = join_all(gamenights.iter().map(|gn| async move { let game_results : Result<Vec<GamenightOutput>, DatabaseError> = join_all(gamenights.iter().map(|gn| async move {
let games = get_games_of_gamenight(conn_ref, gn.id).await?; let games = get_games_of_gamenight(conn_ref, gn.id).await?;
let participants = load_participants(conn_ref, gn.id).await?;
Ok(GamenightOutput{ Ok(GamenightOutput{
gamenight: gn.clone(), gamenight: gn.clone(),
game_list: games game_list: games,
participants: participants,
}) })
})).await.into_iter().collect(); })).await.into_iter().collect();
match game_results { match game_results {
Ok(result) => ApiResponseVariant::Value(json!(ApiResponse::gamenight_response(result))), Ok(result) => ApiResponseVariant::Value(json!(ApiResponse::gamenight_response(result))),
Err(err) => ApiResponseVariant::Value(json!(ApiResponse::error(err.to_string()))) Err(err) => ApiResponseVariant::Value(json!(ApiResponse::error(err.to_string())))
@ -338,7 +342,7 @@ pub async fn games_unauthorized() -> ApiResponseVariant {
#[get("/participants", format = "application/json", data = "<gamenight_id_json>")] #[get("/participants", format = "application/json", data = "<gamenight_id_json>")]
pub async fn get_participants(conn: DbConn, _user: User, gamenight_id_json: Json<GamenightId>) -> ApiResponseVariant { pub async fn get_participants(conn: DbConn, _user: User, gamenight_id_json: Json<GamenightId>) -> ApiResponseVariant {
match load_participants(&conn, gamenight_id_json.into_inner()).await { match load_participants(&conn, gamenight_id_json.into_inner().gamenight_id).await {
Ok(_) => ApiResponseVariant::Value(json!(ApiResponse::SUCCES)), Ok(_) => ApiResponseVariant::Value(json!(ApiResponse::SUCCES)),
Err(error) => ApiResponseVariant::Value(json!(ApiResponse::error(error.to_string()))), Err(error) => ApiResponseVariant::Value(json!(ApiResponse::error(error.to_string()))),
} }

View File

@ -1,3 +1,4 @@
use crate::schema::users::{users, User};
use crate::schema::{DatabaseError, DbConn}; use crate::schema::{DatabaseError, DbConn};
use diesel::{Connection, ExpressionMethods, QueryDsl, RunQueryDsl}; use diesel::{Connection, ExpressionMethods, QueryDsl, RunQueryDsl};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -160,12 +161,17 @@ pub async fn add_unknown_games(conn: &DbConn, games: &mut Vec<Game>) -> Result<(
Ok(()) Ok(())
} }
pub async fn load_participants(conn: &DbConn, gamenight_id: GamenightId) -> Result<Vec<GamenightParticipantsEntry>, DatabaseError> { pub async fn load_participants(conn: &DbConn, gamenight_id: Uuid) -> Result<Vec<User>, DatabaseError> {
Ok(conn Ok(conn
.run(move |c| { .run::<_, Result<Vec<User>, _>>(move |c| {
gamenight_participants::table let linked_participants = gamenight_participants::table
.filter(gamenight_participants::gamenight_id.eq(gamenight_id.gamenight_id)) .filter(gamenight_participants::gamenight_id.eq(gamenight_id))
.load::<GamenightParticipantsEntry>(c) .load::<GamenightParticipantsEntry>(c)?;
linked_participants.iter().map(|l| {
users::table
.filter(users::id.eq(l.user_id))
.first::<User>(c)
}).collect()
}) })
.await?) .await?)
} }

View File

@ -50,6 +50,10 @@ function App() {
setUser({...user}); setUser({...user});
}; };
const dismissActiveGamenight = () => {
setActiveGamenight(null);
};
useEffect(() => { useEffect(() => {
if (user !== null) { if (user !== null) {
const requestOptions = { const requestOptions = {
@ -116,12 +120,12 @@ function App() {
setFlash={setFlash} setFlash={setFlash}
refetchGamenights={refetchGamenights} refetchGamenights={refetchGamenights}
gamenights={gamenights} gamenights={gamenights}
setActiveGamenight={setActiveGamenight}/> onSelectGamenight={(g) => setActiveGamenight(g)}/>
</> </>
} else { } else {
mainview = <Gamenight mainview = <Gamenight
gamenight={activeGamenight} gamenight={activeGamenight}
onDismis={setActiveGamenight} onDismis={dismissActiveGamenight}
/> />
} }

View File

@ -2,8 +2,6 @@ import React, { useEffect, useState } from 'react';
import DateTime from 'react-datetime'; import DateTime from 'react-datetime';
import GameAdder from './GameAdder'; import GameAdder from './GameAdder';
import Autocomplete from '@mui/material/Autocomplete';
import "react-datetime/css/react-datetime.css"; import "react-datetime/css/react-datetime.css";
function AddGameNight(props) { function AddGameNight(props) {
@ -12,12 +10,6 @@ function AddGameNight(props) {
const [date, setDate] = useState(Date.now()); const [date, setDate] = useState(Date.now());
const [gameList, setGameList] = useState([]); const [gameList, setGameList] = useState([]);
const emptyUuid = "00000000-0000-0000-0000-000000000000";
//temp hack:
props.games = [{id: emptyUuid, name: "mystic vale"}, {id: emptyUuid, name: "Crew"}];
const handleNameChange = (event) => { const handleNameChange = (event) => {
setGameName(event.target.value); setGameName(event.target.value);
}; };

View File

@ -1,26 +1,38 @@
import * as React from 'react'; import * as React from 'react';
function Gamenight(props) { function Gamenight(props) {
console.log(props.gamenight); console.log(props.gamenight);
let games = props.gamenight.game_list.map(g => let games = props.gamenight.game_list.map(g =>
( (
<li> <li>
<span>{g.name}</span> <span>{g.name}</span>
</li> </li>
) )
); );
let participants = props.gamenight.participants.map(p =>
(
<li>
<span>{p.username}</span>
</li>
)
)
return ( return (
<div> <div>
<button onClick={props.onDismis(null)}>x</button> <h3>{props.gamenight.name}</h3>
<h3>{props.gamenight.name}</h3> <button onClick={(e) => props.onDismis()}>x</button>
<span>{props.gamenight.datetime}</span> <span>{props.gamenight.datetime}</span>
<ul> <h4>Games:</h4>
{games} <ul>
</ul> {games}
</div> </ul>
<h4>Participants:</h4>
<ul>
{participants}
</ul>
</div>
) )
} }

View File

@ -33,12 +33,10 @@ function Gamenights(props) {
let gamenights = props.gamenights.map(g => let gamenights = props.gamenights.map(g =>
( (
<li onClick={(e) => {console.log(g); props.setActiveGamenight(g);}}> <li onClick={(e) => props.onSelectGamenight(g)}>
<span>{g.name}</span> <span>{g.name}</span>
{(props.user.id === g.owner_id || props.user.role === "Admin") && {(props.user.id === g.owner_id || props.user.role === "Admin") &&
<button onClick={() =>DeleteGameNight(g.id, g.owner)}> <button onClick={() =>DeleteGameNight(g.id, g.owner)}>x</button>
x
</button>
} }
</li> </li>
) )