Tickets per rooms shown

In diagnostics
This commit is contained in:
2026-05-02 15:18:11 +02:00
parent 38603dc84b
commit 1017f495f8

View File

@@ -1,3 +1,5 @@
use std::{collections::HashMap, fmt::format};
use chrono::{DateTime, Datelike, Utc}; use chrono::{DateTime, Datelike, Utc};
use gloo_net::http::Request; use gloo_net::http::Request;
use serde::Deserialize; use serde::Deserialize;
@@ -6,9 +8,15 @@ use yew::prelude::*;
use crate::pages::ticket::{ActiveUser, Ticket}; use crate::pages::ticket::{ActiveUser, Ticket};
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone, PartialEq)]
struct Date { struct TicketPartial {
date: DateTime<Utc>, // matches JSON "date": "2026-05-01T14:23:00Z" date: DateTime<Utc>,
room: i16,
}
#[derive(Properties, PartialEq)]
struct RoomTotalsProps {
tickets: Vec<TicketPartial>,
} }
fn weekday_index(dt: &DateTime<Utc>) -> usize { fn weekday_index(dt: &DateTime<Utc>) -> usize {
@@ -24,7 +32,7 @@ fn weekday_index(dt: &DateTime<Utc>) -> usize {
} }
} }
fn count_by_weekday(tickets: &[Date]) -> [usize; 7] { fn count_by_weekday(tickets: &[TicketPartial]) -> [usize; 7] {
let mut counts = [0usize; 7]; let mut counts = [0usize; 7];
for t in tickets { for t in tickets {
counts[weekday_index(&t.date)] += 1; counts[weekday_index(&t.date)] += 1;
@@ -32,14 +40,14 @@ fn count_by_weekday(tickets: &[Date]) -> [usize; 7] {
counts counts
} }
fn day_counts(dates: &[Date]) -> [usize; 7] { fn day_counts(partials: &[TicketPartial]) -> [usize; 7] {
if dates.is_empty() { if partials.is_empty() {
return [0usize; 7]; return [0usize; 7];
} }
let mut min = dates[0].date.date_naive(); let mut min = partials[0].date.date_naive();
let mut max = min; let mut max = min;
for d in dates.iter().skip(1) { for d in partials.iter().skip(1) {
let dt = d.date.date_naive(); let dt = d.date.date_naive();
if dt < min { if dt < min {
min = dt min = dt
@@ -74,6 +82,16 @@ fn day_counts(dates: &[Date]) -> [usize; 7] {
occ occ
} }
fn parse_room(r: i16) -> String {
if r < 0 {
format!("K{}", r.abs())
} else if r > 1000 {
format!("D{}", r - 1000)
} else {
r.to_string()
}
}
#[component(Diagnostics)] #[component(Diagnostics)]
pub fn diagnostics_component() -> Html { pub fn diagnostics_component() -> Html {
html! { html! {
@@ -180,7 +198,7 @@ pub fn ticket_count_component() -> Html {
#[component(SubmitStats)] #[component(SubmitStats)]
pub fn submit_stats_component() -> Html { pub fn submit_stats_component() -> Html {
let tickets = use_state(|| Vec::<Date>::new()); let tickets = use_state(|| Vec::<TicketPartial>::new());
let error = use_state(|| None::<String>); let error = use_state(|| None::<String>);
let loading = use_state(|| false); let loading = use_state(|| false);
@@ -195,7 +213,7 @@ pub fn submit_stats_component() -> Html {
let url = "/api/tickets".to_string(); let url = "/api/tickets".to_string();
match Request::get(&url).send().await { match Request::get(&url).send().await {
Ok(response) if response.status() == 200 => { Ok(response) if response.status() == 200 => {
match response.json::<Vec<Date>>().await { match response.json::<Vec<TicketPartial>>().await {
Ok(t) => tickets.set(t), Ok(t) => tickets.set(t),
Err(e) => error.set(Some(format!("parse error: {}", e))), Err(e) => error.set(Some(format!("parse error: {}", e))),
} }
@@ -255,6 +273,30 @@ pub fn submit_stats_component() -> Html {
} }
})} })}
</ul> </ul>
<RoomTotalTickets tickets={(*tickets).clone()}/>
</div>
}
}
#[component(RoomTotalTickets)]
fn room_total_component(props: &RoomTotalsProps) -> Html {
let mut totals: HashMap<i16, usize> = HashMap::new();
for t in &props.tickets {
*totals.entry(t.room).or_insert(0) += 1;
}
let mut totals_vec: Vec<(i16, usize)> = totals.into_iter().collect();
totals_vec.sort_by(|a, b| b.1.cmp(&a.1));
html! {
<div>
<h3>{ "Tickets pro Raum" }</h3>
<ul>
{ for totals_vec.into_iter().map(|(room, count)| {
let label = parse_room(room);
html! { <li>{ format!("{}: {}", label, count) }</li> }
}) }
</ul>
</div> </div>
} }
} }