@burdenoff/microfe-timecampus 2026.624.1 → 2026.626.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.
Files changed (109) hide show
  1. package/dist/timecampus/components/EmptyState.js +14 -0
  2. package/dist/timecampus/components/EmptyState.js.map +1 -0
  3. package/dist/timecampus/components/ErrorBoundary.js +2 -2
  4. package/dist/timecampus/components/ErrorBoundary.js.map +1 -1
  5. package/dist/timecampus/components/LoadingSkeleton.js +1 -1
  6. package/dist/timecampus/components/LoadingSkeleton.js.map +1 -1
  7. package/dist/timecampus/components/PageLayout.js +26 -14
  8. package/dist/timecampus/components/PageLayout.js.map +1 -1
  9. package/dist/timecampus/components/StatCard.js +19 -16
  10. package/dist/timecampus/components/StatCard.js.map +1 -1
  11. package/dist/timecampus/pages/HomePage.js +169 -149
  12. package/dist/timecampus/pages/HomePage.js.map +1 -1
  13. package/dist/timecampus/pages/applets/AppletStorePage.js +38 -35
  14. package/dist/timecampus/pages/applets/AppletStorePage.js.map +1 -1
  15. package/dist/timecampus/pages/applets/InstalledAppletsPage.js +42 -36
  16. package/dist/timecampus/pages/applets/InstalledAppletsPage.js.map +1 -1
  17. package/dist/timecampus/pages/application-usage/ApplicationUsagePage.js +57 -53
  18. package/dist/timecampus/pages/application-usage/ApplicationUsagePage.js.map +1 -1
  19. package/dist/timecampus/pages/application-usage/ApplicationUsageSettingsPage.js +40 -36
  20. package/dist/timecampus/pages/application-usage/ApplicationUsageSettingsPage.js.map +1 -1
  21. package/dist/timecampus/pages/channels/ChannelsPage.js +32 -29
  22. package/dist/timecampus/pages/channels/ChannelsPage.js.map +1 -1
  23. package/dist/timecampus/pages/client-portal/ClientPortalPage.js +52 -44
  24. package/dist/timecampus/pages/client-portal/ClientPortalPage.js.map +1 -1
  25. package/dist/timecampus/pages/dashboard/AnalyticsPage.js +65 -38
  26. package/dist/timecampus/pages/dashboard/AnalyticsPage.js.map +1 -1
  27. package/dist/timecampus/pages/dashboard/ReportsPage.js +47 -41
  28. package/dist/timecampus/pages/dashboard/ReportsPage.js.map +1 -1
  29. package/dist/timecampus/pages/email-tracking/EmailAnalyticsPage.js +16 -14
  30. package/dist/timecampus/pages/email-tracking/EmailAnalyticsPage.js.map +1 -1
  31. package/dist/timecampus/pages/email-tracking/EmailSettingsPage.js +40 -36
  32. package/dist/timecampus/pages/email-tracking/EmailSettingsPage.js.map +1 -1
  33. package/dist/timecampus/pages/email-tracking/EmailTrackingPage.js +34 -28
  34. package/dist/timecampus/pages/email-tracking/EmailTrackingPage.js.map +1 -1
  35. package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js +49 -41
  36. package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js.map +1 -1
  37. package/dist/timecampus/pages/focus-score/FocusScorePage.js +66 -62
  38. package/dist/timecampus/pages/focus-score/FocusScorePage.js.map +1 -1
  39. package/dist/timecampus/pages/focus-score/FocusScoreSettingsPage.js +37 -33
  40. package/dist/timecampus/pages/focus-score/FocusScoreSettingsPage.js.map +1 -1
  41. package/dist/timecampus/pages/geofencing/GeofencingPage.js +37 -30
  42. package/dist/timecampus/pages/geofencing/GeofencingPage.js.map +1 -1
  43. package/dist/timecampus/pages/geofencing/GeofencingSettingsPage.js +35 -31
  44. package/dist/timecampus/pages/geofencing/GeofencingSettingsPage.js.map +1 -1
  45. package/dist/timecampus/pages/industry-solutions/IndustrySolutionsPage.js +37 -34
  46. package/dist/timecampus/pages/industry-solutions/IndustrySolutionsPage.js.map +1 -1
  47. package/dist/timecampus/pages/location-tracking/LocationPrivacySettingsPage.js +35 -31
  48. package/dist/timecampus/pages/location-tracking/LocationPrivacySettingsPage.js.map +1 -1
  49. package/dist/timecampus/pages/location-tracking/LocationTrackingPage.js +45 -41
  50. package/dist/timecampus/pages/location-tracking/LocationTrackingPage.js.map +1 -1
  51. package/dist/timecampus/pages/meetings/MeetingAnalyticsPage.js +17 -15
  52. package/dist/timecampus/pages/meetings/MeetingAnalyticsPage.js.map +1 -1
  53. package/dist/timecampus/pages/meetings/MeetingCreatePage.js +36 -32
  54. package/dist/timecampus/pages/meetings/MeetingCreatePage.js.map +1 -1
  55. package/dist/timecampus/pages/meetings/MeetingDetailPage.js +120 -102
  56. package/dist/timecampus/pages/meetings/MeetingDetailPage.js.map +1 -1
  57. package/dist/timecampus/pages/meetings/MeetingsPage.js +46 -36
  58. package/dist/timecampus/pages/meetings/MeetingsPage.js.map +1 -1
  59. package/dist/timecampus/pages/pomodoro/PomodoroAnalyticsPage.js +19 -17
  60. package/dist/timecampus/pages/pomodoro/PomodoroAnalyticsPage.js.map +1 -1
  61. package/dist/timecampus/pages/pomodoro/PomodoroPage.js +143 -112
  62. package/dist/timecampus/pages/pomodoro/PomodoroPage.js.map +1 -1
  63. package/dist/timecampus/pages/pomodoro/PomodoroSettingsPage.js +55 -51
  64. package/dist/timecampus/pages/pomodoro/PomodoroSettingsPage.js.map +1 -1
  65. package/dist/timecampus/pages/projects/ProjectCreatePage.js +32 -28
  66. package/dist/timecampus/pages/projects/ProjectCreatePage.js.map +1 -1
  67. package/dist/timecampus/pages/projects/ProjectDetailPage.js +107 -76
  68. package/dist/timecampus/pages/projects/ProjectDetailPage.js.map +1 -1
  69. package/dist/timecampus/pages/projects/ProjectsPage.js +21 -17
  70. package/dist/timecampus/pages/projects/ProjectsPage.js.map +1 -1
  71. package/dist/timecampus/pages/projects/TasksPage.js +44 -34
  72. package/dist/timecampus/pages/projects/TasksPage.js.map +1 -1
  73. package/dist/timecampus/pages/resource-planning/ResourcePlanningPage.js +59 -55
  74. package/dist/timecampus/pages/resource-planning/ResourcePlanningPage.js.map +1 -1
  75. package/dist/timecampus/pages/team/TeamAnalyticsPage.js +24 -20
  76. package/dist/timecampus/pages/team/TeamAnalyticsPage.js.map +1 -1
  77. package/dist/timecampus/pages/team/TeamMembersPage.js +47 -41
  78. package/dist/timecampus/pages/team/TeamMembersPage.js.map +1 -1
  79. package/dist/timecampus/pages/team/TeamPage.js +89 -59
  80. package/dist/timecampus/pages/team/TeamPage.js.map +1 -1
  81. package/dist/timecampus/pages/team-activity/TeamActivityPage.js +47 -43
  82. package/dist/timecampus/pages/team-activity/TeamActivityPage.js.map +1 -1
  83. package/dist/timecampus/pages/team-activity/TeamActivitySettingsPage.js +39 -35
  84. package/dist/timecampus/pages/team-activity/TeamActivitySettingsPage.js.map +1 -1
  85. package/dist/timecampus/pages/templates/TemplateApplicationPage.js +24 -20
  86. package/dist/timecampus/pages/templates/TemplateApplicationPage.js.map +1 -1
  87. package/dist/timecampus/pages/templates/TemplateDetailPage.js +66 -48
  88. package/dist/timecampus/pages/templates/TemplateDetailPage.js.map +1 -1
  89. package/dist/timecampus/pages/templates/TemplatesPage.js +39 -36
  90. package/dist/timecampus/pages/templates/TemplatesPage.js.map +1 -1
  91. package/dist/timecampus/pages/time/TimeEntriesPage.js +53 -44
  92. package/dist/timecampus/pages/time/TimeEntriesPage.js.map +1 -1
  93. package/dist/timecampus/pages/time/TimeTrackingPage.js +72 -71
  94. package/dist/timecampus/pages/time/TimeTrackingPage.js.map +1 -1
  95. package/dist/timecampus/pages/time/TimerPage.js +100 -66
  96. package/dist/timecampus/pages/time/TimerPage.js.map +1 -1
  97. package/dist/timecampus/pages/time-approval/TimeApprovalPage.js +63 -59
  98. package/dist/timecampus/pages/time-approval/TimeApprovalPage.js.map +1 -1
  99. package/dist/timecampus/pages/widgets/WidgetDetailPage.js +64 -46
  100. package/dist/timecampus/pages/widgets/WidgetDetailPage.js.map +1 -1
  101. package/dist/timecampus/pages/widgets/WidgetsPage.js +44 -37
  102. package/dist/timecampus/pages/widgets/WidgetsPage.js.map +1 -1
  103. package/dist/timecampus/pages/work-patterns/WorkPatternsPage.js +18 -16
  104. package/dist/timecampus/pages/work-patterns/WorkPatternsPage.js.map +1 -1
  105. package/dist/timecampus/pages/work-patterns/WorkPatternsSettingsPage.js +40 -36
  106. package/dist/timecampus/pages/work-patterns/WorkPatternsSettingsPage.js.map +1 -1
  107. package/dist/timecampus/pages/workflows/WorkflowsPage.js +47 -37
  108. package/dist/timecampus/pages/workflows/WorkflowsPage.js.map +1 -1
  109. package/package.json +2 -2
@@ -1,88 +1,94 @@
1
1
  import { useTimeCampus as e } from "../../providers/TimeCampusProvider.js";
2
2
  import { formatHours as t } from "../../utils/helpers.js";
3
- import { PageLayout as n } from "../../components/PageLayout.js";
4
- import { LoadingSkeleton as r } from "../../components/LoadingSkeleton.js";
5
- import { useListTimeEntriesQuery as i } from "../../../generated/wspace-operations.js";
6
- import { Plus as a, Users as o } from "lucide-react";
7
- import { jsx as s, jsxs as c } from "react/jsx-runtime";
3
+ import { LoadingSkeleton as n } from "../../components/LoadingSkeleton.js";
4
+ import { useListTimeEntriesQuery as r } from "../../../generated/wspace-operations.js";
5
+ import { PageLayout as i } from "../../components/PageLayout.js";
6
+ import { EmptyState as a } from "../../components/EmptyState.js";
7
+ import { Plus as o, Users as s } from "lucide-react";
8
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
9
+ import { GlassCard as u } from "@burdenoff/fe-libs/ui";
8
10
  //#region src/timecampus/pages/team/TeamMembersPage.tsx
9
- function l() {
10
- let { workspaceId: l = "" } = e(), { data: u, loading: d, error: f } = i({
11
+ function d() {
12
+ let { workspaceId: d = "" } = e(), { data: f, loading: p, error: m } = r({
11
13
  variables: { limit: 100 },
12
- skip: !l
13
- }), p = (u?.timeEntries?.items ?? []).reduce((e, t) => {
14
+ skip: !d
15
+ }), h = (f?.timeEntries?.items ?? []).reduce((e, t) => {
14
16
  let n = t.project?.name ?? "Unassigned", r = t.projectId ?? "unassigned";
15
17
  return e[r] || (e[r] = {
16
18
  name: n,
17
19
  totalHours: 0,
18
20
  entries: 0
19
21
  }), e[r].totalHours += (t.duration ?? 0) / 3600, e[r].entries += 1, e;
20
- }, {}), m = Object.entries(p).map(([e, t]) => ({
22
+ }, {}), g = Object.entries(h).map(([e, t]) => ({
21
23
  id: e,
22
24
  ...t
23
25
  })).sort((e, t) => t.totalHours - e.totalHours);
24
- return d ? /* @__PURE__ */ s(n, {
26
+ return p ? /* @__PURE__ */ c(i, {
25
27
  title: "Team Members",
26
28
  description: "Manage team members and roles",
27
- actions: /* @__PURE__ */ c("button", {
29
+ actions: /* @__PURE__ */ l("button", {
28
30
  className: "inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
29
- children: [/* @__PURE__ */ s(a, { className: "h-4 w-4" }), "Invite Member"]
31
+ children: [/* @__PURE__ */ c(o, { className: "h-4 w-4" }), "Invite Member"]
30
32
  }),
31
- children: /* @__PURE__ */ s(r, {
33
+ children: /* @__PURE__ */ c(n, {
32
34
  variant: "list",
33
35
  count: 5
34
36
  })
35
- }) : f ? /* @__PURE__ */ s(n, {
37
+ }) : m ? /* @__PURE__ */ c(i, {
36
38
  title: "Team Members",
37
39
  description: "Manage team members and roles",
38
- children: /* @__PURE__ */ s("div", {
39
- className: "rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-600 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400",
40
+ children: /* @__PURE__ */ c("div", {
41
+ className: "rounded-lg border border-status-error-bg/40 bg-status-error-bg p-4 text-sm text-status-error-text",
40
42
  children: "Failed to load team data. Please try again later."
41
43
  })
42
- }) : /* @__PURE__ */ c(n, {
44
+ }) : /* @__PURE__ */ l(i, {
43
45
  title: "Team Members",
44
46
  description: "Manage team members and roles",
45
- actions: /* @__PURE__ */ c("button", {
47
+ purpose: "Understand how effort is distributed across your team and projects — use it to spot who's overloaded, where time is concentrated, and when to invite or reassign people.",
48
+ actions: /* @__PURE__ */ l("button", {
46
49
  className: "inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
47
- children: [/* @__PURE__ */ s(a, { className: "h-4 w-4" }), "Invite Member"]
50
+ children: [/* @__PURE__ */ c(o, { className: "h-4 w-4" }), "Invite Member"]
48
51
  }),
49
- children: [/* @__PURE__ */ s("div", {
50
- className: "mb-4 rounded-lg border border-amber-200 bg-amber-50 p-3 text-xs text-amber-700 dark:border-amber-800 dark:bg-amber-900/20 dark:text-amber-400",
52
+ children: [/* @__PURE__ */ c("div", {
53
+ className: "mb-4 rounded-lg border border-status-warning-bg/40 bg-status-warning-bg p-3 text-xs text-status-warning-text",
51
54
  children: "Team member data is managed by the groups module. Showing time entry activity by project."
52
- }), /* @__PURE__ */ s("div", {
53
- className: "rounded-xl border border-border-subtle bg-bg-surface",
54
- children: /* @__PURE__ */ s("div", {
55
+ }), g.length === 0 ? /* @__PURE__ */ c(a, {
56
+ illustration: "empty-people",
57
+ title: "No time entry data available",
58
+ description: "Once your team starts tracking time, their activity by project shows up here."
59
+ }) : /* @__PURE__ */ c(u, {
60
+ treatment: "glass",
61
+ glow: !0,
62
+ className: "overflow-hidden",
63
+ children: /* @__PURE__ */ c("div", {
55
64
  className: "divide-y divide-border",
56
- children: m.length === 0 ? /* @__PURE__ */ s("div", {
57
- className: "p-8 text-center text-sm text-text-secondary",
58
- children: "No time entry data available."
59
- }) : m.map((e) => /* @__PURE__ */ c("div", {
65
+ children: g.map((e) => /* @__PURE__ */ l("div", {
60
66
  className: "flex items-center justify-between p-4 hover:bg-bg-sunken/50 transition-colors",
61
- children: [/* @__PURE__ */ c("div", {
67
+ children: [/* @__PURE__ */ l("div", {
62
68
  className: "flex items-center gap-3",
63
- children: [/* @__PURE__ */ s("div", {
69
+ children: [/* @__PURE__ */ c("div", {
64
70
  className: "flex h-9 w-9 items-center justify-center rounded-full bg-action-primary-bg/10 text-sm font-medium text-primary",
65
- children: /* @__PURE__ */ s(o, { className: "h-4 w-4" })
66
- }), /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("p", {
71
+ children: /* @__PURE__ */ c(s, { className: "h-4 w-4" })
72
+ }), /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("p", {
67
73
  className: "text-sm font-medium text-text-primary",
68
74
  children: e.name
69
- }), /* @__PURE__ */ c("p", {
75
+ }), /* @__PURE__ */ l("p", {
70
76
  className: "text-xs text-text-secondary",
71
77
  children: [e.entries, " time entries"]
72
78
  })] })]
73
- }), /* @__PURE__ */ c("div", {
79
+ }), /* @__PURE__ */ l("div", {
74
80
  className: "flex items-center gap-4",
75
- children: [/* @__PURE__ */ c("div", {
81
+ children: [/* @__PURE__ */ l("div", {
76
82
  className: "text-right",
77
- children: [/* @__PURE__ */ s("p", {
83
+ children: [/* @__PURE__ */ c("p", {
78
84
  className: "text-sm font-medium text-text-primary",
79
85
  children: t(e.totalHours)
80
- }), /* @__PURE__ */ s("p", {
86
+ }), /* @__PURE__ */ c("p", {
81
87
  className: "text-xs text-text-secondary",
82
88
  children: "total tracked"
83
89
  })]
84
- }), /* @__PURE__ */ s("span", {
85
- className: "inline-flex rounded-full bg-emerald-100 px-2 py-0.5 text-xs font-medium text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-400",
90
+ }), /* @__PURE__ */ c("span", {
91
+ className: "inline-flex rounded-full bg-status-success-bg px-2 py-0.5 text-xs font-medium text-status-success-text",
86
92
  children: "active"
87
93
  })]
88
94
  })]
@@ -92,6 +98,6 @@ function l() {
92
98
  });
93
99
  }
94
100
  //#endregion
95
- export { l as TeamMembersPage };
101
+ export { d as TeamMembersPage };
96
102
 
97
103
  //# sourceMappingURL=TeamMembersPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TeamMembersPage.js","names":[],"sources":["../../../../src/timecampus/pages/team/TeamMembersPage.tsx"],"sourcesContent":["import { Users, Plus } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { formatHours } from \"../../utils/helpers\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListTimeEntriesQuery,\n type TimeEntryFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function TeamMembersPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const { data, loading, error } = useListTimeEntriesQuery({\n variables: { limit: 100 },\n skip: !workspaceId,\n });\n\n const entries = data?.timeEntries?.items ?? [];\n\n // Group time entries by project to show team activity (member data comes from groups module)\n const projectSummary = entries.reduce<\n Record<string, { name: string; totalHours: number; entries: number }>\n >(\n (\n acc: Record<\n string,\n { name: string; totalHours: number; entries: number }\n >,\n entry: TimeEntryFieldsFragment,\n ) => {\n const projectName = entry.project?.name ?? \"Unassigned\";\n const projectId = entry.projectId ?? \"unassigned\";\n if (!acc[projectId]) {\n acc[projectId] = { name: projectName, totalHours: 0, entries: 0 };\n }\n acc[projectId].totalHours += (entry.duration ?? 0) / 3600;\n acc[projectId].entries += 1;\n return acc;\n },\n {},\n );\n\n const summaryList = Object.entries(projectSummary)\n .map(([id, info]) => ({\n id,\n ...(info as { name: string; totalHours: number; entries: number }),\n }))\n .sort((a, b) => b.totalHours - a.totalHours);\n\n if (loading) {\n return (\n <PageLayout\n title=\"Team Members\"\n description=\"Manage team members and roles\"\n actions={\n <button className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\">\n <Plus className=\"h-4 w-4\" />\n Invite Member\n </button>\n }\n >\n <LoadingSkeleton variant=\"list\" count={5} />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title=\"Team Members\"\n description=\"Manage team members and roles\"\n >\n <div className=\"rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-600 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400\">\n Failed to load team data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Team Members\"\n description=\"Manage team members and roles\"\n actions={\n <button className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\">\n <Plus className=\"h-4 w-4\" />\n Invite Member\n </button>\n }\n >\n <div className=\"mb-4 rounded-lg border border-amber-200 bg-amber-50 p-3 text-xs text-amber-700 dark:border-amber-800 dark:bg-amber-900/20 dark:text-amber-400\">\n Team member data is managed by the groups module. Showing time entry\n activity by project.\n </div>\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface\">\n <div className=\"divide-y divide-border\">\n {summaryList.length === 0 ? (\n <div className=\"p-8 text-center text-sm text-text-secondary\">\n No time entry data available.\n </div>\n ) : (\n summaryList.map((project) => (\n <div\n key={project.id}\n className=\"flex items-center justify-between p-4 hover:bg-bg-sunken/50 transition-colors\"\n >\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-full bg-action-primary-bg/10 text-sm font-medium text-primary\">\n <Users className=\"h-4 w-4\" />\n </div>\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {project.name}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {project.entries} time entries\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-4\">\n <div className=\"text-right\">\n <p className=\"text-sm font-medium text-text-primary\">\n {formatHours(project.totalHours)}\n </p>\n <p className=\"text-xs text-text-secondary\">\n total tracked\n </p>\n </div>\n <span className=\"inline-flex rounded-full bg-emerald-100 px-2 py-0.5 text-xs font-medium text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-400\">\n active\n </span>\n </div>\n </div>\n ))\n )}\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;AAUA,SAAgB,IAAkB;CAChC,IAAM,EAAE,iBAAc,OAAO,GAAe,EAEtC,EAAE,SAAM,YAAS,aAAU,EAAwB;EACvD,WAAW,EAAE,OAAO,KAAK;EACzB,MAAM,CAAC;EACR,CAAC,EAKI,KAHU,GAAM,aAAa,SAAS,EAAE,EAGf,QAI3B,GAIA,MACG;EACH,IAAM,IAAc,EAAM,SAAS,QAAQ,cACrC,IAAY,EAAM,aAAa;AAMrC,SALK,EAAI,OACP,EAAI,KAAa;GAAE,MAAM;GAAa,YAAY;GAAG,SAAS;GAAG,GAEnE,EAAI,GAAW,eAAe,EAAM,YAAY,KAAK,MACrD,EAAI,GAAW,WAAW,GACnB;IAET,EAAE,CACH,EAEK,IAAc,OAAO,QAAQ,EAAe,CAC/C,KAAK,CAAC,GAAI,QAAW;EACpB;EACA,GAAI;EACL,EAAE,CACF,MAAM,GAAG,MAAM,EAAE,aAAa,EAAE,WAAW;AAgC9C,QA9BI,IAEA,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SACE,kBAAC,UAAD;GAAQ,WAAU;aAAlB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,gBAErB;;YAGX,kBAAC,GAAD;GAAiB,SAAQ;GAAO,OAAO;GAAK,CAAA;EACjC,CAAA,GAIb,IAEA,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,OAAD;GAAK,WAAU;aAA+H;GAExI,CAAA;EACK,CAAA,GAKf,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SACE,kBAAC,UAAD;GAAQ,WAAU;aAAlB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,gBAErB;;YAPb,CAUE,kBAAC,OAAD;GAAK,WAAU;aAAgJ;GAGzJ,CAAA,EACN,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAY,WAAW,IACtB,kBAAC,OAAD;KAAK,WAAU;eAA8C;KAEvD,CAAA,GAEN,EAAY,KAAK,MACf,kBAAC,OAAD;KAEE,WAAU;eAFZ,CAIE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;OACzB,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAQ;OACP,CAAA,EACJ,kBAAC,KAAD;OAAG,WAAU;iBAAb,CACG,EAAQ,SAAQ,gBACf;SACA,EAAA,CAAA,CACF;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAY,EAAQ,WAAW;QAC9B,CAAA,EACJ,kBAAC,KAAD;QAAG,WAAU;kBAA8B;QAEvC,CAAA,CACA;UACN,kBAAC,QAAD;OAAM,WAAU;iBAAwI;OAEjJ,CAAA,CACH;QACF;OA7BC,EAAQ,GA6BT,CACN;IAEA,CAAA;GACF,CAAA,CACK"}
1
+ {"version":3,"file":"TeamMembersPage.js","names":[],"sources":["../../../../src/timecampus/pages/team/TeamMembersPage.tsx"],"sourcesContent":["import { Users, Plus } from \"lucide-react\";\nimport { GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { EmptyState } from \"../../components/EmptyState\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { formatHours } from \"../../utils/helpers\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListTimeEntriesQuery,\n type TimeEntryFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function TeamMembersPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const { data, loading, error } = useListTimeEntriesQuery({\n variables: { limit: 100 },\n skip: !workspaceId,\n });\n\n const entries = data?.timeEntries?.items ?? [];\n\n // Group time entries by project to show team activity (member data comes from groups module)\n const projectSummary = entries.reduce<\n Record<string, { name: string; totalHours: number; entries: number }>\n >(\n (\n acc: Record<\n string,\n { name: string; totalHours: number; entries: number }\n >,\n entry: TimeEntryFieldsFragment,\n ) => {\n const projectName = entry.project?.name ?? \"Unassigned\";\n const projectId = entry.projectId ?? \"unassigned\";\n if (!acc[projectId]) {\n acc[projectId] = { name: projectName, totalHours: 0, entries: 0 };\n }\n acc[projectId].totalHours += (entry.duration ?? 0) / 3600;\n acc[projectId].entries += 1;\n return acc;\n },\n {},\n );\n\n const summaryList = Object.entries(projectSummary)\n .map(([id, info]) => ({\n id,\n ...(info as { name: string; totalHours: number; entries: number }),\n }))\n .sort((a, b) => b.totalHours - a.totalHours);\n\n if (loading) {\n return (\n <PageLayout\n title=\"Team Members\"\n description=\"Manage team members and roles\"\n actions={\n <button className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\">\n <Plus className=\"h-4 w-4\" />\n Invite Member\n </button>\n }\n >\n <LoadingSkeleton variant=\"list\" count={5} />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title=\"Team Members\"\n description=\"Manage team members and roles\"\n >\n <div className=\"rounded-lg border border-status-error-bg/40 bg-status-error-bg p-4 text-sm text-status-error-text\">\n Failed to load team data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Team Members\"\n description=\"Manage team members and roles\"\n purpose=\"Understand how effort is distributed across your team and projects — use it to spot who's overloaded, where time is concentrated, and when to invite or reassign people.\"\n actions={\n <button className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\">\n <Plus className=\"h-4 w-4\" />\n Invite Member\n </button>\n }\n >\n <div className=\"mb-4 rounded-lg border border-status-warning-bg/40 bg-status-warning-bg p-3 text-xs text-status-warning-text\">\n Team member data is managed by the groups module. Showing time entry\n activity by project.\n </div>\n {summaryList.length === 0 ? (\n <EmptyState\n illustration=\"empty-people\"\n title=\"No time entry data available\"\n description=\"Once your team starts tracking time, their activity by project shows up here.\"\n />\n ) : (\n <GlassCard treatment=\"glass\" glow className=\"overflow-hidden\">\n <div className=\"divide-y divide-border\">\n {summaryList.map((project) => (\n <div\n key={project.id}\n className=\"flex items-center justify-between p-4 hover:bg-bg-sunken/50 transition-colors\"\n >\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-full bg-action-primary-bg/10 text-sm font-medium text-primary\">\n <Users className=\"h-4 w-4\" />\n </div>\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {project.name}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {project.entries} time entries\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-4\">\n <div className=\"text-right\">\n <p className=\"text-sm font-medium text-text-primary\">\n {formatHours(project.totalHours)}\n </p>\n <p className=\"text-xs text-text-secondary\">total tracked</p>\n </div>\n <span className=\"inline-flex rounded-full bg-status-success-bg px-2 py-0.5 text-xs font-medium text-status-success-text\">\n active\n </span>\n </div>\n </div>\n ))}\n </div>\n </GlassCard>\n )}\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;AAYA,SAAgB,IAAkB;CAChC,IAAM,EAAE,iBAAc,OAAO,GAAe,EAEtC,EAAE,SAAM,YAAS,aAAU,EAAwB;EACvD,WAAW,EAAE,OAAO,KAAK;EACzB,MAAM,CAAC;EACR,CAAC,EAKI,KAHU,GAAM,aAAa,SAAS,EAAE,EAGf,QAI3B,GAIA,MACG;EACH,IAAM,IAAc,EAAM,SAAS,QAAQ,cACrC,IAAY,EAAM,aAAa;AAMrC,SALK,EAAI,OACP,EAAI,KAAa;GAAE,MAAM;GAAa,YAAY;GAAG,SAAS;GAAG,GAEnE,EAAI,GAAW,eAAe,EAAM,YAAY,KAAK,MACrD,EAAI,GAAW,WAAW,GACnB;IAET,EAAE,CACH,EAEK,IAAc,OAAO,QAAQ,EAAe,CAC/C,KAAK,CAAC,GAAI,QAAW;EACpB;EACA,GAAI;EACL,EAAE,CACF,MAAM,GAAG,MAAM,EAAE,aAAa,EAAE,WAAW;AAgC9C,QA9BI,IAEA,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SACE,kBAAC,UAAD;GAAQ,WAAU;aAAlB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,gBAErB;;YAGX,kBAAC,GAAD;GAAiB,SAAQ;GAAO,OAAO;GAAK,CAAA;EACjC,CAAA,GAIb,IAEA,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,OAAD;GAAK,WAAU;aAAoG;GAE7G,CAAA;EACK,CAAA,GAKf,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SAAQ;EACR,SACE,kBAAC,UAAD;GAAQ,WAAU;aAAlB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,gBAErB;;YARb,CAWE,kBAAC,OAAD;GAAK,WAAU;aAA+G;GAGxH,CAAA,EACL,EAAY,WAAW,IACtB,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,aAAY;GACZ,CAAA,GAEF,kBAAC,GAAD;GAAW,WAAU;GAAQ,MAAA;GAAK,WAAU;aAC1C,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAY,KAAK,MAChB,kBAAC,OAAD;KAEE,WAAU;eAFZ,CAIE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;OACzB,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAQ;OACP,CAAA,EACJ,kBAAC,KAAD;OAAG,WAAU;iBAAb,CACG,EAAQ,SAAQ,gBACf;SACA,EAAA,CAAA,CACF;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAY,EAAQ,WAAW;QAC9B,CAAA,EACJ,kBAAC,KAAD;QAAG,WAAU;kBAA8B;QAAiB,CAAA,CACxD;UACN,kBAAC,QAAD;OAAM,WAAU;iBAAyG;OAElH,CAAA,CACH;QACF;OA3BC,EAAQ,GA2BT,CACN;IACE,CAAA;GACI,CAAA,CAEH"}
@@ -1,82 +1,112 @@
1
- import { useTimeCampus as e } from "../../providers/TimeCampusProvider.js";
2
- import { PageLayout as t } from "../../components/PageLayout.js";
1
+ import { useTimeCampus as e, useTimeCampusNavigate as t } from "../../providers/TimeCampusProvider.js";
3
2
  import { StatCard as n } from "../../components/StatCard.js";
4
3
  import { LoadingSkeleton as r } from "../../components/LoadingSkeleton.js";
5
4
  import { useGetTimeEntryStatsQuery as i } from "../../../generated/wspace-operations.js";
6
- import { Clock as a, TrendingUp as o, Users as s } from "lucide-react";
7
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
5
+ import { PageLayout as a } from "../../components/PageLayout.js";
6
+ import { Clock as o, TrendingUp as s, Users as c } from "lucide-react";
7
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
8
+ import { NextSteps as d } from "@burdenoff/fe-libs/ui";
8
9
  //#region src/timecampus/pages/team/TeamPage.tsx
9
- function u() {
10
- let { workspaceId: u = "" } = e(), { data: d, loading: f, error: p } = i({ skip: !u }), m = d?.timeEntryStats;
11
- if (f) return /* @__PURE__ */ c(t, {
10
+ function f() {
11
+ let { workspaceId: f = "" } = e(), p = t(), { data: m, loading: h, error: g } = i({ skip: !f }), _ = m?.timeEntryStats;
12
+ if (h) return /* @__PURE__ */ l(a, {
12
13
  title: "Team Overview",
13
14
  description: "Monitor team performance and activity",
14
- children: /* @__PURE__ */ c(r, {
15
+ children: /* @__PURE__ */ l(r, {
15
16
  variant: "card",
16
17
  count: 4
17
18
  })
18
19
  });
19
- if (p) return /* @__PURE__ */ c(t, {
20
+ if (g) return /* @__PURE__ */ l(a, {
20
21
  title: "Team Overview",
21
22
  description: "Monitor team performance and activity",
22
- children: /* @__PURE__ */ c("div", {
23
- className: "rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-600 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400",
23
+ children: /* @__PURE__ */ l("div", {
24
+ className: "rounded-lg border border-status-error-bg/40 bg-status-error-bg p-4 text-sm text-status-error-text",
24
25
  children: "Failed to load team data. Please try again later."
25
26
  })
26
27
  });
27
- let h = Math.floor(m?.totalHours ?? 0), g = Math.round(((m?.totalHours ?? 0) - h) * 60), _ = m?.totalHours ? Math.round((m.billableHours ?? 0) / m.totalHours * 100) : 0;
28
- return /* @__PURE__ */ l(t, {
28
+ let v = Math.floor(_?.totalHours ?? 0), y = Math.round(((_?.totalHours ?? 0) - v) * 60), b = _?.totalHours ? Math.round((_.billableHours ?? 0) / _.totalHours * 100) : 0;
29
+ return /* @__PURE__ */ u(a, {
29
30
  title: "Team Overview",
30
31
  description: "Monitor team performance and activity",
31
- children: [/* @__PURE__ */ l("div", {
32
- className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4",
33
- children: [
34
- /* @__PURE__ */ c(n, {
35
- title: "Total Entries",
36
- value: String(m?.totalEntries ?? 0),
37
- icon: /* @__PURE__ */ c(s, { className: "h-5 w-5" })
38
- }),
39
- /* @__PURE__ */ c(n, {
40
- title: "Active Timers",
41
- value: String(m?.activeTimers ?? 0),
42
- icon: /* @__PURE__ */ c(s, { className: "h-5 w-5" }),
43
- iconBgColor: "bg-emerald-100 text-emerald-600 dark:bg-emerald-900/30 dark:text-emerald-400"
44
- }),
45
- /* @__PURE__ */ c(n, {
46
- title: "Total Hours",
47
- value: `${h}h ${g}m`,
48
- icon: /* @__PURE__ */ c(a, { className: "h-5 w-5" }),
49
- trend: {
50
- value: m?.billableHours ?? 0,
51
- label: "billable hours"
32
+ purpose: "See how your whole team is spending its time at a glance — who's active, how many hours are billable, and where capacity is going — so you can balance workload and catch problems early.",
33
+ children: [
34
+ /* @__PURE__ */ l(d, {
35
+ storageKey: "timecampus-team",
36
+ className: "mb-6",
37
+ steps: [
38
+ {
39
+ id: "members",
40
+ label: "Manage team members",
41
+ description: "Add people and check individual workloads.",
42
+ onClick: () => p("/team/members")
43
+ },
44
+ {
45
+ id: "analytics",
46
+ label: "Open team analytics",
47
+ description: "Compare utilisation and trends across the team.",
48
+ onClick: () => p("/team/analytics")
49
+ },
50
+ {
51
+ id: "activity",
52
+ label: "Watch live team activity",
53
+ description: "See what people are working on right now.",
54
+ onClick: () => p("/team-activity")
52
55
  }
53
- }),
54
- /* @__PURE__ */ c(n, {
55
- title: "Billable Rate",
56
- value: `${_}%`,
57
- icon: /* @__PURE__ */ c(o, { className: "h-5 w-5" }),
58
- trend: {
59
- value: _,
60
- label: "of total hours"
61
- }
62
- })
63
- ]
64
- }), /* @__PURE__ */ l("div", {
65
- className: "rounded-xl border border-border-subtle bg-bg-surface p-6",
66
- children: [/* @__PURE__ */ c("h3", {
67
- className: "mb-4 text-sm font-semibold text-text-primary",
68
- children: "Team Activity Feed"
69
- }), /* @__PURE__ */ c("div", {
70
- className: "flex h-48 items-center justify-center rounded-lg border border-dashed border-border-subtle",
71
- children: /* @__PURE__ */ c("p", {
72
- className: "text-sm text-text-secondary",
73
- children: "Team activity timeline will render here"
74
- })
75
- })]
76
- })]
56
+ ]
57
+ }),
58
+ /* @__PURE__ */ u("div", {
59
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4",
60
+ children: [
61
+ /* @__PURE__ */ l(n, {
62
+ featured: !0,
63
+ title: "Total Entries",
64
+ value: String(_?.totalEntries ?? 0),
65
+ icon: /* @__PURE__ */ l(c, { className: "h-5 w-5" })
66
+ }),
67
+ /* @__PURE__ */ l(n, {
68
+ title: "Active Timers",
69
+ value: String(_?.activeTimers ?? 0),
70
+ icon: /* @__PURE__ */ l(c, { className: "h-5 w-5" }),
71
+ iconBgColor: "bg-status-success-bg text-status-success-text"
72
+ }),
73
+ /* @__PURE__ */ l(n, {
74
+ title: "Total Hours",
75
+ value: `${v}h ${y}m`,
76
+ icon: /* @__PURE__ */ l(o, { className: "h-5 w-5" }),
77
+ trend: {
78
+ value: _?.billableHours ?? 0,
79
+ label: "billable hours"
80
+ }
81
+ }),
82
+ /* @__PURE__ */ l(n, {
83
+ title: "Billable Rate",
84
+ value: `${b}%`,
85
+ icon: /* @__PURE__ */ l(s, { className: "h-5 w-5" }),
86
+ trend: {
87
+ value: b,
88
+ label: "of total hours"
89
+ }
90
+ })
91
+ ]
92
+ }),
93
+ /* @__PURE__ */ u("div", {
94
+ className: "rounded-xl border border-border-seam bg-gloss-card shadow-pop p-6",
95
+ children: [/* @__PURE__ */ l("h3", {
96
+ className: "mb-4 text-sm font-semibold text-text-primary",
97
+ children: "Team Activity Feed"
98
+ }), /* @__PURE__ */ l("div", {
99
+ className: "flex h-48 items-center justify-center rounded-lg border border-dashed border-border-subtle",
100
+ children: /* @__PURE__ */ l("p", {
101
+ className: "text-sm text-text-secondary",
102
+ children: "Team activity timeline will render here"
103
+ })
104
+ })]
105
+ })
106
+ ]
77
107
  });
78
108
  }
79
109
  //#endregion
80
- export { u as TeamPage };
110
+ export { f as TeamPage };
81
111
 
82
112
  //# sourceMappingURL=TeamPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TeamPage.js","names":[],"sources":["../../../../src/timecampus/pages/team/TeamPage.tsx"],"sourcesContent":["import { Users, Clock, TrendingUp } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { StatCard } from \"../../components/StatCard\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport { useGetTimeEntryStatsQuery } from \"@/generated/wspace-operations\";\n\nexport function TeamPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const { data, loading, error } = useGetTimeEntryStatsQuery({\n skip: !workspaceId,\n });\n\n const stats = data?.timeEntryStats;\n\n if (loading) {\n return (\n <PageLayout\n title=\"Team Overview\"\n description=\"Monitor team performance and activity\"\n >\n <LoadingSkeleton variant=\"card\" count={4} />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title=\"Team Overview\"\n description=\"Monitor team performance and activity\"\n >\n <div className=\"rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-600 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400\">\n Failed to load team data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n const totalH = Math.floor(stats?.totalHours ?? 0);\n const totalM = Math.round(((stats?.totalHours ?? 0) - totalH) * 60);\n const billablePercent = stats?.totalHours\n ? Math.round(((stats.billableHours ?? 0) / stats.totalHours) * 100)\n : 0;\n\n return (\n <PageLayout\n title=\"Team Overview\"\n description=\"Monitor team performance and activity\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatCard\n title=\"Total Entries\"\n value={String(stats?.totalEntries ?? 0)}\n icon={<Users className=\"h-5 w-5\" />}\n />\n <StatCard\n title=\"Active Timers\"\n value={String(stats?.activeTimers ?? 0)}\n icon={<Users className=\"h-5 w-5\" />}\n iconBgColor=\"bg-emerald-100 text-emerald-600 dark:bg-emerald-900/30 dark:text-emerald-400\"\n />\n <StatCard\n title=\"Total Hours\"\n value={`${totalH}h ${totalM}m`}\n icon={<Clock className=\"h-5 w-5\" />}\n trend={{ value: stats?.billableHours ?? 0, label: \"billable hours\" }}\n />\n <StatCard\n title=\"Billable Rate\"\n value={`${billablePercent}%`}\n icon={<TrendingUp className=\"h-5 w-5\" />}\n trend={{ value: billablePercent, label: \"of total hours\" }}\n />\n </div>\n\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-6\">\n <h3 className=\"mb-4 text-sm font-semibold text-text-primary\">\n Team Activity Feed\n </h3>\n <div className=\"flex h-48 items-center justify-center rounded-lg border border-dashed border-border-subtle\">\n <p className=\"text-sm text-text-secondary\">\n Team activity timeline will render here\n </p>\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;AAOA,SAAgB,IAAW;CACzB,IAAM,EAAE,iBAAc,OAAO,GAAe,EAEtC,EAAE,SAAM,YAAS,aAAU,EAA0B,EACzD,MAAM,CAAC,GACR,CAAC,EAEI,IAAQ,GAAM;AAEpB,KAAI,EACF,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,GAAD;GAAiB,SAAQ;GAAO,OAAO;GAAK,CAAA;EACjC,CAAA;AAIjB,KAAI,EACF,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,OAAD;GAAK,WAAU;aAA+H;GAExI,CAAA;EACK,CAAA;CAIjB,IAAM,IAAS,KAAK,MAAM,GAAO,cAAc,EAAE,EAC3C,IAAS,KAAK,QAAQ,GAAO,cAAc,KAAK,KAAU,GAAG,EAC7D,IAAkB,GAAO,aAC3B,KAAK,OAAQ,EAAM,iBAAiB,KAAK,EAAM,aAAc,IAAI,GACjE;AAEJ,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAFd,CAIE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,OAAO,GAAO,gBAAgB,EAAE;KACvC,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;KACnC,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,OAAO,GAAO,gBAAgB,EAAE;KACvC,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;KACnC,aAAY;KACZ,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,GAAG,EAAO,IAAI,EAAO;KAC5B,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;KACnC,OAAO;MAAE,OAAO,GAAO,iBAAiB;MAAG,OAAO;MAAkB;KACpE,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,GAAG,EAAgB;KAC1B,MAAM,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;KACxC,OAAO;MAAE,OAAO;MAAiB,OAAO;MAAkB;KAC1D,CAAA;IACE;MAEN,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,MAAD;IAAI,WAAU;cAA+C;IAExD,CAAA,EACL,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,KAAD;KAAG,WAAU;eAA8B;KAEvC,CAAA;IACA,CAAA,CACF;KACK"}
1
+ {"version":3,"file":"TeamPage.js","names":[],"sources":["../../../../src/timecampus/pages/team/TeamPage.tsx"],"sourcesContent":["import { Users, Clock, TrendingUp } from \"lucide-react\";\nimport { NextSteps } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { StatCard } from \"../../components/StatCard\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport {\n useTimeCampus,\n useTimeCampusNavigate,\n} from \"../../providers/TimeCampusProvider\";\nimport { useGetTimeEntryStatsQuery } from \"@/generated/wspace-operations\";\n\nexport function TeamPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n const navigate = useTimeCampusNavigate();\n\n const { data, loading, error } = useGetTimeEntryStatsQuery({\n skip: !workspaceId,\n });\n\n const stats = data?.timeEntryStats;\n\n if (loading) {\n return (\n <PageLayout\n title=\"Team Overview\"\n description=\"Monitor team performance and activity\"\n >\n <LoadingSkeleton variant=\"card\" count={4} />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title=\"Team Overview\"\n description=\"Monitor team performance and activity\"\n >\n <div className=\"rounded-lg border border-status-error-bg/40 bg-status-error-bg p-4 text-sm text-status-error-text\">\n Failed to load team data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n const totalH = Math.floor(stats?.totalHours ?? 0);\n const totalM = Math.round(((stats?.totalHours ?? 0) - totalH) * 60);\n const billablePercent = stats?.totalHours\n ? Math.round(((stats.billableHours ?? 0) / stats.totalHours) * 100)\n : 0;\n\n return (\n <PageLayout\n title=\"Team Overview\"\n description=\"Monitor team performance and activity\"\n purpose=\"See how your whole team is spending its time at a glance — who's active, how many hours are billable, and where capacity is going — so you can balance workload and catch problems early.\"\n >\n <NextSteps\n storageKey=\"timecampus-team\"\n className=\"mb-6\"\n steps={[\n {\n id: \"members\",\n label: \"Manage team members\",\n description: \"Add people and check individual workloads.\",\n onClick: () => navigate(\"/team/members\"),\n },\n {\n id: \"analytics\",\n label: \"Open team analytics\",\n description: \"Compare utilisation and trends across the team.\",\n onClick: () => navigate(\"/team/analytics\"),\n },\n {\n id: \"activity\",\n label: \"Watch live team activity\",\n description: \"See what people are working on right now.\",\n onClick: () => navigate(\"/team-activity\"),\n },\n ]}\n />\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatCard\n featured\n title=\"Total Entries\"\n value={String(stats?.totalEntries ?? 0)}\n icon={<Users className=\"h-5 w-5\" />}\n />\n <StatCard\n title=\"Active Timers\"\n value={String(stats?.activeTimers ?? 0)}\n icon={<Users className=\"h-5 w-5\" />}\n iconBgColor=\"bg-status-success-bg text-status-success-text\"\n />\n <StatCard\n title=\"Total Hours\"\n value={`${totalH}h ${totalM}m`}\n icon={<Clock className=\"h-5 w-5\" />}\n trend={{ value: stats?.billableHours ?? 0, label: \"billable hours\" }}\n />\n <StatCard\n title=\"Billable Rate\"\n value={`${billablePercent}%`}\n icon={<TrendingUp className=\"h-5 w-5\" />}\n trend={{ value: billablePercent, label: \"of total hours\" }}\n />\n </div>\n\n <div className=\"rounded-xl border border-border-seam bg-gloss-card shadow-pop p-6\">\n <h3 className=\"mb-4 text-sm font-semibold text-text-primary\">\n Team Activity Feed\n </h3>\n <div className=\"flex h-48 items-center justify-center rounded-lg border border-dashed border-border-subtle\">\n <p className=\"text-sm text-text-secondary\">\n Team activity timeline will render here\n </p>\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;AAWA,SAAgB,IAAW;CACzB,IAAM,EAAE,iBAAc,OAAO,GAAe,EACtC,IAAW,GAAuB,EAElC,EAAE,SAAM,YAAS,aAAU,EAA0B,EACzD,MAAM,CAAC,GACR,CAAC,EAEI,IAAQ,GAAM;AAEpB,KAAI,EACF,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,GAAD;GAAiB,SAAQ;GAAO,OAAO;GAAK,CAAA;EACjC,CAAA;AAIjB,KAAI,EACF,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,OAAD;GAAK,WAAU;aAAoG;GAE7G,CAAA;EACK,CAAA;CAIjB,IAAM,IAAS,KAAK,MAAM,GAAO,cAAc,EAAE,EAC3C,IAAS,KAAK,QAAQ,GAAO,cAAc,KAAK,KAAU,GAAG,EAC7D,IAAkB,GAAO,aAC3B,KAAK,OAAQ,EAAM,iBAAiB,KAAK,EAAM,aAAc,IAAI,GACjE;AAEJ,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SAAQ;YAHV;GAKE,kBAAC,GAAD;IACE,YAAW;IACX,WAAU;IACV,OAAO;KACL;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,eAAe,EAAS,gBAAgB;MACzC;KACD;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,eAAe,EAAS,kBAAkB;MAC3C;KACD;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,eAAe,EAAS,iBAAiB;MAC1C;KACF;IACD,CAAA;GACF,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MACE,UAAA;MACA,OAAM;MACN,OAAO,OAAO,GAAO,gBAAgB,EAAE;MACvC,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;MACnC,CAAA;KACF,kBAAC,GAAD;MACE,OAAM;MACN,OAAO,OAAO,GAAO,gBAAgB,EAAE;MACvC,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;MACnC,aAAY;MACZ,CAAA;KACF,kBAAC,GAAD;MACE,OAAM;MACN,OAAO,GAAG,EAAO,IAAI,EAAO;MAC5B,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;MACnC,OAAO;OAAE,OAAO,GAAO,iBAAiB;OAAG,OAAO;OAAkB;MACpE,CAAA;KACF,kBAAC,GAAD;MACE,OAAM;MACN,OAAO,GAAG,EAAgB;MAC1B,MAAM,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;MACxC,OAAO;OAAE,OAAO;OAAiB,OAAO;OAAkB;MAC1D,CAAA;KACE;;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,MAAD;KAAI,WAAU;eAA+C;KAExD,CAAA,EACL,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,KAAD;MAAG,WAAU;gBAA8B;MAEvC,CAAA;KACA,CAAA,CACF;;GACK"}
@@ -1,86 +1,90 @@
1
1
  import { useTimeCampus as e } from "../../providers/TimeCampusProvider.js";
2
2
  import { formatRelativeTime as t } from "../../utils/helpers.js";
3
- import { PageLayout as n } from "../../components/PageLayout.js";
4
- import { StatCard as r } from "../../components/StatCard.js";
5
- import { LoadingSkeleton as i } from "../../components/LoadingSkeleton.js";
6
- import { useGetTimeEntryStatsQuery as a, useListWorkPatternsQuery as o } from "../../../generated/wspace-operations.js";
7
- import { Activity as s, CheckCircle as c, Clock as l, Users as u } from "lucide-react";
8
- import { jsx as d, jsxs as f } from "react/jsx-runtime";
3
+ import { StatCard as n } from "../../components/StatCard.js";
4
+ import { LoadingSkeleton as r } from "../../components/LoadingSkeleton.js";
5
+ import { useGetTimeEntryStatsQuery as i, useListWorkPatternsQuery as a } from "../../../generated/wspace-operations.js";
6
+ import { PageLayout as o } from "../../components/PageLayout.js";
7
+ import { EmptyState as s } from "../../components/EmptyState.js";
8
+ import { Activity as c, CheckCircle as l, Clock as u, Users as d } from "lucide-react";
9
+ import { jsx as f, jsxs as p } from "react/jsx-runtime";
9
10
  //#region src/timecampus/pages/team-activity/TeamActivityPage.tsx
10
- function p() {
11
- let { workspaceId: p = "" } = e(), { data: m, loading: h, error: g } = a(), { data: _, loading: v, error: y } = o({ variables: { limit: 10 } }), b = m?.timeEntryStats, x = _?.workPatterns ?? [];
12
- return h && v ? /* @__PURE__ */ d(n, {
11
+ function m() {
12
+ let { workspaceId: m = "" } = e(), { data: h, loading: g, error: _ } = i(), { data: v, loading: y, error: b } = a({ variables: { limit: 10 } }), x = h?.timeEntryStats, S = v?.workPatterns ?? [];
13
+ return g && y ? /* @__PURE__ */ f(o, {
13
14
  title: "Team Activity",
14
15
  description: "Real-time team activity feed",
15
- children: /* @__PURE__ */ d(i, {
16
+ children: /* @__PURE__ */ f(r, {
16
17
  variant: "list",
17
18
  count: 5
18
19
  })
19
- }) : g && y ? /* @__PURE__ */ d(n, {
20
+ }) : _ && b ? /* @__PURE__ */ f(o, {
20
21
  title: "Team Activity",
21
22
  description: "Real-time team activity feed",
22
- children: /* @__PURE__ */ d("div", {
23
- className: "rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-600 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400",
23
+ children: /* @__PURE__ */ f("div", {
24
+ className: "rounded-lg border border-status-error-bg/40 bg-status-error-bg p-4 text-sm text-status-error-text",
24
25
  children: "Failed to load team activity data. Please try again later."
25
26
  })
26
- }) : /* @__PURE__ */ f(n, {
27
+ }) : /* @__PURE__ */ p(o, {
27
28
  title: "Team Activity",
28
29
  description: "Real-time team activity feed",
29
- children: [/* @__PURE__ */ f("div", {
30
+ purpose: "A live pulse of what your team is doing right now — who's tracking, recent deep-work sessions, and today's hours — so you stay connected to the team's progress without interrupting anyone.",
31
+ children: [/* @__PURE__ */ p("div", {
30
32
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4",
31
33
  children: [
32
- /* @__PURE__ */ d(r, {
34
+ /* @__PURE__ */ f(n, {
35
+ featured: !0,
33
36
  title: "Active Timers",
34
- value: String(b?.activeTimers ?? 0),
35
- icon: /* @__PURE__ */ d(u, { className: "h-5 w-5" })
37
+ value: String(x?.activeTimers ?? 0),
38
+ icon: /* @__PURE__ */ f(d, { className: "h-5 w-5" })
36
39
  }),
37
- /* @__PURE__ */ d(r, {
40
+ /* @__PURE__ */ f(n, {
38
41
  title: "Total Entries",
39
- value: String(b?.totalEntries ?? 0),
40
- icon: /* @__PURE__ */ d(c, { className: "h-5 w-5" }),
42
+ value: String(x?.totalEntries ?? 0),
43
+ icon: /* @__PURE__ */ f(l, { className: "h-5 w-5" }),
41
44
  description: "Today"
42
45
  }),
43
- /* @__PURE__ */ d(r, {
46
+ /* @__PURE__ */ f(n, {
44
47
  title: "Team Hours",
45
- value: `${Math.round(b?.totalHours ?? 0)}h`,
46
- icon: /* @__PURE__ */ d(l, { className: "h-5 w-5" }),
48
+ value: `${Math.round(x?.totalHours ?? 0)}h`,
49
+ icon: /* @__PURE__ */ f(u, { className: "h-5 w-5" }),
47
50
  description: "Total tracked"
48
51
  }),
49
- /* @__PURE__ */ d(r, {
52
+ /* @__PURE__ */ f(n, {
50
53
  title: "Billable Hours",
51
- value: `${Math.round(b?.billableHours ?? 0)}h`,
52
- icon: /* @__PURE__ */ d(s, { className: "h-5 w-5" }),
53
- iconBgColor: "bg-emerald-100 text-emerald-600 dark:bg-emerald-900/30 dark:text-emerald-400"
54
+ value: `${Math.round(x?.billableHours ?? 0)}h`,
55
+ icon: /* @__PURE__ */ f(c, { className: "h-5 w-5" }),
56
+ iconBgColor: "bg-status-success-bg text-status-success-text"
54
57
  })
55
58
  ]
56
- }), /* @__PURE__ */ f("div", {
57
- className: "rounded-xl border border-border-subtle bg-bg-surface p-6",
58
- children: [/* @__PURE__ */ d("h3", {
59
+ }), /* @__PURE__ */ p("div", {
60
+ className: "rounded-xl border border-border-seam bg-gloss-card shadow-pop p-6",
61
+ children: [/* @__PURE__ */ f("h3", {
59
62
  className: "mb-4 text-sm font-semibold text-text-primary",
60
63
  children: "Activity Feed"
61
- }), /* @__PURE__ */ f("div", {
64
+ }), /* @__PURE__ */ p("div", {
62
65
  className: "space-y-4",
63
- children: [x.length === 0 && !v && /* @__PURE__ */ d("div", {
64
- className: "text-center text-sm text-text-secondary",
65
- children: "No recent activity data available."
66
- }), x.map((e) => /* @__PURE__ */ f("div", {
66
+ children: [S.length === 0 && !y && /* @__PURE__ */ f(s, {
67
+ illustration: "empty-notifications",
68
+ title: "No recent activity yet",
69
+ description: "As your team tracks time and completes focus sessions, their activity will stream in here."
70
+ }), S.map((e) => /* @__PURE__ */ p("div", {
67
71
  className: "flex items-start gap-3",
68
- children: [/* @__PURE__ */ d("div", {
72
+ children: [/* @__PURE__ */ f("div", {
69
73
  className: "mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-action-primary-bg/10",
70
- children: /* @__PURE__ */ d(s, { className: "h-4 w-4 text-primary" })
71
- }), /* @__PURE__ */ f("div", {
74
+ children: /* @__PURE__ */ f(c, { className: "h-4 w-4 text-primary" })
75
+ }), /* @__PURE__ */ p("div", {
72
76
  className: "flex-1",
73
- children: [/* @__PURE__ */ f("p", {
77
+ children: [/* @__PURE__ */ p("p", {
74
78
  className: "text-sm text-text-primary",
75
79
  children: [
76
- /* @__PURE__ */ d("span", {
80
+ /* @__PURE__ */ f("span", {
77
81
  className: "font-medium",
78
82
  children: e.userId
79
83
  }),
80
84
  " ",
81
85
  e.deepWorkSessions > 0 ? "Completed deep work session" : "Logged work pattern"
82
86
  ]
83
- }), /* @__PURE__ */ f("p", {
87
+ }), /* @__PURE__ */ p("p", {
84
88
  className: "text-xs text-text-secondary",
85
89
  children: [
86
90
  e.focusHours.toFixed(1),
@@ -102,6 +106,6 @@ function p() {
102
106
  });
103
107
  }
104
108
  //#endregion
105
- export { p as TeamActivityPage };
109
+ export { m as TeamActivityPage };
106
110
 
107
111
  //# sourceMappingURL=TeamActivityPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TeamActivityPage.js","names":[],"sources":["../../../../src/timecampus/pages/team-activity/TeamActivityPage.tsx"],"sourcesContent":["import { Activity, Users, Clock, CheckCircle } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { StatCard } from \"../../components/StatCard\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { formatRelativeTime } from \"../../utils/helpers\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useGetTimeEntryStatsQuery,\n useListWorkPatternsQuery,\n type WorkPatternFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function TeamActivityPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const {\n data: statsData,\n loading: statsLoading,\n error: statsError,\n } = useGetTimeEntryStatsQuery();\n const {\n data: patternsData,\n loading: patternsLoading,\n error: patternsError,\n } = useListWorkPatternsQuery({ variables: { limit: 10 } });\n\n const stats = statsData?.timeEntryStats;\n const patterns = patternsData?.workPatterns ?? [];\n\n if (statsLoading && patternsLoading) {\n return (\n <PageLayout\n title=\"Team Activity\"\n description=\"Real-time team activity feed\"\n >\n <LoadingSkeleton variant=\"list\" count={5} />\n </PageLayout>\n );\n }\n\n if (statsError && patternsError) {\n return (\n <PageLayout\n title=\"Team Activity\"\n description=\"Real-time team activity feed\"\n >\n <div className=\"rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-600 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400\">\n Failed to load team activity data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Team Activity\"\n description=\"Real-time team activity feed\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatCard\n title=\"Active Timers\"\n value={String(stats?.activeTimers ?? 0)}\n icon={<Users className=\"h-5 w-5\" />}\n />\n <StatCard\n title=\"Total Entries\"\n value={String(stats?.totalEntries ?? 0)}\n icon={<CheckCircle className=\"h-5 w-5\" />}\n description=\"Today\"\n />\n <StatCard\n title=\"Team Hours\"\n value={`${Math.round(stats?.totalHours ?? 0)}h`}\n icon={<Clock className=\"h-5 w-5\" />}\n description=\"Total tracked\"\n />\n <StatCard\n title=\"Billable Hours\"\n value={`${Math.round(stats?.billableHours ?? 0)}h`}\n icon={<Activity className=\"h-5 w-5\" />}\n iconBgColor=\"bg-emerald-100 text-emerald-600 dark:bg-emerald-900/30 dark:text-emerald-400\"\n />\n </div>\n\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-6\">\n <h3 className=\"mb-4 text-sm font-semibold text-text-primary\">\n Activity Feed\n </h3>\n <div className=\"space-y-4\">\n {patterns.length === 0 && !patternsLoading && (\n <div className=\"text-center text-sm text-text-secondary\">\n No recent activity data available.\n </div>\n )}\n {patterns.map((pattern: WorkPatternFieldsFragment) => (\n <div key={pattern.id} className=\"flex items-start gap-3\">\n <div className=\"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-action-primary-bg/10\">\n <Activity className=\"h-4 w-4 text-primary\" />\n </div>\n <div className=\"flex-1\">\n <p className=\"text-sm text-text-primary\">\n <span className=\"font-medium\">{pattern.userId}</span>{\" \"}\n {pattern.deepWorkSessions > 0\n ? \"Completed deep work session\"\n : \"Logged work pattern\"}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {pattern.focusHours.toFixed(1)}h focus &middot;{\" \"}\n {pattern.meetingHours.toFixed(1)}h meetings &middot;{\" \"}\n {pattern.productivityScore\n ? `${pattern.productivityScore}% productivity`\n : pattern.date}{\" \"}\n &middot; {formatRelativeTime(pattern.createdAt)}\n </p>\n </div>\n </div>\n ))}\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;AAYA,SAAgB,IAAmB;CACjC,IAAM,EAAE,iBAAc,OAAO,GAAe,EAEtC,EACJ,MAAM,GACN,SAAS,GACT,OAAO,MACL,GAA2B,EACzB,EACJ,MAAM,GACN,SAAS,GACT,OAAO,MACL,EAAyB,EAAE,WAAW,EAAE,OAAO,IAAI,EAAE,CAAC,EAEpD,IAAQ,GAAW,gBACnB,IAAW,GAAc,gBAAgB,EAAE;AA0BjD,QAxBI,KAAgB,IAEhB,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,GAAD;GAAiB,SAAQ;GAAO,OAAO;GAAK,CAAA;EACjC,CAAA,GAIb,KAAc,IAEd,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,OAAD;GAAK,WAAU;aAA+H;GAExI,CAAA;EACK,CAAA,GAKf,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAFd,CAIE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,OAAO,GAAO,gBAAgB,EAAE;KACvC,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;KACnC,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,OAAO,GAAO,gBAAgB,EAAE;KACvC,MAAM,kBAAC,GAAD,EAAa,WAAU,WAAY,CAAA;KACzC,aAAY;KACZ,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,GAAG,KAAK,MAAM,GAAO,cAAc,EAAE,CAAC;KAC7C,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;KACnC,aAAY;KACZ,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,GAAG,KAAK,MAAM,GAAO,iBAAiB,EAAE,CAAC;KAChD,MAAM,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;KACtC,aAAY;KACZ,CAAA;IACE;MAEN,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,MAAD;IAAI,WAAU;cAA+C;IAExD,CAAA,EACL,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,EAAS,WAAW,KAAK,CAAC,KACzB,kBAAC,OAAD;KAAK,WAAU;eAA0C;KAEnD,CAAA,EAEP,EAAS,KAAK,MACb,kBAAC,OAAD;KAAsB,WAAU;eAAhC,CACE,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAU,WAAU,wBAAyB,CAAA;MACzC,CAAA,EACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACE,kBAAC,QAAD;SAAM,WAAU;mBAAe,EAAQ;SAAc,CAAA;QAAC;QACrD,EAAQ,mBAAmB,IACxB,gCACA;QACF;UACJ,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG,EAAQ,WAAW,QAAQ,EAAE;QAAC;QAAiB;QAC/C,EAAQ,aAAa,QAAQ,EAAE;QAAC;QAAoB;QACpD,EAAQ,oBACL,GAAG,EAAQ,kBAAkB,kBAC7B,EAAQ;QAAM;QAAI;QACZ,EAAmB,EAAQ,UAAU;QAC7C;SACA;QACF;OApBI,EAAQ,GAoBZ,CACN,CACE;MACF;KACK"}
1
+ {"version":3,"file":"TeamActivityPage.js","names":[],"sources":["../../../../src/timecampus/pages/team-activity/TeamActivityPage.tsx"],"sourcesContent":["import { Activity, Users, Clock, CheckCircle } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { StatCard } from \"../../components/StatCard\";\nimport { EmptyState } from \"../../components/EmptyState\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { formatRelativeTime } from \"../../utils/helpers\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useGetTimeEntryStatsQuery,\n useListWorkPatternsQuery,\n type WorkPatternFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function TeamActivityPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const {\n data: statsData,\n loading: statsLoading,\n error: statsError,\n } = useGetTimeEntryStatsQuery();\n const {\n data: patternsData,\n loading: patternsLoading,\n error: patternsError,\n } = useListWorkPatternsQuery({ variables: { limit: 10 } });\n\n const stats = statsData?.timeEntryStats;\n const patterns = patternsData?.workPatterns ?? [];\n\n if (statsLoading && patternsLoading) {\n return (\n <PageLayout\n title=\"Team Activity\"\n description=\"Real-time team activity feed\"\n >\n <LoadingSkeleton variant=\"list\" count={5} />\n </PageLayout>\n );\n }\n\n if (statsError && patternsError) {\n return (\n <PageLayout\n title=\"Team Activity\"\n description=\"Real-time team activity feed\"\n >\n <div className=\"rounded-lg border border-status-error-bg/40 bg-status-error-bg p-4 text-sm text-status-error-text\">\n Failed to load team activity data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Team Activity\"\n description=\"Real-time team activity feed\"\n purpose=\"A live pulse of what your team is doing right now — who's tracking, recent deep-work sessions, and today's hours — so you stay connected to the team's progress without interrupting anyone.\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatCard\n featured\n title=\"Active Timers\"\n value={String(stats?.activeTimers ?? 0)}\n icon={<Users className=\"h-5 w-5\" />}\n />\n <StatCard\n title=\"Total Entries\"\n value={String(stats?.totalEntries ?? 0)}\n icon={<CheckCircle className=\"h-5 w-5\" />}\n description=\"Today\"\n />\n <StatCard\n title=\"Team Hours\"\n value={`${Math.round(stats?.totalHours ?? 0)}h`}\n icon={<Clock className=\"h-5 w-5\" />}\n description=\"Total tracked\"\n />\n <StatCard\n title=\"Billable Hours\"\n value={`${Math.round(stats?.billableHours ?? 0)}h`}\n icon={<Activity className=\"h-5 w-5\" />}\n iconBgColor=\"bg-status-success-bg text-status-success-text\"\n />\n </div>\n\n <div className=\"rounded-xl border border-border-seam bg-gloss-card shadow-pop p-6\">\n <h3 className=\"mb-4 text-sm font-semibold text-text-primary\">\n Activity Feed\n </h3>\n <div className=\"space-y-4\">\n {patterns.length === 0 && !patternsLoading && (\n <EmptyState\n illustration=\"empty-notifications\"\n title=\"No recent activity yet\"\n description=\"As your team tracks time and completes focus sessions, their activity will stream in here.\"\n />\n )}\n {patterns.map((pattern: WorkPatternFieldsFragment) => (\n <div key={pattern.id} className=\"flex items-start gap-3\">\n <div className=\"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-action-primary-bg/10\">\n <Activity className=\"h-4 w-4 text-primary\" />\n </div>\n <div className=\"flex-1\">\n <p className=\"text-sm text-text-primary\">\n <span className=\"font-medium\">{pattern.userId}</span>{\" \"}\n {pattern.deepWorkSessions > 0\n ? \"Completed deep work session\"\n : \"Logged work pattern\"}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {pattern.focusHours.toFixed(1)}h focus &middot;{\" \"}\n {pattern.meetingHours.toFixed(1)}h meetings &middot;{\" \"}\n {pattern.productivityScore\n ? `${pattern.productivityScore}% productivity`\n : pattern.date}{\" \"}\n &middot; {formatRelativeTime(pattern.createdAt)}\n </p>\n </div>\n </div>\n ))}\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;AAaA,SAAgB,IAAmB;CACjC,IAAM,EAAE,iBAAc,OAAO,GAAe,EAEtC,EACJ,MAAM,GACN,SAAS,GACT,OAAO,MACL,GAA2B,EACzB,EACJ,MAAM,GACN,SAAS,GACT,OAAO,MACL,EAAyB,EAAE,WAAW,EAAE,OAAO,IAAI,EAAE,CAAC,EAEpD,IAAQ,GAAW,gBACnB,IAAW,GAAc,gBAAgB,EAAE;AA0BjD,QAxBI,KAAgB,IAEhB,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,GAAD;GAAiB,SAAQ;GAAO,OAAO;GAAK,CAAA;EACjC,CAAA,GAIb,KAAc,IAEd,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,OAAD;GAAK,WAAU;aAAoG;GAE7G,CAAA;EACK,CAAA,GAKf,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SAAQ;YAHV,CAKE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,GAAD;KACE,UAAA;KACA,OAAM;KACN,OAAO,OAAO,GAAO,gBAAgB,EAAE;KACvC,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;KACnC,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,OAAO,GAAO,gBAAgB,EAAE;KACvC,MAAM,kBAAC,GAAD,EAAa,WAAU,WAAY,CAAA;KACzC,aAAY;KACZ,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,GAAG,KAAK,MAAM,GAAO,cAAc,EAAE,CAAC;KAC7C,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;KACnC,aAAY;KACZ,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,GAAG,KAAK,MAAM,GAAO,iBAAiB,EAAE,CAAC;KAChD,MAAM,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;KACtC,aAAY;KACZ,CAAA;IACE;MAEN,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,MAAD;IAAI,WAAU;cAA+C;IAExD,CAAA,EACL,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,EAAS,WAAW,KAAK,CAAC,KACzB,kBAAC,GAAD;KACE,cAAa;KACb,OAAM;KACN,aAAY;KACZ,CAAA,EAEH,EAAS,KAAK,MACb,kBAAC,OAAD;KAAsB,WAAU;eAAhC,CACE,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAU,WAAU,wBAAyB,CAAA;MACzC,CAAA,EACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACE,kBAAC,QAAD;SAAM,WAAU;mBAAe,EAAQ;SAAc,CAAA;QAAC;QACrD,EAAQ,mBAAmB,IACxB,gCACA;QACF;UACJ,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG,EAAQ,WAAW,QAAQ,EAAE;QAAC;QAAiB;QAC/C,EAAQ,aAAa,QAAQ,EAAE;QAAC;QAAoB;QACpD,EAAQ,oBACL,GAAG,EAAQ,kBAAkB,kBAC7B,EAAQ;QAAM;QAAI;QACZ,EAAmB,EAAQ,UAAU;QAC7C;SACA;QACF;OApBI,EAAQ,GAoBZ,CACN,CACE;MACF;KACK"}