Viewing ticket by ID

This is now possible by going to /tickets/{id}
This commit is contained in:
2026-04-28 21:23:40 +02:00
parent ac7b2e59b9
commit 21aa213ff4
4 changed files with 257 additions and 5 deletions

156
frontend/Cargo.lock generated
View File

@@ -2,6 +2,21 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "autocfg"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "bincode"
version = "1.3.3"
@@ -23,12 +38,36 @@ version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]]
name = "cc"
version = "1.2.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d"
dependencies = [
"find-msvc-tools",
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "chrono"
version = "0.4.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
dependencies = [
"iana-time-zone",
"js-sys",
"num-traits",
"serde",
"wasm-bindgen",
"windows-link",
]
[[package]]
name = "console_error_panic_hook"
version = "0.1.7"
@@ -39,12 +78,24 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]]
name = "fnv"
version = "1.0.7"
@@ -64,6 +115,7 @@ dependencies = [
name = "frontend"
version = "0.1.0"
dependencies = [
"chrono",
"gloo 0.12.0",
"gloo-net 0.7.0",
"serde",
@@ -562,6 +614,30 @@ dependencies = [
"itoa",
]
[[package]]
name = "iana-time-zone"
version = "0.1.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"log",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "implicit-clone"
version = "0.6.0"
@@ -616,12 +692,27 @@ version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]]
name = "log"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "memchr"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.17.0"
@@ -836,6 +927,12 @@ dependencies = [
"serde",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "slab"
version = "0.4.12"
@@ -1100,6 +1197,65 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "windows-core"
version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
dependencies = [
"windows-implement",
"windows-interface",
"windows-link",
"windows-result",
"windows-strings",
]
[[package]]
name = "windows-implement"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "windows-interface"
version = "0.59.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-result"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-strings"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
dependencies = [
"windows-link",
]
[[package]]
name = "winnow"
version = "0.5.40"

View File

@@ -23,4 +23,4 @@ gloo-net = "0.7.0"
yew-router = "0.20.0"
serde_json = "1.0.149"
gloo = "0.12.0"
chrono = { version = "0.4.44", features = ["serde"] }

View File

@@ -9,6 +9,8 @@ enum Route {
Home,
#[at("/ticket")]
Ticket,
#[at("/tickets/:id")]
TicketById { id: i32 },
#[not_found]
#[at("/404")]
NotFound,
@@ -18,7 +20,8 @@ fn switch(route: Route) -> Html {
match route {
Route::Home => html! { <basic_pages::Home/>},
Route::NotFound => html! { <basic_pages::NotFound/> },
Route::Ticket => html! { <ticket::Ticket/> },
Route::Ticket => html! { <ticket::SubmitTicket/> },
Route::TicketById { id } => html! { <ticket::ShowTicketByID id={id}/> },
}
}

View File

@@ -1,9 +1,10 @@
use gloo_net::http::Request;
use serde::{Deserialize, Serialize};
use serde_json::json;
use wasm_bindgen_futures::spawn_local;
use yew::prelude::*;
#[derive(Serialize, Deserialize, Clone, Debug)]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct TicketCreateScheme {
pub category: String,
pub betreff: String,
@@ -11,8 +12,31 @@ pub struct TicketCreateScheme {
pub room: i16,
}
#[component(Ticket)]
pub fn ticket_component() -> Html {
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct Ticket {
pub id: i32,
pub category: String,
pub betreff: String,
pub description: String,
pub room: i16,
pub status: String,
pub date: chrono::NaiveDateTime,
pub user_id: i16,
}
#[derive(Properties, PartialEq)]
pub struct TicketProps {
pub id: i32,
}
#[derive(Deserialize, Debug)]
pub struct ApiError {
message: String,
status: String,
}
#[component(SubmitTicket)]
pub fn submit_ticket_component() -> Html {
let category = use_state(|| "".to_string());
let betreff = use_state(|| "".to_string());
let description = use_state(|| "".to_string());
@@ -118,3 +142,72 @@ pub fn ticket_component() -> Html {
</form>
}
}
#[component(ShowTicketByID)]
pub fn show_ticket_by_id_component(props: &TicketProps) -> Html {
let ticket = use_state(|| None::<Ticket>);
let error = use_state(|| None::<String>);
let loading = use_state(|| false);
let id = props.id;
{
let ticket = ticket.clone();
let error = error.clone();
let loading = loading.clone();
use_effect_with(id, move |id_ref| {
loading.set(true);
let ticket = ticket.clone();
let error = error.clone();
let id = *id_ref;
spawn_local(async move {
let url = format!("http://localhost:8001/api/tickets/{}", id);
match Request::get(&url).send().await {
Ok(response) => {
let status = response.status();
if status == 200 {
match response.json::<Ticket>().await {
Ok(t) => ticket.set(Some(t)),
Err(err) => error.set(Some(format!("Parse error: {}", err))),
}
} else {
match response.json::<ApiError>().await {
Ok(ae) => error.set(Some(ae.message)),
Err(_) => {
if let Ok(text) = response.text().await {
error.set(Some(text));
} else {
error.set(Some(format!("Server error: {}", status)));
}
}
}
}
}
Err(err) => error.set(Some(format!("Network error: {}", err))),
}
loading.set(false);
});
|| ()
});
}
if *loading {
html! {<p>{ "Loading" }</p>}
} else if let Some(e) = &*error {
html! { <p>{ format!("Error: {}", e) }</p> }
} else if let Some(t) = &*ticket {
html! {
<div>
<h1>{ format!("Ticket #{}", t.id) }</h1>
<p><strong>{ "Kategorie: " }</strong>{ &t.category }</p>
<p><strong>{ "Betreff: " }</strong>{ &t.betreff }</p>
<p><strong>{ "Beschreibung: " }</strong>{ &t.description }</p>
<p><strong>{ "Raum: " }</strong>{ t.room }</p>
<p><strong>{ "Datum: " }</strong>{ &t.date }</p>
<p><strong>{ "Status: "}</strong>{ &t.status }</p>
</div>
}
} else {
html! { <p>{ "No ticket found." }</p> }
}
}