use serde_json::{Map, Value, json};
use crate::error::Error;
use crate::generated::routes;
use crate::generated::types::Recording;
use crate::types::Date;
pub use crate::generated::services::calendar_todos::*;
#[derive(Debug, Clone, Default, PartialEq)]
pub struct TodoChanges {
pub title: Option<String>,
pub starts_at: Option<Date>,
pub focused: Option<bool>,
}
impl<'a> CalendarTodos<'a> {
pub async fn create_todo(
&self,
title: &str,
starts_at: Option<Date>,
) -> Result<Recording, Error> {
let starts_at = starts_at.unwrap_or_else(Date::today);
let body = json!({ "calendar_todo": { "title": title, "starts_at": starts_at } });
let mut operation = self.client().operation(&routes::CREATE_CALENDAR_TODO, &[]);
operation.json(&body)?;
self.client().send(operation).await
}
pub async fn update_todo(
&self,
todo_id: i64,
changes: &TodoChanges,
) -> Result<Recording, Error> {
let fields = changed_fields(changes);
if fields.is_empty() {
return Err(Error::usage(format!(
"update calendar todo {todo_id}: nothing to change"
)));
}
let mut operation = self
.client()
.operation(&routes::UPDATE_CALENDAR_TODO, &[&todo_id]);
operation.resource_id(todo_id);
operation.json(&json!({ "calendar_todo": fields }))?;
self.client().send(operation).await
}
}
fn changed_fields(changes: &TodoChanges) -> Map<String, Value> {
let mut fields = Map::new();
if let Some(title) = changes.title.as_deref().filter(|title| !title.is_empty()) {
fields.insert("title".to_string(), json!(title));
}
if let Some(starts_at) = changes.starts_at {
fields.insert("starts_at".to_string(), json!(starts_at));
}
if let Some(focused) = changes.focused {
fields.insert("focused".to_string(), json!(focused));
}
fields
}