Tickets per rooms shown
In diagnostics
This commit is contained in:
@@ -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>
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user