@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.
- package/dist/timecampus/components/EmptyState.js +14 -0
- package/dist/timecampus/components/EmptyState.js.map +1 -0
- package/dist/timecampus/components/ErrorBoundary.js +2 -2
- package/dist/timecampus/components/ErrorBoundary.js.map +1 -1
- package/dist/timecampus/components/LoadingSkeleton.js +1 -1
- package/dist/timecampus/components/LoadingSkeleton.js.map +1 -1
- package/dist/timecampus/components/PageLayout.js +26 -14
- package/dist/timecampus/components/PageLayout.js.map +1 -1
- package/dist/timecampus/components/StatCard.js +19 -16
- package/dist/timecampus/components/StatCard.js.map +1 -1
- package/dist/timecampus/pages/HomePage.js +169 -149
- package/dist/timecampus/pages/HomePage.js.map +1 -1
- package/dist/timecampus/pages/applets/AppletStorePage.js +38 -35
- package/dist/timecampus/pages/applets/AppletStorePage.js.map +1 -1
- package/dist/timecampus/pages/applets/InstalledAppletsPage.js +42 -36
- package/dist/timecampus/pages/applets/InstalledAppletsPage.js.map +1 -1
- package/dist/timecampus/pages/application-usage/ApplicationUsagePage.js +57 -53
- package/dist/timecampus/pages/application-usage/ApplicationUsagePage.js.map +1 -1
- package/dist/timecampus/pages/application-usage/ApplicationUsageSettingsPage.js +40 -36
- package/dist/timecampus/pages/application-usage/ApplicationUsageSettingsPage.js.map +1 -1
- package/dist/timecampus/pages/channels/ChannelsPage.js +32 -29
- package/dist/timecampus/pages/channels/ChannelsPage.js.map +1 -1
- package/dist/timecampus/pages/client-portal/ClientPortalPage.js +52 -44
- package/dist/timecampus/pages/client-portal/ClientPortalPage.js.map +1 -1
- package/dist/timecampus/pages/dashboard/AnalyticsPage.js +65 -38
- package/dist/timecampus/pages/dashboard/AnalyticsPage.js.map +1 -1
- package/dist/timecampus/pages/dashboard/ReportsPage.js +47 -41
- package/dist/timecampus/pages/dashboard/ReportsPage.js.map +1 -1
- package/dist/timecampus/pages/email-tracking/EmailAnalyticsPage.js +16 -14
- package/dist/timecampus/pages/email-tracking/EmailAnalyticsPage.js.map +1 -1
- package/dist/timecampus/pages/email-tracking/EmailSettingsPage.js +40 -36
- package/dist/timecampus/pages/email-tracking/EmailSettingsPage.js.map +1 -1
- package/dist/timecampus/pages/email-tracking/EmailTrackingPage.js +34 -28
- package/dist/timecampus/pages/email-tracking/EmailTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js +49 -41
- package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/focus-score/FocusScorePage.js +66 -62
- package/dist/timecampus/pages/focus-score/FocusScorePage.js.map +1 -1
- package/dist/timecampus/pages/focus-score/FocusScoreSettingsPage.js +37 -33
- package/dist/timecampus/pages/focus-score/FocusScoreSettingsPage.js.map +1 -1
- package/dist/timecampus/pages/geofencing/GeofencingPage.js +37 -30
- package/dist/timecampus/pages/geofencing/GeofencingPage.js.map +1 -1
- package/dist/timecampus/pages/geofencing/GeofencingSettingsPage.js +35 -31
- package/dist/timecampus/pages/geofencing/GeofencingSettingsPage.js.map +1 -1
- package/dist/timecampus/pages/industry-solutions/IndustrySolutionsPage.js +37 -34
- package/dist/timecampus/pages/industry-solutions/IndustrySolutionsPage.js.map +1 -1
- package/dist/timecampus/pages/location-tracking/LocationPrivacySettingsPage.js +35 -31
- package/dist/timecampus/pages/location-tracking/LocationPrivacySettingsPage.js.map +1 -1
- package/dist/timecampus/pages/location-tracking/LocationTrackingPage.js +45 -41
- package/dist/timecampus/pages/location-tracking/LocationTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/meetings/MeetingAnalyticsPage.js +17 -15
- package/dist/timecampus/pages/meetings/MeetingAnalyticsPage.js.map +1 -1
- package/dist/timecampus/pages/meetings/MeetingCreatePage.js +36 -32
- package/dist/timecampus/pages/meetings/MeetingCreatePage.js.map +1 -1
- package/dist/timecampus/pages/meetings/MeetingDetailPage.js +120 -102
- package/dist/timecampus/pages/meetings/MeetingDetailPage.js.map +1 -1
- package/dist/timecampus/pages/meetings/MeetingsPage.js +46 -36
- package/dist/timecampus/pages/meetings/MeetingsPage.js.map +1 -1
- package/dist/timecampus/pages/pomodoro/PomodoroAnalyticsPage.js +19 -17
- package/dist/timecampus/pages/pomodoro/PomodoroAnalyticsPage.js.map +1 -1
- package/dist/timecampus/pages/pomodoro/PomodoroPage.js +143 -112
- package/dist/timecampus/pages/pomodoro/PomodoroPage.js.map +1 -1
- package/dist/timecampus/pages/pomodoro/PomodoroSettingsPage.js +55 -51
- package/dist/timecampus/pages/pomodoro/PomodoroSettingsPage.js.map +1 -1
- package/dist/timecampus/pages/projects/ProjectCreatePage.js +32 -28
- package/dist/timecampus/pages/projects/ProjectCreatePage.js.map +1 -1
- package/dist/timecampus/pages/projects/ProjectDetailPage.js +107 -76
- package/dist/timecampus/pages/projects/ProjectDetailPage.js.map +1 -1
- package/dist/timecampus/pages/projects/ProjectsPage.js +21 -17
- package/dist/timecampus/pages/projects/ProjectsPage.js.map +1 -1
- package/dist/timecampus/pages/projects/TasksPage.js +44 -34
- package/dist/timecampus/pages/projects/TasksPage.js.map +1 -1
- package/dist/timecampus/pages/resource-planning/ResourcePlanningPage.js +59 -55
- package/dist/timecampus/pages/resource-planning/ResourcePlanningPage.js.map +1 -1
- package/dist/timecampus/pages/team/TeamAnalyticsPage.js +24 -20
- package/dist/timecampus/pages/team/TeamAnalyticsPage.js.map +1 -1
- package/dist/timecampus/pages/team/TeamMembersPage.js +47 -41
- package/dist/timecampus/pages/team/TeamMembersPage.js.map +1 -1
- package/dist/timecampus/pages/team/TeamPage.js +89 -59
- package/dist/timecampus/pages/team/TeamPage.js.map +1 -1
- package/dist/timecampus/pages/team-activity/TeamActivityPage.js +47 -43
- package/dist/timecampus/pages/team-activity/TeamActivityPage.js.map +1 -1
- package/dist/timecampus/pages/team-activity/TeamActivitySettingsPage.js +39 -35
- package/dist/timecampus/pages/team-activity/TeamActivitySettingsPage.js.map +1 -1
- package/dist/timecampus/pages/templates/TemplateApplicationPage.js +24 -20
- package/dist/timecampus/pages/templates/TemplateApplicationPage.js.map +1 -1
- package/dist/timecampus/pages/templates/TemplateDetailPage.js +66 -48
- package/dist/timecampus/pages/templates/TemplateDetailPage.js.map +1 -1
- package/dist/timecampus/pages/templates/TemplatesPage.js +39 -36
- package/dist/timecampus/pages/templates/TemplatesPage.js.map +1 -1
- package/dist/timecampus/pages/time/TimeEntriesPage.js +53 -44
- package/dist/timecampus/pages/time/TimeEntriesPage.js.map +1 -1
- package/dist/timecampus/pages/time/TimeTrackingPage.js +72 -71
- package/dist/timecampus/pages/time/TimeTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/time/TimerPage.js +100 -66
- package/dist/timecampus/pages/time/TimerPage.js.map +1 -1
- package/dist/timecampus/pages/time-approval/TimeApprovalPage.js +63 -59
- package/dist/timecampus/pages/time-approval/TimeApprovalPage.js.map +1 -1
- package/dist/timecampus/pages/widgets/WidgetDetailPage.js +64 -46
- package/dist/timecampus/pages/widgets/WidgetDetailPage.js.map +1 -1
- package/dist/timecampus/pages/widgets/WidgetsPage.js +44 -37
- package/dist/timecampus/pages/widgets/WidgetsPage.js.map +1 -1
- package/dist/timecampus/pages/work-patterns/WorkPatternsPage.js +18 -16
- package/dist/timecampus/pages/work-patterns/WorkPatternsPage.js.map +1 -1
- package/dist/timecampus/pages/work-patterns/WorkPatternsSettingsPage.js +40 -36
- package/dist/timecampus/pages/work-patterns/WorkPatternsSettingsPage.js.map +1 -1
- package/dist/timecampus/pages/workflows/WorkflowsPage.js +47 -37
- package/dist/timecampus/pages/workflows/WorkflowsPage.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,45 +1,58 @@
|
|
|
1
1
|
import { getPriorityColor as e, getStatusColor as t } from "../../utils/helpers.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
2
|
+
import { LoadingSkeleton as n } from "../../components/LoadingSkeleton.js";
|
|
3
|
+
import { useListTasksQuery as r } from "../../../generated/wspace-operations.js";
|
|
4
|
+
import { PageLayout as i } from "../../components/PageLayout.js";
|
|
5
|
+
import { EmptyState as a } from "../../components/EmptyState.js";
|
|
6
|
+
import { CheckSquare as o, Plus as s } from "lucide-react";
|
|
7
|
+
import { useParams as c } from "react-router-dom";
|
|
8
|
+
import { jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
9
|
+
import { GlassCard as d } from "@burdenoff/fe-libs/ui";
|
|
8
10
|
//#region src/timecampus/pages/projects/TasksPage.tsx
|
|
9
|
-
function
|
|
10
|
-
let { projectId:
|
|
11
|
-
variables: { projectId:
|
|
12
|
-
skip: !
|
|
13
|
-
}),
|
|
14
|
-
return
|
|
11
|
+
function f() {
|
|
12
|
+
let { projectId: f } = c(), { data: p, loading: m, error: h } = r({
|
|
13
|
+
variables: { projectId: f },
|
|
14
|
+
skip: !f
|
|
15
|
+
}), g = p?.tasks?.items ?? [];
|
|
16
|
+
return h ? /* @__PURE__ */ l(i, {
|
|
15
17
|
title: "Tasks",
|
|
16
|
-
description: `Tasks for project ${
|
|
17
|
-
children: /* @__PURE__ */
|
|
18
|
-
className: "rounded-xl border border-
|
|
18
|
+
description: `Tasks for project ${f}`,
|
|
19
|
+
children: /* @__PURE__ */ l("div", {
|
|
20
|
+
className: "rounded-xl border border-status-error-bg/40 bg-status-error-bg p-6 text-sm text-status-error-text",
|
|
19
21
|
children: "Failed to load tasks. Please try again later."
|
|
20
22
|
})
|
|
21
|
-
}) : /* @__PURE__ */
|
|
23
|
+
}) : /* @__PURE__ */ l(i, {
|
|
22
24
|
title: "Tasks",
|
|
23
|
-
description: `Tasks for project ${
|
|
24
|
-
|
|
25
|
+
description: `Tasks for project ${f}`,
|
|
26
|
+
purpose: "Break a project down into the concrete pieces of work that need doing, then track hours against each one — so you can see what's done, what's blocking, and where effort is actually being spent.",
|
|
27
|
+
actions: /* @__PURE__ */ u("button", {
|
|
25
28
|
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",
|
|
26
|
-
children: [/* @__PURE__ */
|
|
29
|
+
children: [/* @__PURE__ */ l(s, { className: "h-4 w-4" }), "Add Task"]
|
|
27
30
|
}),
|
|
28
|
-
children:
|
|
31
|
+
children: m ? /* @__PURE__ */ l(n, {
|
|
29
32
|
variant: "list",
|
|
30
33
|
count: 5
|
|
31
|
-
}) : /* @__PURE__ */
|
|
32
|
-
|
|
34
|
+
}) : g.length === 0 ? /* @__PURE__ */ l(a, {
|
|
35
|
+
illustration: "empty-generic",
|
|
36
|
+
title: "No tasks yet",
|
|
37
|
+
description: "Add a task to break this project into trackable work.",
|
|
38
|
+
action: /* @__PURE__ */ u("button", {
|
|
39
|
+
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",
|
|
40
|
+
children: [/* @__PURE__ */ l(s, { className: "h-4 w-4" }), "Add Task"]
|
|
41
|
+
})
|
|
42
|
+
}) : /* @__PURE__ */ l(d, {
|
|
43
|
+
treatment: "glass",
|
|
44
|
+
glow: !0,
|
|
45
|
+
className: "overflow-hidden",
|
|
33
46
|
children: /* @__PURE__ */ l("div", {
|
|
34
47
|
className: "divide-y divide-border",
|
|
35
|
-
children:
|
|
48
|
+
children: g.map((n) => /* @__PURE__ */ u("div", {
|
|
36
49
|
className: "flex items-center justify-between p-4 hover:bg-bg-sunken/50 transition-colors",
|
|
37
|
-
children: [/* @__PURE__ */
|
|
50
|
+
children: [/* @__PURE__ */ u("div", {
|
|
38
51
|
className: "flex items-center gap-3",
|
|
39
|
-
children: [/* @__PURE__ */
|
|
52
|
+
children: [/* @__PURE__ */ l(o, { className: `h-5 w-5 ${n.status === "done" ? "text-status-success-text" : "text-text-secondary"}` }), /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("p", {
|
|
40
53
|
className: `text-sm font-medium ${n.status === "done" ? "text-text-secondary line-through" : "text-text-primary"}`,
|
|
41
54
|
children: n.title
|
|
42
|
-
}), /* @__PURE__ */
|
|
55
|
+
}), /* @__PURE__ */ u("p", {
|
|
43
56
|
className: "text-xs text-text-secondary",
|
|
44
57
|
children: [
|
|
45
58
|
n.assigneeId ?? "Unassigned",
|
|
@@ -49,25 +62,22 @@ function u() {
|
|
|
49
62
|
"h tracked"
|
|
50
63
|
]
|
|
51
64
|
})] })]
|
|
52
|
-
}), /* @__PURE__ */
|
|
65
|
+
}), /* @__PURE__ */ u("div", {
|
|
53
66
|
className: "flex items-center gap-2",
|
|
54
|
-
children: [/* @__PURE__ */
|
|
67
|
+
children: [/* @__PURE__ */ l("span", {
|
|
55
68
|
className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${e(n.priority)}`,
|
|
56
69
|
children: n.priority
|
|
57
|
-
}), /* @__PURE__ */
|
|
70
|
+
}), /* @__PURE__ */ l("span", {
|
|
58
71
|
className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${t(n.status)}`,
|
|
59
72
|
children: n.status
|
|
60
73
|
})]
|
|
61
74
|
})]
|
|
62
|
-
}, n.id))
|
|
63
|
-
className: "p-8 text-center text-sm text-text-secondary",
|
|
64
|
-
children: "No tasks yet. Add a task to get started."
|
|
65
|
-
})]
|
|
75
|
+
}, n.id))
|
|
66
76
|
})
|
|
67
77
|
})
|
|
68
78
|
});
|
|
69
79
|
}
|
|
70
80
|
//#endregion
|
|
71
|
-
export {
|
|
81
|
+
export { f as TasksPage };
|
|
72
82
|
|
|
73
83
|
//# sourceMappingURL=TasksPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TasksPage.js","names":[],"sources":["../../../../src/timecampus/pages/projects/TasksPage.tsx"],"sourcesContent":["import { useParams } from \"react-router-dom\";\nimport { Plus, CheckSquare } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { getStatusColor, getPriorityColor } from \"../../utils/helpers\";\nimport {\n useListTasksQuery,\n type TaskFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function TasksPage() {\n const { projectId } = useParams<{ projectId: string }>();\n\n const { data, loading, error } = useListTasksQuery({\n variables: { projectId: projectId! },\n skip: !projectId,\n });\n\n const tasks = data?.tasks?.items ?? [];\n\n if (error) {\n return (\n <PageLayout title=\"Tasks\" description={`Tasks for project ${projectId}`}>\n <div className=\"rounded-xl border border-
|
|
1
|
+
{"version":3,"file":"TasksPage.js","names":[],"sources":["../../../../src/timecampus/pages/projects/TasksPage.tsx"],"sourcesContent":["import { useParams } from \"react-router-dom\";\nimport { Plus, CheckSquare } 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 { getStatusColor, getPriorityColor } from \"../../utils/helpers\";\nimport {\n useListTasksQuery,\n type TaskFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function TasksPage() {\n const { projectId } = useParams<{ projectId: string }>();\n\n const { data, loading, error } = useListTasksQuery({\n variables: { projectId: projectId! },\n skip: !projectId,\n });\n\n const tasks = data?.tasks?.items ?? [];\n\n if (error) {\n return (\n <PageLayout title=\"Tasks\" description={`Tasks for project ${projectId}`}>\n <div className=\"rounded-xl border border-status-error-bg/40 bg-status-error-bg p-6 text-sm text-status-error-text\">\n Failed to load tasks. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Tasks\"\n description={`Tasks for project ${projectId}`}\n purpose=\"Break a project down into the concrete pieces of work that need doing, then track hours against each one — so you can see what's done, what's blocking, and where effort is actually being spent.\"\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 Add Task\n </button>\n }\n >\n {loading ? (\n <LoadingSkeleton variant=\"list\" count={5} />\n ) : tasks.length === 0 ? (\n <EmptyState\n illustration=\"empty-generic\"\n title=\"No tasks yet\"\n description=\"Add a task to break this project into trackable work.\"\n action={\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 Add Task\n </button>\n }\n />\n ) : (\n <GlassCard treatment=\"glass\" glow className=\"overflow-hidden\">\n <div className=\"divide-y divide-border\">\n {tasks.map((task: TaskFieldsFragment) => (\n <div\n key={task.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 <CheckSquare\n className={`h-5 w-5 ${task.status === \"done\" ? \"text-status-success-text\" : \"text-text-secondary\"}`}\n />\n <div>\n <p\n className={`text-sm font-medium ${task.status === \"done\" ? \"text-text-secondary line-through\" : \"text-text-primary\"}`}\n >\n {task.title}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {task.assigneeId ?? \"Unassigned\"} ·{\" \"}\n {task.trackedHours}h tracked\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <span\n className={`inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${getPriorityColor(task.priority)}`}\n >\n {task.priority}\n </span>\n <span\n className={`inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${getStatusColor(task.status)}`}\n >\n {task.status}\n </span>\n </div>\n </div>\n ))}\n </div>\n </GlassCard>\n )}\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;AAYA,SAAgB,IAAY;CAC1B,IAAM,EAAE,iBAAc,GAAkC,EAElD,EAAE,SAAM,YAAS,aAAU,EAAkB;EACjD,WAAW,EAAa,cAAY;EACpC,MAAM,CAAC;EACR,CAAC,EAEI,IAAQ,GAAM,OAAO,SAAS,EAAE;AAYtC,QAVI,IAEA,kBAAC,GAAD;EAAY,OAAM;EAAQ,aAAa,qBAAqB;YAC1D,kBAAC,OAAD;GAAK,WAAU;aAAoG;GAE7G,CAAA;EACK,CAAA,GAKf,kBAAC,GAAD;EACE,OAAM;EACN,aAAa,qBAAqB;EAClC,SAAQ;EACR,SACE,kBAAC,UAAD;GAAQ,WAAU;aAAlB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,WAErB;;YAGV,IACC,kBAAC,GAAD;GAAiB,SAAQ;GAAO,OAAO;GAAK,CAAA,GAC1C,EAAM,WAAW,IACnB,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,aAAY;GACZ,QACE,kBAAC,UAAD;IAAQ,WAAU;cAAlB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,WAErB;;GAEX,CAAA,GAEF,kBAAC,GAAD;GAAW,WAAU;GAAQ,MAAA;GAAK,WAAU;aAC1C,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAM,KAAK,MACV,kBAAC,OAAD;KAEE,WAAU;eAFZ,CAIE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EACE,WAAW,WAAW,EAAK,WAAW,SAAS,6BAA6B,yBAC5E,CAAA,EACF,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;OACE,WAAW,uBAAuB,EAAK,WAAW,SAAS,qCAAqC;iBAE/F,EAAK;OACJ,CAAA,EACJ,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG,EAAK,cAAc;QAAa;QAAU;QAC1C,EAAK;QAAa;QACjB;SACA,EAAA,CAAA,CACF;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OACE,WAAW,4DAA4D,EAAiB,EAAK,SAAS;iBAErG,EAAK;OACD,CAAA,EACP,kBAAC,QAAD;OACE,WAAW,4DAA4D,EAAe,EAAK,OAAO;iBAEjG,EAAK;OACD,CAAA,CACH;QACF;OA/BC,EAAK,GA+BN,CACN;IACE,CAAA;GACI,CAAA;EAEH,CAAA"}
|
|
@@ -1,86 +1,90 @@
|
|
|
1
1
|
import { useTimeCampus as e } from "../../providers/TimeCampusProvider.js";
|
|
2
2
|
import { getInitials as t } from "../../utils/helpers.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
3
|
+
import { StatCard as n } from "../../components/StatCard.js";
|
|
4
|
+
import { LoadingSkeleton as r } from "../../components/LoadingSkeleton.js";
|
|
5
|
+
import { useGetCapacityOverviewQuery as i, useListResourcePlansQuery 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 { CalendarRange as c, TrendingUp as l, Users as u } from "lucide-react";
|
|
9
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
9
10
|
//#region src/timecampus/pages/resource-planning/ResourcePlanningPage.tsx
|
|
10
|
-
function
|
|
11
|
-
let { workspaceId:
|
|
12
|
-
startDate:
|
|
13
|
-
endDate:
|
|
14
|
-
} }),
|
|
11
|
+
function p() {
|
|
12
|
+
let { workspaceId: p = "" } = e(), m = /* @__PURE__ */ new Date(), h = new Date(m.getFullYear(), m.getMonth(), m.getDate()).toISOString(), g = new Date(m.getFullYear(), m.getMonth(), m.getDate() + 7).toISOString(), { data: _, loading: v, error: y } = a(), { data: b } = i({ variables: {
|
|
13
|
+
startDate: h,
|
|
14
|
+
endDate: g
|
|
15
|
+
} }), x = _?.resourcePlans?.items ?? [], S = b?.capacityOverview, C = x.flatMap((e) => e.allocations.map((t) => ({
|
|
15
16
|
...t,
|
|
16
17
|
planName: e.name
|
|
17
18
|
})));
|
|
18
|
-
if (
|
|
19
|
+
if (v) return /* @__PURE__ */ d(o, {
|
|
19
20
|
title: "Resource Planning",
|
|
20
21
|
description: "Plan and optimize team resource allocation",
|
|
21
|
-
children: /* @__PURE__ */
|
|
22
|
+
children: /* @__PURE__ */ d(r, {
|
|
22
23
|
variant: "list",
|
|
23
24
|
count: 5
|
|
24
25
|
})
|
|
25
26
|
});
|
|
26
|
-
if (
|
|
27
|
+
if (y) return /* @__PURE__ */ d(o, {
|
|
27
28
|
title: "Resource Planning",
|
|
28
29
|
description: "Plan and optimize team resource allocation",
|
|
29
|
-
children: /* @__PURE__ */
|
|
30
|
-
className: "rounded-lg border border-
|
|
30
|
+
children: /* @__PURE__ */ d("div", {
|
|
31
|
+
className: "rounded-lg border border-status-error-bg/40 bg-status-error-bg p-4 text-sm text-status-error-text",
|
|
31
32
|
children: "Failed to load resource planning data. Please try again later."
|
|
32
33
|
})
|
|
33
34
|
});
|
|
34
|
-
let
|
|
35
|
-
return /* @__PURE__ */
|
|
35
|
+
let w = S?.utilizationRate ?? 0, T = S?.overallocatedUsers?.length ?? 0, E = S?.availableCapacity ?? 0;
|
|
36
|
+
return /* @__PURE__ */ f(o, {
|
|
36
37
|
title: "Resource Planning",
|
|
37
38
|
description: "Plan and optimize team resource allocation",
|
|
38
|
-
|
|
39
|
+
purpose: "Match the work ahead to the people you have — see who's over- or under-booked and how much capacity is free this week — so you can commit to deadlines you can actually hit without burning anyone out.",
|
|
40
|
+
children: [/* @__PURE__ */ f("div", {
|
|
39
41
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4",
|
|
40
42
|
children: [
|
|
41
|
-
/* @__PURE__ */
|
|
43
|
+
/* @__PURE__ */ d(n, {
|
|
44
|
+
featured: !0,
|
|
42
45
|
title: "Team Utilization",
|
|
43
|
-
value: `${Math.round(
|
|
44
|
-
icon: /* @__PURE__ */
|
|
46
|
+
value: `${Math.round(w)}%`,
|
|
47
|
+
icon: /* @__PURE__ */ d(l, { className: "h-5 w-5" })
|
|
45
48
|
}),
|
|
46
|
-
/* @__PURE__ */
|
|
49
|
+
/* @__PURE__ */ d(n, {
|
|
47
50
|
title: "Over-allocated",
|
|
48
|
-
value: String(
|
|
49
|
-
icon: /* @__PURE__ */ u
|
|
50
|
-
iconBgColor: "bg-
|
|
51
|
+
value: String(T),
|
|
52
|
+
icon: /* @__PURE__ */ d(u, { className: "h-5 w-5" }),
|
|
53
|
+
iconBgColor: "bg-status-error-bg text-status-error-text"
|
|
51
54
|
}),
|
|
52
|
-
/* @__PURE__ */
|
|
55
|
+
/* @__PURE__ */ d(n, {
|
|
53
56
|
title: "Active Plans",
|
|
54
|
-
value: String(
|
|
55
|
-
icon: /* @__PURE__ */ u
|
|
57
|
+
value: String(x.length),
|
|
58
|
+
icon: /* @__PURE__ */ d(u, { className: "h-5 w-5" })
|
|
56
59
|
}),
|
|
57
|
-
/* @__PURE__ */
|
|
60
|
+
/* @__PURE__ */ d(n, {
|
|
58
61
|
title: "Available Capacity",
|
|
59
|
-
value: `${Math.round(
|
|
60
|
-
icon: /* @__PURE__ */
|
|
62
|
+
value: `${Math.round(E)}h`,
|
|
63
|
+
icon: /* @__PURE__ */ d(c, { className: "h-5 w-5" }),
|
|
61
64
|
description: "This week"
|
|
62
65
|
})
|
|
63
66
|
]
|
|
64
|
-
}), /* @__PURE__ */
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
}), C.length === 0 ? /* @__PURE__ */ d(s, {
|
|
68
|
+
illustration: "empty-people",
|
|
69
|
+
title: "No resource allocations found",
|
|
70
|
+
description: "Create a resource plan to start allocating team members and balancing workload across the week."
|
|
71
|
+
}) : /* @__PURE__ */ d("div", {
|
|
72
|
+
className: "rounded-xl border border-border-seam bg-gloss-card shadow-pop",
|
|
73
|
+
children: /* @__PURE__ */ d("div", {
|
|
67
74
|
className: "divide-y divide-border",
|
|
68
|
-
children:
|
|
69
|
-
className: "p-8 text-center text-sm text-text-secondary",
|
|
70
|
-
children: "No resource allocations found. Create a resource plan to start allocating team members."
|
|
71
|
-
}) : S.map((e) => {
|
|
75
|
+
children: C.map((e) => {
|
|
72
76
|
let n = e.utilizationRate ?? (e.allocatedHours > 0 ? Math.round(e.actualHours / e.allocatedHours * 100) : 0);
|
|
73
|
-
return /* @__PURE__ */
|
|
77
|
+
return /* @__PURE__ */ f("div", {
|
|
74
78
|
className: "flex items-center justify-between p-4 hover:bg-bg-sunken/50 transition-colors",
|
|
75
|
-
children: [/* @__PURE__ */
|
|
79
|
+
children: [/* @__PURE__ */ f("div", {
|
|
76
80
|
className: "flex items-center gap-3",
|
|
77
|
-
children: [/* @__PURE__ */
|
|
81
|
+
children: [/* @__PURE__ */ d("div", {
|
|
78
82
|
className: "flex h-9 w-9 items-center justify-center rounded-full bg-action-primary-bg/10 text-sm font-medium text-primary",
|
|
79
83
|
children: t(e.userId)
|
|
80
|
-
}), /* @__PURE__ */
|
|
84
|
+
}), /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("p", {
|
|
81
85
|
className: "text-sm font-medium text-text-primary",
|
|
82
86
|
children: e.userId
|
|
83
|
-
}), /* @__PURE__ */
|
|
87
|
+
}), /* @__PURE__ */ f("p", {
|
|
84
88
|
className: "text-xs text-text-secondary",
|
|
85
89
|
children: [
|
|
86
90
|
e.planName,
|
|
@@ -92,26 +96,26 @@ function f() {
|
|
|
92
96
|
e.endDate.slice(0, 10)
|
|
93
97
|
]
|
|
94
98
|
})] })]
|
|
95
|
-
}), /* @__PURE__ */
|
|
99
|
+
}), /* @__PURE__ */ f("div", {
|
|
96
100
|
className: "flex items-center gap-4",
|
|
97
|
-
children: [/* @__PURE__ */
|
|
101
|
+
children: [/* @__PURE__ */ d("div", {
|
|
98
102
|
className: "text-right",
|
|
99
|
-
children: /* @__PURE__ */
|
|
103
|
+
children: /* @__PURE__ */ f("p", {
|
|
100
104
|
className: "text-sm font-medium text-text-primary",
|
|
101
105
|
children: [e.allocatedHours, "h allocated"]
|
|
102
106
|
})
|
|
103
|
-
}), /* @__PURE__ */
|
|
107
|
+
}), /* @__PURE__ */ f("div", {
|
|
104
108
|
className: "w-24",
|
|
105
|
-
children: [/* @__PURE__ */
|
|
109
|
+
children: [/* @__PURE__ */ d("div", {
|
|
106
110
|
className: "flex items-center justify-between text-xs mb-0.5",
|
|
107
|
-
children: /* @__PURE__ */
|
|
108
|
-
className: `font-medium ${n > 100 ? "text-
|
|
111
|
+
children: /* @__PURE__ */ f("span", {
|
|
112
|
+
className: `font-medium ${n > 100 ? "text-status-error-text" : n < 70 ? "text-status-warning-text" : "text-status-success-text"}`,
|
|
109
113
|
children: [n, "%"]
|
|
110
114
|
})
|
|
111
|
-
}), /* @__PURE__ */
|
|
115
|
+
}), /* @__PURE__ */ d("div", {
|
|
112
116
|
className: "h-2 rounded-full bg-bg-sunken",
|
|
113
|
-
children: /* @__PURE__ */
|
|
114
|
-
className: `h-2 rounded-full ${n > 100 ? "bg-
|
|
117
|
+
children: /* @__PURE__ */ d("div", {
|
|
118
|
+
className: `h-2 rounded-full ${n > 100 ? "bg-status-error-text" : n < 70 ? "bg-status-warning-text" : "bg-status-success-text"}`,
|
|
115
119
|
style: { width: `${Math.min(n, 100)}%` }
|
|
116
120
|
})
|
|
117
121
|
})]
|
|
@@ -124,6 +128,6 @@ function f() {
|
|
|
124
128
|
});
|
|
125
129
|
}
|
|
126
130
|
//#endregion
|
|
127
|
-
export {
|
|
131
|
+
export { p as ResourcePlanningPage };
|
|
128
132
|
|
|
129
133
|
//# sourceMappingURL=ResourcePlanningPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResourcePlanningPage.js","names":[],"sources":["../../../../src/timecampus/pages/resource-planning/ResourcePlanningPage.tsx"],"sourcesContent":["import { CalendarRange, Users, TrendingUp } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { StatCard } from \"../../components/StatCard\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { getStatusColor, getInitials } from \"../../utils/helpers\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListResourcePlansQuery,\n useGetCapacityOverviewQuery,\n type ResourcePlanFieldsFragment,\n type ResourceAllocationFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function ResourcePlanningPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const now = new Date();\n const startDate = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate(),\n ).toISOString();\n const endDate = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate() + 7,\n ).toISOString();\n\n const {\n data: plansData,\n loading: plansLoading,\n error: plansError,\n } = useListResourcePlansQuery();\n const { data: capacityData } = useGetCapacityOverviewQuery({\n variables: { startDate, endDate },\n });\n\n const plans = plansData?.resourcePlans?.items ?? [];\n const capacity = capacityData?.capacityOverview;\n\n // Flatten all allocations across plans for display\n const allocations = plans.flatMap((plan: ResourcePlanFieldsFragment) =>\n plan.allocations.map((alloc: ResourceAllocationFieldsFragment) => ({\n ...alloc,\n planName: plan.name,\n })),\n );\n\n if (plansLoading) {\n return (\n <PageLayout\n title=\"Resource Planning\"\n description=\"Plan and optimize team resource allocation\"\n >\n <LoadingSkeleton variant=\"list\" count={5} />\n </PageLayout>\n );\n }\n\n if (plansError) {\n return (\n <PageLayout\n title=\"Resource Planning\"\n description=\"Plan and optimize team resource allocation\"\n >\n <div className=\"rounded-lg border border-
|
|
1
|
+
{"version":3,"file":"ResourcePlanningPage.js","names":[],"sources":["../../../../src/timecampus/pages/resource-planning/ResourcePlanningPage.tsx"],"sourcesContent":["import { CalendarRange, Users, TrendingUp } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { StatCard } from \"../../components/StatCard\";\nimport { EmptyState } from \"../../components/EmptyState\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { getStatusColor, getInitials } from \"../../utils/helpers\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListResourcePlansQuery,\n useGetCapacityOverviewQuery,\n type ResourcePlanFieldsFragment,\n type ResourceAllocationFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function ResourcePlanningPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const now = new Date();\n const startDate = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate(),\n ).toISOString();\n const endDate = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate() + 7,\n ).toISOString();\n\n const {\n data: plansData,\n loading: plansLoading,\n error: plansError,\n } = useListResourcePlansQuery();\n const { data: capacityData } = useGetCapacityOverviewQuery({\n variables: { startDate, endDate },\n });\n\n const plans = plansData?.resourcePlans?.items ?? [];\n const capacity = capacityData?.capacityOverview;\n\n // Flatten all allocations across plans for display\n const allocations = plans.flatMap((plan: ResourcePlanFieldsFragment) =>\n plan.allocations.map((alloc: ResourceAllocationFieldsFragment) => ({\n ...alloc,\n planName: plan.name,\n })),\n );\n\n if (plansLoading) {\n return (\n <PageLayout\n title=\"Resource Planning\"\n description=\"Plan and optimize team resource allocation\"\n >\n <LoadingSkeleton variant=\"list\" count={5} />\n </PageLayout>\n );\n }\n\n if (plansError) {\n return (\n <PageLayout\n title=\"Resource Planning\"\n description=\"Plan and optimize team resource allocation\"\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 resource planning data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n const utilizationRate = capacity?.utilizationRate ?? 0;\n const overallocatedCount = capacity?.overallocatedUsers?.length ?? 0;\n const availableHours = capacity?.availableCapacity ?? 0;\n\n return (\n <PageLayout\n title=\"Resource Planning\"\n description=\"Plan and optimize team resource allocation\"\n purpose=\"Match the work ahead to the people you have — see who's over- or under-booked and how much capacity is free this week — so you can commit to deadlines you can actually hit without burning anyone out.\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatCard\n featured\n title=\"Team Utilization\"\n value={`${Math.round(utilizationRate)}%`}\n icon={<TrendingUp className=\"h-5 w-5\" />}\n />\n <StatCard\n title=\"Over-allocated\"\n value={String(overallocatedCount)}\n icon={<Users className=\"h-5 w-5\" />}\n iconBgColor=\"bg-status-error-bg text-status-error-text\"\n />\n <StatCard\n title=\"Active Plans\"\n value={String(plans.length)}\n icon={<Users className=\"h-5 w-5\" />}\n />\n <StatCard\n title=\"Available Capacity\"\n value={`${Math.round(availableHours)}h`}\n icon={<CalendarRange className=\"h-5 w-5\" />}\n description=\"This week\"\n />\n </div>\n\n {allocations.length === 0 ? (\n <EmptyState\n illustration=\"empty-people\"\n title=\"No resource allocations found\"\n description=\"Create a resource plan to start allocating team members and balancing workload across the week.\"\n />\n ) : (\n <div className=\"rounded-xl border border-border-seam bg-gloss-card shadow-pop\">\n <div className=\"divide-y divide-border\">\n {allocations.map(\n (\n alloc: ResourceAllocationFieldsFragment & { planName: string },\n ) => {\n const utilization =\n alloc.utilizationRate ??\n (alloc.allocatedHours > 0\n ? Math.round(\n (alloc.actualHours / alloc.allocatedHours) * 100,\n )\n : 0);\n return (\n <div\n key={alloc.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 {getInitials(alloc.userId)}\n </div>\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {alloc.userId}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {alloc.planName} ·{\" \"}\n {alloc.startDate.slice(0, 10)} to{\" \"}\n {alloc.endDate.slice(0, 10)}\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 {alloc.allocatedHours}h allocated\n </p>\n </div>\n <div className=\"w-24\">\n <div className=\"flex items-center justify-between text-xs mb-0.5\">\n <span\n className={`font-medium ${utilization > 100 ? \"text-status-error-text\" : utilization < 70 ? \"text-status-warning-text\" : \"text-status-success-text\"}`}\n >\n {utilization}%\n </span>\n </div>\n <div className=\"h-2 rounded-full bg-bg-sunken\">\n <div\n className={`h-2 rounded-full ${utilization > 100 ? \"bg-status-error-text\" : utilization < 70 ? \"bg-status-warning-text\" : \"bg-status-success-text\"}`}\n style={{ width: `${Math.min(utilization, 100)}%` }}\n />\n </div>\n </div>\n </div>\n </div>\n );\n },\n )}\n </div>\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;AAcA,SAAgB,IAAuB;CACrC,IAAM,EAAE,iBAAc,OAAO,GAAe,EAEtC,oBAAM,IAAI,MAAM,EAChB,IAAY,IAAI,KACpB,EAAI,aAAa,EACjB,EAAI,UAAU,EACd,EAAI,SAAS,CACd,CAAC,aAAa,EACT,IAAU,IAAI,KAClB,EAAI,aAAa,EACjB,EAAI,UAAU,EACd,EAAI,SAAS,GAAG,EACjB,CAAC,aAAa,EAET,EACJ,MAAM,GACN,SAAS,GACT,OAAO,MACL,GAA2B,EACzB,EAAE,MAAM,MAAiB,EAA4B,EACzD,WAAW;EAAE;EAAW;EAAS,EAClC,CAAC,EAEI,IAAQ,GAAW,eAAe,SAAS,EAAE,EAC7C,IAAW,GAAc,kBAGzB,IAAc,EAAM,SAAS,MACjC,EAAK,YAAY,KAAK,OAA6C;EACjE,GAAG;EACH,UAAU,EAAK;EAChB,EAAE,CACJ;AAED,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,IAAkB,GAAU,mBAAmB,GAC/C,IAAqB,GAAU,oBAAoB,UAAU,GAC7D,IAAiB,GAAU,qBAAqB;AAEtD,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SAAQ;YAHV,CAKE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,GAAD;KACE,UAAA;KACA,OAAM;KACN,OAAO,GAAG,KAAK,MAAM,EAAgB,CAAC;KACtC,MAAM,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;KACxC,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,OAAO,EAAmB;KACjC,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;KACnC,aAAY;KACZ,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,OAAO,EAAM,OAAO;KAC3B,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;KACnC,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,GAAG,KAAK,MAAM,EAAe,CAAC;KACrC,MAAM,kBAAC,GAAD,EAAe,WAAU,WAAY,CAAA;KAC3C,aAAY;KACZ,CAAA;IACE;MAEL,EAAY,WAAW,IACtB,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,aAAY;GACZ,CAAA,GAEF,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAY,KAET,MACG;KACH,IAAM,IACJ,EAAM,oBACL,EAAM,iBAAiB,IACpB,KAAK,MACF,EAAM,cAAc,EAAM,iBAAkB,IAC9C,GACD;AACN,YACE,kBAAC,OAAD;MAEE,WAAU;gBAFZ,CAIE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBACZ,EAAY,EAAM,OAAO;QACtB,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAM;QACL,CAAA,EACJ,kBAAC,KAAD;QAAG,WAAU;kBAAb;SACG,EAAM;SAAS;SAAU;SACzB,EAAM,UAAU,MAAM,GAAG,GAAG;SAAC;SAAI;SACjC,EAAM,QAAQ,MAAM,GAAG,GAAG;SACzB;UACA,EAAA,CAAA,CACF;UACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,KAAD;SAAG,WAAU;mBAAb,CACG,EAAM,gBAAe,cACpB;;QACA,CAAA,EACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBACb,kBAAC,QAAD;UACE,WAAW,eAAe,IAAc,MAAM,2BAA2B,IAAc,KAAK,6BAA6B;oBAD3H,CAGG,GAAY,IACR;;SACH,CAAA,EACN,kBAAC,OAAD;SAAK,WAAU;mBACb,kBAAC,OAAD;UACE,WAAW,oBAAoB,IAAc,MAAM,yBAAyB,IAAc,KAAK,2BAA2B;UAC1H,OAAO,EAAE,OAAO,GAAG,KAAK,IAAI,GAAa,IAAI,CAAC,IAAI;UAClD,CAAA;SACE,CAAA,CACF;UACF;SACF;QAxCC,EAAM,GAwCP;MAGX;IACG,CAAA;GACF,CAAA,CAEG"}
|
|
@@ -1,33 +1,37 @@
|
|
|
1
1
|
import { useTimeCampus as e } from "../../providers/TimeCampusProvider.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { LoadingSkeleton as t } from "../../components/LoadingSkeleton.js";
|
|
3
|
+
import { useGetTimeEntryStatsQuery as n, useGetWorkPatternSummaryQuery as r } from "../../../generated/wspace-operations.js";
|
|
4
|
+
import { PageLayout as i } from "../../components/PageLayout.js";
|
|
5
5
|
import { BarChart3 as a, Users as o } from "lucide-react";
|
|
6
6
|
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
7
|
+
import { GlassCard as l } from "@burdenoff/fe-libs/ui";
|
|
7
8
|
//#region src/timecampus/pages/team/TeamAnalyticsPage.tsx
|
|
8
|
-
function
|
|
9
|
-
let { workspaceId:
|
|
10
|
-
return
|
|
9
|
+
function u() {
|
|
10
|
+
let { workspaceId: u = "" } = e(), { data: d, loading: f, error: p } = n({ skip: !u }), { data: m, loading: h } = r({ skip: !u }), g = d?.timeEntryStats, _ = m?.workPatternSummary;
|
|
11
|
+
return f || h ? /* @__PURE__ */ s(i, {
|
|
11
12
|
title: "Team Analytics",
|
|
12
13
|
description: "Team performance insights and metrics",
|
|
13
|
-
children: /* @__PURE__ */ s(
|
|
14
|
+
children: /* @__PURE__ */ s(t, {
|
|
14
15
|
variant: "card",
|
|
15
16
|
count: 4
|
|
16
17
|
})
|
|
17
|
-
}) :
|
|
18
|
+
}) : p ? /* @__PURE__ */ s(i, {
|
|
18
19
|
title: "Team Analytics",
|
|
19
20
|
description: "Team performance insights and metrics",
|
|
20
21
|
children: /* @__PURE__ */ s("div", {
|
|
21
|
-
className: "rounded-lg border border-
|
|
22
|
+
className: "rounded-lg border border-status-error-bg/40 bg-status-error-bg p-4 text-sm text-status-error-text",
|
|
22
23
|
children: "Failed to load team analytics. Please try again later."
|
|
23
24
|
})
|
|
24
|
-
}) : /* @__PURE__ */ s(
|
|
25
|
+
}) : /* @__PURE__ */ s(i, {
|
|
25
26
|
title: "Team Analytics",
|
|
26
27
|
description: "Team performance insights and metrics",
|
|
28
|
+
purpose: "Compare how your team works — hours by member, productive days, focus versus meeting time — so you can rebalance workload, recognise top contributors, and fix the patterns that slow everyone down.",
|
|
27
29
|
children: /* @__PURE__ */ c("div", {
|
|
28
30
|
className: "grid grid-cols-1 gap-6 lg:grid-cols-2",
|
|
29
|
-
children: [/* @__PURE__ */ c(
|
|
30
|
-
|
|
31
|
+
children: [/* @__PURE__ */ c(l, {
|
|
32
|
+
treatment: "glass",
|
|
33
|
+
glow: !0,
|
|
34
|
+
className: "p-6",
|
|
31
35
|
children: [/* @__PURE__ */ c("div", {
|
|
32
36
|
className: "mb-4 flex items-center gap-2",
|
|
33
37
|
children: [/* @__PURE__ */ s(o, { className: "h-5 w-5 text-primary" }), /* @__PURE__ */ s("h3", {
|
|
@@ -40,15 +44,15 @@ function l() {
|
|
|
40
44
|
className: "text-center",
|
|
41
45
|
children: [/* @__PURE__ */ s("p", {
|
|
42
46
|
className: "text-sm text-text-secondary",
|
|
43
|
-
children:
|
|
44
|
-
}),
|
|
47
|
+
children: g ? `${Math.round(g.totalHours)}h total · ${Math.round(g.billableHours)}h billable` : "No data available"
|
|
48
|
+
}), _?.mostProductiveDay && /* @__PURE__ */ c("p", {
|
|
45
49
|
className: "mt-1 text-xs text-text-secondary",
|
|
46
|
-
children: ["Most productive: ",
|
|
50
|
+
children: ["Most productive: ", _.mostProductiveDay]
|
|
47
51
|
})]
|
|
48
52
|
})
|
|
49
53
|
})]
|
|
50
54
|
}), /* @__PURE__ */ c("div", {
|
|
51
|
-
className: "rounded-xl border border-border-
|
|
55
|
+
className: "rounded-xl border border-border-seam bg-bg-surface shadow-elevation-1 p-6",
|
|
52
56
|
children: [/* @__PURE__ */ c("div", {
|
|
53
57
|
className: "mb-4 flex items-center gap-2",
|
|
54
58
|
children: [/* @__PURE__ */ s(a, { className: "h-5 w-5 text-primary" }), /* @__PURE__ */ s("h3", {
|
|
@@ -61,10 +65,10 @@ function l() {
|
|
|
61
65
|
className: "text-center",
|
|
62
66
|
children: [/* @__PURE__ */ s("p", {
|
|
63
67
|
className: "text-sm text-text-secondary",
|
|
64
|
-
children:
|
|
65
|
-
}),
|
|
68
|
+
children: _ ? `${Math.round(_.averageProductivity)}% avg productivity · ${_.averageFocusHours.toFixed(1)}h avg focus` : "No data available"
|
|
69
|
+
}), _?.insights && _.insights.length > 0 && /* @__PURE__ */ s("p", {
|
|
66
70
|
className: "mt-1 text-xs text-text-secondary",
|
|
67
|
-
children:
|
|
71
|
+
children: _.insights[0].title
|
|
68
72
|
})]
|
|
69
73
|
})
|
|
70
74
|
})]
|
|
@@ -73,6 +77,6 @@ function l() {
|
|
|
73
77
|
});
|
|
74
78
|
}
|
|
75
79
|
//#endregion
|
|
76
|
-
export {
|
|
80
|
+
export { u as TeamAnalyticsPage };
|
|
77
81
|
|
|
78
82
|
//# sourceMappingURL=TeamAnalyticsPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TeamAnalyticsPage.js","names":[],"sources":["../../../../src/timecampus/pages/team/TeamAnalyticsPage.tsx"],"sourcesContent":["import { BarChart3, Users } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useGetTimeEntryStatsQuery,\n useGetWorkPatternSummaryQuery,\n} from \"@/generated/wspace-operations\";\n\nexport function TeamAnalyticsPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const {\n data: statsData,\n loading: statsLoading,\n error: statsError,\n } = useGetTimeEntryStatsQuery({\n skip: !workspaceId,\n });\n\n const { data: patternData, loading: patternLoading } =\n useGetWorkPatternSummaryQuery({\n skip: !workspaceId,\n });\n\n const stats = statsData?.timeEntryStats;\n const pattern = patternData?.workPatternSummary;\n\n if (statsLoading || patternLoading) {\n return (\n <PageLayout\n title=\"Team Analytics\"\n description=\"Team performance insights and metrics\"\n >\n <LoadingSkeleton variant=\"card\" count={4} />\n </PageLayout>\n );\n }\n\n if (statsError) {\n return (\n <PageLayout\n title=\"Team Analytics\"\n description=\"Team performance insights and metrics\"\n >\n <div className=\"rounded-lg border border-
|
|
1
|
+
{"version":3,"file":"TeamAnalyticsPage.js","names":[],"sources":["../../../../src/timecampus/pages/team/TeamAnalyticsPage.tsx"],"sourcesContent":["import { BarChart3, Users } from \"lucide-react\";\nimport { GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useGetTimeEntryStatsQuery,\n useGetWorkPatternSummaryQuery,\n} from \"@/generated/wspace-operations\";\n\nexport function TeamAnalyticsPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const {\n data: statsData,\n loading: statsLoading,\n error: statsError,\n } = useGetTimeEntryStatsQuery({\n skip: !workspaceId,\n });\n\n const { data: patternData, loading: patternLoading } =\n useGetWorkPatternSummaryQuery({\n skip: !workspaceId,\n });\n\n const stats = statsData?.timeEntryStats;\n const pattern = patternData?.workPatternSummary;\n\n if (statsLoading || patternLoading) {\n return (\n <PageLayout\n title=\"Team Analytics\"\n description=\"Team performance insights and metrics\"\n >\n <LoadingSkeleton variant=\"card\" count={4} />\n </PageLayout>\n );\n }\n\n if (statsError) {\n return (\n <PageLayout\n title=\"Team Analytics\"\n description=\"Team performance insights and metrics\"\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 analytics. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Team Analytics\"\n description=\"Team performance insights and metrics\"\n purpose=\"Compare how your team works — hours by member, productive days, focus versus meeting time — so you can rebalance workload, recognise top contributors, and fix the patterns that slow everyone down.\"\n >\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-2\">\n <GlassCard treatment=\"glass\" glow className=\"p-6\">\n <div className=\"mb-4 flex items-center gap-2\">\n <Users className=\"h-5 w-5 text-primary\" />\n <h3 className=\"text-sm font-semibold text-text-primary\">\n Hours by Member\n </h3>\n </div>\n <div className=\"flex h-48 items-center justify-center rounded-lg border border-dashed border-border-subtle\">\n <div className=\"text-center\">\n <p className=\"text-sm text-text-secondary\">\n {stats\n ? `${Math.round(stats.totalHours)}h total · ${Math.round(stats.billableHours)}h billable`\n : \"No data available\"}\n </p>\n {pattern?.mostProductiveDay && (\n <p className=\"mt-1 text-xs text-text-secondary\">\n Most productive: {pattern.mostProductiveDay}\n </p>\n )}\n </div>\n </div>\n </GlassCard>\n <div className=\"rounded-xl border border-border-seam bg-bg-surface shadow-elevation-1 p-6\">\n <div className=\"mb-4 flex items-center gap-2\">\n <BarChart3 className=\"h-5 w-5 text-primary\" />\n <h3 className=\"text-sm font-semibold text-text-primary\">\n Productivity Trends\n </h3>\n </div>\n <div className=\"flex h-48 items-center justify-center rounded-lg border border-dashed border-border-subtle\">\n <div className=\"text-center\">\n <p className=\"text-sm text-text-secondary\">\n {pattern\n ? `${Math.round(pattern.averageProductivity)}% avg productivity · ${pattern.averageFocusHours.toFixed(1)}h avg focus`\n : \"No data available\"}\n </p>\n {pattern?.insights && pattern.insights.length > 0 && (\n <p className=\"mt-1 text-xs text-text-secondary\">\n {pattern.insights[0].title}\n </p>\n )}\n </div>\n </div>\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;AAUA,SAAgB,IAAoB;CAClC,IAAM,EAAE,iBAAc,OAAO,GAAe,EAEtC,EACJ,MAAM,GACN,SAAS,GACT,OAAO,MACL,EAA0B,EAC5B,MAAM,CAAC,GACR,CAAC,EAEI,EAAE,MAAM,GAAa,SAAS,MAClC,EAA8B,EAC5B,MAAM,CAAC,GACR,CAAC,EAEE,IAAQ,GAAW,gBACnB,IAAU,GAAa;AA0B7B,QAxBI,KAAgB,IAEhB,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,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;YAER,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD;IAAW,WAAU;IAAQ,MAAA;IAAK,WAAU;cAA5C,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAO,WAAU,wBAAyB,CAAA,EAC1C,kBAAC,MAAD;MAAI,WAAU;gBAA0C;MAEnD,CAAA,CACD;QACN,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,IACG,GAAG,KAAK,MAAM,EAAM,WAAW,CAAC,YAAY,KAAK,MAAM,EAAM,cAAc,CAAC,cAC5E;OACF,CAAA,EACH,GAAS,qBACR,kBAAC,KAAD;OAAG,WAAU;iBAAb,CAAgD,qBAC5B,EAAQ,kBACxB;SAEF;;KACF,CAAA,CACI;OACZ,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAW,WAAU,wBAAyB,CAAA,EAC9C,kBAAC,MAAD;MAAI,WAAU;gBAA0C;MAEnD,CAAA,CACD;QACN,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,IACG,GAAG,KAAK,MAAM,EAAQ,oBAAoB,CAAC,uBAAuB,EAAQ,kBAAkB,QAAQ,EAAE,CAAC,eACvG;OACF,CAAA,EACH,GAAS,YAAY,EAAQ,SAAS,SAAS,KAC9C,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAQ,SAAS,GAAG;OACnB,CAAA,CAEF;;KACF,CAAA,CACF;MACF;;EACK,CAAA"}
|