use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub struct Project {
pub completed_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub description: Option<String>,
pub id: u32,
pub key: String,
pub name: String,
pub task_ids: Vec<u32>,
pub updated_at: DateTime<Utc>,
}
impl Project {
pub fn new(id: u32, name: impl Into<String>) -> Self {
let now = Utc::now();
let name = name.into();
let key = if name.len() >= 3 {
name[0..3].to_uppercase()
} else {
name.to_uppercase()
};
Self {
completed_at: None,
created_at: now,
description: None,
id,
key,
name,
task_ids: Vec::new(),
updated_at: now,
}
}
pub fn add_desc(&mut self, description: impl Into<String>) {
self.add_description(description);
}
pub fn add_description(&mut self, description: impl Into<String>) {
self.description = Some(description.into());
self.touch();
}
pub fn add_task(&mut self, task_id: u32) {
if !self.task_ids.contains(&task_id) {
self.task_ids.push(task_id);
self.touch();
}
}
pub fn complete(&mut self) {
if !self.is_complete() {
self.completed_at = Some(Utc::now());
self.touch();
}
}
pub fn contains_task(&self, task_id: u32) -> bool {
self.task_ids.contains(&task_id)
}
pub fn is_complete(&self) -> bool {
self.completed_at.is_some()
}
pub fn is_empty(&self) -> bool {
self.task_ids.is_empty()
}
pub fn len(&self) -> usize {
self.task_ids.len()
}
pub fn remove_task(&mut self, task_id: u32) {
self.task_ids.retain(|id| *id != task_id);
self.touch();
}
pub fn touch(&mut self) {
self.updated_at = Utc::now();
}
#[must_use = "this method returns a new instance with an updated description"]
pub fn with_desc(self, description: impl Into<String>) -> Self {
self.with_description(description)
}
#[must_use = "this method returns a new instance with an updated description"]
pub fn with_description(mut self, description: impl Into<String>) -> Self {
self.description = Some(description.into());
self
}
#[must_use = "this method returns a new instance with an updated key"]
pub fn with_key(mut self, key: impl Into<String>) -> Self {
self.key = key.into();
self
}
#[must_use = "this method returns a new instance with an updated task list"]
pub fn with_tasks(mut self, task_ids: Vec<u32>) -> Self {
self.task_ids = task_ids;
self
}
}