1use serde::{Deserialize, Serialize};
4
5use crate::{CalendarId, GrantId};
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
32pub struct Calendar {
33 pub id: CalendarId,
35
36 pub grant_id: GrantId,
38
39 pub name: String,
41
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub description: Option<String>,
45
46 #[serde(skip_serializing_if = "Option::is_none")]
48 pub location: Option<String>,
49
50 pub timezone: String,
52
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub is_primary: Option<bool>,
56
57 #[serde(default)]
59 pub read_only: bool,
60
61 #[serde(skip_serializing_if = "Option::is_none")]
63 pub is_owned_by_user: Option<bool>,
64
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub hex_color: Option<String>,
68
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub hex_foreground_color: Option<String>,
72
73 #[serde(default = "default_object_type")]
75 pub object: String,
76
77 #[serde(skip_serializing_if = "Option::is_none")]
79 pub metadata: Option<serde_json::Value>,
80}
81
82fn default_object_type() -> String {
83 "calendar".to_string()
84}
85
86#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
88pub struct CreateCalendarRequest {
89 pub name: String,
91
92 #[serde(skip_serializing_if = "Option::is_none")]
94 pub description: Option<String>,
95
96 #[serde(skip_serializing_if = "Option::is_none")]
98 pub location: Option<String>,
99
100 #[serde(skip_serializing_if = "Option::is_none")]
102 pub timezone: Option<String>,
103
104 #[serde(skip_serializing_if = "Option::is_none")]
106 pub metadata: Option<serde_json::Value>,
107}
108
109impl CreateCalendarRequest {
110 pub fn new(name: impl Into<String>) -> Self {
112 Self {
113 name: name.into(),
114 description: None,
115 location: None,
116 timezone: None,
117 metadata: None,
118 }
119 }
120
121 pub fn description(mut self, description: impl Into<String>) -> Self {
123 self.description = Some(description.into());
124 self
125 }
126
127 pub fn location(mut self, location: impl Into<String>) -> Self {
129 self.location = Some(location.into());
130 self
131 }
132
133 pub fn timezone(mut self, timezone: impl Into<String>) -> Self {
135 self.timezone = Some(timezone.into());
136 self
137 }
138
139 pub fn metadata(mut self, metadata: serde_json::Value) -> Self {
141 self.metadata = Some(metadata);
142 self
143 }
144}
145
146#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
148pub struct UpdateCalendarRequest {
149 #[serde(skip_serializing_if = "Option::is_none")]
151 pub name: Option<String>,
152
153 #[serde(skip_serializing_if = "Option::is_none")]
155 pub description: Option<String>,
156
157 #[serde(skip_serializing_if = "Option::is_none")]
159 pub location: Option<String>,
160
161 #[serde(skip_serializing_if = "Option::is_none")]
163 pub timezone: Option<String>,
164
165 #[serde(skip_serializing_if = "Option::is_none")]
167 pub metadata: Option<serde_json::Value>,
168}
169
170impl UpdateCalendarRequest {
171 pub fn new() -> Self {
173 Self::default()
174 }
175
176 pub fn name(mut self, name: impl Into<String>) -> Self {
178 self.name = Some(name.into());
179 self
180 }
181
182 pub fn description(mut self, description: impl Into<String>) -> Self {
184 self.description = Some(description.into());
185 self
186 }
187
188 pub fn location(mut self, location: impl Into<String>) -> Self {
190 self.location = Some(location.into());
191 self
192 }
193
194 pub fn timezone(mut self, timezone: impl Into<String>) -> Self {
196 self.timezone = Some(timezone.into());
197 self
198 }
199
200 pub fn metadata(mut self, metadata: serde_json::Value) -> Self {
202 self.metadata = Some(metadata);
203 self
204 }
205}
206
207#[cfg(test)]
208mod tests {
209 use super::*;
210
211 #[test]
212 fn test_calendar_creation() {
213 let calendar = Calendar {
214 id: CalendarId::new("cal_123"),
215 grant_id: GrantId::new("grant_123"),
216 name: "My Calendar".to_string(),
217 description: Some("Test calendar".to_string()),
218 location: None,
219 timezone: "UTC".to_string(),
220 is_primary: Some(true),
221 read_only: false,
222 is_owned_by_user: Some(true),
223 hex_color: Some("#039be5".to_string()),
224 hex_foreground_color: Some("#ffffff".to_string()),
225 object: "calendar".to_string(),
226 metadata: None,
227 };
228
229 assert_eq!(calendar.name, "My Calendar");
230 assert_eq!(calendar.timezone, "UTC");
231 assert_eq!(calendar.is_primary, Some(true));
232 }
233
234 #[test]
235 fn test_calendar_serialization() {
236 let calendar = Calendar {
237 id: CalendarId::new("cal_123"),
238 grant_id: GrantId::new("grant_123"),
239 name: "Test".to_string(),
240 description: None,
241 location: None,
242 timezone: "America/New_York".to_string(),
243 is_primary: Some(false),
244 read_only: false,
245 is_owned_by_user: Some(true),
246 hex_color: None,
247 hex_foreground_color: None,
248 object: "calendar".to_string(),
249 metadata: None,
250 };
251
252 let json = serde_json::to_string(&calendar).unwrap();
253 assert!(json.contains("cal_123"));
254 assert!(json.contains("Test"));
255 assert!(json.contains("America/New_York"));
256
257 let deserialized: Calendar = serde_json::from_str(&json).unwrap();
258 assert_eq!(deserialized, calendar);
259 }
260
261 #[test]
262 fn test_create_calendar_request_builder() {
263 let request = CreateCalendarRequest::new("Work Calendar")
264 .description("My work events")
265 .timezone("America/Los_Angeles")
266 .location("Office");
267
268 assert_eq!(request.name, "Work Calendar");
269 assert_eq!(request.description, Some("My work events".to_string()));
270 assert_eq!(request.timezone, Some("America/Los_Angeles".to_string()));
271 assert_eq!(request.location, Some("Office".to_string()));
272 }
273
274 #[test]
275 fn test_update_calendar_request_builder() {
276 let request = UpdateCalendarRequest::new()
277 .name("Updated Calendar")
278 .timezone("UTC");
279
280 assert_eq!(request.name, Some("Updated Calendar".to_string()));
281 assert_eq!(request.timezone, Some("UTC".to_string()));
282 assert_eq!(request.description, None);
283 }
284
285 #[test]
286 fn test_create_calendar_request_serialization() {
287 let request = CreateCalendarRequest::new("Test Calendar").description("Test description");
288
289 let json = serde_json::to_string(&request).unwrap();
290 assert!(json.contains("Test Calendar"));
291 assert!(json.contains("Test description"));
292
293 let deserialized: CreateCalendarRequest = serde_json::from_str(&json).unwrap();
294 assert_eq!(deserialized, request);
295 }
296}