Skip to main content

max / goingson

5.2 KB · 181 lines History Blame Raw
1 //! Project domain types and DTOs.
2 //!
3 //! Projects group related tasks, events, and emails under a single umbrella.
4 //! Each project has a type classification (Job, SideProject, Company, Essay,
5 //! Article, Painting, Other) and a lifecycle status (Active, OnHold, Completed,
6 //! Archived). Projects can contain milestones for phased tracking.
7
8 use chrono::{DateTime, Utc};
9 use serde::{Deserialize, Serialize};
10 use strum_macros::EnumString;
11 use crate::id_types::ProjectId;
12 use super::shared::{CssClass, DbValue, ParseableEnum};
13
14 // ============ Project Types ============
15
16 /// Classification of project types.
17 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default, EnumString)]
18 pub enum ProjectType {
19 /// Employment or client work.
20 #[strum(serialize = "Job")]
21 Job,
22 /// Personal side project.
23 #[strum(serialize = "SideProject")]
24 SideProject,
25 /// Company or business venture.
26 #[strum(serialize = "Company")]
27 Company,
28 /// Long-form writing project.
29 #[strum(serialize = "Essay")]
30 Essay,
31 /// Article or blog post.
32 #[strum(serialize = "Article")]
33 Article,
34 /// Art or visual project.
35 #[strum(serialize = "Painting")]
36 Painting,
37 /// Uncategorized project.
38 #[strum(serialize = "Other")]
39 #[default]
40 Other,
41 }
42
43 impl ProjectType {
44 /// Returns a human-readable display string.
45 pub fn as_str(&self) -> &'static str {
46 match self {
47 ProjectType::Job => "Job",
48 ProjectType::SideProject => "Side Project",
49 ProjectType::Company => "Company",
50 ProjectType::Essay => "Essay",
51 ProjectType::Article => "Article",
52 ProjectType::Painting => "Painting",
53 ProjectType::Other => "Other",
54 }
55 }
56
57 }
58
59 impl ParseableEnum for ProjectType {}
60
61 impl DbValue for ProjectType {
62 fn db_value(&self) -> &'static str {
63 match self {
64 ProjectType::Job => "Job",
65 ProjectType::SideProject => "SideProject",
66 ProjectType::Company => "Company",
67 ProjectType::Essay => "Essay",
68 ProjectType::Article => "Article",
69 ProjectType::Painting => "Painting",
70 ProjectType::Other => "Other",
71 }
72 }
73 }
74
75 impl CssClass for ProjectType {
76 fn css_class(&self) -> &'static str {
77 match self {
78 ProjectType::Job => "type-job",
79 ProjectType::SideProject => "type-sideproject",
80 ProjectType::Company => "type-company",
81 ProjectType::Essay => "type-essay",
82 ProjectType::Article => "type-article",
83 ProjectType::Painting => "type-painting",
84 ProjectType::Other => "type-other",
85 }
86 }
87 }
88
89 /// Lifecycle status of a project.
90 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default, EnumString)]
91 pub enum ProjectStatus {
92 /// Currently being worked on.
93 #[strum(serialize = "Active")]
94 #[default]
95 Active,
96 /// Temporarily paused.
97 #[strum(serialize = "OnHold")]
98 OnHold,
99 /// Successfully finished.
100 #[strum(serialize = "Completed")]
101 Completed,
102 /// No longer relevant, hidden from views.
103 #[strum(serialize = "Archived")]
104 Archived,
105 }
106
107 impl ProjectStatus {
108 /// Returns a human-readable display string.
109 pub fn as_str(&self) -> &'static str {
110 match self {
111 ProjectStatus::Active => "Active",
112 ProjectStatus::OnHold => "On Hold",
113 ProjectStatus::Completed => "Completed",
114 ProjectStatus::Archived => "Archived",
115 }
116 }
117
118 }
119
120 impl ParseableEnum for ProjectStatus {}
121
122 impl DbValue for ProjectStatus {
123 fn db_value(&self) -> &'static str {
124 match self {
125 ProjectStatus::Active => "Active",
126 ProjectStatus::OnHold => "OnHold",
127 ProjectStatus::Completed => "Completed",
128 ProjectStatus::Archived => "Archived",
129 }
130 }
131 }
132
133 impl CssClass for ProjectStatus {
134 fn css_class(&self) -> &'static str {
135 match self {
136 ProjectStatus::Active => "status-active",
137 ProjectStatus::OnHold => "status-onhold",
138 ProjectStatus::Completed => "status-completed",
139 ProjectStatus::Archived => "status-archived",
140 }
141 }
142 }
143
144 /// A project that groups related tasks, events, and emails.
145 #[derive(Debug, Clone, Serialize, Deserialize)]
146 #[serde(rename_all = "camelCase")]
147 pub struct Project {
148 /// Unique identifier.
149 pub id: ProjectId,
150 /// Project name.
151 pub name: String,
152 /// Optional description.
153 pub description: String,
154 /// Project classification.
155 pub project_type: ProjectType,
156 /// Current lifecycle status.
157 pub status: ProjectStatus,
158 /// When the project was created.
159 pub created_at: DateTime<Utc>,
160 }
161
162 // ============ Project DTOs ============
163
164 /// Data for creating a new project.
165 #[derive(Debug, Clone, Serialize, Deserialize)]
166 pub struct NewProject {
167 pub name: String,
168 pub description: String,
169 pub project_type: ProjectType,
170 pub status: ProjectStatus,
171 }
172
173 /// Data for updating an existing project.
174 #[derive(Debug, Clone, Serialize, Deserialize)]
175 pub struct UpdateProject {
176 pub name: String,
177 pub description: String,
178 pub project_type: ProjectType,
179 pub status: ProjectStatus,
180 }
181