@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,69 +1,72 @@
1
1
  import { useTimeCampus as e } from "../../providers/TimeCampusProvider.js";
2
- import { PageLayout as t } from "../../components/PageLayout.js";
3
- import { LoadingSkeleton as n } from "../../components/LoadingSkeleton.js";
4
- import { useListConfigurationsQuery as r } from "../../../generated/wspace-operations.js";
5
- import { Sparkles as i, Star as a, Users as o } from "lucide-react";
6
- import { jsx as s, jsxs as c } from "react/jsx-runtime";
2
+ import { LoadingSkeleton as t } from "../../components/LoadingSkeleton.js";
3
+ import { useListConfigurationsQuery as n } from "../../../generated/wspace-operations.js";
4
+ import { PageLayout as r } from "../../components/PageLayout.js";
5
+ import { EmptyState as i } from "../../components/EmptyState.js";
6
+ import { Sparkles as a, Star as o, Users as s } from "lucide-react";
7
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
7
8
  //#region src/timecampus/pages/templates/TemplatesPage.tsx
8
- function l() {
9
- let { workspaceId: l = "" } = e(), { data: u, loading: d, error: f } = r({ variables: { scope: "WORKSPACE" } }), p = (u?.configurations ?? []).filter((e) => e.key.startsWith("template."));
10
- return d ? /* @__PURE__ */ s(t, {
9
+ function u() {
10
+ let { workspaceId: u = "" } = e(), { data: d, loading: f, error: p } = n({ variables: { scope: "WORKSPACE" } }), m = (d?.configurations ?? []).filter((e) => e.key.startsWith("template."));
11
+ return f ? /* @__PURE__ */ c(r, {
11
12
  title: "Templates",
12
13
  description: "Pre-built workspace templates for different workflows",
13
- children: /* @__PURE__ */ s(n, {
14
+ children: /* @__PURE__ */ c(t, {
14
15
  variant: "card",
15
16
  count: 6
16
17
  })
17
- }) : f ? /* @__PURE__ */ s(t, {
18
+ }) : p ? /* @__PURE__ */ c(r, {
18
19
  title: "Templates",
19
20
  description: "Pre-built workspace templates for different workflows",
20
- children: /* @__PURE__ */ s("div", {
21
- className: "rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-700 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400",
21
+ children: /* @__PURE__ */ c("div", {
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 template configurations. Please try again later."
23
24
  })
24
- }) : /* @__PURE__ */ s(t, {
25
+ }) : /* @__PURE__ */ c(r, {
25
26
  title: "Templates",
26
27
  description: "Pre-built workspace templates for different workflows",
27
- children: /* @__PURE__ */ s("div", {
28
+ purpose: "Skip the blank-page setup — apply a ready-made template that pre-loads projects, categories and settings for a common workflow, so a new team or workspace is productive in minutes.",
29
+ children: m.length === 0 ? /* @__PURE__ */ c(i, {
30
+ illustration: "empty-generic",
31
+ title: "No templates configured yet",
32
+ description: "Templates are stored as workspace configurations with the 'template.' key prefix — once added, ready-to-apply workflow setups appear here."
33
+ }) : /* @__PURE__ */ c("div", {
28
34
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
29
- children: p.length === 0 ? /* @__PURE__ */ s("div", {
30
- className: "col-span-full p-8 text-center text-sm text-text-secondary",
31
- children: "No templates configured yet. Templates are stored as workspace configurations with the \"template.\" key prefix."
32
- }) : p.map((e) => {
33
- let t = e.value, n = t.name ?? e.key.replace("template.", ""), r = t.category ?? "General", l = t.industry ?? "Any", u = t.rating ?? 0, d = t.teamSize ?? "-", f = t.downloads ?? 0;
34
- return /* @__PURE__ */ c("div", {
35
- className: "rounded-xl border border-border-subtle bg-bg-surface p-5 transition-colors hover:bg-bg-sunken/50 cursor-pointer",
36
- children: [/* @__PURE__ */ c("div", {
35
+ children: m.map((e) => {
36
+ let t = e.value, n = t.name ?? e.key.replace("template.", ""), r = t.category ?? "General", i = t.industry ?? "Any", u = t.rating ?? 0, d = t.teamSize ?? "-", f = t.downloads ?? 0;
37
+ return /* @__PURE__ */ l("div", {
38
+ className: "rounded-xl border border-border-seam bg-gloss-card shadow-pop p-5 transition-colors hover:bg-bg-sunken/50 cursor-pointer",
39
+ children: [/* @__PURE__ */ l("div", {
37
40
  className: "flex items-start gap-3",
38
- children: [/* @__PURE__ */ s("div", {
41
+ children: [/* @__PURE__ */ c("div", {
39
42
  className: "flex h-12 w-12 items-center justify-center rounded-xl bg-action-primary-bg/10",
40
- children: /* @__PURE__ */ s(i, { className: "h-6 w-6 text-primary" })
41
- }), /* @__PURE__ */ c("div", {
43
+ children: /* @__PURE__ */ c(a, { className: "h-6 w-6 text-primary" })
44
+ }), /* @__PURE__ */ l("div", {
42
45
  className: "flex-1",
43
- children: [/* @__PURE__ */ s("p", {
46
+ children: [/* @__PURE__ */ c("p", {
44
47
  className: "text-sm font-semibold text-text-primary",
45
48
  children: n
46
- }), /* @__PURE__ */ c("p", {
49
+ }), /* @__PURE__ */ l("p", {
47
50
  className: "text-xs text-text-secondary",
48
51
  children: [
49
52
  r,
50
53
  " · ",
51
- l
54
+ i
52
55
  ]
53
56
  })]
54
57
  })]
55
- }), /* @__PURE__ */ c("div", {
58
+ }), /* @__PURE__ */ l("div", {
56
59
  className: "mt-3 flex items-center justify-between text-xs text-text-secondary",
57
- children: [/* @__PURE__ */ c("div", {
60
+ children: [/* @__PURE__ */ l("div", {
58
61
  className: "flex items-center gap-3",
59
- children: [/* @__PURE__ */ c("div", {
62
+ children: [/* @__PURE__ */ l("div", {
60
63
  className: "flex items-center gap-1",
61
- children: [/* @__PURE__ */ s(a, { className: "h-3 w-3 fill-amber-400 text-amber-400" }), /* @__PURE__ */ s("span", { children: u })]
62
- }), /* @__PURE__ */ c("div", {
64
+ children: [/* @__PURE__ */ c(o, { className: "h-3 w-3 fill-amber-400 text-status-warning-text" }), /* @__PURE__ */ c("span", { children: u })]
65
+ }), /* @__PURE__ */ l("div", {
63
66
  className: "flex items-center gap-1",
64
- children: [/* @__PURE__ */ s(o, { className: "h-3 w-3" }), /* @__PURE__ */ s("span", { children: d })]
67
+ children: [/* @__PURE__ */ c(s, { className: "h-3 w-3" }), /* @__PURE__ */ c("span", { children: d })]
65
68
  })]
66
- }), /* @__PURE__ */ c("span", { children: [f, " uses"] })]
69
+ }), /* @__PURE__ */ l("span", { children: [f, " uses"] })]
67
70
  })]
68
71
  }, e.id);
69
72
  })
@@ -71,6 +74,6 @@ function l() {
71
74
  });
72
75
  }
73
76
  //#endregion
74
- export { l as TemplatesPage };
77
+ export { u as TemplatesPage };
75
78
 
76
79
  //# sourceMappingURL=TemplatesPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TemplatesPage.js","names":[],"sources":["../../../../src/timecampus/pages/templates/TemplatesPage.tsx"],"sourcesContent":["import { Sparkles, Star, Users } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListConfigurationsQuery,\n type ConfigurationFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function TemplatesPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const { data, loading, error } = useListConfigurationsQuery({\n variables: { scope: \"WORKSPACE\" as any },\n });\n\n const configurations = data?.configurations ?? [];\n\n // Filter configurations that represent templates (key starts with 'template.')\n const templates = configurations.filter((c: ConfigurationFieldsFragment) =>\n c.key.startsWith(\"template.\"),\n );\n\n if (loading) {\n return (\n <PageLayout\n title=\"Templates\"\n description=\"Pre-built workspace templates for different workflows\"\n >\n <LoadingSkeleton variant=\"card\" count={6} />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title=\"Templates\"\n description=\"Pre-built workspace templates for different workflows\"\n >\n <div className=\"rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-700 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400\">\n Failed to load template configurations. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Templates\"\n description=\"Pre-built workspace templates for different workflows\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {templates.length === 0 ? (\n <div className=\"col-span-full p-8 text-center text-sm text-text-secondary\">\n No templates configured yet. Templates are stored as workspace\n configurations with the \"template.\" key prefix.\n </div>\n ) : (\n templates.map((template: ConfigurationFieldsFragment) => {\n const val = template.value as Record<string, unknown>;\n const name =\n (val.name as string) ?? template.key.replace(\"template.\", \"\");\n const category = (val.category as string) ?? \"General\";\n const industry = (val.industry as string) ?? \"Any\";\n const rating = (val.rating as number) ?? 0;\n const teamSize = (val.teamSize as string) ?? \"-\";\n const downloads = (val.downloads as number) ?? 0;\n\n return (\n <div\n key={template.id}\n className=\"rounded-xl border border-border-subtle bg-bg-surface p-5 transition-colors hover:bg-bg-sunken/50 cursor-pointer\"\n >\n <div className=\"flex items-start gap-3\">\n <div className=\"flex h-12 w-12 items-center justify-center rounded-xl bg-action-primary-bg/10\">\n <Sparkles className=\"h-6 w-6 text-primary\" />\n </div>\n <div className=\"flex-1\">\n <p className=\"text-sm font-semibold text-text-primary\">\n {name}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {category} &middot; {industry}\n </p>\n </div>\n </div>\n <div className=\"mt-3 flex items-center justify-between text-xs text-text-secondary\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 fill-amber-400 text-amber-400\" />\n <span>{rating}</span>\n </div>\n <div className=\"flex items-center gap-1\">\n <Users className=\"h-3 w-3\" />\n <span>{teamSize}</span>\n </div>\n </div>\n <span>{downloads} uses</span>\n </div>\n </div>\n );\n })\n )}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;AASA,SAAgB,IAAgB;CAC9B,IAAM,EAAE,iBAAc,OAAO,GAAe,EAEtC,EAAE,SAAM,YAAS,aAAU,EAA2B,EAC1D,WAAW,EAAE,OAAO,aAAoB,EACzC,CAAC,EAKI,KAHiB,GAAM,kBAAkB,EAAE,EAGhB,QAAQ,MACvC,EAAE,IAAI,WAAW,YAAY,CAC9B;AA0BD,QAxBI,IAEA,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;aAA+H;GAExI,CAAA;EACK,CAAA,GAKf,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAU,WAAW,IACpB,kBAAC,OAAD;IAAK,WAAU;cAA4D;IAGrE,CAAA,GAEN,EAAU,KAAK,MAA0C;IACvD,IAAM,IAAM,EAAS,OACf,IACH,EAAI,QAAmB,EAAS,IAAI,QAAQ,aAAa,GAAG,EACzD,IAAY,EAAI,YAAuB,WACvC,IAAY,EAAI,YAAuB,OACvC,IAAU,EAAI,UAAqB,GACnC,IAAY,EAAI,YAAuB,KACvC,IAAa,EAAI,aAAwB;AAE/C,WACE,kBAAC,OAAD;KAEE,WAAU;eAFZ,CAIE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD,EAAU,WAAU,wBAAyB,CAAA;OACzC,CAAA,EACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBACV;QACC,CAAA,EACJ,kBAAC,KAAD;QAAG,WAAU;kBAAb;SACG;SAAS;SAAW;SACnB;UACA;SACF;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAM,WAAU,yCAA0C,CAAA,EAC1D,kBAAC,QAAD,EAAA,UAAO,GAAc,CAAA,CACjB;WACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA,EAC7B,kBAAC,QAAD,EAAA,UAAO,GAAgB,CAAA,CACnB;UACF;UACN,kBAAC,QAAD,EAAA,UAAA,CAAO,GAAU,QAAY,EAAA,CAAA,CACzB;QACF;OA7BC,EAAS,GA6BV;KAER;GAEA,CAAA;EACK,CAAA"}
1
+ {"version":3,"file":"TemplatesPage.js","names":[],"sources":["../../../../src/timecampus/pages/templates/TemplatesPage.tsx"],"sourcesContent":["import { Sparkles, Star, Users } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { EmptyState } from \"../../components/EmptyState\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListConfigurationsQuery,\n type ConfigurationFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function TemplatesPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const { data, loading, error } = useListConfigurationsQuery({\n variables: { scope: \"WORKSPACE\" as any },\n });\n\n const configurations = data?.configurations ?? [];\n\n // Filter configurations that represent templates (key starts with 'template.')\n const templates = configurations.filter((c: ConfigurationFieldsFragment) =>\n c.key.startsWith(\"template.\"),\n );\n\n if (loading) {\n return (\n <PageLayout\n title=\"Templates\"\n description=\"Pre-built workspace templates for different workflows\"\n >\n <LoadingSkeleton variant=\"card\" count={6} />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title=\"Templates\"\n description=\"Pre-built workspace templates for different workflows\"\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 template configurations. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Templates\"\n description=\"Pre-built workspace templates for different workflows\"\n purpose=\"Skip the blank-page setup — apply a ready-made template that pre-loads projects, categories and settings for a common workflow, so a new team or workspace is productive in minutes.\"\n >\n {templates.length === 0 ? (\n <EmptyState\n illustration=\"empty-generic\"\n title=\"No templates configured yet\"\n description=\"Templates are stored as workspace configurations with the 'template.' key prefix — once added, ready-to-apply workflow setups appear here.\"\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {templates.map((template: ConfigurationFieldsFragment) => {\n const val = template.value as Record<string, unknown>;\n const name =\n (val.name as string) ?? template.key.replace(\"template.\", \"\");\n const category = (val.category as string) ?? \"General\";\n const industry = (val.industry as string) ?? \"Any\";\n const rating = (val.rating as number) ?? 0;\n const teamSize = (val.teamSize as string) ?? \"-\";\n const downloads = (val.downloads as number) ?? 0;\n\n return (\n <div\n key={template.id}\n className=\"rounded-xl border border-border-seam bg-gloss-card shadow-pop p-5 transition-colors hover:bg-bg-sunken/50 cursor-pointer\"\n >\n <div className=\"flex items-start gap-3\">\n <div className=\"flex h-12 w-12 items-center justify-center rounded-xl bg-action-primary-bg/10\">\n <Sparkles className=\"h-6 w-6 text-primary\" />\n </div>\n <div className=\"flex-1\">\n <p className=\"text-sm font-semibold text-text-primary\">\n {name}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {category} &middot; {industry}\n </p>\n </div>\n </div>\n <div className=\"mt-3 flex items-center justify-between text-xs text-text-secondary\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 fill-amber-400 text-status-warning-text\" />\n <span>{rating}</span>\n </div>\n <div className=\"flex items-center gap-1\">\n <Users className=\"h-3 w-3\" />\n <span>{teamSize}</span>\n </div>\n </div>\n <span>{downloads} uses</span>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;AAUA,SAAgB,IAAgB;CAC9B,IAAM,EAAE,iBAAc,OAAO,GAAe,EAEtC,EAAE,SAAM,YAAS,aAAU,EAA2B,EAC1D,WAAW,EAAE,OAAO,aAAoB,EACzC,CAAC,EAKI,KAHiB,GAAM,kBAAkB,EAAE,EAGhB,QAAQ,MACvC,EAAE,IAAI,WAAW,YAAY,CAC9B;AA0BD,QAxBI,IAEA,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;YAEP,EAAU,WAAW,IACpB,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,aAAY;GACZ,CAAA,GAEF,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAU,KAAK,MAA0C;IACxD,IAAM,IAAM,EAAS,OACf,IACH,EAAI,QAAmB,EAAS,IAAI,QAAQ,aAAa,GAAG,EACzD,IAAY,EAAI,YAAuB,WACvC,IAAY,EAAI,YAAuB,OACvC,IAAU,EAAI,UAAqB,GACnC,IAAY,EAAI,YAAuB,KACvC,IAAa,EAAI,aAAwB;AAE/C,WACE,kBAAC,OAAD;KAEE,WAAU;eAFZ,CAIE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD,EAAU,WAAU,wBAAyB,CAAA;OACzC,CAAA,EACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBACV;QACC,CAAA,EACJ,kBAAC,KAAD;QAAG,WAAU;kBAAb;SACG;SAAS;SAAW;SACnB;UACA;SACF;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAM,WAAU,mDAAoD,CAAA,EACpE,kBAAC,QAAD,EAAA,UAAO,GAAc,CAAA,CACjB;WACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA,EAC7B,kBAAC,QAAD,EAAA,UAAO,GAAgB,CAAA,CACnB;UACF;UACN,kBAAC,QAAD,EAAA,UAAA,CAAO,GAAU,QAAY,EAAA,CAAA,CACzB;QACF;OA7BC,EAAS,GA6BV;KAER;GACE,CAAA;EAEG,CAAA"}
@@ -1,110 +1,119 @@
1
1
  import { formatDate as e, formatHours as t, getStatusColor as n } from "../../utils/helpers.js";
2
- import { PageLayout as r } from "../../components/PageLayout.js";
3
- import { LoadingSkeleton as i } from "../../components/LoadingSkeleton.js";
4
- import { useListTimeEntriesQuery as a } from "../../../generated/wspace-operations.js";
5
- import { Filter as o, Plus as s } from "lucide-react";
6
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
2
+ import { LoadingSkeleton as r } from "../../components/LoadingSkeleton.js";
3
+ import { useListTimeEntriesQuery as i } from "../../../generated/wspace-operations.js";
4
+ import { PageLayout as a } from "../../components/PageLayout.js";
5
+ import { EmptyState as o } from "../../components/EmptyState.js";
6
+ import { Filter as s, Plus as c } from "lucide-react";
7
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
8
+ import { GlassCard as d } from "@burdenoff/fe-libs/ui";
7
9
  //#region src/timecampus/pages/time/TimeEntriesPage.tsx
8
- function u() {
9
- let { data: u, loading: d, error: f } = a({ variables: { limit: 50 } }), p = u?.timeEntries?.items ?? [];
10
- return f ? /* @__PURE__ */ c(r, {
10
+ function f() {
11
+ let { data: f, loading: p, error: m } = i({ variables: { limit: 50 } }), h = f?.timeEntries?.items ?? [];
12
+ return m ? /* @__PURE__ */ l(a, {
11
13
  title: "Time Entries",
12
14
  description: "View and manage all time entries",
13
- children: /* @__PURE__ */ c("div", {
14
- className: "rounded-xl border border-red-200 bg-red-50 p-6 text-sm text-red-700 dark:border-red-900 dark:bg-red-950/50 dark:text-red-400",
15
+ children: /* @__PURE__ */ l("div", {
16
+ className: "rounded-xl border border-status-error-bg/40 bg-status-error-bg p-6 text-sm text-status-error-text",
15
17
  children: "Failed to load time entries. Please try again later."
16
18
  })
17
- }) : /* @__PURE__ */ c(r, {
19
+ }) : /* @__PURE__ */ l(a, {
18
20
  title: "Time Entries",
19
21
  description: "View and manage all time entries",
20
- actions: /* @__PURE__ */ l("div", {
22
+ purpose: "Every tracked block of work in one auditable list — filter, correct and confirm entries here before they roll into timesheets, approvals and client invoices.",
23
+ actions: /* @__PURE__ */ u("div", {
21
24
  className: "flex items-center gap-2",
22
- children: [/* @__PURE__ */ l("button", {
25
+ children: [/* @__PURE__ */ u("button", {
23
26
  className: "inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50",
24
- children: [/* @__PURE__ */ c(o, { className: "h-4 w-4" }), "Filter"]
25
- }), /* @__PURE__ */ l("button", {
27
+ children: [/* @__PURE__ */ l(s, { className: "h-4 w-4" }), "Filter"]
28
+ }), /* @__PURE__ */ u("button", {
26
29
  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",
27
- children: [/* @__PURE__ */ c(s, { className: "h-4 w-4" }), "Add Entry"]
30
+ children: [/* @__PURE__ */ l(c, { className: "h-4 w-4" }), "Add Entry"]
28
31
  })]
29
32
  }),
30
- children: d ? /* @__PURE__ */ c(i, {
33
+ children: p ? /* @__PURE__ */ l(r, {
31
34
  variant: "table",
32
35
  count: 5
33
- }) : /* @__PURE__ */ c("div", {
34
- className: "rounded-xl border border-border-subtle bg-bg-surface",
35
- children: /* @__PURE__ */ c("div", {
36
+ }) : h.length === 0 ? /* @__PURE__ */ l(o, {
37
+ illustration: "empty-data",
38
+ title: "No time entries found",
39
+ description: "Track time with a timer or add a manual entry — your entries will appear here.",
40
+ action: /* @__PURE__ */ u("button", {
41
+ 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",
42
+ children: [/* @__PURE__ */ l(c, { className: "h-4 w-4" }), "Add Entry"]
43
+ })
44
+ }) : /* @__PURE__ */ l(d, {
45
+ treatment: "glass",
46
+ glow: !0,
47
+ className: "overflow-hidden",
48
+ children: /* @__PURE__ */ l("div", {
36
49
  className: "overflow-x-auto",
37
- children: /* @__PURE__ */ l("table", {
50
+ children: /* @__PURE__ */ u("table", {
38
51
  className: "w-full",
39
- children: [/* @__PURE__ */ c("thead", { children: /* @__PURE__ */ l("tr", {
52
+ children: [/* @__PURE__ */ l("thead", { children: /* @__PURE__ */ u("tr", {
40
53
  className: "border-b border-border-subtle",
41
54
  children: [
42
- /* @__PURE__ */ c("th", {
55
+ /* @__PURE__ */ l("th", {
43
56
  className: "px-4 py-3 text-left text-xs font-medium text-text-secondary",
44
57
  children: "Date"
45
58
  }),
46
- /* @__PURE__ */ c("th", {
59
+ /* @__PURE__ */ l("th", {
47
60
  className: "px-4 py-3 text-left text-xs font-medium text-text-secondary",
48
61
  children: "Project"
49
62
  }),
50
- /* @__PURE__ */ c("th", {
63
+ /* @__PURE__ */ l("th", {
51
64
  className: "px-4 py-3 text-left text-xs font-medium text-text-secondary",
52
65
  children: "Task"
53
66
  }),
54
- /* @__PURE__ */ c("th", {
67
+ /* @__PURE__ */ l("th", {
55
68
  className: "px-4 py-3 text-left text-xs font-medium text-text-secondary",
56
69
  children: "Duration"
57
70
  }),
58
- /* @__PURE__ */ c("th", {
71
+ /* @__PURE__ */ l("th", {
59
72
  className: "px-4 py-3 text-left text-xs font-medium text-text-secondary",
60
73
  children: "Billable"
61
74
  }),
62
- /* @__PURE__ */ c("th", {
75
+ /* @__PURE__ */ l("th", {
63
76
  className: "px-4 py-3 text-left text-xs font-medium text-text-secondary",
64
77
  children: "Status"
65
78
  })
66
79
  ]
67
80
  }) }), /* @__PURE__ */ l("tbody", {
68
81
  className: "divide-y divide-border",
69
- children: [p.map((r) => /* @__PURE__ */ l("tr", {
82
+ children: h.map((r) => /* @__PURE__ */ u("tr", {
70
83
  className: "hover:bg-bg-sunken/50 transition-colors",
71
84
  children: [
72
- /* @__PURE__ */ c("td", {
85
+ /* @__PURE__ */ l("td", {
73
86
  className: "px-4 py-3 text-sm text-text-secondary",
74
87
  children: e(r.startTime)
75
88
  }),
76
- /* @__PURE__ */ c("td", {
89
+ /* @__PURE__ */ l("td", {
77
90
  className: "px-4 py-3 text-sm font-medium text-text-primary",
78
91
  children: r.project?.name ?? "No Project"
79
92
  }),
80
- /* @__PURE__ */ c("td", {
93
+ /* @__PURE__ */ l("td", {
81
94
  className: "px-4 py-3 text-sm text-text-secondary",
82
95
  children: r.task?.title ?? r.description ?? "No description"
83
96
  }),
84
- /* @__PURE__ */ c("td", {
97
+ /* @__PURE__ */ l("td", {
85
98
  className: "px-4 py-3 text-sm font-mono text-text-primary",
86
99
  children: t((r.duration ?? 0) / 3600)
87
100
  }),
88
- /* @__PURE__ */ c("td", {
101
+ /* @__PURE__ */ l("td", {
89
102
  className: "px-4 py-3",
90
- children: /* @__PURE__ */ c("span", {
91
- className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${r.billable ? "bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-400" : "bg-gray-100 text-gray-600 dark:bg-gray-900/30 dark:text-gray-400"}`,
103
+ children: /* @__PURE__ */ l("span", {
104
+ className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${r.billable ? "bg-status-success-bg text-status-success-text" : "bg-bg-sunken text-text-secondary"}`,
92
105
  children: r.billable ? "Yes" : "No"
93
106
  })
94
107
  }),
95
- /* @__PURE__ */ c("td", {
108
+ /* @__PURE__ */ l("td", {
96
109
  className: "px-4 py-3",
97
- children: /* @__PURE__ */ c("span", {
110
+ children: /* @__PURE__ */ l("span", {
98
111
  className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${n(r.isRunning ? "running" : "completed")}`,
99
112
  children: r.isRunning ? "running" : "completed"
100
113
  })
101
114
  })
102
115
  ]
103
- }, r.id)), p.length === 0 && /* @__PURE__ */ c("tr", { children: /* @__PURE__ */ c("td", {
104
- colSpan: 6,
105
- className: "px-4 py-8 text-center text-sm text-text-secondary",
106
- children: "No time entries found"
107
- }) })]
116
+ }, r.id))
108
117
  })]
109
118
  })
110
119
  })
@@ -112,6 +121,6 @@ function u() {
112
121
  });
113
122
  }
114
123
  //#endregion
115
- export { u as TimeEntriesPage };
124
+ export { f as TimeEntriesPage };
116
125
 
117
126
  //# sourceMappingURL=TimeEntriesPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TimeEntriesPage.js","names":[],"sources":["../../../../src/timecampus/pages/time/TimeEntriesPage.tsx"],"sourcesContent":["import { Clock, Plus, Filter } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { formatHours, formatDate, getStatusColor } from \"../../utils/helpers\";\nimport {\n useListTimeEntriesQuery,\n type TimeEntryFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function TimeEntriesPage() {\n const { data, loading, error } = useListTimeEntriesQuery({\n variables: { limit: 50 },\n });\n\n const entries = data?.timeEntries?.items ?? [];\n\n if (error) {\n return (\n <PageLayout\n title=\"Time Entries\"\n description=\"View and manage all time entries\"\n >\n <div className=\"rounded-xl border border-red-200 bg-red-50 p-6 text-sm text-red-700 dark:border-red-900 dark:bg-red-950/50 dark:text-red-400\">\n Failed to load time entries. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Time Entries\"\n description=\"View and manage all time entries\"\n actions={\n <div className=\"flex items-center gap-2\">\n <button className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50\">\n <Filter className=\"h-4 w-4\" />\n Filter\n </button>\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 Entry\n </button>\n </div>\n }\n >\n {loading ? (\n <LoadingSkeleton variant=\"table\" count={5} />\n ) : (\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface\">\n <div className=\"overflow-x-auto\">\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b border-border-subtle\">\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary\">\n Date\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary\">\n Project\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary\">\n Task\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary\">\n Duration\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary\">\n Billable\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary\">\n Status\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {entries.map((entry: TimeEntryFieldsFragment) => (\n <tr\n key={entry.id}\n className=\"hover:bg-bg-sunken/50 transition-colors\"\n >\n <td className=\"px-4 py-3 text-sm text-text-secondary\">\n {formatDate(entry.startTime)}\n </td>\n <td className=\"px-4 py-3 text-sm font-medium text-text-primary\">\n {entry.project?.name ?? \"No Project\"}\n </td>\n <td className=\"px-4 py-3 text-sm text-text-secondary\">\n {entry.task?.title ??\n entry.description ??\n \"No description\"}\n </td>\n <td className=\"px-4 py-3 text-sm font-mono text-text-primary\">\n {formatHours((entry.duration ?? 0) / 3600)}\n </td>\n <td className=\"px-4 py-3\">\n <span\n className={`inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${entry.billable ? \"bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-400\" : \"bg-gray-100 text-gray-600 dark:bg-gray-900/30 dark:text-gray-400\"}`}\n >\n {entry.billable ? \"Yes\" : \"No\"}\n </span>\n </td>\n <td className=\"px-4 py-3\">\n <span\n className={`inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${getStatusColor(entry.isRunning ? \"running\" : \"completed\")}`}\n >\n {entry.isRunning ? \"running\" : \"completed\"}\n </span>\n </td>\n </tr>\n ))}\n {entries.length === 0 && (\n <tr>\n <td\n colSpan={6}\n className=\"px-4 py-8 text-center text-sm text-text-secondary\"\n >\n No time entries found\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;AASA,SAAgB,IAAkB;CAChC,IAAM,EAAE,SAAM,YAAS,aAAU,EAAwB,EACvD,WAAW,EAAE,OAAO,IAAI,EACzB,CAAC,EAEI,IAAU,GAAM,aAAa,SAAS,EAAE;AAe9C,QAbI,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,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,UAAD;IAAQ,WAAU;cAAlB,CACE,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA,EAAA,SAEvB;OACT,kBAAC,UAAD;IAAQ,WAAU;cAAlB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,YAErB;MACL;;YAGP,IACC,kBAAC,GAAD;GAAiB,SAAQ;GAAQ,OAAO;GAAK,CAAA,GAE7C,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,SAAD;KAAO,WAAU;eAAjB,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD;MAAI,WAAU;gBAAd;OACE,kBAAC,MAAD;QAAI,WAAU;kBAA8D;QAEvE,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBAA8D;QAEvE,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBAA8D;QAEvE,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBAA8D;QAEvE,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBAA8D;QAEvE,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBAA8D;QAEvE,CAAA;OACF;SACC,CAAA,EACR,kBAAC,SAAD;MAAO,WAAU;gBAAjB,CACG,EAAQ,KAAK,MACZ,kBAAC,MAAD;OAEE,WAAU;iBAFZ;QAIE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAW,EAAM,UAAU;SACzB,CAAA;QACL,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAM,SAAS,QAAQ;SACrB,CAAA;QACL,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAM,MAAM,SACX,EAAM,eACN;SACC,CAAA;QACL,kBAAC,MAAD;SAAI,WAAU;mBACX,GAAa,EAAM,YAAY,KAAK,KAAK;SACvC,CAAA;QACL,kBAAC,MAAD;SAAI,WAAU;mBACZ,kBAAC,QAAD;UACE,WAAW,4DAA4D,EAAM,WAAW,iFAAiF;oBAExK,EAAM,WAAW,QAAQ;UACrB,CAAA;SACJ,CAAA;QACL,kBAAC,MAAD;SAAI,WAAU;mBACZ,kBAAC,QAAD;UACE,WAAW,4DAA4D,EAAe,EAAM,YAAY,YAAY,YAAY;oBAE/H,EAAM,YAAY,YAAY;UAC1B,CAAA;SACJ,CAAA;QACF;SA/BE,EAAM,GA+BR,CACL,EACD,EAAQ,WAAW,KAClB,kBAAC,MAAD,EAAA,UACE,kBAAC,MAAD;OACE,SAAS;OACT,WAAU;iBACX;OAEI,CAAA,EACF,CAAA,CAED;QACF;;IACJ,CAAA;GACF,CAAA;EAEG,CAAA"}
1
+ {"version":3,"file":"TimeEntriesPage.js","names":[],"sources":["../../../../src/timecampus/pages/time/TimeEntriesPage.tsx"],"sourcesContent":["import { Plus, Filter } 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, formatDate, getStatusColor } from \"../../utils/helpers\";\nimport {\n useListTimeEntriesQuery,\n type TimeEntryFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function TimeEntriesPage() {\n const { data, loading, error } = useListTimeEntriesQuery({\n variables: { limit: 50 },\n });\n\n const entries = data?.timeEntries?.items ?? [];\n\n if (error) {\n return (\n <PageLayout\n title=\"Time Entries\"\n description=\"View and manage all time entries\"\n >\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 time entries. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Time Entries\"\n description=\"View and manage all time entries\"\n purpose=\"Every tracked block of work in one auditable list — filter, correct and confirm entries here before they roll into timesheets, approvals and client invoices.\"\n actions={\n <div className=\"flex items-center gap-2\">\n <button className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50\">\n <Filter className=\"h-4 w-4\" />\n Filter\n </button>\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 Entry\n </button>\n </div>\n }\n >\n {loading ? (\n <LoadingSkeleton variant=\"table\" count={5} />\n ) : entries.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n title=\"No time entries found\"\n description=\"Track time with a timer or add a manual entry — your entries will appear here.\"\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 Entry\n </button>\n }\n />\n ) : (\n <GlassCard treatment=\"glass\" glow className=\"overflow-hidden\">\n <div className=\"overflow-x-auto\">\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b border-border-subtle\">\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary\">\n Date\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary\">\n Project\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary\">\n Task\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary\">\n Duration\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary\">\n Billable\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary\">\n Status\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {entries.map((entry: TimeEntryFieldsFragment) => (\n <tr\n key={entry.id}\n className=\"hover:bg-bg-sunken/50 transition-colors\"\n >\n <td className=\"px-4 py-3 text-sm text-text-secondary\">\n {formatDate(entry.startTime)}\n </td>\n <td className=\"px-4 py-3 text-sm font-medium text-text-primary\">\n {entry.project?.name ?? \"No Project\"}\n </td>\n <td className=\"px-4 py-3 text-sm text-text-secondary\">\n {entry.task?.title ??\n entry.description ??\n \"No description\"}\n </td>\n <td className=\"px-4 py-3 text-sm font-mono text-text-primary\">\n {formatHours((entry.duration ?? 0) / 3600)}\n </td>\n <td className=\"px-4 py-3\">\n <span\n className={`inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${entry.billable ? \"bg-status-success-bg text-status-success-text\" : \"bg-bg-sunken text-text-secondary\"}`}\n >\n {entry.billable ? \"Yes\" : \"No\"}\n </span>\n </td>\n <td className=\"px-4 py-3\">\n <span\n className={`inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${getStatusColor(entry.isRunning ? \"running\" : \"completed\")}`}\n >\n {entry.isRunning ? \"running\" : \"completed\"}\n </span>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </GlassCard>\n )}\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;AAWA,SAAgB,IAAkB;CAChC,IAAM,EAAE,SAAM,YAAS,aAAU,EAAwB,EACvD,WAAW,EAAE,OAAO,IAAI,EACzB,CAAC,EAEI,IAAU,GAAM,aAAa,SAAS,EAAE;AAe9C,QAbI,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,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,UAAD;IAAQ,WAAU;cAAlB,CACE,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA,EAAA,SAEvB;OACT,kBAAC,UAAD;IAAQ,WAAU;cAAlB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,YAErB;MACL;;YAGP,IACC,kBAAC,GAAD;GAAiB,SAAQ;GAAQ,OAAO;GAAK,CAAA,GAC3C,EAAQ,WAAW,IACrB,kBAAC,GAAD;GACE,cAAa;GACb,OAAM;GACN,aAAY;GACZ,QACE,kBAAC,UAAD;IAAQ,WAAU;cAAlB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,YAErB;;GAEX,CAAA,GAEF,kBAAC,GAAD;GAAW,WAAU;GAAQ,MAAA;GAAK,WAAU;aAC1C,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,SAAD;KAAO,WAAU;eAAjB,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD;MAAI,WAAU;gBAAd;OACE,kBAAC,MAAD;QAAI,WAAU;kBAA8D;QAEvE,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBAA8D;QAEvE,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBAA8D;QAEvE,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBAA8D;QAEvE,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBAA8D;QAEvE,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBAA8D;QAEvE,CAAA;OACF;SACC,CAAA,EACR,kBAAC,SAAD;MAAO,WAAU;gBACd,EAAQ,KAAK,MACZ,kBAAC,MAAD;OAEE,WAAU;iBAFZ;QAIE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAW,EAAM,UAAU;SACzB,CAAA;QACL,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAM,SAAS,QAAQ;SACrB,CAAA;QACL,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAM,MAAM,SACX,EAAM,eACN;SACC,CAAA;QACL,kBAAC,MAAD;SAAI,WAAU;mBACX,GAAa,EAAM,YAAY,KAAK,KAAK;SACvC,CAAA;QACL,kBAAC,MAAD;SAAI,WAAU;mBACZ,kBAAC,QAAD;UACE,WAAW,4DAA4D,EAAM,WAAW,kDAAkD;oBAEzI,EAAM,WAAW,QAAQ;UACrB,CAAA;SACJ,CAAA;QACL,kBAAC,MAAD;SAAI,WAAU;mBACZ,kBAAC,QAAD;UACE,WAAW,4DAA4D,EAAe,EAAM,YAAY,YAAY,YAAY;oBAE/H,EAAM,YAAY,YAAY;UAC1B,CAAA;SACJ,CAAA;QACF;SA/BE,EAAM,GA+BR,CACL;MACI,CAAA,CACF;;IACJ,CAAA;GACI,CAAA;EAEH,CAAA"}
@@ -1,104 +1,105 @@
1
1
  import { formatHours as e, formatTimerDuration as t } from "../../utils/helpers.js";
2
- import { PageLayout as n } from "../../components/PageLayout.js";
3
- import { StatCard as r } from "../../components/StatCard.js";
4
- import { LoadingSkeleton as i } from "../../components/LoadingSkeleton.js";
5
- import { useTimeCampusStore as a } from "../../store/timecampusStore.js";
6
- import { useGetTimeEntryStatsQuery as o, useListTimeEntriesQuery as s } from "../../../generated/wspace-operations.js";
7
- import { Clock as c, Pause as l, Play as u, Square as d } from "lucide-react";
8
- import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
9
- import { useI18n as h } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
2
+ import { StatCard as n } from "../../components/StatCard.js";
3
+ import { LoadingSkeleton as r } from "../../components/LoadingSkeleton.js";
4
+ import { useTimeCampusStore as i } from "../../store/timecampusStore.js";
5
+ import { useGetTimeEntryStatsQuery as a, useListTimeEntriesQuery as o } from "../../../generated/wspace-operations.js";
6
+ import { PageLayout as s } from "../../components/PageLayout.js";
7
+ import { EmptyState as c } from "../../components/EmptyState.js";
8
+ import { Clock as l, Pause as u, Play as d, Square as f } from "lucide-react";
9
+ import { Fragment as p, jsx as m, jsxs as h } from "react/jsx-runtime";
10
+ import { useI18n as g } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
10
11
  //#region src/timecampus/pages/time/TimeTrackingPage.tsx
11
- function g() {
12
- let { t: g } = h(), _ = (e, t) => {
13
- let n = g(e);
12
+ function _() {
13
+ let { t: _ } = g(), v = (e, t) => {
14
+ let n = _(e);
14
15
  return n === e ? t : n;
15
- }, { activeTimer: v, startTimer: y, stopTimer: b } = a(), { data: x, loading: S } = o(), { data: C, loading: w } = s({ variables: { limit: 10 } }), T = x?.timeEntryStats, E = C?.timeEntries?.items ?? [];
16
- return S ? /* @__PURE__ */ p(n, {
17
- title: _("timecampus.timeTracking.title", "Time Tracking"),
18
- description: _("timecampus.timeTracking.description", "Track and manage your work hours"),
19
- children: /* @__PURE__ */ p(i, {
16
+ }, { activeTimer: y, startTimer: b, stopTimer: x } = i(), { data: S, loading: C } = a(), { data: w, loading: T } = o({ variables: { limit: 10 } }), E = S?.timeEntryStats, D = w?.timeEntries?.items ?? [];
17
+ return C ? /* @__PURE__ */ m(s, {
18
+ title: v("timecampus.timeTracking.title", "Time Tracking"),
19
+ description: v("timecampus.timeTracking.description", "Track and manage your work hours"),
20
+ children: /* @__PURE__ */ m(r, {
20
21
  variant: "card",
21
22
  count: 4
22
23
  })
23
- }) : /* @__PURE__ */ m(n, {
24
- title: _("timecampus.timeTracking.title", "Time Tracking"),
25
- description: _("timecampus.timeTracking.description", "Track and manage your work hours"),
26
- actions: /* @__PURE__ */ p("button", {
27
- onClick: () => v ? b() : y(),
28
- className: `inline-flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium ${v ? "bg-red-500 text-white hover:bg-red-600" : "bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90"}`,
29
- children: v ? /* @__PURE__ */ m(f, { children: [
30
- /* @__PURE__ */ p(d, { className: "h-4 w-4" }),
31
- _("timecampus.timeTracking.actions.stop", "Stop"),
24
+ }) : /* @__PURE__ */ h(s, {
25
+ title: v("timecampus.timeTracking.title", "Time Tracking"),
26
+ description: v("timecampus.timeTracking.description", "Track and manage your work hours"),
27
+ purpose: v("timecampus.timeTracking.purpose", "Start a timer the moment you begin work and your hours are captured automatically — review today's totals, see what's billable, and stop guessing where your day went."),
28
+ actions: /* @__PURE__ */ m("button", {
29
+ onClick: () => y ? x() : b(),
30
+ className: `inline-flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium ${y ? "bg-action-danger-bg text-action-primary-text hover:bg-action-danger-bg/90" : "bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90"}`,
31
+ children: y ? /* @__PURE__ */ h(p, { children: [
32
+ /* @__PURE__ */ m(f, { className: "h-4 w-4" }),
33
+ v("timecampus.timeTracking.actions.stop", "Stop"),
32
34
  " (",
33
- t(v.seconds),
35
+ t(y.seconds),
34
36
  ")"
35
- ] }) : /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(u, { className: "h-4 w-4" }), _("timecampus.timeTracking.actions.startTimer", "Start Timer")] })
37
+ ] }) : /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m(d, { className: "h-4 w-4" }), v("timecampus.timeTracking.actions.startTimer", "Start Timer")] })
36
38
  }),
37
- children: [/* @__PURE__ */ m("div", {
39
+ children: [/* @__PURE__ */ h("div", {
38
40
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4",
39
41
  children: [
40
- /* @__PURE__ */ p(r, {
41
- title: _("timecampus.timeTracking.stats.today", "Today"),
42
- value: e(T?.totalHours ?? 0),
43
- icon: /* @__PURE__ */ p(c, { className: "h-5 w-5" }),
42
+ /* @__PURE__ */ m(n, {
43
+ featured: !0,
44
+ title: v("timecampus.timeTracking.stats.today", "Today"),
45
+ value: e(E?.totalHours ?? 0),
46
+ icon: /* @__PURE__ */ m(l, { className: "h-5 w-5" }),
44
47
  trend: {
45
48
  value: 15,
46
- label: _("timecampus.timeTracking.stats.vsYesterday", "vs yesterday")
49
+ label: v("timecampus.timeTracking.stats.vsYesterday", "vs yesterday")
47
50
  }
48
51
  }),
49
- /* @__PURE__ */ p(r, {
50
- title: _("timecampus.timeTracking.stats.billable", "Billable"),
51
- value: e(T?.billableHours ?? 0),
52
- icon: /* @__PURE__ */ p(c, { className: "h-5 w-5" }),
53
- description: `${T?.totalEntries ?? 0} ${_("timecampus.timeTracking.stats.entries", "entries")}`
52
+ /* @__PURE__ */ m(n, {
53
+ title: v("timecampus.timeTracking.stats.billable", "Billable"),
54
+ value: e(E?.billableHours ?? 0),
55
+ icon: /* @__PURE__ */ m(l, { className: "h-5 w-5" }),
56
+ description: `${E?.totalEntries ?? 0} ${v("timecampus.timeTracking.stats.entries", "entries")}`
54
57
  }),
55
- /* @__PURE__ */ p(r, {
56
- title: _("timecampus.timeTracking.stats.activeTimers", "Active Timers"),
57
- value: T?.activeTimers ?? 0,
58
- icon: /* @__PURE__ */ p(c, { className: "h-5 w-5" }),
59
- description: _("timecampus.timeTracking.stats.currentlyRunning", "Currently running")
58
+ /* @__PURE__ */ m(n, {
59
+ title: v("timecampus.timeTracking.stats.activeTimers", "Active Timers"),
60
+ value: E?.activeTimers ?? 0,
61
+ icon: /* @__PURE__ */ m(l, { className: "h-5 w-5" }),
62
+ description: v("timecampus.timeTracking.stats.currentlyRunning", "Currently running")
60
63
  }),
61
- /* @__PURE__ */ p(r, {
62
- title: _("timecampus.timeTracking.stats.activeTimer", "Active Timer"),
63
- value: v ? t(v.seconds) : _("timecampus.timeTracking.stats.stopped", "Stopped"),
64
- icon: p(v ? l : u, { className: "h-5 w-5" })
64
+ /* @__PURE__ */ m(n, {
65
+ title: v("timecampus.timeTracking.stats.activeTimer", "Active Timer"),
66
+ value: y ? t(y.seconds) : v("timecampus.timeTracking.stats.stopped", "Stopped"),
67
+ icon: m(y ? u : d, { className: "h-5 w-5" })
65
68
  })
66
69
  ]
67
- }), /* @__PURE__ */ m("div", {
68
- className: "rounded-xl border border-border-subtle bg-bg-surface p-6",
69
- children: [/* @__PURE__ */ p("h3", {
70
+ }), /* @__PURE__ */ h("div", {
71
+ className: "rounded-xl border border-border-seam bg-gloss-card shadow-pop p-6",
72
+ children: [/* @__PURE__ */ m("h3", {
70
73
  className: "mb-4 text-sm font-semibold text-text-primary",
71
- children: _("timecampus.timeTracking.entries.title", "Today's Entries")
72
- }), w ? /* @__PURE__ */ p(i, {
74
+ children: v("timecampus.timeTracking.entries.title", "Today's Entries")
75
+ }), T ? /* @__PURE__ */ m(r, {
73
76
  variant: "list",
74
77
  count: 4
75
- }) : E.length === 0 ? /* @__PURE__ */ p("div", {
76
- className: "flex h-48 items-center justify-center rounded-lg border border-dashed border-border-subtle",
77
- children: /* @__PURE__ */ p("p", {
78
- className: "text-sm text-text-secondary",
79
- children: _("timecampus.timeTracking.entries.empty", "No time entries yet. Start a timer to begin tracking.")
80
- })
81
- }) : /* @__PURE__ */ p("div", {
78
+ }) : D.length === 0 ? /* @__PURE__ */ m(c, {
79
+ illustration: "empty-data",
80
+ title: v("timecampus.timeTracking.entries.empty.title", "No time entries yet"),
81
+ description: v("timecampus.timeTracking.entries.empty", "No time entries yet. Start a timer to begin tracking.")
82
+ }) : /* @__PURE__ */ m("div", {
82
83
  className: "flex flex-col gap-2",
83
- children: E.map((t) => /* @__PURE__ */ m("div", {
84
+ children: D.map((t) => /* @__PURE__ */ h("div", {
84
85
  className: "flex items-center justify-between rounded-lg border border-border-subtle p-3 transition-colors hover:bg-bg-sunken/50",
85
- children: [/* @__PURE__ */ m("div", {
86
+ children: [/* @__PURE__ */ h("div", {
86
87
  className: "min-w-0 flex-1",
87
- children: [/* @__PURE__ */ p("p", {
88
+ children: [/* @__PURE__ */ m("p", {
88
89
  className: "text-sm font-medium text-text-primary",
89
- children: t.project?.name ?? _("timecampus.timeTracking.entries.noProject", "No Project")
90
- }), /* @__PURE__ */ p("p", {
90
+ children: t.project?.name ?? v("timecampus.timeTracking.entries.noProject", "No Project")
91
+ }), /* @__PURE__ */ m("p", {
91
92
  className: "text-xs text-text-secondary",
92
- children: t.description ?? _("timecampus.timeTracking.entries.noDescription", "No description")
93
+ children: t.description ?? v("timecampus.timeTracking.entries.noDescription", "No description")
93
94
  })]
94
- }), /* @__PURE__ */ m("div", {
95
+ }), /* @__PURE__ */ h("div", {
95
96
  className: "ml-4 text-right",
96
- children: [/* @__PURE__ */ p("p", {
97
+ children: [/* @__PURE__ */ m("p", {
97
98
  className: "text-sm font-mono font-medium text-text-primary",
98
99
  children: e((t.duration ?? 0) / 3600)
99
- }), /* @__PURE__ */ p("span", {
100
- className: "inline-flex items-center 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",
101
- children: t.isRunning ? _("timecampus.timeTracking.entries.status.running", "running") : _("timecampus.timeTracking.entries.status.completed", "completed")
100
+ }), /* @__PURE__ */ m("span", {
101
+ className: "inline-flex items-center rounded-full bg-status-success-bg px-2 py-0.5 text-xs font-medium text-status-success-text",
102
+ children: t.isRunning ? v("timecampus.timeTracking.entries.status.running", "running") : v("timecampus.timeTracking.entries.status.completed", "completed")
102
103
  })]
103
104
  })]
104
105
  }, t.id))
@@ -107,6 +108,6 @@ function g() {
107
108
  });
108
109
  }
109
110
  //#endregion
110
- export { g as TimeTrackingPage };
111
+ export { _ as TimeTrackingPage };
111
112
 
112
113
  //# sourceMappingURL=TimeTrackingPage.js.map