There is now an archive for tickets
This commit is contained in:
2026-05-11 20:46:06 +02:00
parent d9ef5746a2
commit 6eb84d24e0
5 changed files with 146 additions and 3 deletions

View File

@@ -665,7 +665,7 @@ pub fn all_tickets_component() -> Html {
} else {
html! {
<ul>
{ for tickets.iter().filter(|t| if user.is_admin { true } else if let Some(uid) = user.id { t.user_id == uid } else { false }).map(|t| html! {
{ for tickets.iter().filter(|t| t.status != "Archived" && (if user.is_admin { true } else if let Some(uid) = user.id { t.user_id == uid } else { false })).map(|t| html! {
<div>
<li key={t.id.to_string()}>
<Link<crate::Route> to={crate::Route::TicketById{id: t.id}}><h3>{ format!("{} - #{}", t.betreff, t.id) }</h3></Link<crate::Route>>
@@ -686,3 +686,136 @@ pub fn all_tickets_component() -> Html {
}
}
}
/// A component for fetching and displaying a list of archived tickets.
///
/// This component retrieves all tickets from the backend and presents them as a list,
/// filtered to only show those with "Archived" status.
///
/// # State
/// Uses `use_state` hooks to manage:
/// - `tickets`: A vector of `Ticket` structs to store the fetched tickets.
/// - `error`: Any error message encountered during API calls.
/// - `loading`: A boolean indicating if data is currently being fetched.
/// - `user`: An `ActiveUser` struct holding the current user's ID and admin status.
///
/// # Functionality
/// - **Fetch Tickets**: On component mount, fetches all tickets from `/api/tickets`.
/// - **Fetch Current User**: Concurrently fetches the current user's details from
/// `/api/users/current` to determine their `user_id` and `is_admin` status.
/// - **Conditional Display**:
/// - If `loading` is true, displays "Loading...".
/// - If an `error` occurs, displays the error message.
/// - Otherwise, renders a list of tickets.
/// - **Filtering**:
/// - Only tickets with `t.status == "Archived"` are displayed.
/// - If the user is an admin, all archived tickets are shown.
/// - If the user is not an admin, only their own archived tickets are shown.
/// - **Navigation**: Each ticket in the list is a link to [`crate::Route::TicketById`]
/// for viewing individual ticket details.
///
/// # Example
/// ```rust
/// html! {
/// <ArchivedTickets />
/// }
/// ```
#[component(ArchivedTickets)]
pub fn archived_tickets_component() -> Html {
let tickets = use_state(|| Vec::<Ticket>::new());
let error = use_state(|| None::<String>);
let loading = use_state(|| false);
let user = use_state(|| ActiveUser {
id: None,
is_admin: false,
});
{
let tickets = tickets.clone();
let error = error.clone();
let loading = loading.clone();
use_effect_with((), move |_| {
loading.set(true);
spawn_local(async move {
let url = format!("/api/tickets");
match Request::get(&url).send().await {
Ok(response) if response.status() == 200 => {
match response.json::<Vec<Ticket>>().await {
Ok(t) => tickets.set(t),
Err(e) => error.set(Some(format!("parse error: {}", e))),
}
}
Ok(response) => {
if let Ok(text) = response.text().await {
error.set(Some(text));
} else {
error.set(Some(format!("status {}", response.status())));
}
}
Err(err) => error.set(Some(format!("Network error: {}", err))),
}
loading.set(false);
});
|| ()
});
}
{
let user = user.clone();
use_effect_with((), move |_| {
let user = user.clone();
spawn_local(async move {
if let Ok(response) = Request::get("/api/users/current")
.credentials(web_sys::RequestCredentials::Include)
.send()
.await
{
if response.status() == 200 {
if let Ok(json) = response.json::<serde_json::Value>().await {
let id = json
.get("data")
.and_then(|d| d.get("id"))
.and_then(|v| v.as_i64())
.and_then(|n| i16::try_from(n).ok());
let is_admin = json
.get("data")
.and_then(|d| d.get("is_admin"))
.and_then(|v| v.as_bool())
.unwrap_or(false);
user.set(ActiveUser { id, is_admin });
}
}
}
});
|| ()
});
}
if *loading {
html! {<p>{ "Loading" }</p>}
} else if let Some(e) = &*error {
html! { <p>{ format!("Error: {}", e) }</p> }
} else {
html! {
<ul>
{ for tickets.iter().filter(|t| t.status == "Archived" && (user.is_admin || if let Some(uid) = user.id { t.user_id == uid } else { false })).map(|t| html! {
<div>
<li key={t.id.to_string()}>
<Link<crate::Route> to={crate::Route::TicketById{id: t.id}}><h3>{ format!("{} - #{}", t.betreff, t.id) }</h3></Link<crate::Route>>
<p>{ &t.description }</p>
<p>{ match t.status.as_str() {
"ToDo" => "Zu tun",
"InProgress" => "In Bearbeitung",
"Completed" => "Erledigt",
"Archived" => "Archiviert",
_ => "Ungültiger Status"
}}</p>
</li>
</div>
})}
</ul>
}
}
}