initial
This commit is contained in:
@@ -0,0 +1 @@
|
||||
pub mod tool;
|
||||
@@ -0,0 +1,235 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Tool – Hauptstruktur
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub struct Tool {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub anzahl: Anzahl,
|
||||
pub beschaffung: Beschaffung,
|
||||
pub verwendung: Vec<String>,
|
||||
pub tags: Vec<String>,
|
||||
pub status: Status,
|
||||
pub prioritaet: Prioritaet,
|
||||
pub notizen: Option<String>,
|
||||
pub verantwortlich: Option<String>,
|
||||
pub erstellt_am: String, // ISO-8601, wird nur serverseitig gesetzt
|
||||
}
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
impl Tool {
|
||||
pub fn neu(input: NewTool) -> Self {
|
||||
Tool {
|
||||
id: uuid::Uuid::new_v4().to_string(),
|
||||
erstellt_am: chrono::Utc::now().to_rfc3339(),
|
||||
name: input.name,
|
||||
anzahl: input.anzahl,
|
||||
beschaffung: input.beschaffung,
|
||||
verwendung: input.verwendung,
|
||||
tags: input.tags,
|
||||
status: input.status,
|
||||
prioritaet: input.prioritaet,
|
||||
notizen: input.notizen,
|
||||
verantwortlich: input.verantwortlich,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Anzahl
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Entweder eine konkrete Zahl oder "Mehrere" (unbestimmt).
|
||||
/// Flache Struct-Darstellung für problemlose TOML-Serialisierung.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub struct Anzahl {
|
||||
/// None bedeutet "Mehrere"
|
||||
pub zahl: Option<u32>,
|
||||
}
|
||||
|
||||
impl Anzahl {
|
||||
pub fn zahl(n: u32) -> Self {
|
||||
Self { zahl: Some(n) }
|
||||
}
|
||||
pub fn mehrere() -> Self {
|
||||
Self { zahl: None }
|
||||
}
|
||||
pub fn ist_mehrere(&self) -> bool {
|
||||
self.zahl.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Anzahl {
|
||||
fn default() -> Self {
|
||||
Self::zahl(1)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Anzahl {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.zahl {
|
||||
Some(n) => write!(f, "{}", n),
|
||||
None => write!(f, "Mehrere"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Beschaffung
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
|
||||
pub enum BeschaffungsArt {
|
||||
#[default]
|
||||
Unbekannt,
|
||||
InBesitz,
|
||||
Leihen,
|
||||
Mieten,
|
||||
Kaufen,
|
||||
}
|
||||
|
||||
impl fmt::Display for BeschaffungsArt {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
BeschaffungsArt::Unbekannt => write!(f, "Unbekannt"),
|
||||
BeschaffungsArt::InBesitz => write!(f, "In Besitz"),
|
||||
BeschaffungsArt::Leihen => write!(f, "Leihen"),
|
||||
BeschaffungsArt::Mieten => write!(f, "Mieten"),
|
||||
BeschaffungsArt::Kaufen => write!(f, "Kaufen"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Flache Struct-Darstellung damit TOML-Serialisierung einfach bleibt.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
|
||||
pub struct Beschaffung {
|
||||
pub art: BeschaffungsArt,
|
||||
/// Für Leihen: von wem
|
||||
pub von: Option<String>,
|
||||
/// Für Mieten/Kaufen: wo
|
||||
pub wo: Option<String>,
|
||||
/// Für Mieten/Kaufen: Preis in €
|
||||
pub preis: Option<f64>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Beschaffung {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.art {
|
||||
BeschaffungsArt::Unbekannt => write!(f, "Unbekannt"),
|
||||
BeschaffungsArt::InBesitz => write!(f, "In Besitz"),
|
||||
BeschaffungsArt::Leihen => {
|
||||
if let Some(von) = &self.von {
|
||||
write!(f, "Leihen (von {})", von)
|
||||
} else {
|
||||
write!(f, "Leihen")
|
||||
}
|
||||
}
|
||||
BeschaffungsArt::Mieten => {
|
||||
let wo = self.wo.as_deref().unwrap_or("?");
|
||||
if let Some(p) = self.preis {
|
||||
write!(f, "Mieten bei {} ({:.2} €)", wo, p)
|
||||
} else {
|
||||
write!(f, "Mieten bei {}", wo)
|
||||
}
|
||||
}
|
||||
BeschaffungsArt::Kaufen => {
|
||||
let wo = self.wo.as_deref().unwrap_or("?");
|
||||
if let Some(p) = self.preis {
|
||||
write!(f, "Kaufen bei {} ({:.2} €)", wo, p)
|
||||
} else {
|
||||
write!(f, "Kaufen bei {}", wo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Status
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
|
||||
pub enum Status {
|
||||
#[default]
|
||||
Offen,
|
||||
Organisiert,
|
||||
VorOrt,
|
||||
}
|
||||
|
||||
impl fmt::Display for Status {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Status::Offen => write!(f, "Offen"),
|
||||
Status::Organisiert => write!(f, "Organisiert"),
|
||||
Status::VorOrt => write!(f, "Vor Ort"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Prioritaet
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
|
||||
pub enum Prioritaet {
|
||||
Hoch,
|
||||
#[default]
|
||||
Mittel,
|
||||
Niedrig,
|
||||
}
|
||||
|
||||
impl fmt::Display for Prioritaet {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Prioritaet::Hoch => write!(f, "Hoch"),
|
||||
Prioritaet::Mittel => write!(f, "Mittel"),
|
||||
Prioritaet::Niedrig => write!(f, "Niedrig"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// NewTool – Eingabe-Struct für Erstellen und Bearbeiten
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Wird als serde-Default für NewTool::anzahl verwendet, damit ein leeres
|
||||
// Anzahl-Objekt (Mehrere = zahl: None, keine URL-Keys) korrekt deserialisiert.
|
||||
fn default_anzahl_mehrere() -> Anzahl {
|
||||
Anzahl::mehrere()
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
pub struct NewTool {
|
||||
pub name: String,
|
||||
#[serde(default = "default_anzahl_mehrere")]
|
||||
pub anzahl: Anzahl,
|
||||
pub beschaffung: Beschaffung,
|
||||
#[serde(default)]
|
||||
pub verwendung: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub tags: Vec<String>,
|
||||
pub status: Status,
|
||||
pub prioritaet: Prioritaet,
|
||||
pub notizen: Option<String>,
|
||||
pub verantwortlich: Option<String>,
|
||||
}
|
||||
|
||||
impl From<&Tool> for NewTool {
|
||||
fn from(t: &Tool) -> Self {
|
||||
NewTool {
|
||||
name: t.name.clone(),
|
||||
anzahl: t.anzahl.clone(),
|
||||
beschaffung: t.beschaffung.clone(),
|
||||
verwendung: t.verwendung.clone(),
|
||||
tags: t.tags.clone(),
|
||||
status: t.status.clone(),
|
||||
prioritaet: t.prioritaet.clone(),
|
||||
notizen: t.notizen.clone(),
|
||||
verantwortlich: t.verantwortlich.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user