Files
rota/src-tauri/src/slot.rs
2026-01-13 21:08:24 +02:00

221 lines
6.1 KiB
Rust

use chrono::{Datelike, NaiveDate, Weekday};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, PartialEq, PartialOrd, Ord, Eq, Debug, Hash, Clone, Copy)]
#[serde(rename_all = "camelCase")]
pub struct Slot {
pub day: Day,
pub position: ShiftPosition,
}
impl Slot {
pub fn new(day: Day, position: ShiftPosition) -> Self {
Self { day, position }
}
pub fn is_open_shift(&self) -> bool {
self.day.is_open_shift()
}
pub fn is_first(&self) -> bool {
self.day == Day(1) && self.position == ShiftPosition::First
}
pub fn is_open_first(&self) -> bool {
self.is_open_shift() && self.position == ShiftPosition::First
}
pub fn is_open_second(&self) -> bool {
self.is_open_shift() && self.position == ShiftPosition::Second
}
pub fn shift_type_str(&self) -> String {
match (self.day.is_open_shift(), self.position) {
(true, ShiftPosition::First) => "Ανοιχτή(1)".to_string(),
(true, ShiftPosition::Second) => "Ανοιχτή(2)".to_string(),
_ => "Κλειστή".to_string(),
}
}
pub fn next(&self) -> Self {
match self.position {
ShiftPosition::First if self.is_open_shift() => Self {
day: self.day,
position: ShiftPosition::Second,
},
_ => Self {
day: self.day.next(),
position: ShiftPosition::First,
},
}
}
pub fn previous(&self) -> Self {
match self.position {
ShiftPosition::First => {
let past_day = self.day.previous();
if past_day.is_open_shift() {
Self {
day: past_day,
position: ShiftPosition::Second,
}
} else {
Self {
day: past_day,
position: ShiftPosition::First,
}
}
}
ShiftPosition::Second => Self {
day: self.day,
position: ShiftPosition::First,
},
}
}
pub fn greater_than(&self, limit: u8) -> bool {
self.day.greater_than(&Day(limit))
}
pub fn default() -> Self {
Self {
day: Day(1),
position: ShiftPosition::First,
}
}
}
#[derive(Serialize, Deserialize, PartialEq, PartialOrd, Ord, Eq, Debug, Hash, Clone, Copy)]
#[serde(rename_all = "camelCase")]
pub struct Day(pub u8);
impl Day {
pub fn is_open_shift(&self) -> bool {
!self.0.is_multiple_of(2)
}
pub fn next(&self) -> Self {
Self(self.0 + 1)
}
pub fn previous(&self) -> Self {
if self.0 <= 1 {
Self(1)
} else {
Self(self.0 - 1)
}
}
pub fn greater_than(&self, other: &Day) -> bool {
self.0 > other.0
}
pub fn is_weekend(&self, month: u32, year: i32) -> bool {
let date = NaiveDate::from_ymd_opt(year, month, self.0 as u32).unwrap();
let weekday = date.weekday();
weekday == Weekday::Sat || weekday == Weekday::Sun
}
pub fn weekday(&self, month: u32, year: i32) -> Weekday {
let date = NaiveDate::from_ymd_opt(year, month, self.0 as u32).unwrap();
date.weekday()
}
}
#[derive(Serialize, Deserialize, PartialEq, PartialOrd, Ord, Eq, Debug, Hash, Clone, Copy)]
pub enum ShiftPosition {
First,
Second,
}
pub fn weekday_to_greek(weekday: Weekday) -> &'static str {
match weekday {
Weekday::Mon => "Δευτέρα",
Weekday::Tue => "Τρίτη",
Weekday::Wed => "Τετάρτη",
Weekday::Thu => "Πέμπτη",
Weekday::Fri => "Παρασκευή",
Weekday::Sat => "Σάββατο",
Weekday::Sun => "Κυριακή",
}
}
pub fn month_to_greek(month: u32) -> &'static str {
match month {
1 => "Ιανουάριος",
2 => "Φεβρουάριος",
3 => "Μάρτιος",
4 => "Απρίλιος",
5 => "Μάιος",
6 => "Ιούνιος",
7 => "Ιούλιος",
8 => "Αύγουστος",
9 => "Σεπτέμβριος",
10 => "Οκτώβριος",
11 => "Νοέμβριος",
12 => "Δεκέμβριος",
_ => panic!("Unable to find translation for month {}", month),
}
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use crate::slot::{Day, ShiftPosition, Slot};
#[rstest]
fn test_slot() {
let slot_1 = Slot::new(Day(1), ShiftPosition::First);
let slot_2 = Slot::new(Day(1), ShiftPosition::Second);
let slot_3 = Slot::new(Day(2), ShiftPosition::First);
assert!(slot_1.is_open_shift());
assert!(slot_2.is_open_shift());
assert!(!slot_3.is_open_shift());
assert!(slot_1.is_first());
assert!(!slot_2.is_first());
assert!(!slot_3.is_first());
assert!(!slot_1.is_open_second());
assert!(slot_2.is_open_second());
assert!(!slot_3.is_open_second());
assert_eq!(slot_1.next(), slot_2);
assert_eq!(slot_2.next(), slot_3);
assert_eq!(slot_3.previous(), slot_2);
assert_eq!(slot_2.previous(), slot_1);
assert!(!slot_1.greater_than(1));
assert!(!slot_2.greater_than(1));
assert!(slot_3.greater_than(1));
}
#[rstest]
fn test_day() {
let day_1 = Day(1);
let day_2 = Day(2);
let day_3 = Day(3);
assert!(day_1.is_open_shift());
assert!(!day_2.is_open_shift());
assert!(day_3.is_open_shift());
assert_eq!(day_1.next(), day_2);
assert_eq!(day_2.next(), day_3);
assert_eq!(day_3.previous(), day_2);
assert_eq!(day_2.previous(), day_1);
assert!(!day_1.greater_than(&day_1));
assert!(day_2.greater_than(&day_1));
assert!(day_3.greater_than(&day_1));
assert!(day_1.is_weekend(2, 2026));
assert!(!day_2.is_weekend(2, 2026));
assert!(!day_3.is_weekend(2, 2026));
}
}