@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Toast.js","names":[],"sources":["../../../src/timecampus/components/Toast.tsx"],"sourcesContent":["import { useEffect, useCallback, useState, type FC } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { X, CheckCircle, AlertTriangle, Info, XCircle } from \"lucide-react\";\nimport { cn } from \"../utils/helpers\";\n\nexport type ToastVariant = \"success\" | \"error\" | \"warning\" | \"info\";\n\nexport interface ToastData {\n id: string;\n title: string;\n description?: string;\n variant: ToastVariant;\n duration?: number;\n}\n\ninterface ToastProps extends ToastData {\n onDismiss: (id: string) => void;\n}\n\nconst variantConfig: Record<\n ToastVariant,\n { icon: typeof CheckCircle; className: string }\n> = {\n success: {\n icon: CheckCircle,\n className:\n \"border-status-success-bg/40 bg-status-success-bg text-status-success-text\",\n },\n error: {\n icon: XCircle,\n className:\n \"border-status-error-bg/40 bg-status-error-bg text-status-error-text\",\n },\n warning: {\n icon: AlertTriangle,\n className:\n \"border-status-warning-bg/40 bg-status-warning-bg text-status-warning-text\",\n },\n info: {\n icon: Info,\n className:\n \"border-status-info-bg/40 bg-status-info-bg text-status-info-text\",\n },\n};\n\nexport const Toast: FC<ToastProps> = ({\n id,\n title,\n description,\n variant,\n duration = 4000,\n onDismiss,\n}) => {\n const { icon: Icon, className } = variantConfig[variant];\n\n useEffect(() => {\n if (duration > 0) {\n const timer = setTimeout(() => onDismiss(id), duration);\n return () => clearTimeout(timer);\n }\n }, [id, duration, onDismiss]);\n\n return (\n <div\n className={cn(\n \"flex items-start gap-3 rounded-lg border p-4 shadow-pop animate-in slide-in-from-right-full\",\n className,\n )}\n role=\"alert\"\n >\n <Icon className=\"mt-0.5 h-5 w-5 shrink-0\" />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium\">{title}</p>\n {description && (\n <p className=\"mt-0.5 text-xs opacity-80\">{description}</p>\n )}\n </div>\n <button\n onClick={() => onDismiss(id)}\n className=\"shrink-0 opacity-60 hover:opacity-100\"\n aria-label=\"Dismiss\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n );\n};\n\ninterface ToastContainerProps {\n toasts: ToastData[];\n onDismiss: (id: string) => void;\n}\n\nexport const ToastContainer: FC<ToastContainerProps> = ({\n toasts,\n onDismiss,\n}) => {\n if (toasts.length === 0) return null;\n return createPortal(\n <div className=\"fixed bottom-4 right-4 z-50 flex w-80 flex-col gap-2\">\n {toasts.map((t) => (\n <Toast key={t.id} {...t} onDismiss={onDismiss} />\n ))}\n </div>,\n document.body,\n );\n};\n\n/** Hook for managing toast state */\nexport function useToast() {\n const [toasts, setToasts] = useState<ToastData[]>([]);\n\n const addToast = useCallback((toast: Omit<ToastData, \"id\">) => {\n const id = `toast-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n setToasts((prev) => [...prev, { ...toast, id }]);\n return id;\n }, []);\n\n const dismissToast = useCallback((id: string) => {\n setToasts((prev) => prev.filter((t) => t.id !== id));\n }, []);\n\n const clearToasts = useCallback(() => {\n setToasts([]);\n }, []);\n\n return { toasts, addToast, dismissToast, clearToasts };\n}\n"],"mappings":";;;;;;AAmBA,IAAM,IAGF;CACF,SAAS;EACP,MAAM;EACN,WACE;EACH;CACD,OAAO;EACL,MAAM;EACN,WACE;EACH;CACD,SAAS;EACP,MAAM;EACN,WACE;EACH;CACD,MAAM;EACJ,MAAM;EACN,WACE;EACH;CACF,EAEY,KAAyB,EACpC,OACA,UACA,gBACA,YACA,cAAW,KACX,mBACI;CACJ,IAAM,EAAE,MAAM,GAAM,iBAAc,EAAc;AAShD,QAPA,QAAgB;AACd,MAAI,IAAW,GAAG;GAChB,IAAM,IAAQ,iBAAiB,EAAU,EAAG,EAAE,EAAS;AACvD,gBAAa,aAAa,EAAM;;IAEjC;EAAC;EAAI;EAAU;EAAU,CAAC,EAG3B,kBAAC,OAAD;EACE,WAAW,EACT,+FACA,EACD;EACD,MAAK;YALP;GAOE,kBAAC,GAAD,EAAM,WAAU,2BAA4B,CAAA;GAC5C,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,KAAD;KAAG,WAAU;eAAuB;KAAU,CAAA,EAC7C,KACC,kBAAC,KAAD;KAAG,WAAU;eAA6B;KAAgB,CAAA,CAExD;;GACN,kBAAC,UAAD;IACE,eAAe,EAAU,EAAG;IAC5B,WAAU;IACV,cAAW;cAEX,kBAAC,GAAD,EAAG,WAAU,WAAY,CAAA;IAClB,CAAA;GACL;;GASG,KAA2C,EACtD,WACA,mBAEI,EAAO,WAAW,IAAU,OACzB,EACL,kBAAC,OAAD;CAAK,WAAU;WACZ,EAAO,KAAK,MACX,kBAAC,GAAD;EAAkB,GAAI;EAAc;EAAa,EAArC,EAAE,GAAmC,CACjD;CACE,CAAA,EACN,SAAS,KACV;AAIH,SAAgB,IAAW;CACzB,IAAM,CAAC,GAAQ,KAAa,EAAsB,EAAE,CAAC;AAgBrD,QAAO;EAAE;EAAQ,UAdA,GAAa,MAAiC;GAC7D,IAAM,IAAK,SAAS,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE;AAExE,UADA,GAAW,MAAS,CAAC,GAAG,GAAM;IAAE,GAAG;IAAO;IAAI,CAAC,CAAC,EACzC;KACN,EAAE,CAAC;EAUqB,cARN,GAAa,MAAe;AAC/C,MAAW,MAAS,EAAK,QAAQ,MAAM,EAAE,OAAO,EAAG,CAAC;KACnD,EAAE,CAAC;EAMmC,aAJrB,QAAkB;AACpC,KAAU,EAAE,CAAC;KACZ,EAAE,CAAC;EAEgD"}
@@ -1,4 +1,4 @@
1
1
  import "./providers/TimeCampusProvider.js";
2
- import "./store/timecampusStore.js";
3
2
  import "../generated/wspace-operations.js";
4
3
  import "./TimeCampusRoot.js";
4
+ import "./store/timecampusStore.js";
@@ -1,248 +1,256 @@
1
- import { cn as e, formatHours as t, formatTimerDuration as n } from "../utils/helpers.js";
1
+ import { useTimeCampusNavigate as e } from "../providers/TimeCampusProvider.js";
2
+ import { cn as t, formatHours as n } from "../utils/helpers.js";
2
3
  import { StatCard as r } from "../components/StatCard.js";
3
4
  import { LoadingSkeleton as i } from "../components/LoadingSkeleton.js";
4
- import { useTimeCampusStore as a } from "../store/timecampusStore.js";
5
- import { useGetTimeEntryStatsQuery as o, useListTimeEntriesQuery as s } from "../../generated/wspace-operations.js";
6
- import { ArrowRight as c, BarChart3 as l, CheckCircle as u, Clock as d, FolderOpen as f, Play as p, Timer as m, TrendingUp as h, Users as g } from "lucide-react";
7
- import { jsx as _, jsxs as v } from "react/jsx-runtime";
8
- import { AuroraBackground as y, CTAOverflowMenu as b, EmphasisPanel as x, GlassCard as S, GradientText as C } from "@burdenoff/fe-libs/ui";
9
- import { useI18n as w } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
5
+ import { useGetTimeEntryStatsQuery as a, useListTimeEntriesQuery as o } from "../../generated/wspace-operations.js";
6
+ import { ArrowRight as s, BarChart3 as c, CheckCircle as l, Clock as u, FolderOpen as d, Play as f, TrendingUp as p, Users as m } from "lucide-react";
7
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
8
+ import { AuroraBackground as _, CTAOverflowMenu as v, EmphasisPanel as y, GlassCard as b, GradientText as x } from "@burdenoff/fe-libs/ui";
9
+ import { useI18n as S } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
10
10
  //#region src/timecampus/pages/HomePage.tsx
11
- var T = () => {
12
- let { t: T } = w(), E = (e, t) => {
13
- let n = T(e);
11
+ var C = () => {
12
+ let { t: C } = S(), w = (e, t) => {
13
+ let n = C(e);
14
14
  return n === e ? t : n;
15
- }, { activeTimer: D, startTimer: O, stopTimer: k } = a(), { data: A, loading: j } = o(), { data: M, loading: N } = s({ variables: { limit: 4 } }), P = A?.timeEntryStats, F = M?.timeEntries?.items ?? [], I = /* @__PURE__ */ _(b, {
15
+ }, T = e(), { data: E, loading: D } = a(), { data: O, loading: k } = o({ variables: { limit: 4 } }), A = E?.timeEntryStats, j = O?.timeEntries?.items ?? [], M = /* @__PURE__ */ h(v, {
16
16
  primary: {
17
- label: D ? `${n(D.seconds)} - ${E("timecampus.home.actions.stop", "Stop")}` : E("timecampus.home.actions.startTimer", "Start Timer"),
18
- onSelect: () => D ? k() : O(),
19
- icon: _(D ? m : p, { className: "h-4 w-4" })
17
+ label: w("timecampus.home.actions.startTimer", "Start Timer"),
18
+ onSelect: () => T("/time/timer"),
19
+ icon: /* @__PURE__ */ h(f, { className: "h-4 w-4" })
20
20
  },
21
21
  actions: [{
22
- label: E("timecampus.home.quickActions.viewProjects.label", "View Projects"),
23
- onSelect: () => {},
24
- icon: /* @__PURE__ */ _(f, { className: "h-4 w-4" })
22
+ label: w("timecampus.home.quickActions.viewProjects.label", "View Projects"),
23
+ onSelect: () => T("/projects"),
24
+ icon: /* @__PURE__ */ h(d, { className: "h-4 w-4" })
25
25
  }, {
26
- label: E("timecampus.home.quickActions.reports.label", "Reports"),
27
- onSelect: () => {},
28
- icon: /* @__PURE__ */ _(l, { className: "h-4 w-4" })
26
+ label: w("timecampus.home.quickActions.reports.label", "Reports"),
27
+ onSelect: () => T("/reports"),
28
+ icon: /* @__PURE__ */ h(c, { className: "h-4 w-4" })
29
29
  }]
30
- }), L = () => /* @__PURE__ */ v("div", {
30
+ }), N = () => /* @__PURE__ */ g("div", {
31
31
  className: "relative overflow-hidden rounded-2xl border border-border-seam bg-gloss-card p-5 sm:p-6",
32
- children: [/* @__PURE__ */ _(y, { intensity: "subtle" }), /* @__PURE__ */ v("div", {
32
+ children: [/* @__PURE__ */ h(_, { intensity: "subtle" }), /* @__PURE__ */ g("div", {
33
33
  className: "relative flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
34
- children: [/* @__PURE__ */ v("div", {
34
+ children: [/* @__PURE__ */ g("div", {
35
35
  className: "min-w-0",
36
- children: [/* @__PURE__ */ _("h1", {
36
+ children: [/* @__PURE__ */ h("h1", {
37
37
  className: "text-2xl font-bold text-text-primary",
38
- children: /* @__PURE__ */ _(C, { children: E("timecampus.home.title", "Dashboard") })
39
- }), /* @__PURE__ */ _("p", {
38
+ children: /* @__PURE__ */ h(x, { children: w("timecampus.home.title", "Dashboard") })
39
+ }), /* @__PURE__ */ h("p", {
40
40
  className: "mt-1 text-sm text-text-secondary",
41
- children: E("timecampus.home.description", "Overview of your time tracking and productivity")
41
+ children: w("timecampus.home.description", "Overview of your time tracking and productivity")
42
42
  })]
43
- }), I]
43
+ }), M]
44
44
  })]
45
45
  });
46
- return j && N ? /* @__PURE__ */ v("div", {
46
+ return D && k ? /* @__PURE__ */ g("div", {
47
47
  className: "min-h-full space-y-6 p-4 sm:p-6",
48
- children: [L(), /* @__PURE__ */ _(i, {
48
+ children: [N(), /* @__PURE__ */ h(i, {
49
49
  variant: "card",
50
50
  count: 4
51
51
  })]
52
- }) : /* @__PURE__ */ v("div", {
52
+ }) : /* @__PURE__ */ g("div", {
53
53
  className: "min-h-full space-y-6 p-4 sm:p-6",
54
54
  children: [
55
- L(),
56
- /* @__PURE__ */ v("div", {
55
+ N(),
56
+ /* @__PURE__ */ g("div", {
57
57
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
58
58
  children: [
59
- /* @__PURE__ */ _(r, {
59
+ /* @__PURE__ */ h(r, {
60
60
  featured: !0,
61
- title: E("timecampus.home.stats.today", "Today"),
62
- value: t(P?.totalHours ?? 0),
63
- icon: /* @__PURE__ */ _(d, { className: "h-5 w-5" }),
61
+ title: w("timecampus.home.stats.today", "Today"),
62
+ value: n(A?.totalHours ?? 0),
63
+ icon: /* @__PURE__ */ h(u, { className: "h-5 w-5" }),
64
64
  trend: {
65
65
  value: 12.5,
66
- label: E("timecampus.home.stats.vsYesterday", "vs yesterday")
66
+ label: w("timecampus.home.stats.vsYesterday", "vs yesterday")
67
67
  }
68
68
  }),
69
- /* @__PURE__ */ _(r, {
70
- title: E("timecampus.home.stats.billable", "Billable"),
71
- value: t(P?.billableHours ?? 0),
72
- icon: /* @__PURE__ */ _(h, { className: "h-5 w-5" }),
73
- description: `${P?.totalEntries ?? 0} ${E("timecampus.home.stats.entries", "entries")}`
69
+ /* @__PURE__ */ h(r, {
70
+ title: w("timecampus.home.stats.billable", "Billable"),
71
+ value: n(A?.billableHours ?? 0),
72
+ icon: /* @__PURE__ */ h(p, { className: "h-5 w-5" }),
73
+ description: `${A?.totalEntries ?? 0} ${w("timecampus.home.stats.entries", "entries")}`
74
74
  }),
75
- /* @__PURE__ */ _(r, {
76
- title: E("timecampus.home.stats.activeTimers", "Active Timers"),
77
- value: P?.activeTimers ?? 0,
78
- icon: /* @__PURE__ */ _(f, { className: "h-5 w-5" }),
79
- description: E("timecampus.home.stats.currentlyRunning", "Currently running")
75
+ /* @__PURE__ */ h(r, {
76
+ title: w("timecampus.home.stats.activeTimers", "Active Timers"),
77
+ value: A?.activeTimers ?? 0,
78
+ icon: /* @__PURE__ */ h(d, { className: "h-5 w-5" }),
79
+ description: w("timecampus.home.stats.currentlyRunning", "Currently running")
80
80
  }),
81
- /* @__PURE__ */ _(r, {
82
- title: E("timecampus.home.stats.totalEntries", "Entries"),
83
- value: P?.totalEntries ?? 0,
84
- icon: /* @__PURE__ */ _(l, { className: "h-5 w-5" }),
85
- description: E("timecampus.home.stats.totalEntriesDescription", "Total time entries")
81
+ /* @__PURE__ */ h(r, {
82
+ title: w("timecampus.home.stats.totalEntries", "Entries"),
83
+ value: A?.totalEntries ?? 0,
84
+ icon: /* @__PURE__ */ h(c, { className: "h-5 w-5" }),
85
+ description: w("timecampus.home.stats.totalEntriesDescription", "Total time entries")
86
86
  })
87
87
  ]
88
88
  }),
89
- /* @__PURE__ */ v("div", {
89
+ /* @__PURE__ */ g("div", {
90
90
  className: "grid grid-cols-1 gap-6 lg:grid-cols-3",
91
- children: [/* @__PURE__ */ v(S, {
91
+ children: [/* @__PURE__ */ g(b, {
92
92
  treatment: "plain",
93
93
  className: "border-border-seam p-6 lg:col-span-2",
94
- children: [/* @__PURE__ */ v("div", {
94
+ children: [/* @__PURE__ */ g("div", {
95
95
  className: "mb-4 flex items-center justify-between",
96
- children: [/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("h3", {
96
+ children: [/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("h3", {
97
97
  className: "text-sm font-semibold text-text-primary",
98
- children: E("timecampus.home.recentEntries.title", "Recent Time Entries")
99
- }), /* @__PURE__ */ _("p", {
98
+ children: w("timecampus.home.recentEntries.title", "Recent Time Entries")
99
+ }), /* @__PURE__ */ h("p", {
100
100
  className: "text-xs text-text-secondary",
101
- children: E("timecampus.home.recentEntries.description", "Your latest tracked activities")
102
- })] }), /* @__PURE__ */ v("button", {
101
+ children: w("timecampus.home.recentEntries.description", "Your latest tracked activities")
102
+ })] }), /* @__PURE__ */ g("button", {
103
+ onClick: () => T("/time/entries"),
103
104
  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",
104
105
  children: [
105
- E("timecampus.home.recentEntries.viewAll", "View all"),
106
+ w("timecampus.home.recentEntries.viewAll", "View all"),
106
107
  " ",
107
- /* @__PURE__ */ _(c, { className: "h-3 w-3" })
108
+ /* @__PURE__ */ h(s, { className: "h-3 w-3" })
108
109
  ]
109
110
  })]
110
- }), N ? /* @__PURE__ */ _(i, {
111
+ }), k ? /* @__PURE__ */ h(i, {
111
112
  variant: "list",
112
113
  count: 4
113
- }) : /* @__PURE__ */ v("div", {
114
+ }) : /* @__PURE__ */ g("div", {
114
115
  className: "flex flex-col gap-3",
115
- children: [F.map((n) => /* @__PURE__ */ v("div", {
116
+ children: [j.map((e) => /* @__PURE__ */ g("div", {
116
117
  className: "flex items-center justify-between rounded-lg border border-border-seam p-3 transition-colors hover:bg-bg-sunken/50",
117
- children: [/* @__PURE__ */ v("div", {
118
+ children: [/* @__PURE__ */ g("div", {
118
119
  className: "min-w-0 flex-1",
119
- children: [/* @__PURE__ */ _("p", {
120
+ children: [/* @__PURE__ */ h("p", {
120
121
  className: "text-sm font-medium text-text-primary",
121
- children: n.project?.name ?? E("timecampus.home.recentEntries.noProject", "No Project")
122
- }), /* @__PURE__ */ _("p", {
122
+ children: e.project?.name ?? w("timecampus.home.recentEntries.noProject", "No Project")
123
+ }), /* @__PURE__ */ h("p", {
123
124
  className: "text-xs text-text-secondary",
124
- children: n.description ?? E("timecampus.home.recentEntries.noDescription", "No description")
125
+ children: e.description ?? w("timecampus.home.recentEntries.noDescription", "No description")
125
126
  })]
126
- }), /* @__PURE__ */ v("div", {
127
+ }), /* @__PURE__ */ g("div", {
127
128
  className: "ml-4 text-right",
128
- children: [/* @__PURE__ */ _("p", {
129
+ children: [/* @__PURE__ */ h("p", {
129
130
  className: "font-mono text-sm font-medium tabular-nums text-text-primary",
130
- children: t((n.duration ?? 0) / 3600)
131
- }), /* @__PURE__ */ v("span", {
132
- className: e("inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-medium", n.isRunning ? "bg-status-info-bg text-status-info-text" : "bg-status-success-bg text-status-success-text"),
133
- children: [n.isRunning && /* @__PURE__ */ _("span", { className: "h-1.5 w-1.5 rounded-full bg-status-info-text motion-safe:animate-vc-glow-pulse" }), n.isRunning ? E("timecampus.home.recentEntries.status.running", "running") : E("timecampus.home.recentEntries.status.completed", "completed")]
131
+ children: n((e.duration ?? 0) / 3600)
132
+ }), /* @__PURE__ */ g("span", {
133
+ 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"),
134
+ children: [e.isRunning && /* @__PURE__ */ h("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")]
134
135
  })]
135
136
  })]
136
- }, n.id)), F.length === 0 && /* @__PURE__ */ _("p", {
137
+ }, e.id)), j.length === 0 && /* @__PURE__ */ h("p", {
137
138
  className: "py-4 text-center text-sm text-text-secondary",
138
- children: E("timecampus.home.recentEntries.empty", "No time entries yet")
139
+ children: w("timecampus.home.recentEntries.empty", "No time entries yet")
139
140
  })]
140
141
  })]
141
- }), /* @__PURE__ */ v(x, {
142
+ }), /* @__PURE__ */ g(y, {
142
143
  className: "p-6",
143
- children: [/* @__PURE__ */ v("div", {
144
+ children: [/* @__PURE__ */ g("div", {
144
145
  className: "mb-4",
145
- children: [/* @__PURE__ */ _("h3", {
146
+ children: [/* @__PURE__ */ h("h3", {
146
147
  className: "text-sm font-semibold text-text-primary",
147
- children: E("timecampus.home.summary.title", "Quick Summary")
148
- }), /* @__PURE__ */ _("p", {
148
+ children: w("timecampus.home.summary.title", "Quick Summary")
149
+ }), /* @__PURE__ */ h("p", {
149
150
  className: "text-xs text-text-secondary",
150
- children: E("timecampus.home.summary.description", "Time tracking overview")
151
+ children: w("timecampus.home.summary.description", "Time tracking overview")
151
152
  })]
152
- }), /* @__PURE__ */ v("div", {
153
+ }), /* @__PURE__ */ g("div", {
153
154
  className: "flex flex-col gap-4",
154
155
  children: [
155
- /* @__PURE__ */ v("div", {
156
+ /* @__PURE__ */ g("div", {
156
157
  className: "flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface/40 p-3",
157
- children: [/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
158
+ children: [/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("p", {
158
159
  className: "text-xs font-medium text-text-secondary",
159
- children: E("timecampus.home.summary.totalHours", "Total Hours")
160
- }), /* @__PURE__ */ _("p", {
160
+ children: w("timecampus.home.summary.totalHours", "Total Hours")
161
+ }), /* @__PURE__ */ h("p", {
161
162
  className: "mt-1 text-xl font-bold tabular-nums text-text-primary",
162
- children: t(P?.totalHours ?? 0)
163
- })] }), /* @__PURE__ */ _(d, { className: "h-5 w-5 text-text-secondary" })]
163
+ children: n(A?.totalHours ?? 0)
164
+ })] }), /* @__PURE__ */ h(u, { className: "h-5 w-5 text-text-secondary" })]
164
165
  }),
165
- /* @__PURE__ */ v("div", {
166
+ /* @__PURE__ */ g("div", {
166
167
  className: "flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface/40 p-3",
167
- children: [/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
168
+ children: [/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("p", {
168
169
  className: "text-xs font-medium text-text-secondary",
169
- children: E("timecampus.home.summary.billableHours", "Billable Hours")
170
- }), /* @__PURE__ */ _("p", {
170
+ children: w("timecampus.home.summary.billableHours", "Billable Hours")
171
+ }), /* @__PURE__ */ h("p", {
171
172
  className: "mt-1 text-xl font-bold tabular-nums text-text-primary",
172
- children: t(P?.billableHours ?? 0)
173
- })] }), /* @__PURE__ */ _(h, { className: "h-5 w-5 text-text-secondary" })]
173
+ children: n(A?.billableHours ?? 0)
174
+ })] }), /* @__PURE__ */ h(p, { className: "h-5 w-5 text-text-secondary" })]
174
175
  }),
175
- /* @__PURE__ */ v("div", {
176
+ /* @__PURE__ */ g("div", {
176
177
  className: "flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface/40 p-3",
177
- children: [/* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
178
+ children: [/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("p", {
178
179
  className: "text-xs font-medium text-text-secondary",
179
- children: E("timecampus.home.summary.activeTimers", "Active Timers")
180
- }), /* @__PURE__ */ _("p", {
180
+ children: w("timecampus.home.summary.activeTimers", "Active Timers")
181
+ }), /* @__PURE__ */ h("p", {
181
182
  className: "mt-1 text-xl font-bold tabular-nums text-text-primary",
182
- children: P?.activeTimers ?? 0
183
- })] }), /* @__PURE__ */ _(g, { className: "h-5 w-5 text-text-secondary" })]
183
+ children: A?.activeTimers ?? 0
184
+ })] }), /* @__PURE__ */ h(m, { className: "h-5 w-5 text-text-secondary" })]
184
185
  })
185
186
  ]
186
187
  })]
187
188
  })]
188
189
  }),
189
- /* @__PURE__ */ v(S, {
190
+ /* @__PURE__ */ g(b, {
190
191
  treatment: "plain",
191
192
  className: "border-border-seam p-6",
192
- children: [/* @__PURE__ */ v("div", {
193
+ children: [/* @__PURE__ */ g("div", {
193
194
  className: "mb-4",
194
- children: [/* @__PURE__ */ _("h3", {
195
+ children: [/* @__PURE__ */ h("h3", {
195
196
  className: "text-sm font-semibold text-text-primary",
196
- children: E("timecampus.home.quickActions.title", "Quick Actions")
197
- }), /* @__PURE__ */ _("p", {
197
+ children: w("timecampus.home.quickActions.title", "Quick Actions")
198
+ }), /* @__PURE__ */ h("p", {
198
199
  className: "text-xs text-text-secondary",
199
- children: E("timecampus.home.quickActions.description", "Frequently used features")
200
+ children: w("timecampus.home.quickActions.description", "Frequently used features")
200
201
  })]
201
- }), /* @__PURE__ */ _("div", {
202
+ }), /* @__PURE__ */ h("div", {
202
203
  className: "grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-6",
203
204
  children: [
204
205
  {
205
- label: E("timecampus.home.quickActions.startTimer.label", "Start Timer"),
206
- icon: p,
207
- description: E("timecampus.home.quickActions.startTimer.description", "Track your time")
208
- },
209
- {
210
- label: E("timecampus.home.quickActions.viewProjects.label", "View Projects"),
206
+ label: w("timecampus.home.quickActions.startTimer.label", "Start Timer"),
211
207
  icon: f,
212
- description: E("timecampus.home.quickActions.viewProjects.description", "Manage projects")
208
+ route: "/time/timer",
209
+ description: w("timecampus.home.quickActions.startTimer.description", "Track your time")
213
210
  },
214
211
  {
215
- label: E("timecampus.home.quickActions.timeEntries.label", "Time Entries"),
212
+ label: w("timecampus.home.quickActions.viewProjects.label", "View Projects"),
216
213
  icon: d,
217
- description: E("timecampus.home.quickActions.timeEntries.description", "View all entries")
214
+ route: "/projects",
215
+ description: w("timecampus.home.quickActions.viewProjects.description", "Manage projects")
218
216
  },
219
217
  {
220
- label: E("timecampus.home.quickActions.teamActivity.label", "Team Activity"),
221
- icon: g,
222
- description: E("timecampus.home.quickActions.teamActivity.description", "See team status")
218
+ label: w("timecampus.home.quickActions.timeEntries.label", "Time Entries"),
219
+ icon: u,
220
+ route: "/time/entries",
221
+ description: w("timecampus.home.quickActions.timeEntries.description", "View all entries")
223
222
  },
224
223
  {
225
- label: E("timecampus.home.quickActions.reports.label", "Reports"),
226
- icon: l,
227
- description: E("timecampus.home.quickActions.reports.description", "Generate reports")
224
+ label: w("timecampus.home.quickActions.teamActivity.label", "Team Activity"),
225
+ icon: m,
226
+ route: "/team-activity",
227
+ description: w("timecampus.home.quickActions.teamActivity.description", "See team status")
228
228
  },
229
229
  {
230
- label: E("timecampus.home.quickActions.approvals.label", "Approvals"),
231
- icon: u,
232
- description: E("timecampus.home.quickActions.approvals.description", "Review timesheets")
230
+ label: w("timecampus.home.quickActions.reports.label", "Reports"),
231
+ icon: c,
232
+ route: "/reports",
233
+ description: w("timecampus.home.quickActions.reports.description", "Generate reports")
234
+ },
235
+ {
236
+ label: w("timecampus.home.quickActions.approvals.label", "Approvals"),
237
+ icon: l,
238
+ route: "/time-approval",
239
+ description: w("timecampus.home.quickActions.approvals.description", "Review timesheets")
233
240
  }
234
- ].map(({ label: e, icon: t, description: n }) => /* @__PURE__ */ v("button", {
241
+ ].map(({ label: e, icon: t, description: n, route: r }) => /* @__PURE__ */ g("button", {
242
+ onClick: () => T(r),
235
243
  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",
236
244
  children: [
237
- /* @__PURE__ */ _("div", {
245
+ /* @__PURE__ */ h("div", {
238
246
  className: "rounded-full bg-action-primary-bg/10 p-3",
239
- children: /* @__PURE__ */ _(t, { className: "h-5 w-5 text-primary" })
247
+ children: /* @__PURE__ */ h(t, { className: "h-5 w-5 text-primary" })
240
248
  }),
241
- /* @__PURE__ */ _("span", {
249
+ /* @__PURE__ */ h("span", {
242
250
  className: "text-sm font-medium text-text-primary",
243
251
  children: e
244
252
  }),
245
- /* @__PURE__ */ _("span", {
253
+ /* @__PURE__ */ h("span", {
246
254
  className: "text-xs text-text-secondary",
247
255
  children: n
248
256
  })
@@ -254,6 +262,6 @@ var T = () => {
254
262
  });
255
263
  };
256
264
  //#endregion
257
- export { T as HomePage };
265
+ export { C as HomePage };
258
266
 
259
267
  //# 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 Timer,\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, formatTimerDuration } from \"../utils/helpers\";\nimport { useTimeCampusStore } from \"../store/timecampusStore\";\nimport {\n useGetTimeEntryStatsQuery,\n useListTimeEntriesQuery,\n type TimeEntryFieldsFragment,\n} from \"@/generated/wspace-operations\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\n\nexport const HomePage: FC = () => {\n const { t: translate } = useI18n();\n const t = (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n };\n const { activeTimer, startTimer, stopTimer } = useTimeCampusStore();\n\n const { data: statsData, loading: statsLoading } =\n useGetTimeEntryStatsQuery();\n const { data: entriesData, loading: entriesLoading } =\n useListTimeEntriesQuery({\n variables: { limit: 4 },\n });\n\n const stats = statsData?.timeEntryStats;\n const recentEntries = entriesData?.timeEntries?.items ?? [];\n\n const timerLabel = activeTimer\n ? `${formatTimerDuration(activeTimer.seconds)} - ${t(\"timecampus.home.actions.stop\", \"Stop\")}`\n : t(\"timecampus.home.actions.startTimer\", \"Start Timer\");\n\n const headerActions = (\n <CTAOverflowMenu\n primary={{\n label: timerLabel,\n onSelect: () => (activeTimer ? stopTimer() : startTimer()),\n icon: activeTimer ? (\n <Timer className=\"h-4 w-4\" />\n ) : (\n <Play className=\"h-4 w-4\" />\n ),\n }}\n actions={[\n {\n label: t(\n \"timecampus.home.quickActions.viewProjects.label\",\n \"View Projects\",\n ),\n onSelect: () => {},\n icon: <FolderOpen className=\"h-4 w-4\" />,\n },\n {\n label: t(\"timecampus.home.quickActions.reports.label\", \"Reports\"),\n onSelect: () => {},\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 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 {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 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 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 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 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 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 description: t(\n \"timecampus.home.quickActions.approvals.description\",\n \"Review timesheets\",\n ),\n },\n ].map(({ label, icon: Icon, description }) => (\n <button\n key={label}\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":";;;;;;;;;;AA8BA,IAAa,UAAqB;CAChC,IAAM,EAAE,GAAG,MAAc,GAAS,EAC5B,KAAK,GAAa,MAA6B;EACnD,IAAM,IAAQ,EAAU,EAAI;AAC5B,SAAO,MAAU,IAAM,IAAW;IAE9B,EAAE,gBAAa,eAAY,iBAAc,GAAoB,EAE7D,EAAE,MAAM,GAAW,SAAS,MAChC,GAA2B,EACvB,EAAE,MAAM,GAAa,SAAS,MAClC,EAAwB,EACtB,WAAW,EAAE,OAAO,GAAG,EACxB,CAAC,EAEE,IAAQ,GAAW,gBACnB,IAAgB,GAAa,aAAa,SAAS,EAAE,EAMrD,IACJ,kBAAC,GAAD;EACE,SAAS;GACP,OAPa,IACf,GAAG,EAAoB,EAAY,QAAQ,CAAC,KAAK,EAAE,gCAAgC,OAAO,KAC1F,EAAE,sCAAsC,cAAc;GAMpD,gBAAiB,IAAc,GAAW,GAAG,GAAY;GACzD,MACE,EADI,IACH,IAEA,GAFD,EAAO,WAAU,WAAY,CAED;GAE/B;EACD,SAAS,CACP;GACE,OAAO,EACL,mDACA,gBACD;GACD,gBAAgB;GAChB,MAAM,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;GACzC,EACD;GACE,OAAO,EAAE,8CAA8C,UAAU;GACjE,gBAAgB;GAChB,MAAM,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;GACxC,CACF;EACD,CAAA,EAGE,UACJ,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,GAAD,EAAkB,WAAU,UAAW,CAAA,EACvC,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,MAAD;KAAI,WAAU;eACZ,kBAAC,GAAD,EAAA,UACG,EAAE,yBAAyB,YAAY,EAC3B,CAAA;KACZ,CAAA,EACL,kBAAC,KAAD;KAAG,WAAU;eACV,EACC,+BACA,kDACD;KACC,CAAA,CACA;OACL,EACG;KACF;;AAYR,QATI,KAAgB,IAEhB,kBAAC,OAAD;EAAK,WAAU;YAAf,CACG,GAAc,EACf,kBAAC,GAAD;GAAiB,SAAQ;GAAO,OAAO;GAAK,CAAA,CACxC;MAKR,kBAAC,OAAD;EAAK,WAAU;YAAf;GACG,GAAc;GAGf,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MACE,UAAA;MACA,OAAO,EAAE,+BAA+B,QAAQ;MAChD,OAAO,EAAY,GAAO,cAAc,EAAE;MAC1C,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;MACnC,OAAO;OACL,OAAO;OACP,OAAO,EAAE,qCAAqC,eAAe;OAC9D;MACD,CAAA;KACF,kBAAC,GAAD;MACE,OAAO,EAAE,kCAAkC,WAAW;MACtD,OAAO,EAAY,GAAO,iBAAiB,EAAE;MAC7C,MAAM,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;MACxC,aAAa,GAAG,GAAO,gBAAgB,EAAE,GAAG,EAAE,iCAAiC,UAAU;MACzF,CAAA;KACF,kBAAC,GAAD;MACE,OAAO,EAAE,sCAAsC,gBAAgB;MAC/D,OAAO,GAAO,gBAAgB;MAC9B,MAAM,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;MACxC,aAAa,EACX,0CACA,oBACD;MACD,CAAA;KACF,kBAAC,GAAD;MACE,OAAO,EAAE,sCAAsC,UAAU;MACzD,OAAO,GAAO,gBAAgB;MAC9B,MAAM,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;MACvC,aAAa,EACX,iDACA,qBACD;MACD,CAAA;KACE;;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf,CAEE,kBAAC,GAAD;KACE,WAAU;KACV,WAAU;eAFZ,CAIE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EACC,uCACA,sBACD;OACE,CAAA,EACL,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,6CACA,iCACD;OACC,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,UAAD;OAAQ,WAAU;iBAAlB;QACG,EAAE,yCAAyC,WAAW;QAAE;QACzD,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;QAC3B;SACL;SACL,IACC,kBAAC,GAAD;MAAiB,SAAQ;MAAO,OAAO;MAAK,CAAA,GAE5C,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACG,EAAc,KAAK,MAClB,kBAAC,OAAD;OAEE,WAAU;iBAFZ,CAIE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,KAAD;SAAG,WAAU;mBACV,EAAM,SAAS,QACd,EACE,2CACA,aACD;SACD,CAAA,EACJ,kBAAC,KAAD;SAAG,WAAU;mBACV,EAAM,eACL,EACE,+CACA,iBACD;SACD,CAAA,CACA;WACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,KAAD;SAAG,WAAU;mBACV,GAAa,EAAM,YAAY,KAAK,KAAK;SACxC,CAAA,EACJ,kBAAC,QAAD;SACE,WAAW,EACT,iFACA,EAAM,YACF,4CACA,gDACL;mBANH,CAQG,EAAM,aACL,kBAAC,QAAD,EAAM,WAAU,kFAAmF,CAAA,EAEpG,EAAM,YACH,EACE,gDACA,UACD,GACD,EACE,kDACA,YACD,CACA;WACH;UACF;SA7CC,EAAM,GA6CP,CACN,EACD,EAAc,WAAW,KACxB,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,uCACA,sBACD;OACC,CAAA,CAEF;QAEE;QAGZ,kBAAC,GAAD;KAAe,WAAU;eAAzB,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAE,iCAAiC,gBAAgB;OACjD,CAAA,EACL,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,uCACA,yBACD;OACC,CAAA,CACA;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;SAAG,WAAU;mBACV,EAAE,sCAAsC,cAAc;SACrD,CAAA,EACJ,kBAAC,KAAD;SAAG,WAAU;mBACV,EAAY,GAAO,cAAc,EAAE;SAClC,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,GAAD,EAAO,WAAU,+BAAgC,CAAA,CAC7C;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;SAAG,WAAU;mBACV,EAAE,yCAAyC,iBAAiB;SAC3D,CAAA,EACJ,kBAAC,KAAD;SAAG,WAAU;mBACV,EAAY,GAAO,iBAAiB,EAAE;SACrC,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,GAAD,EAAY,WAAU,+BAAgC,CAAA,CAClD;;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;SAAG,WAAU;mBACV,EAAE,wCAAwC,gBAAgB;SACzD,CAAA,EACJ,kBAAC,KAAD;SAAG,WAAU;mBACV,GAAO,gBAAgB;SACtB,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,GAAD,EAAO,WAAU,+BAAgC,CAAA,CAC7C;;OACF;QACQ;OACZ;;GAGN,kBAAC,GAAD;IAAW,WAAU;IAAQ,WAAU;cAAvC,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAE,sCAAsC,gBAAgB;MACtD,CAAA,EACL,kBAAC,KAAD;MAAG,WAAU;gBACV,EACC,4CACA,2BACD;MACC,CAAA,CACA;QACN,kBAAC,OAAD;KAAK,WAAU;eACZ;MACC;OACE,OAAO,EACL,iDACA,cACD;OACD,MAAM;OACN,aAAa,EACX,uDACA,kBACD;OACF;MACD;OACE,OAAO,EACL,mDACA,gBACD;OACD,MAAM;OACN,aAAa,EACX,yDACA,kBACD;OACF;MACD;OACE,OAAO,EACL,kDACA,eACD;OACD,MAAM;OACN,aAAa,EACX,wDACA,mBACD;OACF;MACD;OACE,OAAO,EACL,mDACA,gBACD;OACD,MAAM;OACN,aAAa,EACX,yDACA,kBACD;OACF;MACD;OACE,OAAO,EAAE,8CAA8C,UAAU;OACjE,MAAM;OACN,aAAa,EACX,oDACA,mBACD;OACF;MACD;OACE,OAAO,EACL,gDACA,YACD;OACD,MAAM;OACN,aAAa,EACX,sDACA,oBACD;OACF;MACF,CAAC,KAAK,EAAE,UAAO,MAAM,GAAM,qBAC1B,kBAAC,UAAD;MAEE,WAAU;gBAFZ;OAIE,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,GAAD,EAAM,WAAU,wBAAyB,CAAA;QACrC,CAAA;OACN,kBAAC,QAAD;QAAM,WAAU;kBACb;QACI,CAAA;OACP,kBAAC,QAAD;QAAM,WAAU;kBAA+B;QAAmB,CAAA;OAC3D;QAVF,EAUE,CACT;KACE,CAAA,CACI;;GACR"}
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 { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\n\nexport const HomePage: FC = () => {\n const { t: translate } = useI18n();\n const t = (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n };\n const navigate = useTimeCampusNavigate();\n\n const { data: statsData, loading: statsLoading } =\n useGetTimeEntryStatsQuery();\n const { data: entriesData, loading: entriesLoading } =\n useListTimeEntriesQuery({\n variables: { 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,13 +1,14 @@
1
- import { useTimeCampus as e } from "../../providers/TimeCampusProvider.js";
1
+ import { useTimeCampusNavigate as e } from "../../providers/TimeCampusProvider.js";
2
2
  import { LoadingSkeleton as t } from "../../components/LoadingSkeleton.js";
3
3
  import { useListConfigurationsQuery as n } from "../../../generated/wspace-operations.js";
4
4
  import { PageLayout as r } from "../../components/PageLayout.js";
5
5
  import { EmptyState as i } from "../../components/EmptyState.js";
6
- import { Download as a, Puzzle as o, Star as s } from "lucide-react";
6
+ import { TimeCampusConfigScope as a } from "../../../generated/wspace-types.js";
7
+ import { Puzzle as o, Store as s } from "lucide-react";
7
8
  import { jsx as c, jsxs as l } from "react/jsx-runtime";
8
9
  //#region src/timecampus/pages/applets/AppletStorePage.tsx
9
10
  function u() {
10
- let { workspaceId: u = "" } = e(), { data: d, loading: f, error: p } = n({ variables: { scope: "WORKSPACE" } }), m = (d?.configurations ?? []).filter((e) => e.key.startsWith("applet.store."));
11
+ let u = e(), { data: d, loading: f, error: p } = n({ variables: { scope: a.Workspace } }), m = (d?.configurations ?? []).filter((e) => e.key.startsWith("applet.store."));
11
12
  return f ? /* @__PURE__ */ c(r, {
12
13
  title: "Applet Store",
13
14
  description: "Browse and install applets to extend TimeCampus",
@@ -33,11 +34,9 @@ function u() {
33
34
  }) : /* @__PURE__ */ c("div", {
34
35
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
35
36
  children: m.map((e) => {
36
- let t = e.value, n = t.name ?? e.key.replace("applet.store.", ""), r = e.description ?? t.description ?? "";
37
- t.category;
38
- let i = t.rating ?? 0, u = t.downloads ?? 0;
37
+ let t = e.value, n = t.name ?? e.key.replace("applet.store.", ""), r = e.description ?? t.description ?? "", i = t.category ?? "general";
39
38
  return /* @__PURE__ */ l("div", {
40
- className: "rounded-xl border border-border-seam bg-gloss-card shadow-pop p-5 transition-colors hover:bg-bg-sunken/50 cursor-pointer",
39
+ className: "rounded-xl border border-border-seam bg-gloss-card shadow-pop p-5 transition-colors hover:bg-bg-sunken/50",
41
40
  children: [/* @__PURE__ */ l("div", {
42
41
  className: "flex items-start gap-3",
43
42
  children: [/* @__PURE__ */ c("div", {
@@ -55,18 +54,14 @@ function u() {
55
54
  })]
56
55
  }), /* @__PURE__ */ l("div", {
57
56
  className: "mt-3 flex items-center justify-between",
58
- children: [/* @__PURE__ */ l("div", {
59
- className: "flex items-center gap-3 text-xs text-text-secondary",
60
- children: [/* @__PURE__ */ l("div", {
61
- className: "flex items-center gap-1",
62
- children: [/* @__PURE__ */ c(s, { className: "h-3 w-3 fill-amber-400 text-status-warning-text" }), /* @__PURE__ */ c("span", { children: i })]
63
- }), /* @__PURE__ */ l("div", {
64
- className: "flex items-center gap-1",
65
- children: [/* @__PURE__ */ c(a, { className: "h-3 w-3" }), /* @__PURE__ */ c("span", { children: u })]
66
- })]
67
- }), /* @__PURE__ */ c("button", {
68
- className: "rounded-md bg-action-primary-bg px-3 py-1 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90",
69
- children: "Install"
57
+ children: [/* @__PURE__ */ c("span", {
58
+ className: "inline-flex rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary",
59
+ children: i
60
+ }), /* @__PURE__ */ l("button", {
61
+ type: "button",
62
+ onClick: () => u("/store"),
63
+ className: "inline-flex items-center gap-1 rounded-md bg-action-primary-bg px-3 py-1 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90",
64
+ children: [/* @__PURE__ */ c(s, { className: "h-3 w-3" }), "Get it"]
70
65
  })]
71
66
  })]
72
67
  }, e.id);