more external string, continue #12
Some checks failed
CI/CD Pipeline / deploy (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled

This commit is contained in:
Philipp Hofer 2025-04-23 14:36:22 +02:00
parent 1628bdc252
commit 7f354879fe
9 changed files with 219 additions and 242 deletions

22
Cargo.lock generated
View File

@ -1126,9 +1126,9 @@ dependencies = [
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.15" version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"js-sys", "js-sys",
@ -1720,9 +1720,9 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]] [[package]]
name = "libm" name = "libm"
version = "0.2.11" version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" checksum = "c9627da5196e5d8ed0b0495e61e518847578da83483c37288316d9b2e03a7f72"
[[package]] [[package]]
name = "libredox" name = "libredox"
@ -2134,7 +2134,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a2a4764cc1f8d961d802af27193c6f4f0124bd0e76e8393cf818e18880f0524" checksum = "1a2a4764cc1f8d961d802af27193c6f4f0124bd0e76e8393cf818e18880f0524"
dependencies = [ dependencies = [
"argon2", "argon2",
"getrandom 0.2.15", "getrandom 0.2.16",
"password-hash", "password-hash",
"rand_core 0.6.4", "rand_core 0.6.4",
] ]
@ -2462,7 +2462,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [ dependencies = [
"getrandom 0.2.15", "getrandom 0.2.16",
] ]
[[package]] [[package]]
@ -2509,7 +2509,7 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
dependencies = [ dependencies = [
"getrandom 0.2.15", "getrandom 0.2.16",
"libredox", "libredox",
"thiserror 2.0.12", "thiserror 2.0.12",
] ]
@ -2586,7 +2586,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
dependencies = [ dependencies = [
"cc", "cc",
"cfg-if", "cfg-if",
"getrandom 0.2.15", "getrandom 0.2.16",
"libc", "libc",
"untrusted", "untrusted",
"windows-sys 0.52.0", "windows-sys 0.52.0",
@ -2643,8 +2643,6 @@ dependencies = [
[[package]] [[package]]
name = "rust-i18n" name = "rust-i18n"
version = "3.1.4" version = "3.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2b6307cde881492032919adf26e254981604a6657b339ae23cce8358e9ee203"
dependencies = [ dependencies = [
"globwalk", "globwalk",
"once_cell", "once_cell",
@ -2657,8 +2655,6 @@ dependencies = [
[[package]] [[package]]
name = "rust-i18n-macro" name = "rust-i18n-macro"
version = "3.1.4" version = "3.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c0dc724669fe2ddbbec5ed9daea8147a9030de87ebb46fdc7bb9315701d9912"
dependencies = [ dependencies = [
"glob", "glob",
"once_cell", "once_cell",
@ -2674,8 +2670,6 @@ dependencies = [
[[package]] [[package]]
name = "rust-i18n-support" name = "rust-i18n-support"
version = "3.1.4" version = "3.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b47501de04282525d0192c4b4133f9e3574e1fab3542ddc7bb109ff773dc108b"
dependencies = [ dependencies = [
"arc-swap", "arc-swap",
"base62", "base62",

View File

@ -13,7 +13,8 @@ serde = "1.0"
sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio-rustls", "macros", "chrono"] } sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio-rustls", "macros", "chrono"] }
tokio = { version = "1.44", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.44", features = ["macros", "rt-multi-thread"] }
tower-sessions = "0.14" tower-sessions = "0.14"
rust-i18n = "3" #rust-i18n = { version = "3", features = [ "log-miss-tr" ] }
rust-i18n = { path="/home/ph/rust-i18n" }
thiserror = "2.0" thiserror = "2.0"
async-trait = "0.1" async-trait = "0.1"
password-auth = "1.0" password-auth = "1.0"
@ -37,3 +38,7 @@ typst-pdf = "0.13"
[dev-dependencies] [dev-dependencies]
axum-test = "17.3" axum-test = "17.3"
[package.metadata.i18n]
available-locales = ["de-AT"]
default-locale = "de-AT"

View File

@ -24,6 +24,7 @@ run_restarted: "Stationslauf erfolgreich wieder aufgenommen"
come_home_with_these_groups: "Gruppen mitnehmen" come_home_with_these_groups: "Gruppen mitnehmen"
station_info: "Schön, dass du uns als Stationsbetreuer hilfst." station_info: "Schön, dass du uns als Stationsbetreuer hilfst."
info_crewless_station: "Wenn das eine unbemannte Station ist, wähle hier 0 Personen aus. Dann werden dieser Station keine Startteams zugeteilt und es wird kein PDF generiert." info_crewless_station: "Wenn das eine unbemannte Station ist, wähle hier 0 Personen aus. Dann werden dieser Station keine Startteams zugeteilt und es wird kein PDF generiert."
time: "Uhrzeit"
# #
# ###### # ######
@ -34,15 +35,15 @@ info_crewless_station: "Wenn das eine unbemannte Station ist, wähle hier 0 Pers
# # # # ## ## # # # # # # # ## # # # # # # ## ## # # # # # # # ## # #
# ###### ###### # # ###### # # # #### # # #### # ###### ###### # # ###### # # # #### # # ####
# #
rating: "Bewertung"
ratings: "Bewertungen" ratings: "Bewertungen"
rate_crewless_stations: "Unbemannte Stationen bewerten"
invalid_rating_code: "Falscher Quick-Login-Link. Bitte nochmal scannen oder neu eingeben." invalid_rating_code: "Falscher Quick-Login-Link. Bitte nochmal scannen oder neu eingeben."
infos: "Infos" infos: "Infos"
station_has_no_teams_to_take_to_start: "Nachdem es offiziell losgeht kannst du gleich direkt zu deiner Station gehen, du musst keine Teams mitnehmen." station_has_no_teams_to_take_to_start: "Nachdem es offiziell losgeht kannst du gleich direkt zu deiner Station gehen, du musst keine Teams mitnehmen."
station_should_take_one_teams_to_start: "Nachdem es offiziell losgeht, nimm bitte folgendes Team am Anfang zu deiner Station mit:" station_should_take_one_teams_to_start: "Nachdem es offiziell losgeht, nimm bitte folgendes Team am Anfang zu deiner Station mit:"
station_should_take_n_teams_to_start: "Nachdem es offiziell losgeht, nimm bitte folgende %{amount} Teams am Anfang zu deiner Station mit:" station_should_take_n_teams_to_start: "Nachdem es offiziell losgeht, nimm bitte folgende %{amount} Teams am Anfang zu deiner Station mit:"
your_station_is_here: "Deine Station befindet sich hier:" your_station_is_here: "Deine Station befindet sich hier:"
station_ready: "Sobald du bei deiner Station bist und bereit zu starten bist, drücke diesen Button damit wir Bescheid wissen" button_station_ready: "Sobald du bei deiner Station bist und bereit zu starten bist, drücke diesen Button damit wir Bescheid wissen"
station_not_yet_ready: "Bin mit der Station doch noch nicht bereit..." station_not_yet_ready: "Bin mit der Station doch noch nicht bereit..."
one_team_should_come_to_station: "Insgesamt sollte 1 Team zu deiner Station kommen." one_team_should_come_to_station: "Insgesamt sollte 1 Team zu deiner Station kommen."
n_teams_should_come_to_station: "Insgesamt sollten %{amount} Teams zu deiner Station kommen." n_teams_should_come_to_station: "Insgesamt sollten %{amount} Teams zu deiner Station kommen."
@ -116,8 +117,9 @@ confirm_station_cancel_team_finished: "Bist du sicher, dass das Team noch nicht
# #
station: "Station" station: "Station"
stations: "Stationen" stations: "Stationen"
nonexisting_station: "Station mit ID %{id} existiert nicht."
station_url: "Stations-Link" station_url: "Stations-Link"
station_url_info: "Diesen Link nur Betreuern der Station #{station} geben! Mit diesem Link erhält man die Berechtigung, Teams zu bewerten." station_url_info: "Diesen Link nur Betreuern der Station %{station} geben! Mit diesem Link erhält man die Berechtigung, Teams zu bewerten."
login_link: "Login-Link" login_link: "Login-Link"
station_name_edit: "Routennamen bearbeiten" station_name_edit: "Routennamen bearbeiten"
go_to_stations: "Zu den Stationen" go_to_stations: "Zu den Stationen"
@ -166,6 +168,11 @@ location_deleted: "Standort für die Station %{station} wurde erfolgreich gelös
progress: "Fortschritt" progress: "Fortschritt"
station_team_progress: "%{arrived}/%{total} (davon %{waiting} wartend + %{active} aktiv)" station_team_progress: "%{arrived}/%{total} (davon %{waiting} wartend + %{active} aktiv)"
station_ready: "Station bereit!" station_ready: "Station bereit!"
first_station: "Erste Station"
first_station_expl: "Die erste Station wird beim Anlegen eines Team automatisch an diejenige Station vergeben, die aktuell am wenigsten Startteams hat. Diese Zuteilung kannst du hier auch manuell verändern."
new_team_name: "Team %{old} heißt ab sofort %{new}"
notes_edited: "Notizen für das Team %{team} erfolgreich geändert"
amount_teammembers_edited: "Anzahl an Mitglieder für das Team %{team} erfolgreich geändert"
# #
@ -179,10 +186,39 @@ station_ready: "Station bereit!"
# #
team: "Team" team: "Team"
teams: "Teams" teams: "Teams"
nonexisting_team: "Team mit ID %{id} existiert nicht."
select_team: "Team auswählen" select_team: "Team auswählen"
new_team: "Neues Team"
edit_teamname: "Teamname bearbeiten"
teamname: "Teamname"
go_to_teams: "Zu den Teams" go_to_teams: "Zu den Teams"
not_yet_started: "nocht nicht gestartet" not_yet_started: "nocht nicht gestartet"
not_yet_done: "nocht nicht fertig" not_yet_done: "nocht nicht fertig"
team_created: "Team %{team} erstellt"
team_deleted: "Team %{team} gelöscht"
add_new_note: "Neue Notiz hinzufügen"
team_not_created_duplicate_name: "Team %{team} konnte nicht erstellt werden, da es bereits ein Team mit diesem Namen gibt (%{err})"
team_not_created_no_station_in_route: "Team %{team} konnte nicht erstellt werden, da in der angegebenen Route %{route} keine Station vorkommt und daher die Startstation nicht festgelegt werden kann."
team_not_deleted_already_in_use: "Team %{team} kann nicht gelöscht werden, da es bereits verwendet wird. (%{err})"
amount_teammembers: "Anzahl Teammitglieder"
not_sure_about_amount_team: "Ich weiß noch nicht wv. Personen dieses Team beherbergt."
select_station: "Station auswählen"
already_has_1_start_team: "schon 1 Startteam"
already_has_n_start_team: "schon %{amount} Startteams"
last_station: "Letzte Station"
route_edited: "Team %{team} läuft ab sofort die Route %{route}. Auch die erste Station hat sich dadurch auf %{first_station} verändert"
team_not_edited_route_has_no_stations: "Team %{team} kann nicht zur Route %{route} zugeteilt werden, da diese Route noch keine Station hat und daher die Startstation nicht festgelegt werden kann."
first_station_not_edited_not_on_route: "Konnte Station %{station} nicht als erste Station dem Team %{team} zuteilen, weil dieses Team bei Route %{route} mitläuft und die Station nicht auf dieser Route liegt."
last_station_not_edited_not_on_route: "Konnte Station %{station} nicht als letzte Station dem Team %{team} zuteilen, weil dieses Team bei Route %{route} mitläuft und die Station nicht auf dieser Route liegt."
changed_first_station: "Erste Station des Teams %{team} ist ab sofort Station %{station}"
changed_last_station: "Letzte Station des Teams %{team} ist ab sofort Station %{station}"
last_contact_team: "Letzter Stationskontakt der Teams"
not_yet_seen: "Noch nicht gesehen"
no_teams: "Es gibt noch keine Teams."
route_needed_before_creating_teams: "Bevor du ein Team erstellen kannst, musst du zumindest eine Route erstellen, die das Team gehen kann"
have_i_lost_groups: "Hab ich eine Gruppe verloren? 😳"
confirm_delete_team: "Bist du sicher, dass das Team gelöscht werden soll? Das kann _NICHT_ mehr rückgängig gemacht werden."
# #
@ -239,8 +275,11 @@ confirm_admin_delete: "Bist du sicher, dass der User gelöscht werden soll? Das
# #
route: "Route" route: "Route"
routes: "Routen" routes: "Routen"
nonexisting_route: "Route mit ID %{id} existiert nicht."
route_new: "Neue Route" route_new: "Neue Route"
route_name: "Routenname" route_name: "Routenname"
create_route: "Route erstellen"
select_route: "Route auswählen"
route_name_edit: "Routennamen bearbeiten" route_name_edit: "Routennamen bearbeiten"
route_has_no_station_assigned: "Keine Station zugeteilt" # should be short -> tooltip route_has_no_station_assigned: "Keine Station zugeteilt" # should be short -> tooltip
route_confirm_deletion: "Bist du sicher, dass die Route gelöscht werden soll? Das kann _NICHT_ mehr rückgängig gemacht werden." route_confirm_deletion: "Bist du sicher, dass die Route gelöscht werden soll? Das kann _NICHT_ mehr rückgängig gemacht werden."
@ -258,7 +297,7 @@ teams_with_this_route: "Teams mit dieser Route"
no_team_with_this_route: "Noch kein Team ist dieser Route zugeteilt" no_team_with_this_route: "Noch kein Team ist dieser Route zugeteilt"
route_update_err_nonexisting: "Route mit ID %{id} konnte nicht bearbeitet werden, da sie nicht existiert" route_update_err_nonexisting: "Route mit ID %{id} konnte nicht bearbeitet werden, da sie nicht existiert"
route_new_name: "Route %{old} heißt ab sofort %{new}." route_new_name: "Route %{old} heißt ab sofort %{new}."
route_cant_add_nonexisting_station: "Station mit ID {id} konnte nicht der Route %{route} hinzugefügt werden, da die Station nicht existiert" route_cant_add_nonexisting_station: "Station mit ID %{id} konnte nicht der Route %{route} hinzugefügt werden, da die Station nicht existiert"
station_added_to_route: "Station %{station} wurde erfolgreich der Route %{route} hinzugefügt" station_added_to_route: "Station %{station} wurde erfolgreich der Route %{route} hinzugefügt"
station_can_only_be_added_once_to_route: "Station %{station} kann nur 1x der Route %{route} hinzugefügt werden (%{err})" station_can_only_be_added_once_to_route: "Station %{station} kann nur 1x der Route %{route} hinzugefügt werden (%{err})"
cant_remove_station_from_nonexisting_route: "Konnte keine Station von der Route mit ID %{id} entfernen, da diese Route nicht existiert." cant_remove_station_from_nonexisting_route: "Konnte keine Station von der Route mit ID %{id} entfernen, da diese Route nicht existiert."

View File

@ -1,12 +1,12 @@
use super::Route; use super::Route;
use crate::{AppState, admin::station::Station, er, page, suc}; use crate::{admin::station::Station, er, page, suc, AppState};
use axum::{ use axum::{
Form, Router,
extract::State, extract::State,
response::{IntoResponse, Redirect}, response::{IntoResponse, Redirect},
routing::{get, post}, routing::{get, post},
Form, Router,
}; };
use maud::{Markup, PreEscaped, html}; use maud::{html, Markup, PreEscaped};
use serde::Deserialize; use serde::Deserialize;
use sqlx::SqlitePool; use sqlx::SqlitePool;
use std::sync::Arc; use std::sync::Arc;
@ -91,13 +91,12 @@ async fn delete(
axum::extract::Path(id): axum::extract::Path<i64>, axum::extract::Path(id): axum::extract::Path<i64>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(route) = Route::find_by_id(&db, id).await else { let Some(route) = Route::find_by_id(&db, id).await else {
er!(session, t!("route_delete_err_nonexisting")); er!(session, t!("route_delete_err_nonexisting", id = id));
return Redirect::to("/admin/route"); return Redirect::to("/admin/route");
}; };
match route.delete(&db).await { match route.delete(&db).await {
Ok(()) => suc!(session, t!("route_delete_succ")), Ok(()) => suc!(session, t!("route_delete_succ", name = route.name)),
Err(e) => er!( Err(e) => er!(
session, session,
t!("route_delete_err_already_used", name = route.name, err = e) t!("route_delete_err_already_used", name = route.name, err = e)
@ -113,8 +112,7 @@ async fn view(
axum::extract::Path(id): axum::extract::Path<i64>, axum::extract::Path(id): axum::extract::Path<i64>,
) -> Result<Markup, impl IntoResponse> { ) -> Result<Markup, impl IntoResponse> {
let Some(route) = Route::find_by_id(&db, id).await else { let Some(route) = Route::find_by_id(&db, id).await else {
er!(session, t!("route_delete_err_nonexisting")); er!(session, t!("route_delete_err_nonexisting", id = id));
return Err(Redirect::to("/admin/route")); return Err(Redirect::to("/admin/route"));
}; };

View File

@ -128,7 +128,7 @@ async fn view(
@if !station.crewless() { @if !station.crewless() {
tr { tr {
th scope="row" { th scope="row" {
(t!("station_link")) (t!("station_url"))
article class="warning" { article class="warning" {
(t!("station_url_info", station=station.name)) (t!("station_url_info", station=station.name))
} }
@ -584,7 +584,7 @@ async fn update_location_clear(
station.update_location_clear(&db).await; station.update_location_clear(&db).await;
suc!(session, t!("location_changed", station = station.name)); suc!(session, t!("location_deleted", station = station.name));
Redirect::to(&format!("/admin/station/{id}")) Redirect::to(&format!("/admin/station/{id}"))
} }

View File

@ -1,10 +1,10 @@
use super::{CreateError, LastContactTeam, Team}; use super::{CreateError, LastContactTeam, Team};
use crate::{ use crate::{
admin::{route::Route, station::Station}, admin::{route::Route, station::Station},
err, er,
models::rating::Rating, models::rating::Rating,
partials::page, partials::page,
pl, succ, AppState, suc, AppState,
}; };
use axum::{ use axum::{
extract::State, extract::State,
@ -30,36 +30,32 @@ async fn create(
Form(form): Form<CreateForm>, Form(form): Form<CreateForm>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(route) = Route::find_by_id(&db, form.route_id).await else { let Some(route) = Route::find_by_id(&db, form.route_id).await else {
err!( er!(session, t!("nonexisting_route", id = form.route_id));
session,
"Team mit {} konnte nicht erstellt werden, da keine Route mit ID {} existiert",
form.name,
form.route_id
);
return Redirect::to("/admin/team"); return Redirect::to("/admin/team");
}; };
let id = match Team::create(&db, &form.name, &route).await { let id = match Team::create(&db, &form.name, &route).await {
Ok(id) => { Ok(id) => {
succ!(session, "Team '{}' erfolgreich erstellt!", form.name); suc!(session, t!("team_created", team = form.name));
id id
} }
Err(CreateError::DuplicateName(e)) => { Err(CreateError::DuplicateName(e)) => {
err!( er!(
session, session,
"Team '{}' konnte _NICHT_ erstellt werden, da es bereits ein Team mit diesem Namen gibt ({e})!", t!("team_not_created_duplicate_name", team = form.name, err = e)
form.name
); );
return Redirect::to("/admin/team"); return Redirect::to("/admin/team");
} }
Err(CreateError::NoStationForRoute) => { Err(CreateError::NoStationForRoute) => {
err!( er!(
session, session,
"Team '{}' konnte _NICHT_ erstellt werden, da in der angegebenen Route '{}' noch keine Stationen vorkommen", t!(
form.name, "team_not_created_no_station_in_route",
route.name team = form.name,
route = route.name
)
); );
return Redirect::to("/admin/team"); return Redirect::to("/admin/team");
@ -75,20 +71,15 @@ async fn delete(
axum::extract::Path(id): axum::extract::Path<i64>, axum::extract::Path(id): axum::extract::Path<i64>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(team) = Team::find_by_id(&db, id).await else { let Some(team) = Team::find_by_id(&db, id).await else {
err!( er!(session, t!("nonexisting_team", id = id));
session,
"Team mit ID {id} konnte nicht gelöscht werden, da sie nicht existiert"
);
return Redirect::to("/admin/team"); return Redirect::to("/admin/team");
}; };
match team.delete(&db).await { match team.delete(&db).await {
Ok(()) => succ!(session, "Team '{}' erfolgreich gelöscht!", team.name), Ok(()) => suc!(session, t!("team_deleted", team = team.name)),
Err(e) => err!( Err(e) => er!(
session, session,
"Team '{}' kann nicht gelöscht werden, da sie bereits verwendet wird. ({e})", t!("team_not_deleted_already_in_use", team = team.name, err = e)
team.name
), ),
} }
@ -99,15 +90,19 @@ async fn quick(db: Arc<SqlitePool>, team: &Team, stations: Vec<Station>, redirec
html! { html! {
h1 { h1 {
a href=(format!("/admin/team/{}", team.id)) { "↩️" } a href=(format!("/admin/team/{}", team.id)) { "↩️" }
"Bewertungen Team " (team.name) (t!("ratings"))
" "
(t!("team"))
" "
(team.name)
} }
form action=(format!("/admin/team/{}/quick", team.id)) method="post" { form action=(format!("/admin/team/{}/quick", team.id)) method="post" {
input type="hidden" name="redirect" value=(redirect); input type="hidden" name="redirect" value=(redirect);
table { table {
thead { thead {
tr { tr {
th { "Station" } th { (t!("station")) }
th { "Punkte" } th { (t!("points")) }
} }
} }
tbody { tbody {
@ -122,11 +117,11 @@ async fn quick(db: Arc<SqlitePool>, team: &Team, stations: Vec<Station>, redirec
@if let Some(rating) = Rating::find_by_team_and_station(&db, team, station).await { @if let Some(rating) = Rating::find_by_team_and_station(&db, team, station).await {
a href=(format!("/s/{}/{}", station.id, station.pw)){ a href=(format!("/s/{}/{}", station.id, station.pw)){
@if let Some(points) = rating.points { @if let Some(points) = rating.points {
em data-tooltip="Schon eingetragen" { em data-tooltip=(t!("already_entered")) {
(points) (points)
} }
} @else { } @else {
em data-tooltip="Team gerade bei Station" { "?" } em data-tooltip=(t!("team_currently_at_station")) { "?" }
} }
} }
} @else { } @else {
@ -138,7 +133,7 @@ async fn quick(db: Arc<SqlitePool>, team: &Team, stations: Vec<Station>, redirec
} }
} }
} }
input type="submit" value="Speichern"; input type="submit" value=(t!("save"));
} }
} }
} }
@ -148,11 +143,7 @@ async fn quick_crewless(
axum::extract::Path(id): axum::extract::Path<i64>, axum::extract::Path(id): axum::extract::Path<i64>,
) -> Result<Markup, impl IntoResponse> { ) -> Result<Markup, impl IntoResponse> {
let Some(team) = Team::find_by_id(&db, id).await else { let Some(team) = Team::find_by_id(&db, id).await else {
err!( er!(session, t!("nonexisting_team", id = id));
session,
"Team mit ID {id} konnte nicht geöffnet werden, da sie nicht existiert"
);
return Err(Redirect::to("/admin/team")); return Err(Redirect::to("/admin/team"));
}; };
@ -169,11 +160,7 @@ async fn quick_all(
axum::extract::Path(id): axum::extract::Path<i64>, axum::extract::Path(id): axum::extract::Path<i64>,
) -> Result<Markup, impl IntoResponse> { ) -> Result<Markup, impl IntoResponse> {
let Some(team) = Team::find_by_id(&db, id).await else { let Some(team) = Team::find_by_id(&db, id).await else {
err!( er!(session, t!("nonexisting_team", id = id));
session,
"Team mit ID {id} konnte nicht geöffnet werden, da sie nicht existiert"
);
return Err(Redirect::to("/admin/team")); return Err(Redirect::to("/admin/team"));
}; };
@ -197,11 +184,7 @@ async fn quick_post(
Form(form): Form<QuickUpdate>, Form(form): Form<QuickUpdate>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(team) = Team::find_by_id(&db, id).await else { let Some(team) = Team::find_by_id(&db, id).await else {
err!( er!(session, t!("nonexisting_team", id = id));
session,
"Team mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"
);
return Redirect::to("/admin/team"); return Redirect::to("/admin/team");
}; };
@ -231,7 +214,13 @@ async fn quick_post(
.await .await
.is_some() .is_some()
{ {
ret.push_str(&format!("Skipped rating for station {} because this station already has a rating for team {}", station.name, team.name)); let msg: String = t!(
"error_rating_team_already_rated",
team = team.name,
station = station.name
)
.into();
ret.push_str(&msg);
continue; continue;
} }
@ -245,12 +234,9 @@ async fn quick_post(
} }
if amount_succ == 0 { if amount_succ == 0 {
succ!( suc!(session, t!("funny_you_entered_no_rating"));
session,
"Du hast keine Bewertungen eingegeben... Spaßvogel!"
);
} else { } else {
succ!(session, "Erfolgreich {amount_succ} Bewertungen eingetragen"); suc!(session, t!("entered_n_ratings", amount = amount_succ));
} }
Redirect::to(&format!("/admin/team/{id}/quick{}", form.redirect)) Redirect::to(&format!("/admin/team/{id}/quick{}", form.redirect))
@ -262,11 +248,7 @@ async fn view(
axum::extract::Path(id): axum::extract::Path<i64>, axum::extract::Path(id): axum::extract::Path<i64>,
) -> Result<Markup, impl IntoResponse> { ) -> Result<Markup, impl IntoResponse> {
let Some(team) = Team::find_by_id(&db, id).await else { let Some(team) = Team::find_by_id(&db, id).await else {
err!( er!(session, t!("nonexisting_team", id = id));
session,
"Team mit ID {id} konnte nicht geöffnet werden, da sie nicht existiert"
);
return Err(Redirect::to("/admin/team")); return Err(Redirect::to("/admin/team"));
}; };
let first_station = team.first_station(&db).await; let first_station = team.first_station(&db).await;
@ -279,14 +261,19 @@ async fn view(
let content = html! { let content = html! {
h1 { h1 {
a href="/admin/team" { "↩️" } a href="/admin/team" { "↩️" }
"Team " (team.name) (t!("team"))
" "
(team.name)
} }
article { article {
details { details {
summary { "Teamnamen bearbeiten ✏️" } summary {
(t!("edit_teamname"))
" ✏️"
}
form action=(format!("/admin/team/{}/name", team.id)) method="post" { form action=(format!("/admin/team/{}/name", team.id)) method="post" {
input type="text" name="name" value=(team.name) required; input type="text" name="name" value=(team.name) required;
input type="submit" value="Speichern"; input type="submit" value=(t!("save"));
} }
} }
@ -294,7 +281,7 @@ async fn view(
table { table {
tbody { tbody {
tr { tr {
th scope="row" { "Notizen" }; th scope="row" { (t!("notes")) };
td { td {
@match &team.notes { @match &team.notes {
Some(notes) => { Some(notes) => {
@ -303,22 +290,22 @@ async fn view(
summary { "✏️" } summary { "✏️" }
form action=(format!("/admin/team/{}/notes", team.id)) method="post" { form action=(format!("/admin/team/{}/notes", team.id)) method="post" {
textarea name="notes" required rows="10" { (notes) }; textarea name="notes" required rows="10" { (notes) };
input type="submit" value="Speichern"; input type="submit" value=(t!("save"));
} }
} }
}, },
None => details { None => details {
summary { "Neue Notiz hinzufügen" } summary { (t!("add_new_note")) }
form action=(format!("/admin/team/{}/notes", team.id)) method="post" { form action=(format!("/admin/team/{}/notes", team.id)) method="post" {
textarea name="notes" required rows="10" {}; textarea name="notes" required rows="10" {};
input type="submit" value="Speichern"; input type="submit" value=(t!("save"));
} }
} }
} }
} }
} }
tr { tr {
th scope="row" { "Anzahl Teammitglieder" }; th scope="row" { (t!("amount_teammembers")) };
td { td {
@match team.amount_people { @match team.amount_people {
Some(amount) => (amount), Some(amount) => (amount),
@ -328,11 +315,11 @@ async fn view(
summary { "✏️" } summary { "✏️" }
form action=(format!("/admin/team/{}/amount-people", team.id)) method="post" { form action=(format!("/admin/team/{}/amount-people", team.id)) method="post" {
input type="number" name="amount_people" min="0" max="10"; input type="number" name="amount_people" min="0" max="10";
input type="submit" value="Speichern"; input type="submit" value=(t!("save"));
} }
a href=(format!("/admin/team/{}/amount-people-reset", team.id)) { a href=(format!("/admin/team/{}/amount-people-reset", team.id)) {
button class="error" { button class="error" {
em data-tooltip="Ich weiß noch nicht wv. Personen dieses Team beherbergt." { em data-tooltip=(t!("not_sure_about_amount_team")) {
"?" "?"
} }
} }
@ -341,7 +328,7 @@ async fn view(
} }
} }
tr { tr {
th scope="row" { "Route" }; th scope="row" { (t!("route")) };
td { td {
a href=(format!("/admin/route/{}", &team.route(&db).await.id)) { a href=(format!("/admin/route/{}", &team.route(&db).await.id)) {
(&team.route(&db).await.name) (&team.route(&db).await.name)
@ -350,7 +337,7 @@ async fn view(
details { details {
summary { "✏️" } summary { "✏️" }
form action=(format!("/admin/team/{}/update-route", team.id)) method="post" { form action=(format!("/admin/team/{}/update-route", team.id)) method="post" {
select name="route_id" aria-label="Route auswählen" required { select name="route_id" aria-label=(t!("select_route")) required {
@for route in &routes { @for route in &routes {
@if route.id != team.route(&db).await.id { @if route.id != team.route(&db).await.id {
option value=(route.id) { option value=(route.id) {
@ -359,7 +346,7 @@ async fn view(
} }
} }
} }
input type="submit" value="Team speichern"; input type="submit" value=(t!("save"));
} }
} }
} }
@ -367,9 +354,9 @@ async fn view(
} }
tr { tr {
th scope="row" { th scope="row" {
"Erste Station" (t!("first_station"))
article { article {
"Die erste Station wird beim Anlegen eines Team automatisch an diejenige Station vergeben, die aktuell am wenigsten Startteams hat. Diese Zuteilung kannst du hier auch manuell verändern." (t!("first_station_expl"))
} }
}; };
td { td {
@ -380,20 +367,24 @@ async fn view(
details { details {
summary { "✏️" } summary { "✏️" }
form action=(format!("/admin/team/{}/update-first-station", team.id)) method="post" { form action=(format!("/admin/team/{}/update-first-station", team.id)) method="post" {
select name="first_station_id" aria-label="Station auswählen" required { select name="first_station_id" aria-label=(t!("select_station")) required {
@for station in &stations { @for station in &stations {
@if station.id != first_station.id { @if station.id != first_station.id {
option value=(station.id) { option value=(station.id) {
(station.name) (station.name)
@let amount_start_teams = Team::all_with_first_station(&db, station).await.len(); @let amount_start_teams = Team::all_with_first_station(&db, station).await.len();
@if amount_start_teams > 0 { @if amount_start_teams > 0 {
(format!(" (schon {amount_start_teams} {})", pl(amount_start_teams, "Startteam", "s"))) @if amount_start_teams == 1 {
(t!("already_has_1_start_team"))
}@else{
(t!("already_has_n_start_team", amount=amount_start_teams))
}
} }
} }
} }
} }
} }
input type="submit" value="Station speichern"; input type="submit" value=(t!("save"));
} }
} }
} }
@ -402,7 +393,7 @@ async fn view(
@if let Some(last_station) = last_station { @if let Some(last_station) = last_station {
tr { tr {
th scope="row" { th scope="row" {
"Letzte Station" (t!("last_station"))
}; };
td { td {
a href=(format!("/admin/station/{}", last_station.id)) { a href=(format!("/admin/station/{}", last_station.id)) {
@ -412,7 +403,7 @@ async fn view(
details { details {
summary { "✏️" } summary { "✏️" }
form action=(format!("/admin/team/{}/update-last-station", team.id)) method="post" { form action=(format!("/admin/team/{}/update-last-station", team.id)) method="post" {
select name="last_station_id" aria-label="Station auswählen" required { select name="last_station_id" aria-label=(t!("select_station")) required {
@for station in &stations { @for station in &stations {
@if station.id != last_station.id { @if station.id != last_station.id {
option value=(station.id) { option value=(station.id) {
@ -421,7 +412,7 @@ async fn view(
} }
} }
} }
input type="submit" value="Station speichern"; input type="submit" value=(t!("save"));
} }
} }
} }
@ -433,13 +424,13 @@ async fn view(
} }
a href=(format!("/admin/team/{}/quick", team.id)){ a href=(format!("/admin/team/{}/quick", team.id)){
button { button {
"Bewertungen" (t!("ratings"))
} }
} }
hr; hr;
a href=(format!("/admin/team/{}/quick/crewless", team.id)){ a href=(format!("/admin/team/{}/quick/crewless", team.id)){
button { button {
"Unbemannte Bewertungen" (t!("rate_crewless_stations"))
} }
} }
}; };
@ -457,21 +448,15 @@ async fn update_name(
Form(form): Form<UpdateNameForm>, Form(form): Form<UpdateNameForm>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(team) = Team::find_by_id(&db, id).await else { let Some(team) = Team::find_by_id(&db, id).await else {
err!( er!(session, t!("nonexisting_team", id = id));
session,
"Team mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"
);
return Redirect::to("/admin/team"); return Redirect::to("/admin/team");
}; };
team.update_name(&db, &form.name).await; team.update_name(&db, &form.name).await;
succ!( suc!(
session, session,
"Team '{}' heißt ab sofort '{}'.", t!("new_team_name", old = team.name, new = form.name)
team.name,
form.name
); );
Redirect::to(&format!("/admin/team/{id}")) Redirect::to(&format!("/admin/team/{id}"))
@ -488,21 +473,13 @@ async fn update_notes(
Form(form): Form<UpdateNotesForm>, Form(form): Form<UpdateNotesForm>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(team) = Team::find_by_id(&db, id).await else { let Some(team) = Team::find_by_id(&db, id).await else {
err!( er!(session, t!("nonexisting_team", id = id));
session,
"Team mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"
);
return Redirect::to("/admin/team"); return Redirect::to("/admin/team");
}; };
team.update_notes(&db, &form.notes).await; team.update_notes(&db, &form.notes).await;
succ!( suc!(session, t!("notes_edited", team = team.name));
session,
"Notizen für das Team '{}' wurden erfolgreich bearbeitet!",
team.name
);
Redirect::to(&format!("/admin/team/{id}")) Redirect::to(&format!("/admin/team/{id}"))
} }
@ -518,21 +495,13 @@ async fn update_amount_people(
Form(form): Form<UpdateAmountPeopleForm>, Form(form): Form<UpdateAmountPeopleForm>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(team) = Team::find_by_id(&db, id).await else { let Some(team) = Team::find_by_id(&db, id).await else {
err!( er!(session, t!("nonexisting_team", id = id));
session,
"Team mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"
);
return Redirect::to("/admin/team"); return Redirect::to("/admin/team");
}; };
team.update_amount_people(&db, form.amount_people).await; team.update_amount_people(&db, form.amount_people).await;
succ!( suc!(session, t!("amount_teammembers_edited", team = team.name));
session,
"Anzahl an Mitglieder für das Team '{}' wurden erfolgreich bearbeitet!",
team.name
);
Redirect::to(&format!("/admin/team/{id}")) Redirect::to(&format!("/admin/team/{id}"))
} }
@ -549,38 +518,32 @@ async fn update_route(
) -> impl IntoResponse { ) -> impl IntoResponse {
// TODO: move sanity checks into mod.rs // TODO: move sanity checks into mod.rs
let Some(team) = Team::find_by_id(&db, id).await else { let Some(team) = Team::find_by_id(&db, id).await else {
err!( er!(session, t!("nonexisting_team", id = id));
session,
"Team mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"
);
return Redirect::to("/admin/team"); return Redirect::to("/admin/team");
}; };
let Some(route) = Route::find_by_id(&db, form.route_id).await else { let Some(route) = Route::find_by_id(&db, form.route_id).await else {
err!( er!(session, t!("nonexisting_route", id = form.route_id));
session,
"Konnte Team mit ID {id} konnte nicht zur Route mit ID {} bearbeiten, da diese Route nicht existiert.",
form.route_id
);
return Redirect::to(&format!("/admin/team/{id}")); return Redirect::to(&format!("/admin/team/{id}"));
}; };
match team.update_route(&db, &route).await { match team.update_route(&db, &route).await {
Ok(new_first_station_name) => succ!( Ok(new_first_station_name) => suc!(
session, session,
"Team '{}' läuft ab sofort die Route '{}'. Auch die erste Station hat sich dadurch auf {} verändert!!", t!(
team.name, "route_edited",
route.name, team = team.name,
new_first_station_name route = route.name,
first_station = new_first_station_name
)
), ),
Err(()) => err!( Err(()) => er!(
session, session,
"Konnte für das Team {} nicht die Route {} auswählen, da Route {} keine Stationen zugeteilt hat.", t!(
team.name, "team_not_edited_route_has_no_stations",
route.name, team = team.name,
route.name route = route.name
)
), ),
} }
@ -598,33 +561,28 @@ async fn update_first_station(
Form(form): Form<UpdateFirstStationForm>, Form(form): Form<UpdateFirstStationForm>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(team) = Team::find_by_id(&db, id).await else { let Some(team) = Team::find_by_id(&db, id).await else {
err!( er!(session, t!("nonexisting_team", id = id));
session,
"Team mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"
);
return Redirect::to("/admin/team"); return Redirect::to("/admin/team");
}; };
let Some(station) = Station::find_by_id(&db, form.first_station_id).await else { let Some(station) = Station::find_by_id(&db, form.first_station_id).await else {
err!( er!(
session, session,
"Konnte die erste Station (ID={}) des Teams mit ID {} nicht bearbeiten, da diese Station nicht existiert.", t!("nonexisting_station", id = form.first_station_id)
form.first_station_id,
team.id
); );
return Redirect::to(&format!("/admin/team/{id}")); return Redirect::to(&format!("/admin/team/{id}"));
}; };
if !station.is_in_route(&db, &team.route(&db).await).await { if !station.is_in_route(&db, &team.route(&db).await).await {
err!( er!(
session, session,
"Konnte Station {} nicht dem Team {} hinzufügen, weil dieses Team bei Route {} und nicht bei Route {} mitläuft.", t!(
station.name, "first_station_not_edited_not_on_route",
team.name, station = station.name,
team.route(&db).await.name, team = team.name,
team.name route = team.route(&db).await.name
)
); );
return Redirect::to(&format!("/admin/team/{id}")); return Redirect::to(&format!("/admin/team/{id}"));
@ -632,11 +590,13 @@ async fn update_first_station(
team.update_first_station(&db, &station).await; team.update_first_station(&db, &station).await;
succ!( suc!(
session, session,
"Erste Station des Teams {} ist ab sofort {}", t!(
team.name, "changed_first_station",
station.name team = team.name,
station = station.name
)
); );
Redirect::to(&format!("/admin/team/{id}")) Redirect::to(&format!("/admin/team/{id}"))
@ -653,33 +613,27 @@ async fn update_last_station(
Form(form): Form<UpdateLastStationForm>, Form(form): Form<UpdateLastStationForm>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(team) = Team::find_by_id(&db, id).await else { let Some(team) = Team::find_by_id(&db, id).await else {
err!( er!(session, t!("nonexisting_team", id = id));
session,
"Team mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"
);
return Redirect::to("/admin/team"); return Redirect::to("/admin/team");
}; };
let Some(station) = Station::find_by_id(&db, form.last_station_id).await else { let Some(station) = Station::find_by_id(&db, form.last_station_id).await else {
err!( er!(
session, session,
"Konnte die letzte Station (ID={}) des Teams mit ID {} nicht bearbeiten, da diese Station nicht existiert.", t!("nonexisting_station", id = form.last_station_id)
form.last_station_id,
team.id
); );
return Redirect::to(&format!("/admin/team/{id}")); return Redirect::to(&format!("/admin/team/{id}"));
}; };
if !station.is_in_route(&db, &team.route(&db).await).await { if !station.is_in_route(&db, &team.route(&db).await).await {
err!( er!(
session, session,
"Konnte Station {} nicht dem Team {} hinzufügen, weil dieses Team bei Route {} und nicht bei Route {} mitläuft.", t!(
station.name, "last_station_not_edited_not_on_route",
team.name, station = station.name,
team.route(&db).await.name, team = team.name,
team.name route = team.route(&db).await.name
)
); );
return Redirect::to(&format!("/admin/team/{id}")); return Redirect::to(&format!("/admin/team/{id}"));
@ -687,11 +641,13 @@ async fn update_last_station(
team.update_last_station(&db, &station).await; team.update_last_station(&db, &station).await;
succ!( suc!(
session, session,
"Letzte Station des Teams {} ist ab sofort {}", t!(
team.name, "changed_last_station",
station.name team = team.name,
station = station.name
)
); );
Redirect::to(&format!("/admin/team/{id}")) Redirect::to(&format!("/admin/team/{id}"))
@ -703,21 +659,13 @@ async fn update_amount_people_reset(
axum::extract::Path(id): axum::extract::Path<i64>, axum::extract::Path(id): axum::extract::Path<i64>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(team) = Team::find_by_id(&db, id).await else { let Some(team) = Team::find_by_id(&db, id).await else {
err!( er!(session, t!("nonexisting_team", id = id));
session,
"Team mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"
);
return Redirect::to("/admin/team"); return Redirect::to("/admin/team");
}; };
team.update_amount_people_reset(&db).await; team.update_amount_people_reset(&db).await;
succ!( suc!(session, t!("amount_teammembers_edited", team = team.name));
session,
"Anzahl an Mitglieder für das Team '{}' wurden erfolgreich bearbeitet!",
team.name
);
Redirect::to(&format!("/admin/team/{id}")) Redirect::to(&format!("/admin/team/{id}"))
} }
@ -728,15 +676,15 @@ async fn lost(State(db): State<Arc<SqlitePool>>, session: Session) -> Markup {
let content = html! { let content = html! {
h1 { h1 {
a href="/admin/team" { "↩️" } a href="/admin/team" { "↩️" }
"Teams: Letzter Kontakt" (t!("last_contact_team"))
} }
div class="overflow-auto" { div class="overflow-auto" {
table { table {
thead { thead {
tr { tr {
td { "Gruppe" } td { (t!("team")) }
td { "Uhrzeit" } td { (t!("time")) }
td { "Station" } td { (t!("station")) }
} }
} }
tbody { tbody {
@ -751,7 +699,7 @@ async fn lost(State(db): State<Arc<SqlitePool>>, session: Session) -> Markup {
@if let Some(time) = lost.local_last_contact() { @if let Some(time) = lost.local_last_contact() {
(time) (time)
}@else{ }@else{
"Noch nicht gesehen" (t!("not_yet_seen"))
} }
} }
td { td {
@ -760,7 +708,7 @@ async fn lost(State(db): State<Arc<SqlitePool>>, session: Session) -> Markup {
(station.name) (station.name)
} }
}@else{ }@else{
"Noch nicht gesehen" (t!("not_yet_seen"))
} }
} }
} }
@ -780,10 +728,10 @@ async fn index(State(db): State<Arc<SqlitePool>>, session: Session) -> Markup {
let content = html! { let content = html! {
h1 { h1 {
a href="/admin" { "↩️" } a href="/admin" { "↩️" }
"Teams" (t!("teams"))
} }
article { article {
em { "Teams " } em { (t!("teams")) }
"sind eine Menge an Personen, die verschiedene " "sind eine Menge an Personen, die verschiedene "
a href="/admin/station" { "Stationen" } a href="/admin/station" { "Stationen" }
" ablaufen. Welche Stationen, entscheidet sich je nachdem, welcher " " ablaufen. Welche Stationen, entscheidet sich je nachdem, welcher "
@ -792,46 +740,47 @@ async fn index(State(db): State<Arc<SqlitePool>>, session: Session) -> Markup {
} }
@if teams.is_empty() { @if teams.is_empty() {
article class="warning" { article class="warning" {
"Es gibt noch keine Teams. " (t!("no_teams"))
@if !routes.is_empty() { @if !routes.is_empty() {
"Das kannst du hier ändern ⤵️" (t!("change_that_below"))
} }
} }
} }
article { article {
h2 { "Neues Team" } h2 { (t!("new_team")) }
@if routes.is_empty() { @if routes.is_empty() {
article class="error" { article class="error" {
(PreEscaped("Bevor du ein Team erstellen kannst, musst du zumindest eine Route erstellen, die das Team gehen kann &rarr; ")) (t!("route_needed_before_creating_teams"))
(PreEscaped(" &rarr; "))
a role="button" href="/admin/route" { a role="button" href="/admin/route" {
"Route erstellen" (t!("create_route"))
} }
} }
} @else { } @else {
form action="/admin/team" method="post" { form action="/admin/team" method="post" {
@if routes.len() == 1 { @if routes.len() == 1 {
fieldset role="group" { fieldset role="group" {
input type="text" name="name" placeholder="Teamnamen" required; input type="text" name="name" placeholder=(t!("teamname")) required;
input type="hidden" name="route_id" value=(routes[0].id) ; input type="hidden" name="route_id" value=(routes[0].id) ;
input type="submit" value="Neues Team"; input type="submit" value="Neues Team";
} }
} @else { } @else {
input type="text" name="name" placeholder="Teamnamen" required; input type="text" name="name" placeholder=(t!("teamname")) required;
select name="route_id" aria-label="Route auswählen" required { select name="route_id" aria-label=(t!("select_route")) required {
@for route in &routes { @for route in &routes {
option value=(route.id) { option value=(route.id) {
(route.name) (route.name)
} }
} }
} }
input type="submit" value="Neues Team"; input type="submit" value=(t!("new_team"));
} }
} }
} }
} }
a href="/admin/team/lost" { a href="/admin/team/lost" {
button class="outline" { button class="outline" {
"Hab ich eine Gruppe verloren? 😳" (t!("have_i_lost_groups"))
} }
} }
@for route in &routes { @for route in &routes {
@ -843,7 +792,7 @@ async fn index(State(db): State<Arc<SqlitePool>>, session: Session) -> Markup {
(team.name) (team.name)
} }
a href=(format!("/admin/team/{}/delete", team.id)) a href=(format!("/admin/team/{}/delete", team.id))
onclick="return confirm('Bist du sicher, dass das Team gelöscht werden soll? Das kann _NICHT_ mehr rückgängig gemacht werden.');" { onclick=(format!("return confirm('{}');", t!("confirm_delete_team"))) {
"🗑️" "🗑️"
} }
} }

View File

@ -27,7 +27,7 @@ async fn create(
id id
} }
Err(e) => { Err(e) => {
er!(session, t!("user_create_err", err = e)); er!(session, t!("user_create_error", name = form.name, err = e));
return Redirect::to("/admin/user"); return Redirect::to("/admin/user");
} }
@ -48,12 +48,12 @@ async fn delete(
}; };
match user.delete(&db).await { match user.delete(&db).await {
Ok(()) => suc!(session, t!("user_deleted", user = user.name)), Ok(()) => suc!(session, t!("user_deleted", name = user.name)),
Err(e) => er!( Err(e) => er!(
session, session,
t!( t!(
"user_delete_error_already_in_use", "user_delete_error_already_in_use",
user = user.name, name = user.name,
err = e err = e
) )
), ),

View File

@ -48,14 +48,6 @@ pub fn url() -> String {
env::var("URL").unwrap() env::var("URL").unwrap()
} }
pub(crate) fn pl(amount: usize, single: &str, append: &str) -> String {
if amount == 1 {
single.into()
} else {
format!("{single}{append}")
}
}
#[macro_export] #[macro_export]
macro_rules! err { macro_rules! err {
($session:expr, $fmt:expr $(, $arg:expr)*) => { ($session:expr, $fmt:expr $(, $arg:expr)*) => {
@ -201,7 +193,7 @@ async fn set_pw(
if correct_code != code { if correct_code != code {
er!( er!(
session, session,
t!("cant_updaet_pw_with_wrong_code", user = user.name) t!("cant_update_pw_with_wrong_code", user = user.name)
); );
return Err(Redirect::to("/")); return Err(Redirect::to("/"));
} }

View File

@ -138,7 +138,7 @@ async fn view(
@if station.ready { @if station.ready {
(t!("station_not_yet_ready")) (t!("station_not_yet_ready"))
} @else { } @else {
button { (t!("station_ready")) } button { (t!("button_station_ready")) }
} }
} }
} }
@ -512,7 +512,7 @@ async fn team_finished(
}; };
match station.team_finished(&db, &team).await { match station.team_finished(&db, &team).await {
Ok(()) => suc!(session, t!("team_added_to_finished")), Ok(()) => suc!(session, t!("team_added_to_finished", team = team.name)),
Err(e) => err!(session, "{e}"), Err(e) => err!(session, "{e}"),
} }
@ -538,7 +538,7 @@ async fn remove_left(
}; };
match station.remove_team_left(&db, &team).await { match station.remove_team_left(&db, &team).await {
Ok(()) => suc!(session, t!("team_removed_from_finished")), Ok(()) => suc!(session, t!("team_removed_from_finished", team = team.name)),
Err(e) => err!(session, "{e}"), Err(e) => err!(session, "{e}"),
} }