Skip to main content

max / goingson

5.1 KB · 160 lines History Blame Raw
1 //! Saved view types and DTOs.
2 //!
3 //! Saved views are user-defined filter/sort configurations that can be pinned
4 //! to the sidebar for quick access. Each view targets a specific domain
5 //! (tasks, emails, or events) and stores its filter criteria as JSON.
6
7 use chrono::{DateTime, Utc};
8 use serde::{Deserialize, Serialize};
9 use strum_macros::EnumString;
10 use crate::id_types::{SavedViewId, UserId, ProjectId};
11
12 use super::shared::{DbValue, ParseableEnum, SortDirection};
13
14 // ============ Saved Views ============
15
16 /// Type of view for saved filters.
17 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default, EnumString)]
18 #[serde(rename_all = "lowercase")]
19 pub enum ViewType {
20 /// Task list view.
21 #[default]
22 #[strum(serialize = "tasks")]
23 Tasks,
24 /// Email list view.
25 #[strum(serialize = "emails")]
26 Emails,
27 /// Event list view.
28 #[strum(serialize = "events")]
29 Events,
30 }
31
32 impl ViewType {
33 /// Returns a human-readable display string.
34 pub fn as_str(&self) -> &'static str {
35 match self {
36 ViewType::Tasks => "Tasks",
37 ViewType::Emails => "Emails",
38 ViewType::Events => "Events",
39 }
40 }
41
42 }
43
44 impl ParseableEnum for ViewType {}
45
46 impl DbValue for ViewType {
47 fn db_value(&self) -> &'static str {
48 match self {
49 ViewType::Tasks => "tasks",
50 ViewType::Emails => "emails",
51 ViewType::Events => "events",
52 }
53 }
54 }
55
56 /// Column to sort saved view results by.
57 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
58 #[serde(rename_all = "snake_case")]
59 pub enum SortField {
60 /// Sort by calculated urgency score (tasks only).
61 Urgency,
62 /// Sort by due date (tasks) or received date (emails). Nulls sort last.
63 Due,
64 /// Sort by creation timestamp.
65 CreatedAt,
66 /// Sort alphabetically by description (tasks) or subject (emails) or title (events).
67 Description,
68 /// Sort by priority level (High > Medium > Low, tasks only).
69 Priority,
70 /// Sort alphabetically by associated project name. Nulls sort last.
71 Project,
72 }
73
74 /// Filter criteria stored as JSON.
75 #[derive(Debug, Clone, Serialize, Deserialize, Default)]
76 #[serde(rename_all = "camelCase")]
77 pub struct ViewFilters {
78 /// Filter by status.
79 #[serde(skip_serializing_if = "Option::is_none")]
80 pub status: Option<Vec<crate::models::TaskStatus>>,
81 /// Filter by project ID.
82 #[serde(skip_serializing_if = "Option::is_none")]
83 pub project_id: Option<ProjectId>,
84 /// Filter by tags (all must match).
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub tags: Option<Vec<String>>,
87 /// Filter by priority.
88 #[serde(skip_serializing_if = "Option::is_none")]
89 pub priority: Option<Vec<crate::models::Priority>>,
90 /// Filter by due date range start.
91 #[serde(skip_serializing_if = "Option::is_none")]
92 pub due_from: Option<DateTime<Utc>>,
93 /// Filter by due date range end.
94 #[serde(skip_serializing_if = "Option::is_none")]
95 pub due_to: Option<DateTime<Utc>>,
96 /// Filter by read/unread status (emails only).
97 #[serde(skip_serializing_if = "Option::is_none")]
98 pub is_read: Option<bool>,
99 /// Filter by archived status.
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub is_archived: Option<bool>,
102 /// Show only snoozed items.
103 #[serde(skip_serializing_if = "Option::is_none")]
104 pub is_snoozed: Option<bool>,
105 /// Show only items waiting for response.
106 #[serde(skip_serializing_if = "Option::is_none")]
107 pub is_waiting: Option<bool>,
108 }
109
110 /// A saved view / filter configuration.
111 #[derive(Debug, Clone, Serialize, Deserialize)]
112 #[serde(rename_all = "camelCase")]
113 pub struct SavedView {
114 /// Unique view ID.
115 pub id: SavedViewId,
116 /// User who owns this view. Not serialized into API responses; `default` lets a
117 /// backup (which omits it) still deserialize -- restore re-homes the row to the
118 /// target user, so the placeholder is never persisted.
119 #[serde(default, skip_serializing)]
120 pub user_id: UserId,
121 /// Display name for the view.
122 pub name: String,
123 /// Type of view (tasks, emails, events).
124 pub view_type: ViewType,
125 /// Filter criteria.
126 pub filters: ViewFilters,
127 /// Sort field.
128 pub sort_by: Option<SortField>,
129 /// Sort order.
130 pub sort_order: SortDirection,
131 /// Whether to show in sidebar.
132 pub is_pinned: bool,
133 /// Position in sidebar.
134 pub position: i32,
135 /// When the view was created.
136 pub created_at: DateTime<Utc>,
137 /// When the view was last modified.
138 pub updated_at: DateTime<Utc>,
139 }
140
141 // ============ Saved View DTOs ============
142
143 /// Data for creating a new saved view.
144 #[derive(Debug, Clone, Serialize, Deserialize)]
145 #[serde(rename_all = "camelCase")]
146 pub struct NewSavedView {
147 /// Display name for the view.
148 pub name: String,
149 /// Type of view (tasks, emails, events).
150 pub view_type: ViewType,
151 /// Filter criteria.
152 pub filters: ViewFilters,
153 /// Sort field.
154 pub sort_by: Option<SortField>,
155 /// Sort order.
156 pub sort_order: Option<SortDirection>,
157 /// Whether to pin to sidebar.
158 pub is_pinned: Option<bool>,
159 }
160