Philipp Hofer bc6244bc03
Some checks failed
CI/CD Pipeline / test (push) Has been cancelled
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
slight restructure of trip
2025-05-22 12:41:01 +02:00

155 lines
4.8 KiB
Rust

use std::io::Write;
use ics::{
components::Property,
properties::{DtEnd, DtStart, Summary},
ICalendar,
};
use sqlx::SqlitePool;
use crate::model::{event::Event, trip::Trip, user::User};
use chrono::{Duration, NaiveTime};
pub(crate) async fn get_personal_cal(db: &SqlitePool, user: &User) -> String {
let mut calendar = ICalendar::new("2.0", "ics-rs");
calendar.push(Property::new(
"X-WR-CALNAME",
"Donau Linz - Deine Ausfahrten",
));
let events = Event::all_with_user(db, user).await;
for event in events {
calendar.add_event(event.get_vevent(db).await);
}
let trips = Trip::all_with_user(db, user).await;
for trip in trips {
calendar.add_event(trip.get_vevent(db, user).await);
}
let mut buf = Vec::new();
write!(&mut buf, "{}", calendar).unwrap();
String::from_utf8(buf).unwrap()
}
impl Trip {
pub(crate) async fn get_vevent<'a>(self, db: &'a SqlitePool, user: &'a User) -> ics::Event<'a> {
let mut vevent =
ics::Event::new(format!("trip-{}@rudernlinz.at", self.id), "19900101T180000");
let time_str = self.planned_starting_time.replace(':', "");
let formatted_time = if time_str.len() == 3 {
format!("0{}", time_str)
} else {
time_str
};
vevent.push(DtStart::new(format!(
"{}T{}00",
self.day.replace('-', ""),
formatted_time
)));
let original_time = NaiveTime::parse_from_str(&self.planned_starting_time, "%H:%M")
.expect("Failed to parse time");
let long_trip = match self.trip_type(db).await {
Some(a) if a.name == "Lange Ausfahrt" => true,
_ => false,
};
let later_time = if long_trip {
original_time + Duration::hours(6)
} else {
original_time + Duration::hours(3)
};
if later_time > original_time {
// Check if no day-overflow
let time_three_hours_later = later_time.format("%H%M").to_string();
vevent.push(DtEnd::new(format!(
"{}T{}00",
self.day.replace('-', ""),
time_three_hours_later
)));
}
let mut name = String::new();
if self.is_cancelled() {
name.push_str("ABGESAGT");
if let Some(notes) = &self.notes {
if !notes.is_empty() {
name.push_str(&format!(" (Grund: {notes})"))
}
}
name.push_str("! :-( ");
}
if self.cox_id == user.id {
name.push_str("Ruderausfahrt (selber ausgeschrieben)");
} else {
name.push_str(&format!("Ruderausfahrt mit {} ", self.cox_name));
}
vevent.push(Summary::new(name));
vevent
}
}
impl Event {
pub(crate) async fn get_vevent(self, db: &SqlitePool) -> ics::Event {
let mut vevent = ics::Event::new(
format!("event-{}@rudernlinz.at", self.id),
"19900101T180000",
);
let time_str = self.planned_starting_time.replace(':', "");
let formatted_time = if time_str.len() == 3 {
format!("0{}", time_str)
} else {
time_str.clone() // TODO: remove again
};
vevent.push(DtStart::new(format!(
"{}T{}00",
self.day.replace('-', ""),
formatted_time
)));
let original_time = NaiveTime::parse_from_str(&self.planned_starting_time, "%H:%M")
.expect("Failed to parse time");
let long_trip = match self.trip_type(db).await {
Some(a) if a.name == "Lange Ausfahrt" => true,
_ => false,
};
let later_time = if long_trip {
original_time + Duration::hours(6)
} else {
original_time + Duration::hours(3)
};
if later_time > original_time {
// Check if no day-overflow
let time_three_hours_later = later_time.format("%H%M").to_string();
vevent.push(DtEnd::new(format!(
"{}T{}00",
self.day.replace('-', ""),
time_three_hours_later
)));
}
let tripdetails = self.trip_details(db).await;
let mut name = String::new();
if self.is_cancelled() {
name.push_str("ABGESAGT");
if let Some(notes) = &tripdetails.notes {
if !notes.is_empty() {
name.push_str(&format!(" (Grund: {notes})"))
}
}
name.push_str("! :-( ");
}
name.push_str(&format!("{} ", self.name));
if let Some(triptype) = tripdetails.triptype(db).await {
name.push_str(&format!("{} ", triptype.name))
}
vevent.push(Summary::new(name));
vevent
}
}