@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.
Files changed (93) hide show
  1. package/dist/generated/wspace-operations.js +996 -816
  2. package/dist/generated/wspace-operations.js.map +1 -1
  3. package/dist/generated/wspace-types.js +28 -0
  4. package/dist/generated/wspace-types.js.map +1 -0
  5. package/dist/index.js +4 -4
  6. package/dist/timecampus/TimeCampusRoutes.js +16 -12
  7. package/dist/timecampus/TimeCampusRoutes.js.map +1 -1
  8. package/dist/timecampus/components/Modal.js +65 -0
  9. package/dist/timecampus/components/Modal.js.map +1 -0
  10. package/dist/timecampus/components/StatusBadge.js +28 -0
  11. package/dist/timecampus/components/StatusBadge.js.map +1 -0
  12. package/dist/timecampus/components/Toast.js +87 -0
  13. package/dist/timecampus/components/Toast.js.map +1 -0
  14. package/dist/timecampus/index.js +1 -1
  15. package/dist/timecampus/pages/HomePage.js +143 -135
  16. package/dist/timecampus/pages/HomePage.js.map +1 -1
  17. package/dist/timecampus/pages/applets/AppletStorePage.js +14 -19
  18. package/dist/timecampus/pages/applets/AppletStorePage.js.map +1 -1
  19. package/dist/timecampus/pages/applets/InstalledAppletsPage.js +49 -37
  20. package/dist/timecampus/pages/applets/InstalledAppletsPage.js.map +1 -1
  21. package/dist/timecampus/pages/application-usage/ApplicationUsagePage.js +315 -87
  22. package/dist/timecampus/pages/application-usage/ApplicationUsagePage.js.map +1 -1
  23. package/dist/timecampus/pages/channels/ChannelsPage.js +340 -46
  24. package/dist/timecampus/pages/channels/ChannelsPage.js.map +1 -1
  25. package/dist/timecampus/pages/client-portal/ClientPortalPage.js +374 -92
  26. package/dist/timecampus/pages/client-portal/ClientPortalPage.js.map +1 -1
  27. package/dist/timecampus/pages/dashboard/ReportsPage.js +70 -37
  28. package/dist/timecampus/pages/dashboard/ReportsPage.js.map +1 -1
  29. package/dist/timecampus/pages/email-tracking/EmailTrackingPage.js +366 -60
  30. package/dist/timecampus/pages/email-tracking/EmailTrackingPage.js.map +1 -1
  31. package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js +461 -87
  32. package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js.map +1 -1
  33. package/dist/timecampus/pages/geofencing/GeofencingPage.js +314 -55
  34. package/dist/timecampus/pages/geofencing/GeofencingPage.js.map +1 -1
  35. package/dist/timecampus/pages/industry-solutions/IndustrySolutionsPage.js +30 -27
  36. package/dist/timecampus/pages/industry-solutions/IndustrySolutionsPage.js.map +1 -1
  37. package/dist/timecampus/pages/location-tracking/LocationTrackingPage.js +269 -74
  38. package/dist/timecampus/pages/location-tracking/LocationTrackingPage.js.map +1 -1
  39. package/dist/timecampus/pages/meetings/ActionItemFormModal.js +127 -0
  40. package/dist/timecampus/pages/meetings/ActionItemFormModal.js.map +1 -0
  41. package/dist/timecampus/pages/meetings/MeetingCreatePage.js +62 -52
  42. package/dist/timecampus/pages/meetings/MeetingCreatePage.js.map +1 -1
  43. package/dist/timecampus/pages/meetings/MeetingDetailPage.js +361 -74
  44. package/dist/timecampus/pages/meetings/MeetingDetailPage.js.map +1 -1
  45. package/dist/timecampus/pages/meetings/MeetingFormModal.js +156 -0
  46. package/dist/timecampus/pages/meetings/MeetingFormModal.js.map +1 -0
  47. package/dist/timecampus/pages/meetings/MeetingsPage.js +175 -74
  48. package/dist/timecampus/pages/meetings/MeetingsPage.js.map +1 -1
  49. package/dist/timecampus/pages/meetings/ParticipantFormModal.js +105 -0
  50. package/dist/timecampus/pages/meetings/ParticipantFormModal.js.map +1 -0
  51. package/dist/timecampus/pages/pomodoro/PomodoroPage.js +307 -67
  52. package/dist/timecampus/pages/pomodoro/PomodoroPage.js.map +1 -1
  53. package/dist/timecampus/pages/projects/ProjectCreatePage.js +51 -48
  54. package/dist/timecampus/pages/projects/ProjectCreatePage.js.map +1 -1
  55. package/dist/timecampus/pages/projects/ProjectDetailPage.js +248 -51
  56. package/dist/timecampus/pages/projects/ProjectDetailPage.js.map +1 -1
  57. package/dist/timecampus/pages/projects/ProjectsPage.js +354 -87
  58. package/dist/timecampus/pages/projects/ProjectsPage.js.map +1 -1
  59. package/dist/timecampus/pages/projects/TasksPage.js +367 -65
  60. package/dist/timecampus/pages/projects/TasksPage.js.map +1 -1
  61. package/dist/timecampus/pages/resource-planning/ResourcePlanningPage.js +674 -104
  62. package/dist/timecampus/pages/resource-planning/ResourcePlanningPage.js.map +1 -1
  63. package/dist/timecampus/pages/team/TeamAnalyticsPage.js +46 -34
  64. package/dist/timecampus/pages/team/TeamAnalyticsPage.js.map +1 -1
  65. package/dist/timecampus/pages/team/TeamMembersPage.js +93 -69
  66. package/dist/timecampus/pages/team/TeamMembersPage.js.map +1 -1
  67. package/dist/timecampus/pages/team/TeamPage.js +4 -3
  68. package/dist/timecampus/pages/team/TeamPage.js.map +1 -1
  69. package/dist/timecampus/pages/templates/TemplateDetailPage.js +72 -53
  70. package/dist/timecampus/pages/templates/TemplateDetailPage.js.map +1 -1
  71. package/dist/timecampus/pages/templates/TemplatesPage.js +40 -35
  72. package/dist/timecampus/pages/templates/TemplatesPage.js.map +1 -1
  73. package/dist/timecampus/pages/time/TimeEntriesPage.js +484 -97
  74. package/dist/timecampus/pages/time/TimeEntriesPage.js.map +1 -1
  75. package/dist/timecampus/pages/time/TimeTrackingPage.js +210 -99
  76. package/dist/timecampus/pages/time/TimeTrackingPage.js.map +1 -1
  77. package/dist/timecampus/pages/time/TimerPage.js +229 -97
  78. package/dist/timecampus/pages/time/TimerPage.js.map +1 -1
  79. package/dist/timecampus/pages/time-approval/TimeApprovalPage.js +315 -110
  80. package/dist/timecampus/pages/time-approval/TimeApprovalPage.js.map +1 -1
  81. package/dist/timecampus/pages/timeline/TimelinePage.js +250 -0
  82. package/dist/timecampus/pages/timeline/TimelinePage.js.map +1 -0
  83. package/dist/timecampus/pages/widgets/WidgetDetailPage.js +158 -76
  84. package/dist/timecampus/pages/widgets/WidgetDetailPage.js.map +1 -1
  85. package/dist/timecampus/pages/widgets/WidgetsPage.js +181 -52
  86. package/dist/timecampus/pages/widgets/WidgetsPage.js.map +1 -1
  87. package/dist/timecampus/pages/workflows/WorkflowsPage.js +212 -61
  88. package/dist/timecampus/pages/workflows/WorkflowsPage.js.map +1 -1
  89. package/dist/timecampus/store/timecampusStore.js +13 -1
  90. package/dist/timecampus/store/timecampusStore.js.map +1 -1
  91. package/dist/timecampus/utils/helpers.js +20 -10
  92. package/dist/timecampus/utils/helpers.js.map +1 -1
  93. package/package.json +1 -1
@@ -1,70 +1,130 @@
1
1
  import { useTimeCampus as e, useTimeCampusNavigate as t } from "../../providers/TimeCampusProvider.js";
2
2
  import { StatCard as n } from "../../components/StatCard.js";
3
3
  import { LoadingSkeleton as r } from "../../components/LoadingSkeleton.js";
4
- import { useCompletePomodoroSessionMutation as i, useGetActivePomodoroSessionQuery as a, useGetPomodoroStatsQuery as o, useStartPomodoroSessionMutation as s } from "../../../generated/wspace-operations.js";
4
+ import { useCompletePomodoroSessionMutation as i, useCreatePomodoroGoalMutation as ee, useDeletePomodoroGoalMutation as te, useGetActivePomodoroSessionQuery as ne, useGetPomodoroStatsQuery as re, useListPomodoroGoalsQuery as a, useStartPomodoroSessionMutation as o, useUpdatePomodoroGoalMutation as s } from "../../../generated/wspace-operations.js";
5
5
  import { PageLayout as c } from "../../components/PageLayout.js";
6
- import { useCallback as l, useEffect as u, useState as d } from "react";
7
- import { Pause as f, Play as p, RotateCcw as m, SkipForward as h } from "lucide-react";
8
- import { jsx as g, jsxs as _ } from "react/jsx-runtime";
9
- import { GlassCard as v, NextSteps as y } from "@burdenoff/fe-libs/ui";
6
+ import { PomodoroGoalType as l } from "../../../generated/wspace-types.js";
7
+ import { Modal as u } from "../../components/Modal.js";
8
+ import { useCallback as d, useEffect as f, useState as p } from "react";
9
+ import { Pause as ie, Pencil as ae, Play as oe, Plus as se, RotateCcw as m, SkipForward as ce, Target as le, Trash2 as ue } from "lucide-react";
10
+ import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
11
+ import { GlassCard as v, NextSteps as de } from "@burdenoff/fe-libs/ui";
10
12
  //#region src/timecampus/pages/pomodoro/PomodoroPage.tsx
11
- function b() {
12
- let { workspaceId: b = "" } = e(), x = t(), { data: S, loading: C, error: w } = o({
13
- variables: { workspaceId: b },
14
- skip: !b
15
- }), { data: T, loading: E, error: D } = a({
16
- variables: { workspaceId: b },
17
- skip: !b
18
- }), [O] = s(), [k] = i(), A = S?.pomodoroStats, j = T?.activePomodoroSession, [M, N] = d(1500), [P, F] = d(!1);
19
- u(() => {
20
- if (j && !j.completed) {
21
- let e = Math.floor((Date.now() - new Date(j.startTime).getTime()) / 1e3), t = j.duration ?? 1500, n = Math.max(0, t - e);
22
- N(n), F(n > 0);
13
+ var y = "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", b = "block text-sm font-medium text-text-primary";
14
+ function x(e) {
15
+ let t = new Date(e);
16
+ return Number.isNaN(t.getTime()) ? "" : (/* @__PURE__ */ new Date(t.getTime() - t.getTimezoneOffset() * 6e4)).toISOString().slice(0, 10);
17
+ }
18
+ function S() {
19
+ let e = /* @__PURE__ */ new Date();
20
+ return (/* @__PURE__ */ new Date(e.getTime() - e.getTimezoneOffset() * 6e4)).toISOString().slice(0, 10);
21
+ }
22
+ function C(e) {
23
+ let t = /* @__PURE__ */ new Date();
24
+ return t.setDate(t.getDate() + e), (/* @__PURE__ */ new Date(t.getTime() - t.getTimezoneOffset() * 6e4)).toISOString().slice(0, 10);
25
+ }
26
+ function w(e) {
27
+ return {
28
+ type: e?.type ?? l.Daily,
29
+ target: e?.target == null ? "8" : String(e.target),
30
+ period: e?.period ?? "DAILY",
31
+ startDate: e?.startDate ? x(e.startDate) : S(),
32
+ endDate: e?.endDate ? x(e.endDate) : C(0)
33
+ };
34
+ }
35
+ function T() {
36
+ let { workspaceId: x = "" } = e(), S = t(), { data: T, loading: fe, error: pe } = re({
37
+ variables: { workspaceId: x },
38
+ skip: !x
39
+ }), { data: me, loading: he, error: ge } = ne({
40
+ variables: { workspaceId: x },
41
+ skip: !x
42
+ }), [E] = o(), [D] = i(), { data: O, refetch: k } = a({
43
+ variables: { workspaceId: x },
44
+ skip: !x
45
+ }), A = O?.pomodoroGoals ?? [], [j, { loading: M, error: N }] = ee(), [P, { loading: F, error: I }] = s(), [L, { loading: R, error: _e }] = te(), [ve, z] = p(!1), [B, V] = p(null), [H, U] = p(null), [W, G] = p(w()), K = (e, t) => G((n) => ({
46
+ ...n,
47
+ [e]: t
48
+ })), ye = () => {
49
+ V(null), G(w()), z(!0);
50
+ }, be = (e) => {
51
+ V(e), G(w(e)), z(!0);
52
+ }, xe = async () => {
53
+ if (!x) return;
54
+ let e = Number(W.target);
55
+ !e || e <= 0 || (B ? await P({ variables: {
56
+ id: B.id,
57
+ workspaceId: x,
58
+ input: {
59
+ type: W.type,
60
+ target: e,
61
+ period: W.period.trim() || W.type,
62
+ startDate: new Date(W.startDate).toISOString(),
63
+ endDate: new Date(W.endDate).toISOString()
64
+ }
65
+ } }) : await j({ variables: { input: {
66
+ workspaceId: x,
67
+ type: W.type,
68
+ target: e,
69
+ period: W.period.trim() || W.type,
70
+ startDate: new Date(W.startDate).toISOString(),
71
+ endDate: new Date(W.endDate).toISOString()
72
+ } } }), z(!1), await k());
73
+ }, Se = async () => {
74
+ !H || !x || (await L({ variables: {
75
+ id: H.id,
76
+ workspaceId: x
77
+ } }), U(null), await k());
78
+ }, q = T?.pomodoroStats, J = me?.activePomodoroSession, [Y, X] = p(1500), [Z, Q] = p(!1);
79
+ f(() => {
80
+ if (J && !J.completed) {
81
+ let e = Math.floor((Date.now() - new Date(J.startTime).getTime()) / 1e3), t = J.duration ?? 1500, n = Math.max(0, t - e);
82
+ X(n), Q(n > 0);
23
83
  }
24
- }, [j]), u(() => {
25
- if (!P || M <= 0) return;
84
+ }, [J]), f(() => {
85
+ if (!Z || Y <= 0) return;
26
86
  let e = setInterval(() => {
27
- N((e) => e <= 1 ? (F(!1), 0) : e - 1);
87
+ X((e) => e <= 1 ? (Q(!1), 0) : e - 1);
28
88
  }, 1e3);
29
89
  return () => clearInterval(e);
30
- }, [P, M]);
31
- let I = (e) => {
90
+ }, [Z, Y]);
91
+ let Ce = (e) => {
32
92
  let t = Math.floor(e / 60), n = e % 60;
33
93
  return `${String(t).padStart(2, "0")}:${String(n).padStart(2, "0")}`;
34
- }, L = l(async () => {
35
- if (b) {
36
- if (j && !j.completed) {
37
- F(!0);
94
+ }, $ = d(async () => {
95
+ if (x) {
96
+ if (J && !J.completed) {
97
+ Q(!0);
38
98
  return;
39
99
  }
40
- await O({
100
+ await E({
41
101
  variables: { input: {
42
- workspaceId: b,
102
+ workspaceId: x,
43
103
  type: "FOCUS"
44
104
  } },
45
105
  refetchQueries: ["GetActivePomodoroSession", "GetPomodoroStats"]
46
- }), N(1500), F(!0);
106
+ }), X(1500), Q(!0);
47
107
  }
48
108
  }, [
49
- b,
50
- j,
51
- O
52
- ]), R = l(async () => {
53
- !j || !b || (await k({
109
+ x,
110
+ J,
111
+ E
112
+ ]), we = d(async () => {
113
+ !J || !x || (await D({
54
114
  variables: {
55
- id: j.id,
56
- workspaceId: b
115
+ id: J.id,
116
+ workspaceId: x
57
117
  },
58
118
  refetchQueries: ["GetActivePomodoroSession", "GetPomodoroStats"]
59
- }), F(!1), N(1500));
119
+ }), Q(!1), X(1500));
60
120
  }, [
61
- j,
62
- b,
63
- k
64
- ]), z = () => {
65
- F(!1), N(1500);
121
+ J,
122
+ x,
123
+ D
124
+ ]), Te = () => {
125
+ Q(!1), X(1500);
66
126
  };
67
- if (C || E) return /* @__PURE__ */ g(c, {
127
+ if (fe || he) return /* @__PURE__ */ g(c, {
68
128
  title: "Pomodoro Timer",
69
129
  description: "Focus with the Pomodoro Technique",
70
130
  children: /* @__PURE__ */ g(r, {
@@ -72,7 +132,7 @@ function b() {
72
132
  count: 3
73
133
  })
74
134
  });
75
- if (w || D) return /* @__PURE__ */ g(c, {
135
+ if (pe || ge) return /* @__PURE__ */ g(c, {
76
136
  title: "Pomodoro Timer",
77
137
  description: "Focus with the Pomodoro Technique",
78
138
  children: /* @__PURE__ */ g("div", {
@@ -80,13 +140,13 @@ function b() {
80
140
  children: "Failed to load pomodoro data. Please try again later."
81
141
  })
82
142
  });
83
- let B = Math.floor((A?.totalFocusMinutes ?? 0) / 60), V = (A?.totalFocusMinutes ?? 0) % 60;
143
+ let Ee = Math.floor((q?.totalFocusMinutes ?? 0) / 60), De = (q?.totalFocusMinutes ?? 0) % 60;
84
144
  return /* @__PURE__ */ _(c, {
85
145
  title: "Pomodoro Timer",
86
146
  description: "Focus with the Pomodoro Technique",
87
147
  purpose: "Work in focused 25-minute sprints with short breaks — the Pomodoro technique helps you beat procrastination and build a streak of deep-work sessions you can actually measure.",
88
148
  children: [
89
- /* @__PURE__ */ g(y, {
149
+ /* @__PURE__ */ g(de, {
90
150
  storageKey: "timecampus-pomodoro",
91
151
  className: "mb-6",
92
152
  steps: [
@@ -94,19 +154,19 @@ function b() {
94
154
  id: "start",
95
155
  label: "Start a focus session",
96
156
  description: "Begin a 25-minute sprint on one task.",
97
- onClick: () => L()
157
+ onClick: () => $()
98
158
  },
99
159
  {
100
160
  id: "analytics",
101
161
  label: "Review your pomodoro stats",
102
162
  description: "See streaks, completion rate and focus time.",
103
- onClick: () => x("/pomodoro/analytics")
163
+ onClick: () => S("/pomodoro/analytics")
104
164
  },
105
165
  {
106
166
  id: "settings",
107
167
  label: "Tune your intervals",
108
168
  description: "Adjust focus and break lengths to fit you.",
109
- onClick: () => x("/pomodoro/settings")
169
+ onClick: () => S("/pomodoro/settings")
110
170
  }
111
171
  ]
112
172
  }),
@@ -115,21 +175,21 @@ function b() {
115
175
  children: [
116
176
  /* @__PURE__ */ g(n, {
117
177
  title: "Sessions Today",
118
- value: String(A?.completedSessions ?? 0),
119
- description: `Total: ${A?.totalSessions ?? 0} sessions`
178
+ value: String(q?.completedSessions ?? 0),
179
+ description: `Total: ${q?.totalSessions ?? 0} sessions`
120
180
  }),
121
181
  /* @__PURE__ */ g(n, {
122
182
  title: "Focus Time",
123
- value: `${B}h ${V}m`,
183
+ value: `${Ee}h ${De}m`,
124
184
  trend: {
125
- value: A?.completionRate ?? 0,
185
+ value: q?.completionRate ?? 0,
126
186
  label: "completion rate"
127
187
  }
128
188
  }),
129
189
  /* @__PURE__ */ g(n, {
130
190
  title: "Current Streak",
131
- value: `${A?.streakDays ?? 0} days`,
132
- description: `Avg: ${A?.averageSessionMinutes ?? 0}m per session`
191
+ value: `${q?.streakDays ?? 0} days`,
192
+ description: `Avg: ${q?.averageSessionMinutes ?? 0}m per session`
133
193
  })
134
194
  ]
135
195
  }),
@@ -144,36 +204,36 @@ function b() {
144
204
  className: "mb-2",
145
205
  children: /* @__PURE__ */ g("span", {
146
206
  className: "inline-flex rounded-full bg-action-primary-bg/10 px-3 py-1 text-xs font-medium text-primary",
147
- children: j ? "Focus Session" : "Ready"
207
+ children: J ? "Focus Session" : "Ready"
148
208
  })
149
209
  }),
150
210
  /* @__PURE__ */ g("p", {
151
211
  className: "text-7xl font-mono font-bold text-text-primary",
152
- children: I(M)
212
+ children: Ce(Y)
153
213
  }),
154
214
  /* @__PURE__ */ g("p", {
155
215
  className: "mt-2 text-sm text-text-secondary",
156
- children: A ? `${A.completedSessions} of ${A.totalSessions} sessions` : "No sessions yet"
216
+ children: q ? `${q.completedSessions} of ${q.totalSessions} sessions` : "No sessions yet"
157
217
  }),
158
218
  /* @__PURE__ */ _("div", {
159
219
  className: "mt-6 flex items-center justify-center gap-3",
160
220
  children: [
161
- P ? /* @__PURE__ */ _("button", {
162
- onClick: () => F(!1),
221
+ Z ? /* @__PURE__ */ _("button", {
222
+ onClick: () => Q(!1),
163
223
  className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-6 py-3 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
164
- children: [/* @__PURE__ */ g(f, { className: "h-4 w-4" }), "Pause"]
224
+ children: [/* @__PURE__ */ g(ie, { className: "h-4 w-4" }), "Pause"]
165
225
  }) : /* @__PURE__ */ _("button", {
166
- onClick: L,
226
+ onClick: $,
167
227
  className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-6 py-3 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
168
- children: [/* @__PURE__ */ g(p, { className: "h-4 w-4" }), "Start"]
228
+ children: [/* @__PURE__ */ g(oe, { className: "h-4 w-4" }), "Start"]
169
229
  }),
170
230
  /* @__PURE__ */ _("button", {
171
- onClick: R,
231
+ onClick: we,
172
232
  className: "inline-flex items-center gap-2 rounded-md border border-border-subtle px-4 py-3 text-sm font-medium text-text-primary hover:bg-bg-sunken/50",
173
- children: [/* @__PURE__ */ g(h, { className: "h-4 w-4" }), "Skip"]
233
+ children: [/* @__PURE__ */ g(ce, { className: "h-4 w-4" }), "Skip"]
174
234
  }),
175
235
  /* @__PURE__ */ _("button", {
176
- onClick: z,
236
+ onClick: Te,
177
237
  className: "inline-flex items-center gap-2 rounded-md border border-border-subtle px-4 py-3 text-sm font-medium text-text-primary hover:bg-bg-sunken/50",
178
238
  children: [/* @__PURE__ */ g(m, { className: "h-4 w-4" }), "Reset"]
179
239
  })
@@ -181,11 +241,191 @@ function b() {
181
241
  })
182
242
  ]
183
243
  })
244
+ }),
245
+ /* @__PURE__ */ _(v, {
246
+ treatment: "glass",
247
+ className: "p-6",
248
+ children: [/* @__PURE__ */ _("div", {
249
+ className: "mb-4 flex items-center justify-between",
250
+ children: [/* @__PURE__ */ _("h3", {
251
+ className: "flex items-center gap-2 text-sm font-semibold text-text-primary",
252
+ children: [/* @__PURE__ */ g(le, { className: "h-4 w-4" }), "Focus Goals"]
253
+ }), /* @__PURE__ */ _("button", {
254
+ onClick: ye,
255
+ className: "inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
256
+ children: [/* @__PURE__ */ g(se, { className: "h-4 w-4" }), "Add Goal"]
257
+ })]
258
+ }), A.length === 0 ? /* @__PURE__ */ g("p", {
259
+ className: "py-6 text-center text-sm text-text-secondary",
260
+ children: "No focus goals yet. Set a daily or weekly target to build a consistent focus habit."
261
+ }) : /* @__PURE__ */ g("div", {
262
+ className: "space-y-3",
263
+ children: A.map((e) => {
264
+ let t = e.target ? Math.min(100, Math.round(e.current / e.target * 100)) : 0;
265
+ return /* @__PURE__ */ _("div", {
266
+ className: "rounded-lg border border-border-subtle p-4",
267
+ children: [/* @__PURE__ */ _("div", {
268
+ className: "flex items-center justify-between",
269
+ children: [/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ _("p", {
270
+ className: "text-sm font-medium capitalize text-text-primary",
271
+ children: [e.type.toLowerCase(), " goal"]
272
+ }), /* @__PURE__ */ _("p", {
273
+ className: "text-xs text-text-secondary",
274
+ children: [
275
+ e.current,
276
+ " of ",
277
+ e.target,
278
+ " sessions"
279
+ ]
280
+ })] }), /* @__PURE__ */ _("div", {
281
+ className: "flex items-center gap-2",
282
+ children: [
283
+ /* @__PURE__ */ _("span", {
284
+ className: "text-sm font-medium text-text-primary",
285
+ children: [t, "%"]
286
+ }),
287
+ /* @__PURE__ */ g("button", {
288
+ onClick: () => be(e),
289
+ className: "rounded-md p-1.5 text-text-secondary hover:bg-bg-sunken hover:text-text-primary",
290
+ "aria-label": "Edit goal",
291
+ children: /* @__PURE__ */ g(ae, { className: "h-4 w-4" })
292
+ }),
293
+ /* @__PURE__ */ g("button", {
294
+ onClick: () => U(e),
295
+ className: "rounded-md p-1.5 text-text-secondary hover:bg-status-error-bg hover:text-status-error-text",
296
+ "aria-label": "Delete goal",
297
+ children: /* @__PURE__ */ g(ue, { className: "h-4 w-4" })
298
+ })
299
+ ]
300
+ })]
301
+ }), /* @__PURE__ */ g("div", {
302
+ className: "mt-3 h-2 w-full rounded-full bg-bg-sunken",
303
+ children: /* @__PURE__ */ g("div", {
304
+ className: "h-2 rounded-full bg-action-primary-bg",
305
+ style: { width: `${t}%` }
306
+ })
307
+ })]
308
+ }, e.id);
309
+ })
310
+ })]
311
+ }),
312
+ /* @__PURE__ */ _(u, {
313
+ open: ve,
314
+ onClose: () => z(!1),
315
+ title: B ? "Edit Focus Goal" : "Add Focus Goal",
316
+ description: "Set a target number of focus sessions",
317
+ footer: /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g("button", {
318
+ onClick: () => z(!1),
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__ */ g("button", {
322
+ onClick: xe,
323
+ disabled: M || F || Number(W.target) <= 0,
324
+ 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",
325
+ children: M || F ? "Saving..." : B ? "Save Changes" : "Add Goal"
326
+ })] }),
327
+ children: [(N || I) && /* @__PURE__ */ g("div", {
328
+ className: "mb-4 rounded-lg border border-status-error-bg/40 bg-status-error-bg p-3 text-sm text-status-error-text",
329
+ children: "Failed to save goal. Please try again."
330
+ }), /* @__PURE__ */ _("div", {
331
+ className: "space-y-4",
332
+ children: [
333
+ /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
334
+ className: b,
335
+ children: "Goal Type"
336
+ }), /* @__PURE__ */ _("select", {
337
+ value: W.type,
338
+ onChange: (e) => {
339
+ let t = e.target.value;
340
+ G((e) => ({
341
+ ...e,
342
+ type: t,
343
+ period: t,
344
+ endDate: t === l.Daily ? C(0) : t === l.Weekly ? C(7) : C(30)
345
+ }));
346
+ },
347
+ className: y,
348
+ children: [
349
+ /* @__PURE__ */ g("option", {
350
+ value: l.Daily,
351
+ children: "Daily"
352
+ }),
353
+ /* @__PURE__ */ g("option", {
354
+ value: l.Weekly,
355
+ children: "Weekly"
356
+ }),
357
+ /* @__PURE__ */ g("option", {
358
+ value: l.Monthly,
359
+ children: "Monthly"
360
+ })
361
+ ]
362
+ })] }),
363
+ /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
364
+ className: b,
365
+ children: "Target Sessions"
366
+ }), /* @__PURE__ */ g("input", {
367
+ type: "number",
368
+ min: "1",
369
+ placeholder: "8",
370
+ value: W.target,
371
+ onChange: (e) => K("target", e.target.value),
372
+ className: y
373
+ })] }),
374
+ /* @__PURE__ */ _("div", {
375
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
376
+ children: [/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
377
+ className: b,
378
+ children: "Start Date"
379
+ }), /* @__PURE__ */ g("input", {
380
+ type: "date",
381
+ value: W.startDate,
382
+ onChange: (e) => K("startDate", e.target.value),
383
+ className: y
384
+ })] }), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
385
+ className: b,
386
+ children: "End Date"
387
+ }), /* @__PURE__ */ g("input", {
388
+ type: "date",
389
+ value: W.endDate,
390
+ onChange: (e) => K("endDate", e.target.value),
391
+ className: y
392
+ })] })]
393
+ })
394
+ ]
395
+ })]
396
+ }),
397
+ /* @__PURE__ */ _(u, {
398
+ open: H !== null,
399
+ onClose: () => U(null),
400
+ title: "Delete Focus Goal",
401
+ size: "sm",
402
+ footer: /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g("button", {
403
+ onClick: () => U(null),
404
+ className: "rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50",
405
+ children: "Cancel"
406
+ }), /* @__PURE__ */ g("button", {
407
+ onClick: Se,
408
+ disabled: R,
409
+ 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",
410
+ children: R ? "Deleting..." : "Delete"
411
+ })] }),
412
+ children: [_e && /* @__PURE__ */ g("div", {
413
+ className: "mb-4 rounded-lg border border-status-error-bg/40 bg-status-error-bg p-3 text-sm text-status-error-text",
414
+ children: "Failed to delete goal. Please try again."
415
+ }), /* @__PURE__ */ _("p", {
416
+ className: "text-sm text-text-secondary",
417
+ children: [
418
+ "Are you sure you want to delete this",
419
+ " ",
420
+ H?.type.toLowerCase(),
421
+ " focus goal? This action cannot be undone."
422
+ ]
423
+ })]
184
424
  })
185
425
  ]
186
426
  });
187
427
  }
188
428
  //#endregion
189
- export { b as PomodoroPage };
429
+ export { T as PomodoroPage };
190
430
 
191
431
  //# sourceMappingURL=PomodoroPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PomodoroPage.js","names":[],"sources":["../../../../src/timecampus/pages/pomodoro/PomodoroPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from \"react\";\nimport { Play, Pause, SkipForward, RotateCcw } from \"lucide-react\";\nimport { GlassCard, NextSteps } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { StatCard } from \"../../components/StatCard\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport {\n useTimeCampus,\n useTimeCampusNavigate,\n} from \"../../providers/TimeCampusProvider\";\nimport {\n useGetActivePomodoroSessionQuery,\n useGetPomodoroStatsQuery,\n useStartPomodoroSessionMutation,\n useCompletePomodoroSessionMutation,\n} from \"@/generated/wspace-operations\";\n\nexport function PomodoroPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n const navigate = useTimeCampusNavigate();\n\n const {\n data: statsData,\n loading: statsLoading,\n error: statsError,\n } = useGetPomodoroStatsQuery({\n variables: { workspaceId },\n skip: !workspaceId,\n });\n\n const {\n data: activeData,\n loading: activeLoading,\n error: activeError,\n } = useGetActivePomodoroSessionQuery({\n variables: { workspaceId },\n skip: !workspaceId,\n });\n\n const [startSession] = useStartPomodoroSessionMutation();\n const [completeSession] = useCompletePomodoroSessionMutation();\n\n const stats = statsData?.pomodoroStats;\n const activeSession = activeData?.activePomodoroSession;\n\n const [timerSeconds, setTimerSeconds] = useState(25 * 60);\n const [isRunning, setIsRunning] = useState(false);\n\n useEffect(() => {\n if (activeSession && !activeSession.completed) {\n const elapsed = Math.floor(\n (Date.now() - new Date(activeSession.startTime).getTime()) / 1000,\n );\n const duration = activeSession.duration ?? 25 * 60;\n const remaining = Math.max(0, duration - elapsed);\n setTimerSeconds(remaining);\n setIsRunning(remaining > 0);\n }\n }, [activeSession]);\n\n useEffect(() => {\n if (!isRunning || timerSeconds <= 0) return;\n const interval = setInterval(() => {\n setTimerSeconds((prev) => {\n if (prev <= 1) {\n setIsRunning(false);\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n return () => clearInterval(interval);\n }, [isRunning, timerSeconds]);\n\n const formatTimer = (seconds: number) => {\n const m = Math.floor(seconds / 60);\n const s = seconds % 60;\n return `${String(m).padStart(2, \"0\")}:${String(s).padStart(2, \"0\")}`;\n };\n\n const handleStart = useCallback(async () => {\n if (!workspaceId) return;\n if (activeSession && !activeSession.completed) {\n setIsRunning(true);\n return;\n }\n await startSession({\n variables: { input: { workspaceId, type: \"FOCUS\" as never } },\n refetchQueries: [\"GetActivePomodoroSession\", \"GetPomodoroStats\"],\n });\n setTimerSeconds(25 * 60);\n setIsRunning(true);\n }, [workspaceId, activeSession, startSession]);\n\n const handleComplete = useCallback(async () => {\n if (!activeSession || !workspaceId) return;\n await completeSession({\n variables: { id: activeSession.id, workspaceId },\n refetchQueries: [\"GetActivePomodoroSession\", \"GetPomodoroStats\"],\n });\n setIsRunning(false);\n setTimerSeconds(25 * 60);\n }, [activeSession, workspaceId, completeSession]);\n\n const handleReset = () => {\n setIsRunning(false);\n setTimerSeconds(25 * 60);\n };\n\n if (statsLoading || activeLoading) {\n return (\n <PageLayout\n title=\"Pomodoro Timer\"\n description=\"Focus with the Pomodoro Technique\"\n >\n <LoadingSkeleton variant=\"card\" count={3} />\n </PageLayout>\n );\n }\n\n if (statsError || activeError) {\n return (\n <PageLayout\n title=\"Pomodoro Timer\"\n description=\"Focus with the Pomodoro Technique\"\n >\n <div className=\"rounded-lg border border-status-error-bg/40 bg-status-error-bg p-4 text-sm text-status-error-text\">\n Failed to load pomodoro data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n const totalFocusH = Math.floor((stats?.totalFocusMinutes ?? 0) / 60);\n const totalFocusM = (stats?.totalFocusMinutes ?? 0) % 60;\n\n return (\n <PageLayout\n title=\"Pomodoro Timer\"\n description=\"Focus with the Pomodoro Technique\"\n purpose=\"Work in focused 25-minute sprints with short breaks — the Pomodoro technique helps you beat procrastination and build a streak of deep-work sessions you can actually measure.\"\n >\n <NextSteps\n storageKey=\"timecampus-pomodoro\"\n className=\"mb-6\"\n steps={[\n {\n id: \"start\",\n label: \"Start a focus session\",\n description: \"Begin a 25-minute sprint on one task.\",\n onClick: () => handleStart(),\n },\n {\n id: \"analytics\",\n label: \"Review your pomodoro stats\",\n description: \"See streaks, completion rate and focus time.\",\n onClick: () => navigate(\"/pomodoro/analytics\"),\n },\n {\n id: \"settings\",\n label: \"Tune your intervals\",\n description: \"Adjust focus and break lengths to fit you.\",\n onClick: () => navigate(\"/pomodoro/settings\"),\n },\n ]}\n />\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <StatCard\n title=\"Sessions Today\"\n value={String(stats?.completedSessions ?? 0)}\n description={`Total: ${stats?.totalSessions ?? 0} sessions`}\n />\n <StatCard\n title=\"Focus Time\"\n value={`${totalFocusH}h ${totalFocusM}m`}\n trend={{\n value: stats?.completionRate ?? 0,\n label: \"completion rate\",\n }}\n />\n <StatCard\n title=\"Current Streak\"\n value={`${stats?.streakDays ?? 0} days`}\n description={`Avg: ${stats?.averageSessionMinutes ?? 0}m per session`}\n />\n </div>\n\n <div className=\"mx-auto max-w-md\">\n <GlassCard treatment=\"glass\" glow className=\"p-8 text-center\">\n <div className=\"mb-2\">\n <span className=\"inline-flex rounded-full bg-action-primary-bg/10 px-3 py-1 text-xs font-medium text-primary\">\n {activeSession ? \"Focus Session\" : \"Ready\"}\n </span>\n </div>\n <p className=\"text-7xl font-mono font-bold text-text-primary\">\n {formatTimer(timerSeconds)}\n </p>\n <p className=\"mt-2 text-sm text-text-secondary\">\n {stats\n ? `${stats.completedSessions} of ${stats.totalSessions} sessions`\n : \"No sessions yet\"}\n </p>\n <div className=\"mt-6 flex items-center justify-center gap-3\">\n {!isRunning ? (\n <button\n onClick={handleStart}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-6 py-3 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n <Play className=\"h-4 w-4\" />\n Start\n </button>\n ) : (\n <button\n onClick={() => setIsRunning(false)}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-6 py-3 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n <Pause className=\"h-4 w-4\" />\n Pause\n </button>\n )}\n <button\n onClick={handleComplete}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-subtle px-4 py-3 text-sm font-medium text-text-primary hover:bg-bg-sunken/50\"\n >\n <SkipForward className=\"h-4 w-4\" />\n Skip\n </button>\n <button\n onClick={handleReset}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-subtle px-4 py-3 text-sm font-medium text-text-primary hover:bg-bg-sunken/50\"\n >\n <RotateCcw className=\"h-4 w-4\" />\n Reset\n </button>\n </div>\n </GlassCard>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"PomodoroPage.js","names":[],"sources":["../../../../src/timecampus/pages/pomodoro/PomodoroPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from \"react\";\nimport {\n Play,\n Pause,\n SkipForward,\n RotateCcw,\n Target,\n Plus,\n Pencil,\n Trash2,\n} from \"lucide-react\";\nimport { GlassCard, NextSteps } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { StatCard } from \"../../components/StatCard\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { Modal } from \"../../components/Modal\";\nimport {\n useTimeCampus,\n useTimeCampusNavigate,\n} from \"../../providers/TimeCampusProvider\";\nimport {\n useGetActivePomodoroSessionQuery,\n useGetPomodoroStatsQuery,\n useStartPomodoroSessionMutation,\n useCompletePomodoroSessionMutation,\n useListPomodoroGoalsQuery,\n useCreatePomodoroGoalMutation,\n useUpdatePomodoroGoalMutation,\n useDeletePomodoroGoalMutation,\n type PomodoroGoalFieldsFragment,\n} from \"@/generated/wspace-operations\";\nimport { PomodoroGoalType } from \"@/generated/wspace-types\";\n\ninterface GoalFormState {\n type: PomodoroGoalType;\n target: string;\n period: string;\n startDate: string;\n endDate: 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 toDateInput(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, 10);\n}\n\nfunction todayInput(): string {\n const d = new Date();\n const local = new Date(d.getTime() - d.getTimezoneOffset() * 60000);\n return local.toISOString().slice(0, 10);\n}\n\nfunction futureInput(days: number): string {\n const d = new Date();\n d.setDate(d.getDate() + days);\n const local = new Date(d.getTime() - d.getTimezoneOffset() * 60000);\n return local.toISOString().slice(0, 10);\n}\n\nfunction toGoalState(goal?: PomodoroGoalFieldsFragment): GoalFormState {\n return {\n type: goal?.type ?? PomodoroGoalType.Daily,\n target: goal?.target != null ? String(goal.target) : \"8\",\n period: goal?.period ?? \"DAILY\",\n startDate: goal?.startDate ? toDateInput(goal.startDate) : todayInput(),\n endDate: goal?.endDate ? toDateInput(goal.endDate) : futureInput(0),\n };\n}\n\nexport function PomodoroPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n const navigate = useTimeCampusNavigate();\n\n const {\n data: statsData,\n loading: statsLoading,\n error: statsError,\n } = useGetPomodoroStatsQuery({\n variables: { workspaceId },\n skip: !workspaceId,\n });\n\n const {\n data: activeData,\n loading: activeLoading,\n error: activeError,\n } = useGetActivePomodoroSessionQuery({\n variables: { workspaceId },\n skip: !workspaceId,\n });\n\n const [startSession] = useStartPomodoroSessionMutation();\n const [completeSession] = useCompletePomodoroSessionMutation();\n\n // Focus goals\n const { data: goalsData, refetch: refetchGoals } = useListPomodoroGoalsQuery({\n variables: { workspaceId },\n skip: !workspaceId,\n });\n const goals = goalsData?.pomodoroGoals ?? [];\n\n const [createGoal, { loading: creatingGoal, error: createGoalError }] =\n useCreatePomodoroGoalMutation();\n const [updateGoal, { loading: updatingGoal, error: updateGoalError }] =\n useUpdatePomodoroGoalMutation();\n const [deleteGoal, { loading: deletingGoal, error: deleteGoalError }] =\n useDeletePomodoroGoalMutation();\n\n const [goalModalOpen, setGoalModalOpen] = useState(false);\n const [editingGoal, setEditingGoal] =\n useState<PomodoroGoalFieldsFragment | null>(null);\n const [deletingGoalEntry, setDeletingGoalEntry] =\n useState<PomodoroGoalFieldsFragment | null>(null);\n const [goalForm, setGoalForm] = useState<GoalFormState>(toGoalState());\n\n const setGoalField = <K extends keyof GoalFormState>(\n key: K,\n v: GoalFormState[K],\n ) => setGoalForm((f) => ({ ...f, [key]: v }));\n\n const openCreateGoal = () => {\n setEditingGoal(null);\n setGoalForm(toGoalState());\n setGoalModalOpen(true);\n };\n\n const openEditGoal = (goal: PomodoroGoalFieldsFragment) => {\n setEditingGoal(goal);\n setGoalForm(toGoalState(goal));\n setGoalModalOpen(true);\n };\n\n const handleSaveGoal = async () => {\n if (!workspaceId) return;\n const target = Number(goalForm.target);\n if (!target || target <= 0) return;\n if (editingGoal) {\n await updateGoal({\n variables: {\n id: editingGoal.id,\n workspaceId,\n input: {\n type: goalForm.type,\n target,\n period: goalForm.period.trim() || goalForm.type,\n startDate: new Date(goalForm.startDate).toISOString(),\n endDate: new Date(goalForm.endDate).toISOString(),\n },\n },\n });\n } else {\n await createGoal({\n variables: {\n input: {\n workspaceId,\n type: goalForm.type,\n target,\n period: goalForm.period.trim() || goalForm.type,\n startDate: new Date(goalForm.startDate).toISOString(),\n endDate: new Date(goalForm.endDate).toISOString(),\n },\n },\n });\n }\n setGoalModalOpen(false);\n await refetchGoals();\n };\n\n const handleDeleteGoal = async () => {\n if (!deletingGoalEntry || !workspaceId) return;\n await deleteGoal({\n variables: { id: deletingGoalEntry.id, workspaceId },\n });\n setDeletingGoalEntry(null);\n await refetchGoals();\n };\n\n const stats = statsData?.pomodoroStats;\n const activeSession = activeData?.activePomodoroSession;\n\n const [timerSeconds, setTimerSeconds] = useState(25 * 60);\n const [isRunning, setIsRunning] = useState(false);\n\n useEffect(() => {\n if (activeSession && !activeSession.completed) {\n const elapsed = Math.floor(\n (Date.now() - new Date(activeSession.startTime).getTime()) / 1000,\n );\n const duration = activeSession.duration ?? 25 * 60;\n const remaining = Math.max(0, duration - elapsed);\n setTimerSeconds(remaining);\n setIsRunning(remaining > 0);\n }\n }, [activeSession]);\n\n useEffect(() => {\n if (!isRunning || timerSeconds <= 0) return;\n const interval = setInterval(() => {\n setTimerSeconds((prev) => {\n if (prev <= 1) {\n setIsRunning(false);\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n return () => clearInterval(interval);\n }, [isRunning, timerSeconds]);\n\n const formatTimer = (seconds: number) => {\n const m = Math.floor(seconds / 60);\n const s = seconds % 60;\n return `${String(m).padStart(2, \"0\")}:${String(s).padStart(2, \"0\")}`;\n };\n\n const handleStart = useCallback(async () => {\n if (!workspaceId) return;\n if (activeSession && !activeSession.completed) {\n setIsRunning(true);\n return;\n }\n await startSession({\n variables: { input: { workspaceId, type: \"FOCUS\" as never } },\n refetchQueries: [\"GetActivePomodoroSession\", \"GetPomodoroStats\"],\n });\n setTimerSeconds(25 * 60);\n setIsRunning(true);\n }, [workspaceId, activeSession, startSession]);\n\n const handleComplete = useCallback(async () => {\n if (!activeSession || !workspaceId) return;\n await completeSession({\n variables: { id: activeSession.id, workspaceId },\n refetchQueries: [\"GetActivePomodoroSession\", \"GetPomodoroStats\"],\n });\n setIsRunning(false);\n setTimerSeconds(25 * 60);\n }, [activeSession, workspaceId, completeSession]);\n\n const handleReset = () => {\n setIsRunning(false);\n setTimerSeconds(25 * 60);\n };\n\n if (statsLoading || activeLoading) {\n return (\n <PageLayout\n title=\"Pomodoro Timer\"\n description=\"Focus with the Pomodoro Technique\"\n >\n <LoadingSkeleton variant=\"card\" count={3} />\n </PageLayout>\n );\n }\n\n if (statsError || activeError) {\n return (\n <PageLayout\n title=\"Pomodoro Timer\"\n description=\"Focus with the Pomodoro Technique\"\n >\n <div className=\"rounded-lg border border-status-error-bg/40 bg-status-error-bg p-4 text-sm text-status-error-text\">\n Failed to load pomodoro data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n const totalFocusH = Math.floor((stats?.totalFocusMinutes ?? 0) / 60);\n const totalFocusM = (stats?.totalFocusMinutes ?? 0) % 60;\n\n return (\n <PageLayout\n title=\"Pomodoro Timer\"\n description=\"Focus with the Pomodoro Technique\"\n purpose=\"Work in focused 25-minute sprints with short breaks — the Pomodoro technique helps you beat procrastination and build a streak of deep-work sessions you can actually measure.\"\n >\n <NextSteps\n storageKey=\"timecampus-pomodoro\"\n className=\"mb-6\"\n steps={[\n {\n id: \"start\",\n label: \"Start a focus session\",\n description: \"Begin a 25-minute sprint on one task.\",\n onClick: () => handleStart(),\n },\n {\n id: \"analytics\",\n label: \"Review your pomodoro stats\",\n description: \"See streaks, completion rate and focus time.\",\n onClick: () => navigate(\"/pomodoro/analytics\"),\n },\n {\n id: \"settings\",\n label: \"Tune your intervals\",\n description: \"Adjust focus and break lengths to fit you.\",\n onClick: () => navigate(\"/pomodoro/settings\"),\n },\n ]}\n />\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <StatCard\n title=\"Sessions Today\"\n value={String(stats?.completedSessions ?? 0)}\n description={`Total: ${stats?.totalSessions ?? 0} sessions`}\n />\n <StatCard\n title=\"Focus Time\"\n value={`${totalFocusH}h ${totalFocusM}m`}\n trend={{\n value: stats?.completionRate ?? 0,\n label: \"completion rate\",\n }}\n />\n <StatCard\n title=\"Current Streak\"\n value={`${stats?.streakDays ?? 0} days`}\n description={`Avg: ${stats?.averageSessionMinutes ?? 0}m per session`}\n />\n </div>\n\n <div className=\"mx-auto max-w-md\">\n <GlassCard treatment=\"glass\" glow className=\"p-8 text-center\">\n <div className=\"mb-2\">\n <span className=\"inline-flex rounded-full bg-action-primary-bg/10 px-3 py-1 text-xs font-medium text-primary\">\n {activeSession ? \"Focus Session\" : \"Ready\"}\n </span>\n </div>\n <p className=\"text-7xl font-mono font-bold text-text-primary\">\n {formatTimer(timerSeconds)}\n </p>\n <p className=\"mt-2 text-sm text-text-secondary\">\n {stats\n ? `${stats.completedSessions} of ${stats.totalSessions} sessions`\n : \"No sessions yet\"}\n </p>\n <div className=\"mt-6 flex items-center justify-center gap-3\">\n {!isRunning ? (\n <button\n onClick={handleStart}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-6 py-3 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n <Play className=\"h-4 w-4\" />\n Start\n </button>\n ) : (\n <button\n onClick={() => setIsRunning(false)}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-6 py-3 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n <Pause className=\"h-4 w-4\" />\n Pause\n </button>\n )}\n <button\n onClick={handleComplete}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-subtle px-4 py-3 text-sm font-medium text-text-primary hover:bg-bg-sunken/50\"\n >\n <SkipForward className=\"h-4 w-4\" />\n Skip\n </button>\n <button\n onClick={handleReset}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-subtle px-4 py-3 text-sm font-medium text-text-primary hover:bg-bg-sunken/50\"\n >\n <RotateCcw className=\"h-4 w-4\" />\n Reset\n </button>\n </div>\n </GlassCard>\n </div>\n\n {/* Focus Goals */}\n <GlassCard treatment=\"glass\" className=\"p-6\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <Target className=\"h-4 w-4\" />\n Focus Goals\n </h3>\n <button\n onClick={openCreateGoal}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n <Plus className=\"h-4 w-4\" />\n Add Goal\n </button>\n </div>\n {goals.length === 0 ? (\n <p className=\"py-6 text-center text-sm text-text-secondary\">\n No focus goals yet. Set a daily or weekly target to build a\n consistent focus habit.\n </p>\n ) : (\n <div className=\"space-y-3\">\n {goals.map((goal: PomodoroGoalFieldsFragment) => {\n const pct = goal.target\n ? Math.min(100, Math.round((goal.current / goal.target) * 100))\n : 0;\n return (\n <div\n key={goal.id}\n className=\"rounded-lg border border-border-subtle p-4\"\n >\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-sm font-medium capitalize text-text-primary\">\n {goal.type.toLowerCase()} goal\n </p>\n <p className=\"text-xs text-text-secondary\">\n {goal.current} of {goal.target} sessions\n </p>\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">\n {pct}%\n </span>\n <button\n onClick={() => openEditGoal(goal)}\n className=\"rounded-md p-1.5 text-text-secondary hover:bg-bg-sunken hover:text-text-primary\"\n aria-label=\"Edit goal\"\n >\n <Pencil className=\"h-4 w-4\" />\n </button>\n <button\n onClick={() => setDeletingGoalEntry(goal)}\n className=\"rounded-md p-1.5 text-text-secondary hover:bg-status-error-bg hover:text-status-error-text\"\n aria-label=\"Delete goal\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n <div className=\"mt-3 h-2 w-full rounded-full bg-bg-sunken\">\n <div\n className=\"h-2 rounded-full bg-action-primary-bg\"\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n })}\n </div>\n )}\n </GlassCard>\n\n {/* Goal create/edit modal */}\n <Modal\n open={goalModalOpen}\n onClose={() => setGoalModalOpen(false)}\n title={editingGoal ? \"Edit Focus Goal\" : \"Add Focus Goal\"}\n description=\"Set a target number of focus sessions\"\n footer={\n <>\n <button\n onClick={() => setGoalModalOpen(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={handleSaveGoal}\n disabled={\n creatingGoal || updatingGoal || Number(goalForm.target) <= 0\n }\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 {creatingGoal || updatingGoal\n ? \"Saving...\"\n : editingGoal\n ? \"Save Changes\"\n : \"Add Goal\"}\n </button>\n </>\n }\n >\n {(createGoalError || updateGoalError) && (\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 save goal. Please try again.\n </div>\n )}\n <div className=\"space-y-4\">\n <div>\n <label className={labelClasses}>Goal Type</label>\n <select\n value={goalForm.type}\n onChange={(e) => {\n const type = e.target.value as PomodoroGoalType;\n setGoalForm((f) => ({\n ...f,\n type,\n period: type,\n endDate:\n type === PomodoroGoalType.Daily\n ? futureInput(0)\n : type === PomodoroGoalType.Weekly\n ? futureInput(7)\n : futureInput(30),\n }));\n }}\n className={inputClasses}\n >\n <option value={PomodoroGoalType.Daily}>Daily</option>\n <option value={PomodoroGoalType.Weekly}>Weekly</option>\n <option value={PomodoroGoalType.Monthly}>Monthly</option>\n </select>\n </div>\n <div>\n <label className={labelClasses}>Target Sessions</label>\n <input\n type=\"number\"\n min=\"1\"\n placeholder=\"8\"\n value={goalForm.target}\n onChange={(e) => setGoalField(\"target\", 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}>Start Date</label>\n <input\n type=\"date\"\n value={goalForm.startDate}\n onChange={(e) => setGoalField(\"startDate\", e.target.value)}\n className={inputClasses}\n />\n </div>\n <div>\n <label className={labelClasses}>End Date</label>\n <input\n type=\"date\"\n value={goalForm.endDate}\n onChange={(e) => setGoalField(\"endDate\", e.target.value)}\n className={inputClasses}\n />\n </div>\n </div>\n </div>\n </Modal>\n\n {/* Goal delete confirm modal */}\n <Modal\n open={deletingGoalEntry !== null}\n onClose={() => setDeletingGoalEntry(null)}\n title=\"Delete Focus Goal\"\n size=\"sm\"\n footer={\n <>\n <button\n onClick={() => setDeletingGoalEntry(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={handleDeleteGoal}\n disabled={deletingGoal}\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 {deletingGoal ? \"Deleting...\" : \"Delete\"}\n </button>\n </>\n }\n >\n {deleteGoalError && (\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 goal. Please try again.\n </div>\n )}\n <p className=\"text-sm text-text-secondary\">\n Are you sure you want to delete this{\" \"}\n {deletingGoalEntry?.type.toLowerCase()} focus goal? This action cannot\n be undone.\n </p>\n </Modal>\n </PageLayout>\n );\n}\n"],"mappings":"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"}