station is able to specify if they are ready; Fixes #25
All checks were successful
CI/CD Pipeline / test (push) Successful in 4m2s
CI/CD Pipeline / deploy (push) Successful in 2m40s

This commit is contained in:
Philipp Hofer 2025-04-13 21:20:58 +02:00
parent 45422c5ea7
commit 2a1d0a7616
4 changed files with 75 additions and 25 deletions

View File

@ -4,6 +4,7 @@ CREATE TABLE IF NOT EXISTS station (
notes TEXT,
amount_people INTEGER,
last_login DATETIME,
ready BOOLEAN NOT NULL DEFAULT false,
pw TEXT NOT NULL DEFAULT (upper(hex(randomblob(4)))),
lat REAL,
lng REAL

View File

@ -19,6 +19,7 @@ pub(crate) struct Station {
amount_people: Option<i64>,
last_login: Option<NaiveDateTime>, // TODO use proper timestamp (NaiveDateTime?)
pub(crate) pw: String,
pub(crate) ready: bool,
pub(crate) lat: Option<f64>,
pub(crate) lng: Option<f64>,
}
@ -26,7 +27,7 @@ pub(crate) struct Station {
impl Station {
pub(crate) async fn all(db: &SqlitePool) -> Vec<Self> {
sqlx::query_as::<_, Self>(
"SELECT id, name, notes, amount_people, last_login, pw, lat, lng FROM station;",
"SELECT id, name, notes, amount_people, last_login, ready, pw, lat, lng FROM station;",
)
.fetch_all(db)
.await
@ -36,7 +37,7 @@ impl Station {
pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option<Self> {
sqlx::query_as!(
Self,
"SELECT id, name, notes, amount_people, last_login, pw, lat, lng FROM station WHERE id = ?",
"SELECT id, name, notes, amount_people, last_login, ready, pw, lat, lng FROM station WHERE id = ?",
id
)
.fetch_one(db)
@ -47,7 +48,7 @@ impl Station {
pub async fn login(db: &SqlitePool, id: i64, code: &str) -> Option<Self> {
let station = sqlx::query_as!(
Self,
"SELECT id, name, notes, amount_people, last_login, pw, lat, lng FROM station WHERE id = ? AND pw = ?",
"SELECT id, name, notes, amount_people, last_login, ready, pw, lat, lng FROM station WHERE id = ? AND pw = ?",
id, code
)
.fetch_one(db)
@ -65,6 +66,18 @@ impl Station {
Some(station)
}
pub async fn switch_ready(&self, db: &SqlitePool) {
let new_ready_status = !self.ready;
sqlx::query!(
"UPDATE station SET ready = ? WHERE id = ?",
new_ready_status,
self.id
)
.execute(db)
.await
.unwrap();
}
pub(crate) async fn create(db: &SqlitePool, name: &str) -> Result<(), String> {
sqlx::query!("INSERT INTO station(name) VALUES (?)", name)
.execute(db)

View File

@ -509,6 +509,11 @@ async fn index(State(db): State<Arc<SqlitePool>>, session: Session) -> Markup {
@let status = TeamsAtStationLocation::for_station(&db, station).await;
tr {
td {
@if station.ready {
em data-tooltip="Station bereit!" {
small { "🟢 " }
}
}
@if station.routes(&db).await.is_empty() {
em data-tooltip=(t!("station_warning_not_assigned_route")) {
"⚠️ "

View File

@ -39,6 +39,8 @@ async fn view(
h1 { (format!("Station {}", station.name)) }
@if let (Some(lat), Some(lng)) = (station.lat, station.lng) {
article {
details open[(!station.ready)]{
summary { "Stationsort" }
b { "Hier befindet sich deine Station:" }
div id="map" style="height: 500px" {}
script { (format!("
@ -55,16 +57,25 @@ async fn view(
}});
currentMarker = L.marker([{lat}, {lng}], {{icon: myIcon}}).addTo(map);
map.setView([lat, lng], 14);
"))
}
div {
sub {
a href=(format!("https://www.google.com/maps?q={lat},{lng}")) target="_blank" {
"Google Maps..."
}
}
}
hr;
a href=(format!("/s/{id}/{code}/ready")){
@if station.ready {
"Bin mit der Station doch noch nicht bereit..."
} @else {
button { "Ich bin bei meiner Station und bin bereit zu starten!" }
}
}
}
}
}
article {
"Insgesamt sollten "
@ -234,6 +245,25 @@ async fn view(
partials::page(content, session, use_map).await
}
async fn ready(
State(db): State<Arc<SqlitePool>>,
session: Session,
axum::extract::Path((id, code)): axum::extract::Path<(i64, String)>,
) -> 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}");
};
station.switch_ready(&db).await;
succ!(session, "Erfolgreich geändert");
Redirect::to(&format!("/s/{id}/{code}"))
}
#[derive(Deserialize)]
struct NewWaitingForm {
team_id: i64,
@ -459,6 +489,7 @@ async fn team_update(
pub(super) fn routes() -> Router<AppState> {
Router::new()
.route("/", get(view))
.route("/ready", get(ready))
.route("/new-waiting", post(new_waiting))
.route("/remove-waiting/{team_id}", get(remove_waiting))
.route("/team-starting/{team_id}", get(team_starting))