use crate::{ admin::team::Team, err, models::rating::TeamsAtStationLocation, partials, succ, AppState, Station, }; use axum::{ extract::State, response::{IntoResponse, Redirect}, routing::{get, post}, Form, Router, }; use maud::{html, Markup}; use serde::Deserialize; use sqlx::SqlitePool; use std::sync::Arc; use tower_sessions::Session; async fn view( State(db): State>, session: Session, axum::extract::Path((id, code)): axum::extract::Path<(i64, String)>, ) -> Markup { let Some(station) = Station::login(&db, id, &code).await else { let content = html! { article class="error" { "Falscher Quick-Einlogg-Link. Bitte nochmal scannen oder neu eingeben." } }; return partials::page(content, session, false).await; }; let teams = TeamsAtStationLocation::for_station(&db, &station).await; //pub(crate) not_yet_here: Vec, //pub(crate) waiting: Vec<(Team, Rating)>, //pub(crate) doing: Vec<(Team, Rating)>, //pub(crate) left: Vec<(Team, Rating)>, let content = html! { h1 { (format!("Station {}", station.name)) } article { "Insgesamt sollten " (teams.total_teams) " Teams zu deiner Station kommen." progress value=(teams.total_teams-teams.not_yet_here.len() as i64) max=(teams.total_teams) {} } h2 { "Teams aktuell bei dir" } @if !teams.waiting.is_empty() { (teams.waiting.len()) " Teams warten an deiner Station:" ol { @for (team, rating) in teams.waiting { li { (team.name) " (seit " (rating.local_time_arrived_at()) ")" a href=(format!("/s/{id}/{code}/remove-waiting/{}", team.id)) onclick="return confirm('Bist du sicher, dass das Team noch nicht bei dir ist? Das kann _NICHT_ mehr rückgängig gemacht werden.');" { "🗑️" } a href=(format!("/s/{id}/{code}/team-starting/{}", team.id)) { button { "Team startet" } } } } } } @if !teams.not_yet_here.is_empty() { form action=(format!("/s/{id}/{code}/new-waiting")) method="post" { fieldset role="group" { select name="team_id" aria-label="Team auswählen" required { @for team in &teams.not_yet_here { option value=(team.id) { (team.name) } } } input type="submit" value="Neues Team da"; } } } @if !teams.doing.is_empty() { (teams.doing.len()) " Teams arbeiten an deiner Station:" ol { @for (team, rating) in teams.doing { li { (team.name) " (seit " (rating.local_time_doing()) ")" a href=(format!("/s/{id}/{code}/remove-doing/{}", team.id)) onclick="return confirm('Bist du sicher, dass das Team noch nicht bei dir arbeitet? Das Team wird zurück auf die Warte-Position gesetzt');" { "🗑️" } a href=(format!("/s/{id}/{code}/team-finished/{}", team.id)) { button { "Team fertig" } } } } } } @if !teams.left.is_empty() { h2 { "Teams die bei dir waren" } (teams.left.len()) " Teams waren schon bei dir" ol { @for (team, rating) in teams.left { li { (team.name) " (gegangen um " (rating.local_time_left()) ")" a href=(format!("/s/{id}/{code}/remove-left/{}", team.id)) onclick="return confirm('Bist du sicher, dass das Team noch nicht bei dir fertig ist? Das Team wird zurück auf die Arbeits-Position gesetzt');" { "🗑️" } } } } } }; partials::page(content, session, false).await } #[derive(Deserialize)] struct NewWaitingForm { team_id: i64, } async fn new_waiting( State(db): State>, session: Session, axum::extract::Path((id, code)): axum::extract::Path<(i64, String)>, Form(form): Form, ) -> impl IntoResponse { let Some(station) = Station::login(&db, id, &code).await else { err!( session, "Falscher Quick-Einlogg-Link. Bitte nochmal scannen oder neu eingeben." ); return Redirect::to("/s/{id}/{code}"); }; let Some(team) = Team::find_by_id(&db, form.team_id).await else { err!(session, "Konnte das Team der Warteschlange nicht hinzufügen, weil ein Team mit ID {} nicht existiert", form.team_id); return Redirect::to("/s/{id}/{code}"); }; match station.new_team_waiting(&db, &team).await { Ok(()) => succ!(session, "Team der Warteschlange hinzugefügt"), Err(e) => err!(session, "{e}"), } Redirect::to(&format!("/s/{id}/{code}")) } async fn remove_waiting( State(db): State>, session: Session, axum::extract::Path((id, code, team_id)): axum::extract::Path<(i64, String, i64)>, ) -> impl IntoResponse { let Some(station) = Station::login(&db, id, &code).await else { err!( session, "Falscher Quick-Einlogg-Link. Bitte nochmal scannen oder neu eingeben." ); return Redirect::to("/s/{id}/{code}"); }; let Some(team) = Team::find_by_id(&db, team_id).await else { err!(session, "Konnte das Team nicht von der Warteschlange entfernen, weil ein Team mit ID {} nicht existiert", team_id); return Redirect::to("/s/{id}/{code}"); }; match station.remove_team_waiting(&db, &team).await { Ok(()) => succ!(session, "Team der Warteschlange gelöscht"), Err(e) => err!(session, "{e}"), } Redirect::to(&format!("/s/{id}/{code}")) } async fn team_starting( State(db): State>, session: Session, axum::extract::Path((id, code, team_id)): axum::extract::Path<(i64, String, i64)>, ) -> impl IntoResponse { let Some(station) = Station::login(&db, id, &code).await else { err!( session, "Falscher Quick-Einlogg-Link. Bitte nochmal scannen oder neu eingeben." ); return Redirect::to("/s/{id}/{code}"); }; let Some(team) = Team::find_by_id(&db, team_id).await else { err!( session, "Team kann nicht starten, weil ein Team mit ID {} nicht existiert", team_id ); return Redirect::to("/s/{id}/{code}"); }; match station.team_starting(&db, &team).await { Ok(()) => succ!(session, "Team der Warteschlange gelöscht"), Err(e) => err!(session, "{e}"), } Redirect::to(&format!("/s/{id}/{code}")) } async fn remove_doing( State(db): State>, session: Session, axum::extract::Path((id, code, team_id)): axum::extract::Path<(i64, String, i64)>, ) -> impl IntoResponse { let Some(station) = Station::login(&db, id, &code).await else { err!( session, "Falscher Quick-Einlogg-Link. Bitte nochmal scannen oder neu eingeben." ); return Redirect::to("/s/{id}/{code}"); }; let Some(team) = Team::find_by_id(&db, team_id).await else { err!(session, "Konnte das Team nicht zur Warteschlange hinzufügen, weil ein Team mit ID {} nicht existiert", team_id); return Redirect::to("/s/{id}/{code}"); }; match station.remove_team_doing(&db, &team).await { Ok(()) => succ!(session, "Team zur Warteschlange hinzugefügt"), Err(e) => err!(session, "{e}"), } Redirect::to(&format!("/s/{id}/{code}")) } async fn team_finished( State(db): State>, session: Session, axum::extract::Path((id, code, team_id)): axum::extract::Path<(i64, String, i64)>, ) -> impl IntoResponse { let Some(station) = Station::login(&db, id, &code).await else { err!( session, "Falscher Quick-Einlogg-Link. Bitte nochmal scannen oder neu eingeben." ); return Redirect::to("/s/{id}/{code}"); }; let Some(team) = Team::find_by_id(&db, team_id).await else { err!( session, "Team kann nicht beenden, weil ein Team mit ID {} nicht existiert", team_id ); return Redirect::to("/s/{id}/{code}"); }; match station.team_finished(&db, &team).await { Ok(()) => succ!(session, "Team erfolgreich beendet"), Err(e) => err!(session, "{e}"), } Redirect::to(&format!("/s/{id}/{code}")) } async fn remove_left( State(db): State>, session: Session, axum::extract::Path((id, code, team_id)): axum::extract::Path<(i64, String, i64)>, ) -> impl IntoResponse { let Some(station) = Station::login(&db, id, &code).await else { err!( session, "Falscher Quick-Einlogg-Link. Bitte nochmal scannen oder neu eingeben." ); return Redirect::to("/s/{id}/{code}"); }; let Some(team) = Team::find_by_id(&db, team_id).await else { err!(session, "Konnte das Team nicht zur Arbeits-Position hinzufügen, weil ein Team mit ID {} nicht existiert", team_id); return Redirect::to("/s/{id}/{code}"); }; match station.remove_team_left(&db, &team).await { Ok(()) => succ!(session, "Team zur Arbeitsposition hinzugefügt"), Err(e) => err!(session, "{e}"), } Redirect::to(&format!("/s/{id}/{code}")) } pub(super) fn routes() -> Router { Router::new() .route("/", get(view)) .route("/new-waiting", post(new_waiting)) .route("/remove-waiting/{team_id}", get(remove_waiting)) .route("/team-starting/{team_id}", get(team_starting)) .route("/remove-doing/{team_id}", get(remove_doing)) .route("/team-finished/{team_id}", get(team_finished)) .route("/remove-left/{team_id}", get(remove_left)) }