aboutsummaryrefslogtreecommitdiff
path: root/src/domain/calendar.rs
diff options
context:
space:
mode:
authorMikkel Thestrup <mikkel_thestrup@mithe.dk>2025-12-09 14:52:58 +0100
committerMikkel Thestrup <mikkel_thestrup@mithe.dk>2025-12-09 17:17:56 +0100
commit147125358b66c2bf097ed11f82042e220a730090 (patch)
tree2b6957d01a1afb0553996e916faea5c646f5cc6e /src/domain/calendar.rs
parent4b1074193991a510fd2129513d5fcb7c6da933d2 (diff)
downloadkal-master.tar.gz
kal-master.zip
feat(domain): Add initial domain models for calendar, event, and recurrenceHEADmaster
- Added `calendar.rs` with Calendar entity and builder - Added `event.rs` with Event model and builder - Added `recurrence.rs` for recurrence rules - Added `mod.rs` to expose domain module structure These files establish the core domain layer structures for future business logic.
Diffstat (limited to 'src/domain/calendar.rs')
-rw-r--r--src/domain/calendar.rs108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/domain/calendar.rs b/src/domain/calendar.rs
new file mode 100644
index 0000000..9e6a7fe
--- /dev/null
+++ b/src/domain/calendar.rs
@@ -0,0 +1,108 @@
+use std::collections::BTreeMap;
+
+use chrono::{DateTime, NaiveDate, Utc};
+use getset::Getters;
+use uuid::Uuid;
+
+use crate::domain::Event;
+
+#[derive(Clone, Debug, Getters)]
+#[getset(get = "pub")]
+pub struct Calendar {
+ id: Uuid,
+ name: String,
+ description: Option<String>,
+ events: BTreeMap<NaiveDate, Vec<Event>>,
+ is_archived: bool,
+ created_at: DateTime<Utc>,
+ updated_at: DateTime<Utc>,
+}
+
+pub struct CalendarBuilder {
+ name: String,
+ description: Option<String>,
+ events: BTreeMap<NaiveDate, Vec<Event>>,
+ is_archived: bool,
+}
+
+impl CalendarBuilder {
+ pub fn new(name: String) -> Result<Self, String> {
+ if name.is_empty() {
+ Err("Name cannot be empty".to_string())
+ } else {
+ Ok(Self {
+ name,
+ description: None,
+ events: BTreeMap::new(),
+ is_archived: false
+ })
+ }
+ }
+
+ pub fn description(mut self, description: Option<String>) -> Self {
+ self.description = description;
+ self
+ }
+
+ pub fn events(mut self, events: BTreeMap<NaiveDate, Vec<Event>>) -> Self {
+ self.events = events;
+ self
+ }
+
+ pub fn is_archived(mut self, is_archived: bool) -> Self {
+ self.is_archived = is_archived;
+ self
+ }
+
+ pub fn build(self) -> Calendar {
+ let now = Utc::now();
+ Calendar {
+ id: Uuid::new_v4(),
+ name: self.name,
+ description: self.description,
+ events: self.events,
+ is_archived: self.is_archived,
+ created_at: now,
+ updated_at: now
+ }
+ }
+}
+
+impl Calendar {
+ pub fn add_events(&mut self, events: Vec<Event>) {
+ for event in events {
+ let date = event.start().date_naive();
+
+ self.events
+ .entry(date)
+ .or_insert_with(Vec::new)
+ .push(event);
+ }
+
+ self.touch()
+ }
+
+ pub fn update_name(&mut self, name: String) -> Result<(), String> {
+ if name.is_empty() {
+ Err("Name cannot be empty".to_string())
+ } else {
+ self.name = name;
+ self.touch();
+ Ok(())
+ }
+ }
+
+ pub fn update_description(&mut self, description: Option<String>) {
+ self.description = description;
+ self.touch()
+ }
+
+ pub fn update_archived(&mut self, is_archived: bool) {
+ self.is_archived = is_archived;
+ self.touch()
+ }
+
+ pub fn touch(&mut self) {
+ self.updated_at = Utc::now()
+ }
+}