use chrono::{DateTime, Utc}; use heromodels_core::BaseModelData; use heromodels_derive::model; use rhai_autobind_macros::rhai_model_export; use rhai::{CustomType, TypeBuilder}; use serde::{Deserialize, Serialize}; /// Represents the status of an attendee for an event #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum AttendanceStatus { Accepted, Declined, Tentative, NoResponse, } /// Represents an attendee of an event #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, CustomType)] pub struct Attendee { /// ID of the user attending // Assuming user_id might be queryable pub contact_id: u32, /// Attendance status of the user for the event pub status: AttendanceStatus, } impl Attendee { pub fn new(contact_id: u32) -> Self { Self { contact_id, status: AttendanceStatus::NoResponse, } } pub fn status(mut self, status: AttendanceStatus) -> Self { self.status = status; self } } /// Represents an event in a calendar #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, CustomType)] pub struct Event { /// Base model data #[serde(flatten)] pub base_data: BaseModelData, /// Title of the event pub title: String, /// Optional description of the event pub description: Option, /// Start time of the event pub start_time: DateTime, /// End time of the event pub end_time: DateTime, /// List of attendees for the event pub attendees: Vec, /// Optional location of the event pub location: Option, } impl Event { /// Creates a new event pub fn new(title: impl ToString, start_time: DateTime, end_time: DateTime) -> Self { Self { base_data: BaseModelData::new(), title: title.to_string(), description: None, start_time, end_time, attendees: Vec::new(), location: None, } } /// Sets the title for the event pub fn title(mut self, title: impl ToString) -> Self { self.title = title.to_string(); self } /// Sets the description for the event pub fn description(mut self, description: impl ToString) -> Self { self.description = Some(description.to_string()); self } /// Sets the location for the event pub fn location(mut self, location: impl ToString) -> Self { self.location = Some(location.to_string()); self } /// Adds an attendee to the event pub fn add_attendee(mut self, attendee: Attendee) -> Self { // Prevent duplicate attendees by contact_id if !self.attendees.iter().any(|a| a.contact_id == attendee.contact_id) { self.attendees.push(attendee); } self } /// Removes an attendee from the event by user_id pub fn remove_attendee(mut self, contact_id: u32) -> Self { self.attendees.retain(|a| a.contact_id != contact_id); self } /// Updates the status of an existing attendee pub fn update_attendee_status(mut self, contact_id: u32, status: AttendanceStatus) -> Self { if let Some(attendee) = self.attendees.iter_mut().find(|a| a.contact_id == contact_id) { attendee.status = status; } self } /// Reschedules the event to new start and end times pub fn reschedule( mut self, new_start_time: DateTime, new_end_time: DateTime, ) -> Self { // Basic validation: end_time should be after start_time if new_end_time > new_start_time { self.start_time = new_start_time; self.end_time = new_end_time; } // Optionally, add error handling or return a Result type self } } /// Represents a calendar with events #[rhai_model_export( db_type = "std::sync::Arc", )] #[model] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, CustomType)] pub struct Calendar { /// Base model data #[serde(flatten)] pub base_data: BaseModelData, /// Name of the calendar pub name: String, /// Optional description of the calendar pub description: Option, /// List of events in the calendar // For now, events are embedded. If they become separate models, this would be Vec<[IDType]>. pub events: Vec, } impl Calendar { /// Creates a new calendar with auto-generated ID /// /// # Arguments /// * `id` - Optional ID for the calendar (use None for auto-generated ID) /// * `name` - Name of the calendar pub fn new(id: Option, name: impl ToString) -> Self { let mut base_data = BaseModelData::new(); if let Some(id) = id { base_data.update_id(id); } Self { base_data, name: name.to_string(), description: None, events: Vec::new(), } } /// Sets the name for the calendar pub fn name(mut self, name: impl ToString) -> Self { self.name = name.to_string(); self } /// Sets the description for the calendar pub fn description(mut self, description: impl ToString) -> Self { self.description = Some(description.to_string()); self } /// Adds an event to the calendar pub fn add_event(mut self, event_id: i64) -> Self { // Prevent duplicate events by id if !self.events.iter().any(|e_id| *e_id == event_id) { self.events.push(event_id); } self } /// Removes an event from the calendar by its ID pub fn remove_event(mut self, event_id_to_remove: i64) -> Self { self.events.retain(|&event_id_in_vec| event_id_in_vec != event_id_to_remove); self } }