307 lines
11 KiB
Rust
307 lines
11 KiB
Rust
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<Arc<SqlitePool>>,
|
|
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<Team>,
|
|
//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<Arc<SqlitePool>>,
|
|
session: Session,
|
|
axum::extract::Path((id, code)): axum::extract::Path<(i64, String)>,
|
|
Form(form): Form<NewWaitingForm>,
|
|
) -> 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<Arc<SqlitePool>>,
|
|
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<Arc<SqlitePool>>,
|
|
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<Arc<SqlitePool>>,
|
|
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<Arc<SqlitePool>>,
|
|
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<Arc<SqlitePool>>,
|
|
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<AppState> {
|
|
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))
|
|
}
|