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 gloo_net::http::Request;
use serde::Deserialize;
@@ -6,9 +8,15 @@ use yew::prelude::*;
use crate::pages::ticket::{ActiveUser, Ticket};
#[derive(Debug, Deserialize, Clone)]
struct Date {
date: DateTime<Utc>, // matches JSON "date": "2026-05-01T14:23:00Z"
#[derive(Debug, Deserialize, Clone, PartialEq)]
struct TicketPartial {
date: DateTime<Utc>,
room: i16,
}
#[derive(Properties, PartialEq)]
struct RoomTotalsProps {
tickets: Vec<TicketPartial>,
}
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];
for t in tickets {
counts[weekday_index(&t.date)] += 1;
@@ -32,14 +40,14 @@ fn count_by_weekday(tickets: &[Date]) -> [usize; 7] {
counts
}
fn day_counts(dates: &[Date]) -> [usize; 7] {
if dates.is_empty() {
fn day_counts(partials: &[TicketPartial]) -> [usize; 7] {
if partials.is_empty() {
return [0usize; 7];
}
let mut min = dates[0].date.date_naive();
let mut min = partials[0].date.date_naive();
let mut max = min;
for d in dates.iter().skip(1) {
for d in partials.iter().skip(1) {
let dt = d.date.date_naive();
if dt < min {
min = dt
@@ -74,6 +82,16 @@ fn day_counts(dates: &[Date]) -> [usize; 7] {
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)]
pub fn diagnostics_component() -> Html {
html! {
@@ -180,7 +198,7 @@ pub fn ticket_count_component() -> Html {
#[component(SubmitStats)]
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 loading = use_state(|| false);
@@ -195,7 +213,7 @@ pub fn submit_stats_component() -> Html {
let url = "/api/tickets".to_string();
match Request::get(&url).send().await {
Ok(response) if response.status() == 200 => {
match response.json::<Vec<Date>>().await {
match response.json::<Vec<TicketPartial>>().await {
Ok(t) => tickets.set(t),
Err(e) => error.set(Some(format!("parse error: {}", e))),
}
@@ -255,6 +273,30 @@ pub fn submit_stats_component() -> Html {
}
})}
</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>
}
}