tempo_cli/models/
project.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use std::path::PathBuf;
4
5#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
6pub struct Project {
7    pub id: Option<i64>,
8    pub name: String,
9    pub path: PathBuf,
10    pub git_hash: Option<String>,
11    pub created_at: DateTime<Utc>,
12    pub updated_at: DateTime<Utc>,
13    pub is_archived: bool,
14    pub description: Option<String>,
15}
16
17#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
18pub enum ProjectStatus {
19    Active,
20    Archived,
21    Tracking,
22    Idle,
23}
24
25impl Project {
26    pub fn new(name: String, path: PathBuf) -> Self {
27        let now = Utc::now();
28        Self {
29            id: None,
30            name,
31            path,
32            git_hash: None,
33            created_at: now,
34            updated_at: now,
35            is_archived: false,
36            description: None,
37        }
38    }
39
40    pub fn with_git_hash(mut self, git_hash: Option<String>) -> Self {
41        self.git_hash = git_hash;
42        self
43    }
44
45    pub fn with_description(mut self, description: Option<String>) -> Self {
46        self.description = description;
47        self
48    }
49
50    pub fn archive(&mut self) {
51        self.is_archived = true;
52        self.updated_at = Utc::now();
53    }
54
55    pub fn unarchive(&mut self) {
56        self.is_archived = false;
57        self.updated_at = Utc::now();
58    }
59
60    pub fn update_path(&mut self, new_path: PathBuf) {
61        self.path = new_path;
62        self.updated_at = Utc::now();
63    }
64
65    pub fn is_git_project(&self) -> bool {
66        self.path.join(".git").exists()
67    }
68
69    pub fn has_timetrack_marker(&self) -> bool {
70        self.path.join(".timetrack").exists()
71    }
72
73    pub fn get_canonical_path(&self) -> anyhow::Result<PathBuf> {
74        Ok(self.path.canonicalize()?)
75    }
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct LinkedProject {
80    pub id: Option<i64>,
81    pub name: String,
82    pub description: Option<String>,
83    pub created_at: DateTime<Utc>,
84    pub is_active: bool,
85    pub member_projects: Vec<Project>,
86}
87
88impl LinkedProject {
89    pub fn new(name: String) -> Self {
90        Self {
91            id: None,
92            name,
93            description: None,
94            created_at: Utc::now(),
95            is_active: true,
96            member_projects: Vec::new(),
97        }
98    }
99
100    pub fn add_project(&mut self, project: Project) {
101        self.member_projects.push(project);
102    }
103
104    pub fn remove_project(&mut self, project_id: i64) {
105        self.member_projects.retain(|p| p.id != Some(project_id));
106    }
107}