@burdenoff/microfe-timecampus 2026.626.2 → 2026.703.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generated/wspace-operations.js +996 -816
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/generated/wspace-types.js +28 -0
- package/dist/generated/wspace-types.js.map +1 -0
- package/dist/index.js +4 -4
- package/dist/timecampus/TimeCampusRoutes.js +16 -12
- package/dist/timecampus/TimeCampusRoutes.js.map +1 -1
- package/dist/timecampus/components/Modal.js +65 -0
- package/dist/timecampus/components/Modal.js.map +1 -0
- package/dist/timecampus/components/StatusBadge.js +28 -0
- package/dist/timecampus/components/StatusBadge.js.map +1 -0
- package/dist/timecampus/components/Toast.js +87 -0
- package/dist/timecampus/components/Toast.js.map +1 -0
- package/dist/timecampus/index.js +1 -1
- package/dist/timecampus/pages/HomePage.js +143 -135
- package/dist/timecampus/pages/HomePage.js.map +1 -1
- package/dist/timecampus/pages/applets/AppletStorePage.js +14 -19
- package/dist/timecampus/pages/applets/AppletStorePage.js.map +1 -1
- package/dist/timecampus/pages/applets/InstalledAppletsPage.js +49 -37
- package/dist/timecampus/pages/applets/InstalledAppletsPage.js.map +1 -1
- package/dist/timecampus/pages/application-usage/ApplicationUsagePage.js +315 -87
- package/dist/timecampus/pages/application-usage/ApplicationUsagePage.js.map +1 -1
- package/dist/timecampus/pages/channels/ChannelsPage.js +340 -46
- package/dist/timecampus/pages/channels/ChannelsPage.js.map +1 -1
- package/dist/timecampus/pages/client-portal/ClientPortalPage.js +374 -92
- package/dist/timecampus/pages/client-portal/ClientPortalPage.js.map +1 -1
- package/dist/timecampus/pages/dashboard/ReportsPage.js +70 -37
- package/dist/timecampus/pages/dashboard/ReportsPage.js.map +1 -1
- package/dist/timecampus/pages/email-tracking/EmailTrackingPage.js +366 -60
- package/dist/timecampus/pages/email-tracking/EmailTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js +461 -87
- package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/geofencing/GeofencingPage.js +314 -55
- package/dist/timecampus/pages/geofencing/GeofencingPage.js.map +1 -1
- package/dist/timecampus/pages/industry-solutions/IndustrySolutionsPage.js +30 -27
- package/dist/timecampus/pages/industry-solutions/IndustrySolutionsPage.js.map +1 -1
- package/dist/timecampus/pages/location-tracking/LocationTrackingPage.js +269 -74
- package/dist/timecampus/pages/location-tracking/LocationTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/meetings/ActionItemFormModal.js +127 -0
- package/dist/timecampus/pages/meetings/ActionItemFormModal.js.map +1 -0
- package/dist/timecampus/pages/meetings/MeetingCreatePage.js +62 -52
- package/dist/timecampus/pages/meetings/MeetingCreatePage.js.map +1 -1
- package/dist/timecampus/pages/meetings/MeetingDetailPage.js +361 -74
- package/dist/timecampus/pages/meetings/MeetingDetailPage.js.map +1 -1
- package/dist/timecampus/pages/meetings/MeetingFormModal.js +156 -0
- package/dist/timecampus/pages/meetings/MeetingFormModal.js.map +1 -0
- package/dist/timecampus/pages/meetings/MeetingsPage.js +175 -74
- package/dist/timecampus/pages/meetings/MeetingsPage.js.map +1 -1
- package/dist/timecampus/pages/meetings/ParticipantFormModal.js +105 -0
- package/dist/timecampus/pages/meetings/ParticipantFormModal.js.map +1 -0
- package/dist/timecampus/pages/pomodoro/PomodoroPage.js +307 -67
- package/dist/timecampus/pages/pomodoro/PomodoroPage.js.map +1 -1
- package/dist/timecampus/pages/projects/ProjectCreatePage.js +51 -48
- package/dist/timecampus/pages/projects/ProjectCreatePage.js.map +1 -1
- package/dist/timecampus/pages/projects/ProjectDetailPage.js +248 -51
- package/dist/timecampus/pages/projects/ProjectDetailPage.js.map +1 -1
- package/dist/timecampus/pages/projects/ProjectsPage.js +354 -87
- package/dist/timecampus/pages/projects/ProjectsPage.js.map +1 -1
- package/dist/timecampus/pages/projects/TasksPage.js +367 -65
- package/dist/timecampus/pages/projects/TasksPage.js.map +1 -1
- package/dist/timecampus/pages/resource-planning/ResourcePlanningPage.js +674 -104
- package/dist/timecampus/pages/resource-planning/ResourcePlanningPage.js.map +1 -1
- package/dist/timecampus/pages/team/TeamAnalyticsPage.js +46 -34
- package/dist/timecampus/pages/team/TeamAnalyticsPage.js.map +1 -1
- package/dist/timecampus/pages/team/TeamMembersPage.js +93 -69
- package/dist/timecampus/pages/team/TeamMembersPage.js.map +1 -1
- package/dist/timecampus/pages/team/TeamPage.js +4 -3
- package/dist/timecampus/pages/team/TeamPage.js.map +1 -1
- package/dist/timecampus/pages/templates/TemplateDetailPage.js +72 -53
- package/dist/timecampus/pages/templates/TemplateDetailPage.js.map +1 -1
- package/dist/timecampus/pages/templates/TemplatesPage.js +40 -35
- package/dist/timecampus/pages/templates/TemplatesPage.js.map +1 -1
- package/dist/timecampus/pages/time/TimeEntriesPage.js +484 -97
- package/dist/timecampus/pages/time/TimeEntriesPage.js.map +1 -1
- package/dist/timecampus/pages/time/TimeTrackingPage.js +210 -99
- package/dist/timecampus/pages/time/TimeTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/time/TimerPage.js +229 -97
- package/dist/timecampus/pages/time/TimerPage.js.map +1 -1
- package/dist/timecampus/pages/time-approval/TimeApprovalPage.js +315 -110
- package/dist/timecampus/pages/time-approval/TimeApprovalPage.js.map +1 -1
- package/dist/timecampus/pages/timeline/TimelinePage.js +250 -0
- package/dist/timecampus/pages/timeline/TimelinePage.js.map +1 -0
- package/dist/timecampus/pages/widgets/WidgetDetailPage.js +158 -76
- package/dist/timecampus/pages/widgets/WidgetDetailPage.js.map +1 -1
- package/dist/timecampus/pages/widgets/WidgetsPage.js +181 -52
- package/dist/timecampus/pages/widgets/WidgetsPage.js.map +1 -1
- package/dist/timecampus/pages/workflows/WorkflowsPage.js +212 -61
- package/dist/timecampus/pages/workflows/WorkflowsPage.js.map +1 -1
- package/dist/timecampus/store/timecampusStore.js +13 -1
- package/dist/timecampus/store/timecampusStore.js.map +1 -1
- package/dist/timecampus/utils/helpers.js +20 -10
- package/dist/timecampus/utils/helpers.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,77 +1,383 @@
|
|
|
1
1
|
import { useTimeCampus as e } from "../../providers/TimeCampusProvider.js";
|
|
2
2
|
import { formatRelativeTime as t, getPriorityColor as n, getStatusColor as r } from "../../utils/helpers.js";
|
|
3
3
|
import { LoadingSkeleton as i } from "../../components/LoadingSkeleton.js";
|
|
4
|
-
import {
|
|
5
|
-
import { PageLayout as
|
|
6
|
-
import { EmptyState as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
4
|
+
import { useCreateEmailTimeEntryMutation as a, useDeleteEmailTimeEntryMutation as o, useListEmailTimeEntriesQuery as s, useUpdateEmailTimeEntryMutation as c } from "../../../generated/wspace-operations.js";
|
|
5
|
+
import { PageLayout as l } from "../../components/PageLayout.js";
|
|
6
|
+
import { EmptyState as ee } from "../../components/EmptyState.js";
|
|
7
|
+
import { Modal as u } from "../../components/Modal.js";
|
|
8
|
+
import { useState as d } from "react";
|
|
9
|
+
import { Filter as f, Mail as p, Pencil as m, Plus as h, Trash2 as g } from "lucide-react";
|
|
10
|
+
import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
11
|
+
import { GlassCard as te } from "@burdenoff/fe-libs/ui";
|
|
10
12
|
//#region src/timecampus/pages/email-tracking/EmailTrackingPage.tsx
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
var b = 25, x = {
|
|
14
|
+
success: "bg-status-success-bg text-status-success-text",
|
|
15
|
+
warning: "bg-status-warning-bg text-status-warning-text",
|
|
16
|
+
error: "bg-status-error-bg text-status-error-text",
|
|
17
|
+
info: "bg-status-info-bg text-status-info-text",
|
|
18
|
+
default: "bg-bg-sunken text-text-secondary",
|
|
19
|
+
muted: "bg-bg-sunken text-text-secondary"
|
|
20
|
+
}, S = "mt-1 w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary", C = "block text-sm font-medium text-text-primary";
|
|
21
|
+
function w(e) {
|
|
22
|
+
let t = new Date(e);
|
|
23
|
+
return Number.isNaN(t.getTime()) ? "" : (/* @__PURE__ */ new Date(t.getTime() - t.getTimezoneOffset() * 6e4)).toISOString().slice(0, 16);
|
|
24
|
+
}
|
|
25
|
+
function T() {
|
|
26
|
+
let e = /* @__PURE__ */ new Date();
|
|
27
|
+
return (/* @__PURE__ */ new Date(e.getTime() - e.getTimezoneOffset() * 6e4)).toISOString().slice(0, 16);
|
|
28
|
+
}
|
|
29
|
+
function E(e) {
|
|
30
|
+
return {
|
|
31
|
+
subject: e?.subject ?? "",
|
|
32
|
+
sender: e?.sender ?? "",
|
|
33
|
+
recipients: e?.recipients ?? "",
|
|
34
|
+
category: e?.category ?? "",
|
|
35
|
+
date: e?.date ? w(e.date) : T(),
|
|
36
|
+
duration: e?.duration == null ? "" : String(e.duration),
|
|
37
|
+
responseTime: e?.responseTime == null ? "" : String(e.responseTime),
|
|
38
|
+
isImportant: e?.isImportant ?? !1,
|
|
39
|
+
threadId: e?.threadId ?? ""
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function D({ value: e, onChange: t }) {
|
|
43
|
+
let n = (n, r) => t({
|
|
44
|
+
...e,
|
|
45
|
+
[n]: r
|
|
46
|
+
});
|
|
47
|
+
return /* @__PURE__ */ y("div", {
|
|
48
|
+
className: "space-y-4",
|
|
49
|
+
children: [
|
|
50
|
+
/* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("label", {
|
|
51
|
+
className: C,
|
|
52
|
+
children: "Subject"
|
|
53
|
+
}), /* @__PURE__ */ v("input", {
|
|
54
|
+
type: "text",
|
|
55
|
+
placeholder: "Email subject",
|
|
56
|
+
value: e.subject,
|
|
57
|
+
onChange: (e) => n("subject", e.target.value),
|
|
58
|
+
className: S
|
|
59
|
+
})] }),
|
|
60
|
+
/* @__PURE__ */ y("div", {
|
|
61
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
62
|
+
children: [/* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("label", {
|
|
63
|
+
className: C,
|
|
64
|
+
children: "Sender"
|
|
65
|
+
}), /* @__PURE__ */ v("input", {
|
|
66
|
+
type: "text",
|
|
67
|
+
placeholder: "sender@example.com",
|
|
68
|
+
value: e.sender,
|
|
69
|
+
onChange: (e) => n("sender", e.target.value),
|
|
70
|
+
className: S
|
|
71
|
+
})] }), /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("label", {
|
|
72
|
+
className: C,
|
|
73
|
+
children: "Recipients"
|
|
74
|
+
}), /* @__PURE__ */ v("input", {
|
|
75
|
+
type: "text",
|
|
76
|
+
placeholder: "recipient@example.com",
|
|
77
|
+
value: e.recipients,
|
|
78
|
+
onChange: (e) => n("recipients", e.target.value),
|
|
79
|
+
className: S
|
|
80
|
+
})] })]
|
|
81
|
+
}),
|
|
82
|
+
/* @__PURE__ */ y("div", {
|
|
83
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
84
|
+
children: [/* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("label", {
|
|
85
|
+
className: C,
|
|
86
|
+
children: "Category"
|
|
87
|
+
}), /* @__PURE__ */ v("input", {
|
|
88
|
+
type: "text",
|
|
89
|
+
placeholder: "e.g. work, newsletter",
|
|
90
|
+
value: e.category,
|
|
91
|
+
onChange: (e) => n("category", e.target.value),
|
|
92
|
+
className: S
|
|
93
|
+
})] }), /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("label", {
|
|
94
|
+
className: C,
|
|
95
|
+
children: "Date & Time"
|
|
96
|
+
}), /* @__PURE__ */ v("input", {
|
|
97
|
+
type: "datetime-local",
|
|
98
|
+
value: e.date,
|
|
99
|
+
onChange: (e) => n("date", e.target.value),
|
|
100
|
+
className: S
|
|
101
|
+
})] })]
|
|
102
|
+
}),
|
|
103
|
+
/* @__PURE__ */ y("div", {
|
|
104
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
105
|
+
children: [/* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("label", {
|
|
106
|
+
className: C,
|
|
107
|
+
children: "Duration (minutes)"
|
|
108
|
+
}), /* @__PURE__ */ v("input", {
|
|
109
|
+
type: "number",
|
|
110
|
+
min: "0",
|
|
111
|
+
placeholder: "0",
|
|
112
|
+
value: e.duration,
|
|
113
|
+
onChange: (e) => n("duration", e.target.value),
|
|
114
|
+
className: S
|
|
115
|
+
})] }), /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("label", {
|
|
116
|
+
className: C,
|
|
117
|
+
children: "Response Time (minutes)"
|
|
118
|
+
}), /* @__PURE__ */ v("input", {
|
|
119
|
+
type: "number",
|
|
120
|
+
min: "0",
|
|
121
|
+
placeholder: "0",
|
|
122
|
+
value: e.responseTime,
|
|
123
|
+
onChange: (e) => n("responseTime", e.target.value),
|
|
124
|
+
className: S
|
|
125
|
+
})] })]
|
|
126
|
+
}),
|
|
127
|
+
/* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("label", {
|
|
128
|
+
className: C,
|
|
129
|
+
children: "Thread ID"
|
|
130
|
+
}), /* @__PURE__ */ v("input", {
|
|
131
|
+
type: "text",
|
|
132
|
+
placeholder: "Optional thread identifier",
|
|
133
|
+
value: e.threadId,
|
|
134
|
+
onChange: (e) => n("threadId", e.target.value),
|
|
135
|
+
className: S
|
|
136
|
+
})] }),
|
|
137
|
+
/* @__PURE__ */ y("label", {
|
|
138
|
+
className: "flex items-center gap-2",
|
|
139
|
+
children: [/* @__PURE__ */ v("input", {
|
|
140
|
+
type: "checkbox",
|
|
141
|
+
checked: e.isImportant,
|
|
142
|
+
onChange: (e) => n("isImportant", e.target.checked),
|
|
143
|
+
className: "h-4 w-4 rounded border-border-subtle"
|
|
144
|
+
}), /* @__PURE__ */ v("span", {
|
|
145
|
+
className: "text-sm font-medium text-text-primary",
|
|
146
|
+
children: "Mark as important"
|
|
147
|
+
})]
|
|
148
|
+
})
|
|
149
|
+
]
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function O() {
|
|
153
|
+
let { workspaceId: S = "" } = e(), [C, w] = d(!1), [T, O] = d(!1), { data: k, loading: A, error: ne, fetchMore: j, refetch: M } = s({
|
|
154
|
+
variables: {
|
|
155
|
+
limit: b,
|
|
156
|
+
offset: 0,
|
|
157
|
+
filter: C ? { isImportant: !0 } : void 0
|
|
158
|
+
},
|
|
159
|
+
skip: !S,
|
|
160
|
+
notifyOnNetworkStatusChange: !0
|
|
161
|
+
}), N = k?.emailTimeEntries ?? [], P = N.length > 0 && N.length % b === 0, [F, I] = d(!1), [L, R] = d(null), [z, B] = d(null), [V, H] = d(E()), [U, W] = d(E()), [G, { loading: K, error: q }] = a(), [J, { loading: Y, error: X }] = c(), [re, { loading: Z, error: ie }] = o(), Q = (e) => ({
|
|
162
|
+
subject: e.subject.trim() || void 0,
|
|
163
|
+
sender: e.sender.trim() || void 0,
|
|
164
|
+
recipients: e.recipients.trim() || void 0,
|
|
165
|
+
category: e.category.trim() || void 0,
|
|
166
|
+
date: new Date(e.date).toISOString(),
|
|
167
|
+
duration: e.duration ? Number(e.duration) : void 0,
|
|
168
|
+
responseTime: e.responseTime ? Number(e.responseTime) : void 0,
|
|
169
|
+
isImportant: e.isImportant,
|
|
170
|
+
threadId: e.threadId.trim() || void 0
|
|
171
|
+
}), $ = () => {
|
|
172
|
+
H(E()), I(!0);
|
|
173
|
+
}, ae = async () => {
|
|
174
|
+
await G({ variables: { input: Q(V) } }), I(!1), await M();
|
|
175
|
+
}, oe = (e) => {
|
|
176
|
+
W(E(e)), R(e);
|
|
177
|
+
};
|
|
178
|
+
return /* @__PURE__ */ y(l, {
|
|
17
179
|
title: "Email Tracking",
|
|
18
180
|
description: "Track time spent on emails",
|
|
19
181
|
purpose: "Surface the hidden hours email steals from your day — every message linked to the time it took and the project it belonged to — so inbox work finally shows up in your timesheets and reports.",
|
|
20
|
-
actions: /* @__PURE__ */
|
|
21
|
-
className: "
|
|
22
|
-
children: [/* @__PURE__ */
|
|
182
|
+
actions: /* @__PURE__ */ y("div", {
|
|
183
|
+
className: "flex items-center gap-2",
|
|
184
|
+
children: [/* @__PURE__ */ y("button", {
|
|
185
|
+
onClick: () => w((e) => !e),
|
|
186
|
+
className: `inline-flex items-center gap-1.5 rounded-md border px-3 py-2 text-sm font-medium ${C ? "border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg" : "border-border-subtle text-text-primary hover:bg-bg-sunken/50"}`,
|
|
187
|
+
children: [/* @__PURE__ */ v(f, { className: "h-4 w-4" }), C ? "Important only" : "Filter"]
|
|
188
|
+
}), /* @__PURE__ */ y("button", {
|
|
189
|
+
onClick: $,
|
|
190
|
+
className: "inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
|
|
191
|
+
children: [/* @__PURE__ */ v(h, { className: "h-4 w-4" }), "Add Entry"]
|
|
192
|
+
})]
|
|
23
193
|
}),
|
|
24
|
-
children:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
194
|
+
children: [
|
|
195
|
+
A && N.length === 0 ? /* @__PURE__ */ v(i, {
|
|
196
|
+
variant: "list",
|
|
197
|
+
count: 4
|
|
198
|
+
}) : ne ? /* @__PURE__ */ v("div", {
|
|
199
|
+
className: "rounded-xl border border-status-error-border/50 bg-status-error-bg/10 p-4 text-sm text-status-error-text",
|
|
200
|
+
children: "Failed to load email entries. Please try again later."
|
|
201
|
+
}) : N.length === 0 ? /* @__PURE__ */ v(ee, {
|
|
202
|
+
illustration: "empty-notifications",
|
|
203
|
+
title: "No email entries found",
|
|
204
|
+
description: "Log the time you spend in your inbox — or connect email tracking — and entries will appear here.",
|
|
205
|
+
action: /* @__PURE__ */ y("button", {
|
|
206
|
+
onClick: $,
|
|
207
|
+
className: "inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
|
|
208
|
+
children: [/* @__PURE__ */ v(h, { className: "h-4 w-4" }), "Add Entry"]
|
|
209
|
+
})
|
|
210
|
+
}) : /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(te, {
|
|
211
|
+
treatment: "glass",
|
|
212
|
+
glow: !0,
|
|
213
|
+
className: "overflow-hidden",
|
|
214
|
+
children: /* @__PURE__ */ v("div", {
|
|
215
|
+
className: "divide-y divide-border",
|
|
216
|
+
children: N.map((e) => /* @__PURE__ */ y("div", {
|
|
217
|
+
className: "flex items-center justify-between gap-3 p-4 transition-colors hover:bg-bg-sunken/50",
|
|
218
|
+
children: [/* @__PURE__ */ y("div", {
|
|
219
|
+
className: "flex min-w-0 items-center gap-3",
|
|
220
|
+
children: [/* @__PURE__ */ v(p, { className: `h-5 w-5 shrink-0 ${e.isImportant ? "text-primary" : "text-text-secondary"}` }), /* @__PURE__ */ y("div", {
|
|
221
|
+
className: "min-w-0",
|
|
222
|
+
children: [/* @__PURE__ */ v("p", {
|
|
223
|
+
className: `truncate text-sm ${e.isImportant ? "font-semibold text-text-primary" : "font-medium text-text-primary"}`,
|
|
224
|
+
children: e.subject ?? "(No subject)"
|
|
225
|
+
}), /* @__PURE__ */ y("p", {
|
|
226
|
+
className: "truncate text-xs text-text-secondary",
|
|
227
|
+
children: [
|
|
228
|
+
e.sender ?? "Unknown",
|
|
229
|
+
" ·",
|
|
230
|
+
" ",
|
|
231
|
+
t(e.date),
|
|
232
|
+
" · ~",
|
|
233
|
+
e.duration ?? 0,
|
|
234
|
+
"min"
|
|
235
|
+
]
|
|
236
|
+
})]
|
|
237
|
+
})]
|
|
238
|
+
}), /* @__PURE__ */ y("div", {
|
|
239
|
+
className: "flex shrink-0 items-center gap-2",
|
|
49
240
|
children: [
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
241
|
+
/* @__PURE__ */ v("span", {
|
|
242
|
+
className: `hidden rounded-full px-2 py-0.5 text-xs font-medium sm:inline-flex ${x[n(e.isImportant ? "high" : "low")]}`,
|
|
243
|
+
children: e.isImportant ? "high" : "normal"
|
|
244
|
+
}),
|
|
245
|
+
/* @__PURE__ */ v("span", {
|
|
246
|
+
className: `hidden rounded-full px-2 py-0.5 text-xs font-medium sm:inline-flex ${x[r(e.category ?? "active")]}`,
|
|
247
|
+
children: e.category ?? "uncategorized"
|
|
248
|
+
}),
|
|
249
|
+
/* @__PURE__ */ v("button", {
|
|
250
|
+
onClick: () => oe(e),
|
|
251
|
+
className: "rounded-md p-1.5 text-text-secondary hover:bg-bg-sunken hover:text-text-primary",
|
|
252
|
+
"aria-label": "Edit entry",
|
|
253
|
+
children: /* @__PURE__ */ v(m, { className: "h-4 w-4" })
|
|
254
|
+
}),
|
|
255
|
+
/* @__PURE__ */ v("button", {
|
|
256
|
+
onClick: () => B(e),
|
|
257
|
+
className: "rounded-md p-1.5 text-text-secondary hover:bg-status-error-bg hover:text-status-error-text",
|
|
258
|
+
"aria-label": "Delete entry",
|
|
259
|
+
children: /* @__PURE__ */ v(g, { className: "h-4 w-4" })
|
|
260
|
+
})
|
|
57
261
|
]
|
|
58
|
-
})] })]
|
|
59
|
-
}), /* @__PURE__ */ d("div", {
|
|
60
|
-
className: "flex items-center gap-2",
|
|
61
|
-
children: [/* @__PURE__ */ u("span", {
|
|
62
|
-
className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${n(e.isImportant ? "high" : "low")}`,
|
|
63
|
-
children: e.isImportant ? "high" : "normal"
|
|
64
|
-
}), /* @__PURE__ */ u("span", {
|
|
65
|
-
className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${r(e.category ?? "active")}`,
|
|
66
|
-
children: e.category ?? "uncategorized"
|
|
67
262
|
})]
|
|
68
|
-
})
|
|
69
|
-
}
|
|
263
|
+
}, e.id))
|
|
264
|
+
})
|
|
265
|
+
}), P && /* @__PURE__ */ v("div", {
|
|
266
|
+
className: "mt-4 flex justify-center",
|
|
267
|
+
children: /* @__PURE__ */ v("button", {
|
|
268
|
+
onClick: async () => {
|
|
269
|
+
O(!0);
|
|
270
|
+
try {
|
|
271
|
+
await j({
|
|
272
|
+
variables: { offset: N.length },
|
|
273
|
+
updateQuery: (e, { fetchMoreResult: t }) => t ? {
|
|
274
|
+
...e,
|
|
275
|
+
emailTimeEntries: [...e.emailTimeEntries, ...t.emailTimeEntries]
|
|
276
|
+
} : e
|
|
277
|
+
});
|
|
278
|
+
} finally {
|
|
279
|
+
O(!1);
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
disabled: T,
|
|
283
|
+
className: "rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50 disabled:opacity-50",
|
|
284
|
+
children: T ? "Loading..." : "Load more"
|
|
285
|
+
})
|
|
286
|
+
})] }),
|
|
287
|
+
/* @__PURE__ */ y(u, {
|
|
288
|
+
open: F,
|
|
289
|
+
onClose: () => I(!1),
|
|
290
|
+
title: "Add Email Entry",
|
|
291
|
+
description: "Log time spent on an email",
|
|
292
|
+
size: "xl",
|
|
293
|
+
footer: /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v("button", {
|
|
294
|
+
onClick: () => I(!1),
|
|
295
|
+
className: "rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50",
|
|
296
|
+
children: "Cancel"
|
|
297
|
+
}), /* @__PURE__ */ v("button", {
|
|
298
|
+
onClick: ae,
|
|
299
|
+
disabled: K || !V.date,
|
|
300
|
+
className: "rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50",
|
|
301
|
+
children: K ? "Saving..." : "Add Entry"
|
|
302
|
+
})] }),
|
|
303
|
+
children: [q && /* @__PURE__ */ v("div", {
|
|
304
|
+
className: "mb-4 rounded-lg border border-status-error-bg/40 bg-status-error-bg p-3 text-sm text-status-error-text",
|
|
305
|
+
children: "Failed to add entry. Please try again."
|
|
306
|
+
}), /* @__PURE__ */ v(D, {
|
|
307
|
+
value: V,
|
|
308
|
+
onChange: H
|
|
309
|
+
})]
|
|
310
|
+
}),
|
|
311
|
+
/* @__PURE__ */ y(u, {
|
|
312
|
+
open: L !== null,
|
|
313
|
+
onClose: () => R(null),
|
|
314
|
+
title: "Edit Email Entry",
|
|
315
|
+
description: "Update this email time entry",
|
|
316
|
+
size: "xl",
|
|
317
|
+
footer: /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v("button", {
|
|
318
|
+
onClick: () => R(null),
|
|
319
|
+
className: "rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50",
|
|
320
|
+
children: "Cancel"
|
|
321
|
+
}), /* @__PURE__ */ v("button", {
|
|
322
|
+
onClick: async () => {
|
|
323
|
+
L && (await J({ variables: {
|
|
324
|
+
id: L.id,
|
|
325
|
+
input: Q(U)
|
|
326
|
+
} }), R(null), await M());
|
|
327
|
+
},
|
|
328
|
+
disabled: Y || !U.date,
|
|
329
|
+
className: "rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50",
|
|
330
|
+
children: Y ? "Saving..." : "Save Changes"
|
|
331
|
+
})] }),
|
|
332
|
+
children: [X && /* @__PURE__ */ v("div", {
|
|
333
|
+
className: "mb-4 rounded-lg border border-status-error-bg/40 bg-status-error-bg p-3 text-sm text-status-error-text",
|
|
334
|
+
children: "Failed to update entry. Please try again."
|
|
335
|
+
}), /* @__PURE__ */ v(D, {
|
|
336
|
+
value: U,
|
|
337
|
+
onChange: W
|
|
338
|
+
})]
|
|
339
|
+
}),
|
|
340
|
+
/* @__PURE__ */ y(u, {
|
|
341
|
+
open: z !== null,
|
|
342
|
+
onClose: () => B(null),
|
|
343
|
+
title: "Delete Email Entry",
|
|
344
|
+
size: "sm",
|
|
345
|
+
footer: /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v("button", {
|
|
346
|
+
onClick: () => B(null),
|
|
347
|
+
className: "rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50",
|
|
348
|
+
children: "Cancel"
|
|
349
|
+
}), /* @__PURE__ */ v("button", {
|
|
350
|
+
onClick: async () => {
|
|
351
|
+
z && (await re({ variables: { id: z.id } }), B(null), await M());
|
|
352
|
+
},
|
|
353
|
+
disabled: Z,
|
|
354
|
+
className: "rounded-md bg-status-error-bg px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg/90 disabled:opacity-50",
|
|
355
|
+
children: Z ? "Deleting..." : "Delete"
|
|
356
|
+
})] }),
|
|
357
|
+
children: [ie && /* @__PURE__ */ v("div", {
|
|
358
|
+
className: "mb-4 rounded-lg border border-status-error-bg/40 bg-status-error-bg p-3 text-sm text-status-error-text",
|
|
359
|
+
children: "Failed to delete entry. Please try again."
|
|
360
|
+
}), /* @__PURE__ */ y("p", {
|
|
361
|
+
className: "text-sm text-text-secondary",
|
|
362
|
+
children: [
|
|
363
|
+
"Are you sure you want to delete the entry",
|
|
364
|
+
" ",
|
|
365
|
+
/* @__PURE__ */ y("span", {
|
|
366
|
+
className: "font-medium text-text-primary",
|
|
367
|
+
children: [
|
|
368
|
+
"“",
|
|
369
|
+
z?.subject ?? "(No subject)",
|
|
370
|
+
"”"
|
|
371
|
+
]
|
|
372
|
+
}),
|
|
373
|
+
"? This action cannot be undone."
|
|
374
|
+
]
|
|
375
|
+
})]
|
|
70
376
|
})
|
|
71
|
-
|
|
377
|
+
]
|
|
72
378
|
});
|
|
73
379
|
}
|
|
74
380
|
//#endregion
|
|
75
|
-
export {
|
|
381
|
+
export { O as EmailTrackingPage };
|
|
76
382
|
|
|
77
383
|
//# sourceMappingURL=EmailTrackingPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmailTrackingPage.js","names":[],"sources":["../../../../src/timecampus/pages/email-tracking/EmailTrackingPage.tsx"],"sourcesContent":["import { Mail, Filter } from \"lucide-react\";\nimport { GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { EmptyState } from \"../../components/EmptyState\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport {\n getStatusColor,\n getPriorityColor,\n formatRelativeTime,\n} from \"../../utils/helpers\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListEmailTimeEntriesQuery,\n type EmailTimeEntryFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function EmailTrackingPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n const { data, loading, error } = useListEmailTimeEntriesQuery({\n variables: { limit: 50 },\n skip: !workspaceId,\n });\n\n const emails = data?.emailTimeEntries ?? [];\n\n return (\n <PageLayout\n title=\"Email Tracking\"\n description=\"Track time spent on emails\"\n purpose=\"Surface the hidden hours email steals from your day — every message linked to the time it took and the project it belonged to — so inbox work finally shows up in your timesheets and reports.\"\n actions={\n <button className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50\">\n <Filter className=\"h-4 w-4\" />\n Filter\n </button>\n }\n >\n {loading ? (\n <LoadingSkeleton variant=\"list\" count={4} />\n ) : error ? (\n <div className=\"rounded-xl border border-status-error-border/50 bg-status-error-bg/10 p-4 text-sm text-status-error-text\">\n Failed to load email entries. Please try again later.\n </div>\n ) : emails.length === 0 ? (\n <EmptyState\n illustration=\"empty-notifications\"\n title=\"No email entries found\"\n description=\"Once email tracking is connected, the time you spend reading and replying shows up here.\"\n />\n ) : (\n <GlassCard treatment=\"glass\" glow className=\"overflow-hidden\">\n <div className=\"divide-y divide-border\">\n {emails.map((email: EmailTimeEntryFieldsFragment) => (\n <div\n key={email.id}\n className=\"flex items-center justify-between p-4 hover:bg-bg-sunken/50 transition-colors cursor-pointer\"\n >\n <div className=\"flex items-center gap-3\">\n <Mail\n className={`h-5 w-5 ${email.isImportant ? \"text-primary\" : \"text-text-secondary\"}`}\n />\n <div>\n <p\n className={`text-sm ${email.isImportant ? \"font-semibold text-text-primary\" : \"font-medium text-text-primary\"}`}\n >\n {email.subject ?? \"(No subject)\"}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {email.sender ?? \"Unknown\"} ·{\" \"}\n {formatRelativeTime(email.date)} · ~\n {email.duration ?? 0}min\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <span\n className={`inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${getPriorityColor(email.isImportant ? \"high\" : \"low\")}`}\n >\n {email.isImportant ? \"high\" : \"normal\"}\n </span>\n <span\n className={`inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${getStatusColor(email.category ?? \"active\")}`}\n >\n {email.category ?? \"uncategorized\"}\n </span>\n </div>\n </div>\n ))}\n </div>\n </GlassCard>\n )}\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;AAgBA,SAAgB,IAAoB;CAClC,IAAM,EAAE,iBAAc,OAAO,GAAe,EACtC,EAAE,SAAM,YAAS,aAAU,EAA6B;EAC5D,WAAW,EAAE,OAAO,IAAI;EACxB,MAAM,CAAC;EACR,CAAC,EAEI,IAAS,GAAM,oBAAoB,EAAE;AAE3C,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SAAQ;EACR,SACE,kBAAC,UAAD;GAAQ,WAAU;aAAlB,CACE,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA,EAAA,SAEvB;;YAGV,IACC,kBAAC,GAAD;GAAiB,SAAQ;GAAO,OAAO;GAAK,CAAA,GAC1C,IACF,kBAAC,OAAD;GAAK,WAAU;aAA2G;GAEpH,CAAA,GACJ,EAAO,WAAW,IACpB,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,aAAY;GACZ,CAAA,GAEF,kBAAC,GAAD;GAAW,WAAU;GAAQ,MAAA;GAAK,WAAU;aAC1C,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAO,KAAK,MACX,kBAAC,OAAD;KAEE,WAAU;eAFZ,CAIE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EACE,WAAW,WAAW,EAAM,cAAc,iBAAiB,yBAC3D,CAAA,EACF,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;OACE,WAAW,WAAW,EAAM,cAAc,oCAAoC;iBAE7E,EAAM,WAAW;OAChB,CAAA,EACJ,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG,EAAM,UAAU;QAAU;QAAU;QACpC,EAAmB,EAAM,KAAK;QAAC;QAC/B,EAAM,YAAY;QAAE;QACnB;SACA,EAAA,CAAA,CACF;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OACE,WAAW,4DAA4D,EAAiB,EAAM,cAAc,SAAS,MAAM;iBAE1H,EAAM,cAAc,SAAS;OACzB,CAAA,EACP,kBAAC,QAAD;OACE,WAAW,4DAA4D,EAAe,EAAM,YAAY,SAAS;iBAEhH,EAAM,YAAY;OACd,CAAA,CACH;QACF;OAhCC,EAAM,GAgCP,CACN;IACE,CAAA;GACI,CAAA;EAEH,CAAA"}
|
|
1
|
+
{"version":3,"file":"EmailTrackingPage.js","names":[],"sources":["../../../../src/timecampus/pages/email-tracking/EmailTrackingPage.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { Mail, Filter, Plus, Pencil, Trash2 } from \"lucide-react\";\nimport { GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { EmptyState } from \"../../components/EmptyState\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { Modal } from \"../../components/Modal\";\nimport {\n getStatusColor,\n getPriorityColor,\n formatRelativeTime,\n type BadgeVariant,\n} from \"../../utils/helpers\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListEmailTimeEntriesQuery,\n useCreateEmailTimeEntryMutation,\n useUpdateEmailTimeEntryMutation,\n useDeleteEmailTimeEntryMutation,\n type EmailTimeEntryFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nconst PAGE_SIZE = 25;\n\nconst BADGE_CLASSES: Record<BadgeVariant, string> = {\n success: \"bg-status-success-bg text-status-success-text\",\n warning: \"bg-status-warning-bg text-status-warning-text\",\n error: \"bg-status-error-bg text-status-error-text\",\n info: \"bg-status-info-bg text-status-info-text\",\n default: \"bg-bg-sunken text-text-secondary\",\n muted: \"bg-bg-sunken text-text-secondary\",\n};\n\ninterface EmailFormState {\n subject: string;\n sender: string;\n recipients: string;\n category: string;\n date: string;\n duration: string;\n responseTime: string;\n isImportant: boolean;\n threadId: string;\n}\n\nconst inputClasses =\n \"mt-1 w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary\";\nconst labelClasses = \"block text-sm font-medium text-text-primary\";\n\nfunction toDatetimeLocal(iso: string): string {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return \"\";\n const local = new Date(d.getTime() - d.getTimezoneOffset() * 60000);\n return local.toISOString().slice(0, 16);\n}\n\nfunction nowDatetimeLocal(): string {\n const d = new Date();\n const local = new Date(d.getTime() - d.getTimezoneOffset() * 60000);\n return local.toISOString().slice(0, 16);\n}\n\nfunction toState(entry?: EmailTimeEntryFieldsFragment): EmailFormState {\n return {\n subject: entry?.subject ?? \"\",\n sender: entry?.sender ?? \"\",\n recipients: entry?.recipients ?? \"\",\n category: entry?.category ?? \"\",\n date: entry?.date ? toDatetimeLocal(entry.date) : nowDatetimeLocal(),\n duration: entry?.duration != null ? String(entry.duration) : \"\",\n responseTime: entry?.responseTime != null ? String(entry.responseTime) : \"\",\n isImportant: entry?.isImportant ?? false,\n threadId: entry?.threadId ?? \"\",\n };\n}\n\ninterface EmailEntryFormProps {\n value: EmailFormState;\n onChange: (next: EmailFormState) => void;\n}\n\nfunction EmailEntryForm({ value, onChange }: EmailEntryFormProps) {\n const set = <K extends keyof EmailFormState>(key: K, v: EmailFormState[K]) =>\n onChange({ ...value, [key]: v });\n\n return (\n <div className=\"space-y-4\">\n <div>\n <label className={labelClasses}>Subject</label>\n <input\n type=\"text\"\n placeholder=\"Email subject\"\n value={value.subject}\n onChange={(e) => set(\"subject\", e.target.value)}\n className={inputClasses}\n />\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className={labelClasses}>Sender</label>\n <input\n type=\"text\"\n placeholder=\"sender@example.com\"\n value={value.sender}\n onChange={(e) => set(\"sender\", e.target.value)}\n className={inputClasses}\n />\n </div>\n <div>\n <label className={labelClasses}>Recipients</label>\n <input\n type=\"text\"\n placeholder=\"recipient@example.com\"\n value={value.recipients}\n onChange={(e) => set(\"recipients\", e.target.value)}\n className={inputClasses}\n />\n </div>\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className={labelClasses}>Category</label>\n <input\n type=\"text\"\n placeholder=\"e.g. work, newsletter\"\n value={value.category}\n onChange={(e) => set(\"category\", e.target.value)}\n className={inputClasses}\n />\n </div>\n <div>\n <label className={labelClasses}>Date & Time</label>\n <input\n type=\"datetime-local\"\n value={value.date}\n onChange={(e) => set(\"date\", e.target.value)}\n className={inputClasses}\n />\n </div>\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className={labelClasses}>Duration (minutes)</label>\n <input\n type=\"number\"\n min=\"0\"\n placeholder=\"0\"\n value={value.duration}\n onChange={(e) => set(\"duration\", e.target.value)}\n className={inputClasses}\n />\n </div>\n <div>\n <label className={labelClasses}>Response Time (minutes)</label>\n <input\n type=\"number\"\n min=\"0\"\n placeholder=\"0\"\n value={value.responseTime}\n onChange={(e) => set(\"responseTime\", e.target.value)}\n className={inputClasses}\n />\n </div>\n </div>\n <div>\n <label className={labelClasses}>Thread ID</label>\n <input\n type=\"text\"\n placeholder=\"Optional thread identifier\"\n value={value.threadId}\n onChange={(e) => set(\"threadId\", e.target.value)}\n className={inputClasses}\n />\n </div>\n <label className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n checked={value.isImportant}\n onChange={(e) => set(\"isImportant\", e.target.checked)}\n className=\"h-4 w-4 rounded border-border-subtle\"\n />\n <span className=\"text-sm font-medium text-text-primary\">\n Mark as important\n </span>\n </label>\n </div>\n );\n}\n\nexport function EmailTrackingPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n const [importantOnly, setImportantOnly] = useState(false);\n const [loadingMore, setLoadingMore] = useState(false);\n\n const { data, loading, error, fetchMore, refetch } =\n useListEmailTimeEntriesQuery({\n variables: {\n limit: PAGE_SIZE,\n offset: 0,\n filter: importantOnly ? { isImportant: true } : undefined,\n },\n skip: !workspaceId,\n notifyOnNetworkStatusChange: true,\n });\n\n const emails = data?.emailTimeEntries ?? [];\n const hasMore = emails.length > 0 && emails.length % PAGE_SIZE === 0;\n\n // Modal state\n const [createOpen, setCreateOpen] = useState(false);\n const [editEntry, setEditEntry] =\n useState<EmailTimeEntryFieldsFragment | null>(null);\n const [deleteEntry, setDeleteEntry] =\n useState<EmailTimeEntryFieldsFragment | null>(null);\n\n const [createForm, setCreateForm] = useState<EmailFormState>(toState());\n const [editForm, setEditForm] = useState<EmailFormState>(toState());\n\n const [createEntry, { loading: creating, error: createError }] =\n useCreateEmailTimeEntryMutation();\n const [updateEntry, { loading: updating, error: updateError }] =\n useUpdateEmailTimeEntryMutation();\n const [removeEntry, { loading: deleting, error: deleteError }] =\n useDeleteEmailTimeEntryMutation();\n\n const buildInput = (form: EmailFormState) => ({\n subject: form.subject.trim() || undefined,\n sender: form.sender.trim() || undefined,\n recipients: form.recipients.trim() || undefined,\n category: form.category.trim() || undefined,\n date: new Date(form.date).toISOString(),\n duration: form.duration ? Number(form.duration) : undefined,\n responseTime: form.responseTime ? Number(form.responseTime) : undefined,\n isImportant: form.isImportant,\n threadId: form.threadId.trim() || undefined,\n });\n\n const openCreate = () => {\n setCreateForm(toState());\n setCreateOpen(true);\n };\n\n const handleCreate = async () => {\n await createEntry({\n variables: { input: buildInput(createForm) },\n });\n setCreateOpen(false);\n await refetch();\n };\n\n const openEdit = (entry: EmailTimeEntryFieldsFragment) => {\n setEditForm(toState(entry));\n setEditEntry(entry);\n };\n\n const handleUpdate = async () => {\n if (!editEntry) return;\n await updateEntry({\n variables: { id: editEntry.id, input: buildInput(editForm) },\n });\n setEditEntry(null);\n await refetch();\n };\n\n const handleDelete = async () => {\n if (!deleteEntry) return;\n await removeEntry({ variables: { id: deleteEntry.id } });\n setDeleteEntry(null);\n await refetch();\n };\n\n const handleLoadMore = async () => {\n setLoadingMore(true);\n try {\n await fetchMore({\n variables: { offset: emails.length },\n updateQuery: (prev, { fetchMoreResult }) => {\n if (!fetchMoreResult) return prev;\n return {\n ...prev,\n emailTimeEntries: [\n ...prev.emailTimeEntries,\n ...fetchMoreResult.emailTimeEntries,\n ],\n };\n },\n });\n } finally {\n setLoadingMore(false);\n }\n };\n\n return (\n <PageLayout\n title=\"Email Tracking\"\n description=\"Track time spent on emails\"\n purpose=\"Surface the hidden hours email steals from your day — every message linked to the time it took and the project it belonged to — so inbox work finally shows up in your timesheets and reports.\"\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setImportantOnly((v) => !v)}\n className={`inline-flex items-center gap-1.5 rounded-md border px-3 py-2 text-sm font-medium ${\n importantOnly\n ? \"border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg\"\n : \"border-border-subtle text-text-primary hover:bg-bg-sunken/50\"\n }`}\n >\n <Filter className=\"h-4 w-4\" />\n {importantOnly ? \"Important only\" : \"Filter\"}\n </button>\n <button\n onClick={openCreate}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n <Plus className=\"h-4 w-4\" />\n Add Entry\n </button>\n </div>\n }\n >\n {loading && emails.length === 0 ? (\n <LoadingSkeleton variant=\"list\" count={4} />\n ) : error ? (\n <div className=\"rounded-xl border border-status-error-border/50 bg-status-error-bg/10 p-4 text-sm text-status-error-text\">\n Failed to load email entries. Please try again later.\n </div>\n ) : emails.length === 0 ? (\n <EmptyState\n illustration=\"empty-notifications\"\n title=\"No email entries found\"\n description=\"Log the time you spend in your inbox — or connect email tracking — and entries will appear here.\"\n action={\n <button\n onClick={openCreate}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n <Plus className=\"h-4 w-4\" />\n Add Entry\n </button>\n }\n />\n ) : (\n <>\n <GlassCard treatment=\"glass\" glow className=\"overflow-hidden\">\n <div className=\"divide-y divide-border\">\n {emails.map((email: EmailTimeEntryFieldsFragment) => (\n <div\n key={email.id}\n className=\"flex items-center justify-between gap-3 p-4 transition-colors hover:bg-bg-sunken/50\"\n >\n <div className=\"flex min-w-0 items-center gap-3\">\n <Mail\n className={`h-5 w-5 shrink-0 ${email.isImportant ? \"text-primary\" : \"text-text-secondary\"}`}\n />\n <div className=\"min-w-0\">\n <p\n className={`truncate text-sm ${email.isImportant ? \"font-semibold text-text-primary\" : \"font-medium text-text-primary\"}`}\n >\n {email.subject ?? \"(No subject)\"}\n </p>\n <p className=\"truncate text-xs text-text-secondary\">\n {email.sender ?? \"Unknown\"} ·{\" \"}\n {formatRelativeTime(email.date)} · ~\n {email.duration ?? 0}min\n </p>\n </div>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n <span\n className={`hidden rounded-full px-2 py-0.5 text-xs font-medium sm:inline-flex ${BADGE_CLASSES[getPriorityColor(email.isImportant ? \"high\" : \"low\")]}`}\n >\n {email.isImportant ? \"high\" : \"normal\"}\n </span>\n <span\n className={`hidden rounded-full px-2 py-0.5 text-xs font-medium sm:inline-flex ${BADGE_CLASSES[getStatusColor(email.category ?? \"active\")]}`}\n >\n {email.category ?? \"uncategorized\"}\n </span>\n <button\n onClick={() => openEdit(email)}\n className=\"rounded-md p-1.5 text-text-secondary hover:bg-bg-sunken hover:text-text-primary\"\n aria-label=\"Edit entry\"\n >\n <Pencil className=\"h-4 w-4\" />\n </button>\n <button\n onClick={() => setDeleteEntry(email)}\n className=\"rounded-md p-1.5 text-text-secondary hover:bg-status-error-bg hover:text-status-error-text\"\n aria-label=\"Delete entry\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n ))}\n </div>\n </GlassCard>\n {hasMore && (\n <div className=\"mt-4 flex justify-center\">\n <button\n onClick={handleLoadMore}\n disabled={loadingMore}\n className=\"rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50 disabled:opacity-50\"\n >\n {loadingMore ? \"Loading...\" : \"Load more\"}\n </button>\n </div>\n )}\n </>\n )}\n\n {/* Create modal */}\n <Modal\n open={createOpen}\n onClose={() => setCreateOpen(false)}\n title=\"Add Email Entry\"\n description=\"Log time spent on an email\"\n size=\"xl\"\n footer={\n <>\n <button\n onClick={() => setCreateOpen(false)}\n className=\"rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50\"\n >\n Cancel\n </button>\n <button\n onClick={handleCreate}\n disabled={creating || !createForm.date}\n className=\"rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50\"\n >\n {creating ? \"Saving...\" : \"Add Entry\"}\n </button>\n </>\n }\n >\n {createError && (\n <div className=\"mb-4 rounded-lg border border-status-error-bg/40 bg-status-error-bg p-3 text-sm text-status-error-text\">\n Failed to add entry. Please try again.\n </div>\n )}\n <EmailEntryForm value={createForm} onChange={setCreateForm} />\n </Modal>\n\n {/* Edit modal */}\n <Modal\n open={editEntry !== null}\n onClose={() => setEditEntry(null)}\n title=\"Edit Email Entry\"\n description=\"Update this email time entry\"\n size=\"xl\"\n footer={\n <>\n <button\n onClick={() => setEditEntry(null)}\n className=\"rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50\"\n >\n Cancel\n </button>\n <button\n onClick={handleUpdate}\n disabled={updating || !editForm.date}\n className=\"rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50\"\n >\n {updating ? \"Saving...\" : \"Save Changes\"}\n </button>\n </>\n }\n >\n {updateError && (\n <div className=\"mb-4 rounded-lg border border-status-error-bg/40 bg-status-error-bg p-3 text-sm text-status-error-text\">\n Failed to update entry. Please try again.\n </div>\n )}\n <EmailEntryForm value={editForm} onChange={setEditForm} />\n </Modal>\n\n {/* Delete confirm modal */}\n <Modal\n open={deleteEntry !== null}\n onClose={() => setDeleteEntry(null)}\n title=\"Delete Email Entry\"\n size=\"sm\"\n footer={\n <>\n <button\n onClick={() => setDeleteEntry(null)}\n className=\"rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50\"\n >\n Cancel\n </button>\n <button\n onClick={handleDelete}\n disabled={deleting}\n className=\"rounded-md bg-status-error-bg px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg/90 disabled:opacity-50\"\n >\n {deleting ? \"Deleting...\" : \"Delete\"}\n </button>\n </>\n }\n >\n {deleteError && (\n <div className=\"mb-4 rounded-lg border border-status-error-bg/40 bg-status-error-bg p-3 text-sm text-status-error-text\">\n Failed to delete entry. Please try again.\n </div>\n )}\n <p className=\"text-sm text-text-secondary\">\n Are you sure you want to delete the entry{\" \"}\n <span className=\"font-medium text-text-primary\">\n “{deleteEntry?.subject ?? \"(No subject)\"}”\n </span>\n ? This action cannot be undone.\n </p>\n </Modal>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|