@burdenoff/microfe-timecampus 2026.830.1 → 2026.903.1
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/timecampus/components/index.js +4 -4
- package/dist/timecampus/pages/HomePage.d.ts.map +1 -1
- package/dist/timecampus/pages/HomePage.js +142 -131
- package/dist/timecampus/pages/HomePage.js.map +1 -1
- package/dist/timecampus/pages/application-usage/ApplicationUsagePage.js +7 -7
- package/dist/timecampus/pages/application-usage/ApplicationUsagePage.js.map +1 -1
- package/dist/timecampus/pages/client-portal/ClientPortalPage.js +7 -7
- package/dist/timecampus/pages/client-portal/ClientPortalPage.js.map +1 -1
- package/dist/timecampus/pages/dashboard/ReportsPage.js +13 -13
- package/dist/timecampus/pages/email-tracking/EmailTrackingPage.js +7 -7
- package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js +7 -7
- package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/focus-score/FocusScorePage.js +13 -13
- package/dist/timecampus/pages/geofencing/GeofencingPage.js +135 -135
- package/dist/timecampus/pages/geofencing/GeofencingPage.js.map +1 -1
- package/dist/timecampus/pages/invoicing/InvoicingPage.js +7 -7
- package/dist/timecampus/pages/invoicing/InvoicingPage.js.map +1 -1
- package/dist/timecampus/pages/lifetime/DeadTimeRadarPage.js +8 -8
- package/dist/timecampus/pages/lifetime/FiniteLifePage.js +4 -4
- package/dist/timecampus/pages/lifetime/FiniteLifePage.js.map +1 -1
- package/dist/timecampus/pages/lifetime/LifeBalancePage.js +104 -104
- package/dist/timecampus/pages/lifetime/LifeBalancePage.js.map +1 -1
- package/dist/timecampus/pages/lifetime/LifeTimelinePage.js +7 -7
- package/dist/timecampus/pages/lifetime/LifeTimelinePage.js.map +1 -1
- package/dist/timecampus/pages/lifetime/PersonalCorporatePage.js +33 -33
- package/dist/timecampus/pages/lifetime/PersonalCorporatePage.js.map +1 -1
- package/dist/timecampus/pages/lifetime/RecommendationsPage.js +80 -80
- package/dist/timecampus/pages/lifetime/RecommendationsPage.js.map +1 -1
- package/dist/timecampus/pages/lifetime/TimeWellSpentPage.js +16 -16
- package/dist/timecampus/pages/lifetime/ValuesGoalsPage.js +11 -11
- package/dist/timecampus/pages/location-tracking/LocationTrackingPage.js +11 -11
- package/dist/timecampus/pages/location-tracking/LocationTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/meetings/MeetingDetailPage.js +14 -14
- package/dist/timecampus/pages/meetings/MeetingDetailPage.js.map +1 -1
- package/dist/timecampus/pages/meetings/MeetingsPage.js +12 -12
- package/dist/timecampus/pages/projects/ProjectsPage.js +5 -5
- package/dist/timecampus/pages/projects/ProjectsPage.js.map +1 -1
- package/dist/timecampus/pages/projects/TasksPage.js +8 -8
- package/dist/timecampus/pages/resource-planning/ResourcePlanningPage.js +8 -8
- package/dist/timecampus/pages/resource-planning/ResourcePlanningPage.js.map +1 -1
- package/dist/timecampus/pages/team/TeamMembersPage.js +8 -8
- package/dist/timecampus/pages/team-activity/TeamActivityPage.js +13 -13
- package/dist/timecampus/pages/time/TimeEntriesPage.js +5 -5
- package/dist/timecampus/pages/time/TimeEntriesPage.js.map +1 -1
- package/dist/timecampus/pages/time/TimeTrackingPage.js +138 -138
- package/dist/timecampus/pages/time/TimeTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/time/TimerPage.js +14 -14
- package/dist/timecampus/pages/time/TimerPage.js.map +1 -1
- package/dist/timecampus/pages/time-approval/TimeApprovalPage.js +26 -26
- package/dist/timecampus/pages/time-approval/TimeApprovalPage.js.map +1 -1
- package/dist/timecampus/pages/timeline/TimelinePage.js +8 -8
- package/dist/timecampus/pages/work-patterns/WorkPatternsPage.js +79 -79
- package/dist/timecampus/pages/work-patterns/WorkPatternsPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { StatCard as e } from "./StatCard.js";
|
|
2
2
|
import { LoadingSkeleton as t } from "./LoadingSkeleton.js";
|
|
3
|
+
import { EmptyState as n } from "./EmptyState.js";
|
|
3
4
|
import "./ErrorBoundary.js";
|
|
4
|
-
import { PageLayout as
|
|
5
|
-
import { StatusBadge as
|
|
6
|
-
import { EmptyState as i } from "./EmptyState.js";
|
|
5
|
+
import { PageLayout as r } from "./PageLayout.js";
|
|
6
|
+
import { StatusBadge as i } from "./StatusBadge.js";
|
|
7
7
|
import { Modal as a } from "./Modal.js";
|
|
8
8
|
import "./DataTable.js";
|
|
9
9
|
import { ChartCard as o } from "./ChartCard.js";
|
|
@@ -20,4 +20,4 @@ import { Heatmap as g } from "./charts/Heatmap.js";
|
|
|
20
20
|
import { BalanceWheel as _ } from "./charts/BalanceWheel.js";
|
|
21
21
|
import { WeeksGrid as v } from "./charts/WeeksGrid.js";
|
|
22
22
|
import "./charts/index.js";
|
|
23
|
-
export { _ as BalanceWheel, f as BarsChart, o as ChartCard, p as DonutChart,
|
|
23
|
+
export { _ as BalanceWheel, f as BarsChart, o as ChartCard, p as DonutChart, n as EmptyState, g as Heatmap, t as LoadingSkeleton, a as Modal, r as PageLayout, h as ProgressMeter, m as RadialGauge, e as StatCard, i as StatusBadge, s as ToastContainer, d as TrendChart, v as WeeksGrid, l as chartTokens, u as formatNumber, c as useToast };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HomePage.d.ts","sourceRoot":"","sources":["../../../src/timecampus/pages/HomePage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"HomePage.d.ts","sourceRoot":"","sources":["../../../src/timecampus/pages/HomePage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AA8BhC,eAAO,MAAM,QAAQ,EAAE,EA2YtB,CAAC"}
|
|
@@ -2,253 +2,264 @@ import { useTimeCampusNavigate as e } from "../providers/TimeCampusProvider.js";
|
|
|
2
2
|
import { cn as t, formatHours as n } from "../utils/helpers.js";
|
|
3
3
|
import { StatCard as r } from "../components/StatCard.js";
|
|
4
4
|
import { LoadingSkeleton as i } from "../components/LoadingSkeleton.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { EmptyState as a } from "../components/EmptyState.js";
|
|
6
|
+
import { useGetTimeEntryStatsQuery as o, useListTimeEntriesQuery as s } from "../../generated/wspace-operations.js";
|
|
7
|
+
import { useTr as c } from "../shared/hooks/useTr.js";
|
|
7
8
|
import "../hooks/index.js";
|
|
8
|
-
import { ArrowRight as
|
|
9
|
-
import { jsx as
|
|
10
|
-
import { AuroraBackground as
|
|
9
|
+
import { ArrowRight as l, BarChart3 as u, CheckCircle as d, Clock as f, FolderOpen as p, Play as m, TrendingUp as h, Users as g } from "lucide-react";
|
|
10
|
+
import { jsx as _, jsxs as v } from "react/jsx-runtime";
|
|
11
|
+
import { AuroraBackground as y, CTAOverflowMenu as b, EmphasisPanel as x, GlassCard as S, GradientText as C } from "@burdenoff/fe-libs/ui";
|
|
11
12
|
//#region src/timecampus/pages/HomePage.tsx
|
|
12
|
-
var
|
|
13
|
-
let
|
|
13
|
+
var w = () => {
|
|
14
|
+
let w = c(), T = e(), { data: E, loading: D } = o(), { data: O, loading: k } = s({ variables: { pagination: { limit: 4 } } }), A = E?.timeEntryStats, j = O?.timeEntries?.items ?? [], M = !D && !k && (A?.totalEntries ?? 0) === 0, N = /* @__PURE__ */ _(b, {
|
|
14
15
|
primary: {
|
|
15
|
-
label:
|
|
16
|
-
onSelect: () =>
|
|
17
|
-
icon: /* @__PURE__ */
|
|
16
|
+
label: w("timecampus.home.actions.startTimer", "Start Timer"),
|
|
17
|
+
onSelect: () => T("/time/timer"),
|
|
18
|
+
icon: /* @__PURE__ */ _(m, { className: "h-4 w-4" })
|
|
18
19
|
},
|
|
19
20
|
actions: [{
|
|
20
|
-
label:
|
|
21
|
-
onSelect: () =>
|
|
22
|
-
icon: /* @__PURE__ */
|
|
21
|
+
label: w("timecampus.home.quickActions.viewProjects.label", "View Projects"),
|
|
22
|
+
onSelect: () => T("/projects"),
|
|
23
|
+
icon: /* @__PURE__ */ _(p, { className: "h-4 w-4" })
|
|
23
24
|
}, {
|
|
24
|
-
label:
|
|
25
|
-
onSelect: () =>
|
|
26
|
-
icon: /* @__PURE__ */
|
|
25
|
+
label: w("timecampus.home.quickActions.reports.label", "Reports"),
|
|
26
|
+
onSelect: () => T("/reports"),
|
|
27
|
+
icon: /* @__PURE__ */ _(u, { className: "h-4 w-4" })
|
|
27
28
|
}]
|
|
28
|
-
}),
|
|
29
|
+
}), P = () => /* @__PURE__ */ v("div", {
|
|
29
30
|
className: "relative overflow-hidden rounded-2xl border border-border-seam bg-gloss-card p-5 sm:p-6",
|
|
30
|
-
children: [/* @__PURE__ */
|
|
31
|
+
children: [/* @__PURE__ */ _(y, { intensity: "subtle" }), /* @__PURE__ */ v("div", {
|
|
31
32
|
className: "relative flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
|
|
32
|
-
children: [/* @__PURE__ */
|
|
33
|
+
children: [/* @__PURE__ */ v("div", {
|
|
33
34
|
className: "min-w-0",
|
|
34
|
-
children: [/* @__PURE__ */
|
|
35
|
+
children: [/* @__PURE__ */ _("h1", {
|
|
35
36
|
className: "text-2xl font-bold text-text-primary",
|
|
36
|
-
children: /* @__PURE__ */
|
|
37
|
-
}), /* @__PURE__ */
|
|
37
|
+
children: /* @__PURE__ */ _(C, { children: w("timecampus.home.title", "Dashboard") })
|
|
38
|
+
}), /* @__PURE__ */ _("p", {
|
|
38
39
|
className: "mt-1 text-sm text-text-secondary",
|
|
39
|
-
children:
|
|
40
|
+
children: w("timecampus.home.description", "Overview of your time tracking and productivity")
|
|
40
41
|
})]
|
|
41
|
-
}),
|
|
42
|
+
}), N]
|
|
42
43
|
})]
|
|
43
44
|
});
|
|
44
|
-
return
|
|
45
|
+
return D && k ? /* @__PURE__ */ v("div", {
|
|
45
46
|
className: "min-h-full space-y-6 p-4 sm:p-6",
|
|
46
|
-
children: [
|
|
47
|
+
children: [P(), /* @__PURE__ */ _(i, {
|
|
47
48
|
variant: "card",
|
|
48
49
|
count: 4
|
|
49
50
|
})]
|
|
50
|
-
}) : /* @__PURE__ */
|
|
51
|
+
}) : /* @__PURE__ */ v("div", {
|
|
51
52
|
className: "min-h-full space-y-6 p-4 sm:p-6",
|
|
52
53
|
children: [
|
|
53
|
-
|
|
54
|
-
/* @__PURE__ */ _(
|
|
54
|
+
P(),
|
|
55
|
+
M ? /* @__PURE__ */ _(a, {
|
|
56
|
+
illustration: "empty-data",
|
|
57
|
+
title: w("timecampus.home.gettingStarted.title", "Let's get you started"),
|
|
58
|
+
description: w("timecampus.home.gettingStarted.description", "TimeCampus tracks your time when you start a timer — stop it when you're done, and everything else (your Timeline, Focus Score, and Reports) fills in automatically from what you track. No extra setup needed."),
|
|
59
|
+
action: /* @__PURE__ */ v("button", {
|
|
60
|
+
type: "button",
|
|
61
|
+
onClick: () => T("/time/timer"),
|
|
62
|
+
className: "inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
|
|
63
|
+
children: [/* @__PURE__ */ _(m, { className: "h-4 w-4" }), w("timecampus.home.gettingStarted.action", "Start your first timer")]
|
|
64
|
+
})
|
|
65
|
+
}) : /* @__PURE__ */ v("div", {
|
|
55
66
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
|
|
56
67
|
children: [
|
|
57
|
-
/* @__PURE__ */
|
|
68
|
+
/* @__PURE__ */ _(r, {
|
|
58
69
|
featured: !0,
|
|
59
|
-
title:
|
|
60
|
-
value: n(
|
|
61
|
-
icon: /* @__PURE__ */
|
|
70
|
+
title: w("timecampus.home.stats.today", "Today"),
|
|
71
|
+
value: n(A?.totalHours ?? 0),
|
|
72
|
+
icon: /* @__PURE__ */ _(f, { className: "h-5 w-5" }),
|
|
62
73
|
trend: {
|
|
63
74
|
value: 12.5,
|
|
64
|
-
label:
|
|
75
|
+
label: w("timecampus.home.stats.vsYesterday", "vs yesterday")
|
|
65
76
|
}
|
|
66
77
|
}),
|
|
67
|
-
/* @__PURE__ */
|
|
68
|
-
title:
|
|
69
|
-
value: n(
|
|
70
|
-
icon: /* @__PURE__ */
|
|
71
|
-
description: `${
|
|
78
|
+
/* @__PURE__ */ _(r, {
|
|
79
|
+
title: w("timecampus.home.stats.billable", "Billable"),
|
|
80
|
+
value: n(A?.billableHours ?? 0),
|
|
81
|
+
icon: /* @__PURE__ */ _(h, { className: "h-5 w-5" }),
|
|
82
|
+
description: `${A?.totalEntries ?? 0} ${w("timecampus.home.stats.entries", "entries")}`
|
|
72
83
|
}),
|
|
73
|
-
/* @__PURE__ */
|
|
74
|
-
title:
|
|
75
|
-
value:
|
|
76
|
-
icon: /* @__PURE__ */
|
|
77
|
-
description:
|
|
84
|
+
/* @__PURE__ */ _(r, {
|
|
85
|
+
title: w("timecampus.home.stats.activeTimers", "Active Timers"),
|
|
86
|
+
value: A?.activeTimers ?? 0,
|
|
87
|
+
icon: /* @__PURE__ */ _(p, { className: "h-5 w-5" }),
|
|
88
|
+
description: w("timecampus.home.stats.currentlyRunning", "Currently running")
|
|
78
89
|
}),
|
|
79
|
-
/* @__PURE__ */
|
|
80
|
-
title:
|
|
81
|
-
value:
|
|
82
|
-
icon: /* @__PURE__ */
|
|
83
|
-
description:
|
|
90
|
+
/* @__PURE__ */ _(r, {
|
|
91
|
+
title: w("timecampus.home.stats.totalEntries", "Entries"),
|
|
92
|
+
value: A?.totalEntries ?? 0,
|
|
93
|
+
icon: /* @__PURE__ */ _(u, { className: "h-5 w-5" }),
|
|
94
|
+
description: w("timecampus.home.stats.totalEntriesDescription", "Total time entries")
|
|
84
95
|
})
|
|
85
96
|
]
|
|
86
97
|
}),
|
|
87
|
-
/* @__PURE__ */
|
|
98
|
+
/* @__PURE__ */ v("div", {
|
|
88
99
|
className: "grid grid-cols-1 gap-6 lg:grid-cols-3",
|
|
89
|
-
children: [/* @__PURE__ */
|
|
100
|
+
children: [/* @__PURE__ */ v(S, {
|
|
90
101
|
treatment: "plain",
|
|
91
102
|
className: "border-border-seam p-6 lg:col-span-2",
|
|
92
|
-
children: [/* @__PURE__ */
|
|
103
|
+
children: [/* @__PURE__ */ v("div", {
|
|
93
104
|
className: "mb-4 flex items-center justify-between",
|
|
94
|
-
children: [/* @__PURE__ */
|
|
105
|
+
children: [/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("h3", {
|
|
95
106
|
className: "text-sm font-semibold text-text-primary",
|
|
96
|
-
children:
|
|
97
|
-
}), /* @__PURE__ */
|
|
107
|
+
children: w("timecampus.home.recentEntries.title", "Recent Time Entries")
|
|
108
|
+
}), /* @__PURE__ */ _("p", {
|
|
98
109
|
className: "text-xs text-text-secondary",
|
|
99
|
-
children:
|
|
100
|
-
})] }), /* @__PURE__ */
|
|
101
|
-
onClick: () =>
|
|
110
|
+
children: w("timecampus.home.recentEntries.description", "Your latest tracked activities")
|
|
111
|
+
})] }), /* @__PURE__ */ v("button", {
|
|
112
|
+
onClick: () => T("/time/entries"),
|
|
102
113
|
className: "inline-flex min-h-[2.75rem] items-center gap-1 rounded-md px-2 text-xs font-medium text-primary transition-colors hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-border",
|
|
103
114
|
children: [
|
|
104
|
-
|
|
115
|
+
w("timecampus.home.recentEntries.viewAll", "View all"),
|
|
105
116
|
" ",
|
|
106
|
-
/* @__PURE__ */
|
|
117
|
+
/* @__PURE__ */ _(l, { className: "h-3 w-3" })
|
|
107
118
|
]
|
|
108
119
|
})]
|
|
109
|
-
}),
|
|
120
|
+
}), k ? /* @__PURE__ */ _(i, {
|
|
110
121
|
variant: "list",
|
|
111
122
|
count: 4
|
|
112
|
-
}) : /* @__PURE__ */
|
|
123
|
+
}) : /* @__PURE__ */ v("div", {
|
|
113
124
|
className: "flex flex-col gap-3",
|
|
114
|
-
children: [
|
|
125
|
+
children: [j.map((e) => /* @__PURE__ */ v("div", {
|
|
115
126
|
className: "flex items-center justify-between rounded-lg border border-border-seam p-3 transition-colors hover:bg-bg-sunken/50",
|
|
116
|
-
children: [/* @__PURE__ */
|
|
127
|
+
children: [/* @__PURE__ */ v("div", {
|
|
117
128
|
className: "min-w-0 flex-1",
|
|
118
|
-
children: [/* @__PURE__ */
|
|
129
|
+
children: [/* @__PURE__ */ _("p", {
|
|
119
130
|
className: "text-sm font-medium text-text-primary",
|
|
120
|
-
children: e.project?.name ??
|
|
121
|
-
}), /* @__PURE__ */
|
|
131
|
+
children: e.project?.name ?? w("timecampus.home.recentEntries.noProject", "No Project")
|
|
132
|
+
}), /* @__PURE__ */ _("p", {
|
|
122
133
|
className: "text-xs text-text-secondary",
|
|
123
|
-
children: e.description ??
|
|
134
|
+
children: e.description ?? w("timecampus.home.recentEntries.noDescription", "No description")
|
|
124
135
|
})]
|
|
125
|
-
}), /* @__PURE__ */
|
|
136
|
+
}), /* @__PURE__ */ v("div", {
|
|
126
137
|
className: "ml-4 text-right",
|
|
127
|
-
children: [/* @__PURE__ */
|
|
138
|
+
children: [/* @__PURE__ */ _("p", {
|
|
128
139
|
className: "font-mono text-sm font-medium tabular-nums text-text-primary",
|
|
129
140
|
children: n((e.duration ?? 0) / 3600)
|
|
130
|
-
}), /* @__PURE__ */
|
|
141
|
+
}), /* @__PURE__ */ v("span", {
|
|
131
142
|
className: t("inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-medium", e.isRunning ? "bg-status-info-bg text-status-info-text" : "bg-status-success-bg text-status-success-text"),
|
|
132
|
-
children: [e.isRunning && /* @__PURE__ */
|
|
143
|
+
children: [e.isRunning && /* @__PURE__ */ _("span", { className: "h-1.5 w-1.5 rounded-full bg-status-info-text motion-safe:animate-vc-glow-pulse" }), e.isRunning ? w("timecampus.home.recentEntries.status.running", "running") : w("timecampus.home.recentEntries.status.completed", "completed")]
|
|
133
144
|
})]
|
|
134
145
|
})]
|
|
135
|
-
}, e.id)),
|
|
146
|
+
}, e.id)), j.length === 0 && /* @__PURE__ */ _("p", {
|
|
136
147
|
className: "py-4 text-center text-sm text-text-secondary",
|
|
137
|
-
children:
|
|
148
|
+
children: w("timecampus.home.recentEntries.empty", "No time entries yet")
|
|
138
149
|
})]
|
|
139
150
|
})]
|
|
140
|
-
}), /* @__PURE__ */
|
|
151
|
+
}), /* @__PURE__ */ v(x, {
|
|
141
152
|
className: "p-6",
|
|
142
|
-
children: [/* @__PURE__ */
|
|
153
|
+
children: [/* @__PURE__ */ v("div", {
|
|
143
154
|
className: "mb-4",
|
|
144
|
-
children: [/* @__PURE__ */
|
|
155
|
+
children: [/* @__PURE__ */ _("h3", {
|
|
145
156
|
className: "text-sm font-semibold text-text-primary",
|
|
146
|
-
children:
|
|
147
|
-
}), /* @__PURE__ */
|
|
157
|
+
children: w("timecampus.home.summary.title", "Quick Summary")
|
|
158
|
+
}), /* @__PURE__ */ _("p", {
|
|
148
159
|
className: "text-xs text-text-secondary",
|
|
149
|
-
children:
|
|
160
|
+
children: w("timecampus.home.summary.description", "Time tracking overview")
|
|
150
161
|
})]
|
|
151
|
-
}), /* @__PURE__ */
|
|
162
|
+
}), /* @__PURE__ */ v("div", {
|
|
152
163
|
className: "flex flex-col gap-4",
|
|
153
164
|
children: [
|
|
154
|
-
/* @__PURE__ */
|
|
165
|
+
/* @__PURE__ */ v("div", {
|
|
155
166
|
className: "flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface/40 p-3",
|
|
156
|
-
children: [/* @__PURE__ */
|
|
167
|
+
children: [/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
|
|
157
168
|
className: "text-xs font-medium text-text-secondary",
|
|
158
|
-
children:
|
|
159
|
-
}), /* @__PURE__ */
|
|
169
|
+
children: w("timecampus.home.summary.totalHours", "Total Hours")
|
|
170
|
+
}), /* @__PURE__ */ _("p", {
|
|
160
171
|
className: "mt-1 text-xl font-bold tabular-nums text-text-primary",
|
|
161
|
-
children: n(
|
|
162
|
-
})] }), /* @__PURE__ */
|
|
172
|
+
children: n(A?.totalHours ?? 0)
|
|
173
|
+
})] }), /* @__PURE__ */ _(f, { className: "h-5 w-5 text-text-secondary" })]
|
|
163
174
|
}),
|
|
164
|
-
/* @__PURE__ */
|
|
175
|
+
/* @__PURE__ */ v("div", {
|
|
165
176
|
className: "flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface/40 p-3",
|
|
166
|
-
children: [/* @__PURE__ */
|
|
177
|
+
children: [/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
|
|
167
178
|
className: "text-xs font-medium text-text-secondary",
|
|
168
|
-
children:
|
|
169
|
-
}), /* @__PURE__ */
|
|
179
|
+
children: w("timecampus.home.summary.billableHours", "Billable Hours")
|
|
180
|
+
}), /* @__PURE__ */ _("p", {
|
|
170
181
|
className: "mt-1 text-xl font-bold tabular-nums text-text-primary",
|
|
171
|
-
children: n(
|
|
172
|
-
})] }), /* @__PURE__ */
|
|
182
|
+
children: n(A?.billableHours ?? 0)
|
|
183
|
+
})] }), /* @__PURE__ */ _(h, { className: "h-5 w-5 text-text-secondary" })]
|
|
173
184
|
}),
|
|
174
|
-
/* @__PURE__ */
|
|
185
|
+
/* @__PURE__ */ v("div", {
|
|
175
186
|
className: "flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface/40 p-3",
|
|
176
|
-
children: [/* @__PURE__ */
|
|
187
|
+
children: [/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
|
|
177
188
|
className: "text-xs font-medium text-text-secondary",
|
|
178
|
-
children:
|
|
179
|
-
}), /* @__PURE__ */
|
|
189
|
+
children: w("timecampus.home.summary.activeTimers", "Active Timers")
|
|
190
|
+
}), /* @__PURE__ */ _("p", {
|
|
180
191
|
className: "mt-1 text-xl font-bold tabular-nums text-text-primary",
|
|
181
|
-
children:
|
|
182
|
-
})] }), /* @__PURE__ */ g
|
|
192
|
+
children: A?.activeTimers ?? 0
|
|
193
|
+
})] }), /* @__PURE__ */ _(g, { className: "h-5 w-5 text-text-secondary" })]
|
|
183
194
|
})
|
|
184
195
|
]
|
|
185
196
|
})]
|
|
186
197
|
})]
|
|
187
198
|
}),
|
|
188
|
-
/* @__PURE__ */
|
|
199
|
+
/* @__PURE__ */ v(S, {
|
|
189
200
|
treatment: "plain",
|
|
190
201
|
className: "border-border-seam p-6",
|
|
191
|
-
children: [/* @__PURE__ */
|
|
202
|
+
children: [/* @__PURE__ */ v("div", {
|
|
192
203
|
className: "mb-4",
|
|
193
|
-
children: [/* @__PURE__ */
|
|
204
|
+
children: [/* @__PURE__ */ _("h3", {
|
|
194
205
|
className: "text-sm font-semibold text-text-primary",
|
|
195
|
-
children:
|
|
196
|
-
}), /* @__PURE__ */
|
|
206
|
+
children: w("timecampus.home.quickActions.title", "Quick Actions")
|
|
207
|
+
}), /* @__PURE__ */ _("p", {
|
|
197
208
|
className: "text-xs text-text-secondary",
|
|
198
|
-
children:
|
|
209
|
+
children: w("timecampus.home.quickActions.description", "Frequently used features")
|
|
199
210
|
})]
|
|
200
|
-
}), /* @__PURE__ */
|
|
211
|
+
}), /* @__PURE__ */ _("div", {
|
|
201
212
|
className: "grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-6",
|
|
202
213
|
children: [
|
|
203
214
|
{
|
|
204
|
-
label:
|
|
205
|
-
icon:
|
|
215
|
+
label: w("timecampus.home.quickActions.startTimer.label", "Start Timer"),
|
|
216
|
+
icon: m,
|
|
206
217
|
route: "/time/timer",
|
|
207
|
-
description:
|
|
218
|
+
description: w("timecampus.home.quickActions.startTimer.description", "Track your time")
|
|
208
219
|
},
|
|
209
220
|
{
|
|
210
|
-
label:
|
|
211
|
-
icon:
|
|
221
|
+
label: w("timecampus.home.quickActions.viewProjects.label", "View Projects"),
|
|
222
|
+
icon: p,
|
|
212
223
|
route: "/projects",
|
|
213
|
-
description:
|
|
224
|
+
description: w("timecampus.home.quickActions.viewProjects.description", "Manage projects")
|
|
214
225
|
},
|
|
215
226
|
{
|
|
216
|
-
label:
|
|
217
|
-
icon:
|
|
227
|
+
label: w("timecampus.home.quickActions.timeEntries.label", "Time Entries"),
|
|
228
|
+
icon: f,
|
|
218
229
|
route: "/time/entries",
|
|
219
|
-
description:
|
|
230
|
+
description: w("timecampus.home.quickActions.timeEntries.description", "View all entries")
|
|
220
231
|
},
|
|
221
232
|
{
|
|
222
|
-
label:
|
|
223
|
-
icon:
|
|
233
|
+
label: w("timecampus.home.quickActions.teamActivity.label", "Team Activity"),
|
|
234
|
+
icon: g,
|
|
224
235
|
route: "/team-activity",
|
|
225
|
-
description:
|
|
236
|
+
description: w("timecampus.home.quickActions.teamActivity.description", "See team status")
|
|
226
237
|
},
|
|
227
238
|
{
|
|
228
|
-
label:
|
|
229
|
-
icon:
|
|
239
|
+
label: w("timecampus.home.quickActions.reports.label", "Reports"),
|
|
240
|
+
icon: u,
|
|
230
241
|
route: "/reports",
|
|
231
|
-
description:
|
|
242
|
+
description: w("timecampus.home.quickActions.reports.description", "Generate reports")
|
|
232
243
|
},
|
|
233
244
|
{
|
|
234
|
-
label:
|
|
235
|
-
icon:
|
|
245
|
+
label: w("timecampus.home.quickActions.approvals.label", "Approvals"),
|
|
246
|
+
icon: d,
|
|
236
247
|
route: "/time-approval",
|
|
237
|
-
description:
|
|
248
|
+
description: w("timecampus.home.quickActions.approvals.description", "Review timesheets")
|
|
238
249
|
}
|
|
239
|
-
].map(({ label: e, icon: t, description: n, route: r }) => /* @__PURE__ */
|
|
240
|
-
onClick: () =>
|
|
250
|
+
].map(({ label: e, icon: t, description: n, route: r }) => /* @__PURE__ */ v("button", {
|
|
251
|
+
onClick: () => T(r),
|
|
241
252
|
className: "flex min-h-[2.75rem] flex-col items-center gap-2 rounded-lg border border-border-seam bg-bg-surface p-4 text-center transition-colors hover:bg-bg-sunken/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-border",
|
|
242
253
|
children: [
|
|
243
|
-
/* @__PURE__ */
|
|
254
|
+
/* @__PURE__ */ _("div", {
|
|
244
255
|
className: "rounded-full bg-action-primary-bg/10 p-3",
|
|
245
|
-
children: /* @__PURE__ */
|
|
256
|
+
children: /* @__PURE__ */ _(t, { className: "h-5 w-5 text-primary" })
|
|
246
257
|
}),
|
|
247
|
-
/* @__PURE__ */
|
|
258
|
+
/* @__PURE__ */ _("span", {
|
|
248
259
|
className: "text-sm font-medium text-text-primary",
|
|
249
260
|
children: e
|
|
250
261
|
}),
|
|
251
|
-
/* @__PURE__ */
|
|
262
|
+
/* @__PURE__ */ _("span", {
|
|
252
263
|
className: "text-xs text-text-secondary",
|
|
253
264
|
children: n
|
|
254
265
|
})
|
|
@@ -260,6 +271,6 @@ var C = () => {
|
|
|
260
271
|
});
|
|
261
272
|
};
|
|
262
273
|
//#endregion
|
|
263
|
-
export {
|
|
274
|
+
export { w as HomePage };
|
|
264
275
|
|
|
265
276
|
//# sourceMappingURL=HomePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HomePage.js","names":[],"sources":["../../../src/timecampus/pages/HomePage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport {\n Clock,\n FolderOpen,\n Users,\n TrendingUp,\n CheckCircle,\n BarChart3,\n Play,\n ArrowRight,\n} from \"lucide-react\";\nimport {\n GlassCard,\n EmphasisPanel,\n AuroraBackground,\n GradientText,\n CTAOverflowMenu,\n} from \"@burdenoff/fe-libs/ui\";\nimport { StatCard } from \"../components/StatCard\";\nimport { LoadingSkeleton } from \"../components/LoadingSkeleton\";\nimport { cn, formatHours } from \"../utils/helpers\";\nimport { useTimeCampusNavigate } from \"../providers/TimeCampusProvider\";\nimport {\n useGetTimeEntryStatsQuery,\n useListTimeEntriesQuery,\n type TimeEntryFieldsFragment,\n} from \"@/generated/wspace-operations\";\nimport { useTr } from \"../hooks\";\n\nexport const HomePage: FC = () => {\n const t = useTr();\n const navigate = useTimeCampusNavigate();\n\n const { data: statsData, loading: statsLoading } =\n useGetTimeEntryStatsQuery();\n const { data: entriesData, loading: entriesLoading } =\n useListTimeEntriesQuery({\n variables: { pagination: { limit: 4 } },\n });\n\n const stats = statsData?.timeEntryStats;\n const recentEntries = entriesData?.timeEntries?.items ?? [];\n\n const headerActions = (\n <CTAOverflowMenu\n primary={{\n label: t(\"timecampus.home.actions.startTimer\", \"Start Timer\"),\n onSelect: () => navigate(\"/time/timer\"),\n icon: <Play className=\"h-4 w-4\" />,\n }}\n actions={[\n {\n label: t(\n \"timecampus.home.quickActions.viewProjects.label\",\n \"View Projects\",\n ),\n onSelect: () => navigate(\"/projects\"),\n icon: <FolderOpen className=\"h-4 w-4\" />,\n },\n {\n label: t(\"timecampus.home.quickActions.reports.label\", \"Reports\"),\n onSelect: () => navigate(\"/reports\"),\n icon: <BarChart3 className=\"h-4 w-4\" />,\n },\n ]}\n />\n );\n\n const renderHeader = () => (\n <div className=\"relative overflow-hidden rounded-2xl border border-border-seam bg-gloss-card p-5 sm:p-6\">\n <AuroraBackground intensity=\"subtle\" />\n <div className=\"relative flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"min-w-0\">\n <h1 className=\"text-2xl font-bold text-text-primary\">\n <GradientText>\n {t(\"timecampus.home.title\", \"Dashboard\")}\n </GradientText>\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {t(\n \"timecampus.home.description\",\n \"Overview of your time tracking and productivity\",\n )}\n </p>\n </div>\n {headerActions}\n </div>\n </div>\n );\n\n if (statsLoading && entriesLoading) {\n return (\n <div className=\"min-h-full space-y-6 p-4 sm:p-6\">\n {renderHeader()}\n <LoadingSkeleton variant=\"card\" count={4} />\n </div>\n );\n }\n\n return (\n <div className=\"min-h-full space-y-6 p-4 sm:p-6\">\n {renderHeader()}\n\n {/* Hero metric + supporting metrics */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n <StatCard\n featured\n title={t(\"timecampus.home.stats.today\", \"Today\")}\n value={formatHours(stats?.totalHours ?? 0)}\n icon={<Clock className=\"h-5 w-5\" />}\n trend={{\n value: 12.5,\n label: t(\"timecampus.home.stats.vsYesterday\", \"vs yesterday\"),\n }}\n />\n <StatCard\n title={t(\"timecampus.home.stats.billable\", \"Billable\")}\n value={formatHours(stats?.billableHours ?? 0)}\n icon={<TrendingUp className=\"h-5 w-5\" />}\n description={`${stats?.totalEntries ?? 0} ${t(\"timecampus.home.stats.entries\", \"entries\")}`}\n />\n <StatCard\n title={t(\"timecampus.home.stats.activeTimers\", \"Active Timers\")}\n value={stats?.activeTimers ?? 0}\n icon={<FolderOpen className=\"h-5 w-5\" />}\n description={t(\n \"timecampus.home.stats.currentlyRunning\",\n \"Currently running\",\n )}\n />\n <StatCard\n title={t(\"timecampus.home.stats.totalEntries\", \"Entries\")}\n value={stats?.totalEntries ?? 0}\n icon={<BarChart3 className=\"h-5 w-5\" />}\n description={t(\n \"timecampus.home.stats.totalEntriesDescription\",\n \"Total time entries\",\n )}\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Recent Time Entries */}\n <GlassCard\n treatment=\"plain\"\n className=\"border-border-seam p-6 lg:col-span-2\"\n >\n <div className=\"mb-4 flex items-center justify-between\">\n <div>\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {t(\n \"timecampus.home.recentEntries.title\",\n \"Recent Time Entries\",\n )}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t(\n \"timecampus.home.recentEntries.description\",\n \"Your latest tracked activities\",\n )}\n </p>\n </div>\n <button\n onClick={() => navigate(\"/time/entries\")}\n className=\"inline-flex min-h-[2.75rem] items-center gap-1 rounded-md px-2 text-xs font-medium text-primary transition-colors hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-border\"\n >\n {t(\"timecampus.home.recentEntries.viewAll\", \"View all\")}{\" \"}\n <ArrowRight className=\"h-3 w-3\" />\n </button>\n </div>\n {entriesLoading ? (\n <LoadingSkeleton variant=\"list\" count={4} />\n ) : (\n <div className=\"flex flex-col gap-3\">\n {recentEntries.map((entry: TimeEntryFieldsFragment) => (\n <div\n key={entry.id}\n className=\"flex items-center justify-between rounded-lg border border-border-seam p-3 transition-colors hover:bg-bg-sunken/50\"\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-text-primary\">\n {entry.project?.name ??\n t(\n \"timecampus.home.recentEntries.noProject\",\n \"No Project\",\n )}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {entry.description ??\n t(\n \"timecampus.home.recentEntries.noDescription\",\n \"No description\",\n )}\n </p>\n </div>\n <div className=\"ml-4 text-right\">\n <p className=\"font-mono text-sm font-medium tabular-nums text-text-primary\">\n {formatHours((entry.duration ?? 0) / 3600)}\n </p>\n <span\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-medium\",\n entry.isRunning\n ? \"bg-status-info-bg text-status-info-text\"\n : \"bg-status-success-bg text-status-success-text\",\n )}\n >\n {entry.isRunning && (\n <span className=\"h-1.5 w-1.5 rounded-full bg-status-info-text motion-safe:animate-vc-glow-pulse\" />\n )}\n {entry.isRunning\n ? t(\n \"timecampus.home.recentEntries.status.running\",\n \"running\",\n )\n : t(\n \"timecampus.home.recentEntries.status.completed\",\n \"completed\",\n )}\n </span>\n </div>\n </div>\n ))}\n {recentEntries.length === 0 && (\n <p className=\"py-4 text-center text-sm text-text-secondary\">\n {t(\n \"timecampus.home.recentEntries.empty\",\n \"No time entries yet\",\n )}\n </p>\n )}\n </div>\n )}\n </GlassCard>\n\n {/* Quick Summary — the one emphasis zone */}\n <EmphasisPanel className=\"p-6\">\n <div className=\"mb-4\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {t(\"timecampus.home.summary.title\", \"Quick Summary\")}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t(\n \"timecampus.home.summary.description\",\n \"Time tracking overview\",\n )}\n </p>\n </div>\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface/40 p-3\">\n <div>\n <p className=\"text-xs font-medium text-text-secondary\">\n {t(\"timecampus.home.summary.totalHours\", \"Total Hours\")}\n </p>\n <p className=\"mt-1 text-xl font-bold tabular-nums text-text-primary\">\n {formatHours(stats?.totalHours ?? 0)}\n </p>\n </div>\n <Clock className=\"h-5 w-5 text-text-secondary\" />\n </div>\n <div className=\"flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface/40 p-3\">\n <div>\n <p className=\"text-xs font-medium text-text-secondary\">\n {t(\"timecampus.home.summary.billableHours\", \"Billable Hours\")}\n </p>\n <p className=\"mt-1 text-xl font-bold tabular-nums text-text-primary\">\n {formatHours(stats?.billableHours ?? 0)}\n </p>\n </div>\n <TrendingUp className=\"h-5 w-5 text-text-secondary\" />\n </div>\n <div className=\"flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface/40 p-3\">\n <div>\n <p className=\"text-xs font-medium text-text-secondary\">\n {t(\"timecampus.home.summary.activeTimers\", \"Active Timers\")}\n </p>\n <p className=\"mt-1 text-xl font-bold tabular-nums text-text-primary\">\n {stats?.activeTimers ?? 0}\n </p>\n </div>\n <Users className=\"h-5 w-5 text-text-secondary\" />\n </div>\n </div>\n </EmphasisPanel>\n </div>\n\n {/* Quick Actions */}\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-6\">\n <div className=\"mb-4\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {t(\"timecampus.home.quickActions.title\", \"Quick Actions\")}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t(\n \"timecampus.home.quickActions.description\",\n \"Frequently used features\",\n )}\n </p>\n </div>\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-6\">\n {[\n {\n label: t(\n \"timecampus.home.quickActions.startTimer.label\",\n \"Start Timer\",\n ),\n icon: Play,\n route: \"/time/timer\",\n description: t(\n \"timecampus.home.quickActions.startTimer.description\",\n \"Track your time\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.viewProjects.label\",\n \"View Projects\",\n ),\n icon: FolderOpen,\n route: \"/projects\",\n description: t(\n \"timecampus.home.quickActions.viewProjects.description\",\n \"Manage projects\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.timeEntries.label\",\n \"Time Entries\",\n ),\n icon: Clock,\n route: \"/time/entries\",\n description: t(\n \"timecampus.home.quickActions.timeEntries.description\",\n \"View all entries\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.teamActivity.label\",\n \"Team Activity\",\n ),\n icon: Users,\n route: \"/team-activity\",\n description: t(\n \"timecampus.home.quickActions.teamActivity.description\",\n \"See team status\",\n ),\n },\n {\n label: t(\"timecampus.home.quickActions.reports.label\", \"Reports\"),\n icon: BarChart3,\n route: \"/reports\",\n description: t(\n \"timecampus.home.quickActions.reports.description\",\n \"Generate reports\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.approvals.label\",\n \"Approvals\",\n ),\n icon: CheckCircle,\n route: \"/time-approval\",\n description: t(\n \"timecampus.home.quickActions.approvals.description\",\n \"Review timesheets\",\n ),\n },\n ].map(({ label, icon: Icon, description, route }) => (\n <button\n key={label}\n onClick={() => navigate(route)}\n className=\"flex min-h-[2.75rem] flex-col items-center gap-2 rounded-lg border border-border-seam bg-bg-surface p-4 text-center transition-colors hover:bg-bg-sunken/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-border\"\n >\n <div className=\"rounded-full bg-action-primary-bg/10 p-3\">\n <Icon className=\"h-5 w-5 text-primary\" />\n </div>\n <span className=\"text-sm font-medium text-text-primary\">\n {label}\n </span>\n <span className=\"text-xs text-text-secondary\">{description}</span>\n </button>\n ))}\n </div>\n </GlassCard>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HomePage.js","names":[],"sources":["../../../src/timecampus/pages/HomePage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport {\n Clock,\n FolderOpen,\n Users,\n TrendingUp,\n CheckCircle,\n BarChart3,\n Play,\n ArrowRight,\n} from \"lucide-react\";\nimport {\n GlassCard,\n EmphasisPanel,\n AuroraBackground,\n GradientText,\n CTAOverflowMenu,\n} from \"@burdenoff/fe-libs/ui\";\nimport { StatCard } from \"../components/StatCard\";\nimport { LoadingSkeleton } from \"../components/LoadingSkeleton\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { cn, formatHours } from \"../utils/helpers\";\nimport { useTimeCampusNavigate } from \"../providers/TimeCampusProvider\";\nimport {\n useGetTimeEntryStatsQuery,\n useListTimeEntriesQuery,\n type TimeEntryFieldsFragment,\n} from \"@/generated/wspace-operations\";\nimport { useTr } from \"../hooks\";\n\nexport const HomePage: FC = () => {\n const t = useTr();\n const navigate = useTimeCampusNavigate();\n\n const { data: statsData, loading: statsLoading } =\n useGetTimeEntryStatsQuery();\n const { data: entriesData, loading: entriesLoading } =\n useListTimeEntriesQuery({\n variables: { pagination: { limit: 4 } },\n });\n\n const stats = statsData?.timeEntryStats;\n const recentEntries = entriesData?.timeEntries?.items ?? [];\n\n // No time entries at all yet — a genuinely new user, not just a quiet day.\n // Swap the stat grid (which would otherwise read as four confusing zeroes)\n // for a single, honest explanation of the core loop before anything else.\n const isNewUser =\n !statsLoading && !entriesLoading && (stats?.totalEntries ?? 0) === 0;\n\n const headerActions = (\n <CTAOverflowMenu\n primary={{\n label: t(\"timecampus.home.actions.startTimer\", \"Start Timer\"),\n onSelect: () => navigate(\"/time/timer\"),\n icon: <Play className=\"h-4 w-4\" />,\n }}\n actions={[\n {\n label: t(\n \"timecampus.home.quickActions.viewProjects.label\",\n \"View Projects\",\n ),\n onSelect: () => navigate(\"/projects\"),\n icon: <FolderOpen className=\"h-4 w-4\" />,\n },\n {\n label: t(\"timecampus.home.quickActions.reports.label\", \"Reports\"),\n onSelect: () => navigate(\"/reports\"),\n icon: <BarChart3 className=\"h-4 w-4\" />,\n },\n ]}\n />\n );\n\n const renderHeader = () => (\n <div className=\"relative overflow-hidden rounded-2xl border border-border-seam bg-gloss-card p-5 sm:p-6\">\n <AuroraBackground intensity=\"subtle\" />\n <div className=\"relative flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"min-w-0\">\n <h1 className=\"text-2xl font-bold text-text-primary\">\n <GradientText>\n {t(\"timecampus.home.title\", \"Dashboard\")}\n </GradientText>\n </h1>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {t(\n \"timecampus.home.description\",\n \"Overview of your time tracking and productivity\",\n )}\n </p>\n </div>\n {headerActions}\n </div>\n </div>\n );\n\n if (statsLoading && entriesLoading) {\n return (\n <div className=\"min-h-full space-y-6 p-4 sm:p-6\">\n {renderHeader()}\n <LoadingSkeleton variant=\"card\" count={4} />\n </div>\n );\n }\n\n return (\n <div className=\"min-h-full space-y-6 p-4 sm:p-6\">\n {renderHeader()}\n\n {/* Hero metric + supporting metrics — or, for a genuinely new user with\n no time entries yet, a single honest explanation of the core loop\n instead of a grid of confusing zeroes. */}\n {isNewUser ? (\n <EmptyState\n illustration=\"empty-data\"\n title={t(\n \"timecampus.home.gettingStarted.title\",\n \"Let's get you started\",\n )}\n description={t(\n \"timecampus.home.gettingStarted.description\",\n \"TimeCampus tracks your time when you start a timer — stop it when you're done, and everything else (your Timeline, Focus Score, and Reports) fills in automatically from what you track. No extra setup needed.\",\n )}\n action={\n <button\n type=\"button\"\n onClick={() => navigate(\"/time/timer\")}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n <Play className=\"h-4 w-4\" />\n {t(\n \"timecampus.home.gettingStarted.action\",\n \"Start your first timer\",\n )}\n </button>\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n <StatCard\n featured\n title={t(\"timecampus.home.stats.today\", \"Today\")}\n value={formatHours(stats?.totalHours ?? 0)}\n icon={<Clock className=\"h-5 w-5\" />}\n trend={{\n value: 12.5,\n label: t(\"timecampus.home.stats.vsYesterday\", \"vs yesterday\"),\n }}\n />\n <StatCard\n title={t(\"timecampus.home.stats.billable\", \"Billable\")}\n value={formatHours(stats?.billableHours ?? 0)}\n icon={<TrendingUp className=\"h-5 w-5\" />}\n description={`${stats?.totalEntries ?? 0} ${t(\"timecampus.home.stats.entries\", \"entries\")}`}\n />\n <StatCard\n title={t(\"timecampus.home.stats.activeTimers\", \"Active Timers\")}\n value={stats?.activeTimers ?? 0}\n icon={<FolderOpen className=\"h-5 w-5\" />}\n description={t(\n \"timecampus.home.stats.currentlyRunning\",\n \"Currently running\",\n )}\n />\n <StatCard\n title={t(\"timecampus.home.stats.totalEntries\", \"Entries\")}\n value={stats?.totalEntries ?? 0}\n icon={<BarChart3 className=\"h-5 w-5\" />}\n description={t(\n \"timecampus.home.stats.totalEntriesDescription\",\n \"Total time entries\",\n )}\n />\n </div>\n )}\n\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Recent Time Entries */}\n <GlassCard\n treatment=\"plain\"\n className=\"border-border-seam p-6 lg:col-span-2\"\n >\n <div className=\"mb-4 flex items-center justify-between\">\n <div>\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {t(\n \"timecampus.home.recentEntries.title\",\n \"Recent Time Entries\",\n )}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t(\n \"timecampus.home.recentEntries.description\",\n \"Your latest tracked activities\",\n )}\n </p>\n </div>\n <button\n onClick={() => navigate(\"/time/entries\")}\n className=\"inline-flex min-h-[2.75rem] items-center gap-1 rounded-md px-2 text-xs font-medium text-primary transition-colors hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-border\"\n >\n {t(\"timecampus.home.recentEntries.viewAll\", \"View all\")}{\" \"}\n <ArrowRight className=\"h-3 w-3\" />\n </button>\n </div>\n {entriesLoading ? (\n <LoadingSkeleton variant=\"list\" count={4} />\n ) : (\n <div className=\"flex flex-col gap-3\">\n {recentEntries.map((entry: TimeEntryFieldsFragment) => (\n <div\n key={entry.id}\n className=\"flex items-center justify-between rounded-lg border border-border-seam p-3 transition-colors hover:bg-bg-sunken/50\"\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-text-primary\">\n {entry.project?.name ??\n t(\n \"timecampus.home.recentEntries.noProject\",\n \"No Project\",\n )}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {entry.description ??\n t(\n \"timecampus.home.recentEntries.noDescription\",\n \"No description\",\n )}\n </p>\n </div>\n <div className=\"ml-4 text-right\">\n <p className=\"font-mono text-sm font-medium tabular-nums text-text-primary\">\n {formatHours((entry.duration ?? 0) / 3600)}\n </p>\n <span\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-medium\",\n entry.isRunning\n ? \"bg-status-info-bg text-status-info-text\"\n : \"bg-status-success-bg text-status-success-text\",\n )}\n >\n {entry.isRunning && (\n <span className=\"h-1.5 w-1.5 rounded-full bg-status-info-text motion-safe:animate-vc-glow-pulse\" />\n )}\n {entry.isRunning\n ? t(\n \"timecampus.home.recentEntries.status.running\",\n \"running\",\n )\n : t(\n \"timecampus.home.recentEntries.status.completed\",\n \"completed\",\n )}\n </span>\n </div>\n </div>\n ))}\n {recentEntries.length === 0 && (\n <p className=\"py-4 text-center text-sm text-text-secondary\">\n {t(\n \"timecampus.home.recentEntries.empty\",\n \"No time entries yet\",\n )}\n </p>\n )}\n </div>\n )}\n </GlassCard>\n\n {/* Quick Summary — the one emphasis zone */}\n <EmphasisPanel className=\"p-6\">\n <div className=\"mb-4\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {t(\"timecampus.home.summary.title\", \"Quick Summary\")}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t(\n \"timecampus.home.summary.description\",\n \"Time tracking overview\",\n )}\n </p>\n </div>\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface/40 p-3\">\n <div>\n <p className=\"text-xs font-medium text-text-secondary\">\n {t(\"timecampus.home.summary.totalHours\", \"Total Hours\")}\n </p>\n <p className=\"mt-1 text-xl font-bold tabular-nums text-text-primary\">\n {formatHours(stats?.totalHours ?? 0)}\n </p>\n </div>\n <Clock className=\"h-5 w-5 text-text-secondary\" />\n </div>\n <div className=\"flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface/40 p-3\">\n <div>\n <p className=\"text-xs font-medium text-text-secondary\">\n {t(\"timecampus.home.summary.billableHours\", \"Billable Hours\")}\n </p>\n <p className=\"mt-1 text-xl font-bold tabular-nums text-text-primary\">\n {formatHours(stats?.billableHours ?? 0)}\n </p>\n </div>\n <TrendingUp className=\"h-5 w-5 text-text-secondary\" />\n </div>\n <div className=\"flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface/40 p-3\">\n <div>\n <p className=\"text-xs font-medium text-text-secondary\">\n {t(\"timecampus.home.summary.activeTimers\", \"Active Timers\")}\n </p>\n <p className=\"mt-1 text-xl font-bold tabular-nums text-text-primary\">\n {stats?.activeTimers ?? 0}\n </p>\n </div>\n <Users className=\"h-5 w-5 text-text-secondary\" />\n </div>\n </div>\n </EmphasisPanel>\n </div>\n\n {/* Quick Actions */}\n <GlassCard treatment=\"plain\" className=\"border-border-seam p-6\">\n <div className=\"mb-4\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {t(\"timecampus.home.quickActions.title\", \"Quick Actions\")}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t(\n \"timecampus.home.quickActions.description\",\n \"Frequently used features\",\n )}\n </p>\n </div>\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-6\">\n {[\n {\n label: t(\n \"timecampus.home.quickActions.startTimer.label\",\n \"Start Timer\",\n ),\n icon: Play,\n route: \"/time/timer\",\n description: t(\n \"timecampus.home.quickActions.startTimer.description\",\n \"Track your time\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.viewProjects.label\",\n \"View Projects\",\n ),\n icon: FolderOpen,\n route: \"/projects\",\n description: t(\n \"timecampus.home.quickActions.viewProjects.description\",\n \"Manage projects\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.timeEntries.label\",\n \"Time Entries\",\n ),\n icon: Clock,\n route: \"/time/entries\",\n description: t(\n \"timecampus.home.quickActions.timeEntries.description\",\n \"View all entries\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.teamActivity.label\",\n \"Team Activity\",\n ),\n icon: Users,\n route: \"/team-activity\",\n description: t(\n \"timecampus.home.quickActions.teamActivity.description\",\n \"See team status\",\n ),\n },\n {\n label: t(\"timecampus.home.quickActions.reports.label\", \"Reports\"),\n icon: BarChart3,\n route: \"/reports\",\n description: t(\n \"timecampus.home.quickActions.reports.description\",\n \"Generate reports\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.approvals.label\",\n \"Approvals\",\n ),\n icon: CheckCircle,\n route: \"/time-approval\",\n description: t(\n \"timecampus.home.quickActions.approvals.description\",\n \"Review timesheets\",\n ),\n },\n ].map(({ label, icon: Icon, description, route }) => (\n <button\n key={label}\n onClick={() => navigate(route)}\n className=\"flex min-h-[2.75rem] flex-col items-center gap-2 rounded-lg border border-border-seam bg-bg-surface p-4 text-center transition-colors hover:bg-bg-sunken/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-border\"\n >\n <div className=\"rounded-full bg-action-primary-bg/10 p-3\">\n <Icon className=\"h-5 w-5 text-primary\" />\n </div>\n <span className=\"text-sm font-medium text-text-primary\">\n {label}\n </span>\n <span className=\"text-xs text-text-secondary\">{description}</span>\n </button>\n ))}\n </div>\n </GlassCard>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -2,10 +2,10 @@ import { useTimeCampus as e } from "../../providers/TimeCampusProvider.js";
|
|
|
2
2
|
import { formatHours as t, formatTime as n } from "../../utils/helpers.js";
|
|
3
3
|
import { StatCard as r } from "../../components/StatCard.js";
|
|
4
4
|
import { LoadingSkeleton as i } from "../../components/LoadingSkeleton.js";
|
|
5
|
-
import {
|
|
5
|
+
import { EmptyState as ee } from "../../components/EmptyState.js";
|
|
6
|
+
import { useCategorizeApplicationMutation as te, useDeleteApplicationUsageMutation as ne, useGetAppUsageSummaryQuery as re, useListApplicationUsagesQuery as ie, useRecordApplicationUsageMutation as ae } from "../../../generated/wspace-operations.js";
|
|
6
7
|
import { PageLayout as a } from "../../components/PageLayout.js";
|
|
7
|
-
import { StatusBadge as
|
|
8
|
-
import { EmptyState as o } from "../../components/EmptyState.js";
|
|
8
|
+
import { StatusBadge as o } from "../../components/StatusBadge.js";
|
|
9
9
|
import { Modal as s } from "../../components/Modal.js";
|
|
10
10
|
import { ChartCard as c } from "../../components/ChartCard.js";
|
|
11
11
|
import { chartTokens as l } from "../../components/charts/chartTheme.js";
|
|
@@ -45,14 +45,14 @@ function he(e, t) {
|
|
|
45
45
|
return !e || !t ? null : `${n(e)} – ${n(t)}`;
|
|
46
46
|
}
|
|
47
47
|
function C() {
|
|
48
|
-
let { workspaceId: n = "" } = e(), { data: l, loading: C, error: ge, fetchMore: _e, refetch: ve } =
|
|
48
|
+
let { workspaceId: n = "" } = e(), { data: l, loading: C, error: ge, fetchMore: _e, refetch: ve } = ie({
|
|
49
49
|
variables: { pagination: {
|
|
50
50
|
limit: v,
|
|
51
51
|
offset: 0
|
|
52
52
|
} },
|
|
53
53
|
skip: !n,
|
|
54
54
|
notifyOnNetworkStatusChange: !0
|
|
55
|
-
}), { data: ye, loading: be, error: xe, refetch: Se } =
|
|
55
|
+
}), { data: ye, loading: be, error: xe, refetch: Se } = re({ skip: !n }), Ce = C || be, we = ge || xe, w = l?.applicationUsages ?? [], T = ye?.appUsageSummary, E = w.length > 0 && w.length % v === 0, [D, O] = u(!1), [k, A] = u(!1), [j, M] = u(""), [N, P] = u("productive"), [F, I] = u(""), [L, R] = u(""), [z, B] = u(null), [V, H] = u("productive"), [U, W] = u(null), [Te, { loading: G, error: Ee }] = ae(), [De, { loading: K, error: Oe }] = te(), [ke, { loading: q, error: Ae }] = ne(), J = async () => {
|
|
56
56
|
await Promise.all([ve(), Se()]);
|
|
57
57
|
}, Y = () => {
|
|
58
58
|
M(""), P("productive"), I(""), R(""), A(!0);
|
|
@@ -166,7 +166,7 @@ function C() {
|
|
|
166
166
|
description: "90+ min each"
|
|
167
167
|
})
|
|
168
168
|
]
|
|
169
|
-
}), w.length === 0 ? /* @__PURE__ */ g(
|
|
169
|
+
}), w.length === 0 ? /* @__PURE__ */ g(ee, {
|
|
170
170
|
illustration: "empty-data",
|
|
171
171
|
title: "No application usage data found",
|
|
172
172
|
description: "Record app usage manually or connect the desktop tracker, and your apps will appear here ranked by time spent.",
|
|
@@ -241,7 +241,7 @@ function C() {
|
|
|
241
241
|
children: [r, "%"]
|
|
242
242
|
})]
|
|
243
243
|
}),
|
|
244
|
-
/* @__PURE__ */ g(
|
|
244
|
+
/* @__PURE__ */ g(o, {
|
|
245
245
|
label: e.category,
|
|
246
246
|
variant: ue[e.category] ?? "muted",
|
|
247
247
|
className: "hidden capitalize sm:inline-flex"
|