use axum::extract::Query; use axum::response::IntoResponse; use axum::routing::get; use axum::{Json, Router}; use chrono::{Datelike, Months, NaiveDate, NaiveDateTime, TimeDelta, Weekday}; use serde::{Deserialize, Serialize}; use std::ops::{Add, Sub}; #[derive(Deserialize)] enum Recurring { Daily, Weeky, BiWeekly, Monthly, Quarterly, Yearly, } #[derive(Deserialize)] enum Move { Before, After, } #[derive(Deserialize)] struct EventQuery { /// Start date start_date_time: NaiveDateTime, /// Recurring date recurring: Recurring, // If set, will ignore time on start_date all_day: bool, /// Title of the event title: String, // Optionals end_date: Option, avoid_weekends: Option, on_collition: Option, } #[derive(Deserialize)] enum Time { /// Specific time at day DateTime { start: NaiveDateTime, end: NaiveDateTime, }, /// All day Date(NaiveDate), } #[derive(Deserialize)] struct EventBody { /// Start date time: Time, /// Recurring date recurring: Recurring, /// Title of the event title: String, // Optionals end_date: Option, ignore_weekdays: Vec, on_collition: Option, } /// TODO create ical object /// TODO implement Before / After /// TODO what if start_date is weekend async fn get_calendar(Query(query): Query) -> impl IntoResponse { let start = query.start_date_time; let start_day = start.day(); let end = query .end_date .unwrap_or_else(|| (start + TimeDelta::days(365)).date()); let mut events = vec![start]; let mut previous_date_time = start; while previous_date_time.date() < end { previous_date_time = previous_date_time.with_day(start_day).unwrap(); let next = match query.recurring { Recurring::Daily => todo!(), Recurring::Weeky => todo!(), Recurring::BiWeekly => todo!(), Recurring::Monthly => { let new_date = previous_date_time .checked_add_months(Months::new(1)) .unwrap(); if let Some(true) = query.avoid_weekends { match new_date.weekday() { Weekday::Sat => new_date.sub(TimeDelta::days(1)), Weekday::Sun => new_date.sub(TimeDelta::days(2)), _ => new_date, } } else { new_date } } Recurring::Quarterly => todo!(), Recurring::Yearly => todo!(), }; events.push(next); previous_date_time = next; } Json(events) } #[tokio::main] async fn main() { let app = Router::new().route("/", get(get_calendar)); let listener = tokio::net::TcpListener::bind("0.0.0.0:8000").await.unwrap(); axum::serve(listener, app).await.unwrap(); }