@burdenoff/microfe-timecampus 2026.529.2 → 2026.624.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/ErrorBoundary.js +2 -2
- package/dist/timecampus/components/ErrorBoundary.js.map +1 -1
- package/dist/timecampus/components/LoadingSkeleton.js +8 -8
- package/dist/timecampus/components/LoadingSkeleton.js.map +1 -1
- package/dist/timecampus/components/PageLayout.js +2 -2
- package/dist/timecampus/components/PageLayout.js.map +1 -1
- package/dist/timecampus/components/StatCard.js +6 -6
- package/dist/timecampus/components/StatCard.js.map +1 -1
- package/dist/timecampus/pages/HomePage.js +31 -31
- package/dist/timecampus/pages/HomePage.js.map +1 -1
- package/dist/timecampus/pages/applets/AppletStorePage.js +7 -7
- package/dist/timecampus/pages/applets/AppletStorePage.js.map +1 -1
- package/dist/timecampus/pages/applets/InstalledAppletsPage.js +8 -8
- package/dist/timecampus/pages/applets/InstalledAppletsPage.js.map +1 -1
- package/dist/timecampus/pages/application-usage/ApplicationUsagePage.js +10 -10
- package/dist/timecampus/pages/application-usage/ApplicationUsagePage.js.map +1 -1
- package/dist/timecampus/pages/application-usage/ApplicationUsageSettingsPage.js +10 -10
- package/dist/timecampus/pages/application-usage/ApplicationUsageSettingsPage.js.map +1 -1
- package/dist/timecampus/pages/channels/ChannelsPage.js +6 -6
- package/dist/timecampus/pages/channels/ChannelsPage.js.map +1 -1
- package/dist/timecampus/pages/client-portal/ClientPortalPage.js +8 -8
- package/dist/timecampus/pages/client-portal/ClientPortalPage.js.map +1 -1
- package/dist/timecampus/pages/dashboard/AnalyticsPage.js +11 -11
- package/dist/timecampus/pages/dashboard/AnalyticsPage.js.map +1 -1
- package/dist/timecampus/pages/dashboard/ReportsPage.js +10 -10
- package/dist/timecampus/pages/dashboard/ReportsPage.js.map +1 -1
- package/dist/timecampus/pages/email-tracking/EmailAnalyticsPage.js +5 -5
- package/dist/timecampus/pages/email-tracking/EmailAnalyticsPage.js.map +1 -1
- package/dist/timecampus/pages/email-tracking/EmailSettingsPage.js +13 -13
- package/dist/timecampus/pages/email-tracking/EmailSettingsPage.js.map +1 -1
- package/dist/timecampus/pages/email-tracking/EmailTrackingPage.js +8 -8
- package/dist/timecampus/pages/email-tracking/EmailTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js +8 -8
- package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/focus-score/FocusScorePage.js +7 -7
- package/dist/timecampus/pages/focus-score/FocusScorePage.js.map +1 -1
- package/dist/timecampus/pages/focus-score/FocusScoreSettingsPage.js +10 -10
- package/dist/timecampus/pages/focus-score/FocusScoreSettingsPage.js.map +1 -1
- package/dist/timecampus/pages/geofencing/GeofencingPage.js +7 -7
- package/dist/timecampus/pages/geofencing/GeofencingPage.js.map +1 -1
- package/dist/timecampus/pages/geofencing/GeofencingSettingsPage.js +9 -9
- package/dist/timecampus/pages/geofencing/GeofencingSettingsPage.js.map +1 -1
- package/dist/timecampus/pages/industry-solutions/IndustrySolutionsPage.js +7 -7
- package/dist/timecampus/pages/industry-solutions/IndustrySolutionsPage.js.map +1 -1
- package/dist/timecampus/pages/location-tracking/LocationPrivacySettingsPage.js +12 -12
- package/dist/timecampus/pages/location-tracking/LocationPrivacySettingsPage.js.map +1 -1
- package/dist/timecampus/pages/location-tracking/LocationTrackingPage.js +8 -8
- package/dist/timecampus/pages/location-tracking/LocationTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/meetings/MeetingAnalyticsPage.js +4 -4
- package/dist/timecampus/pages/meetings/MeetingAnalyticsPage.js.map +1 -1
- package/dist/timecampus/pages/meetings/MeetingCreatePage.js +12 -12
- package/dist/timecampus/pages/meetings/MeetingCreatePage.js.map +1 -1
- package/dist/timecampus/pages/meetings/MeetingDetailPage.js +15 -15
- package/dist/timecampus/pages/meetings/MeetingDetailPage.js.map +1 -1
- package/dist/timecampus/pages/meetings/MeetingsPage.js +11 -11
- package/dist/timecampus/pages/meetings/MeetingsPage.js.map +1 -1
- package/dist/timecampus/pages/pomodoro/PomodoroAnalyticsPage.js +8 -8
- package/dist/timecampus/pages/pomodoro/PomodoroAnalyticsPage.js.map +1 -1
- package/dist/timecampus/pages/pomodoro/PomodoroPage.js +8 -8
- package/dist/timecampus/pages/pomodoro/PomodoroPage.js.map +1 -1
- package/dist/timecampus/pages/pomodoro/PomodoroSettingsPage.js +20 -20
- package/dist/timecampus/pages/pomodoro/PomodoroSettingsPage.js.map +1 -1
- package/dist/timecampus/pages/projects/ProjectCreatePage.js +14 -14
- package/dist/timecampus/pages/projects/ProjectCreatePage.js.map +1 -1
- package/dist/timecampus/pages/projects/ProjectDetailPage.js +8 -8
- package/dist/timecampus/pages/projects/ProjectDetailPage.js.map +1 -1
- package/dist/timecampus/pages/projects/ProjectsPage.js +11 -11
- package/dist/timecampus/pages/projects/ProjectsPage.js.map +1 -1
- package/dist/timecampus/pages/projects/TasksPage.js +7 -7
- package/dist/timecampus/pages/projects/TasksPage.js.map +1 -1
- package/dist/timecampus/pages/resource-planning/ResourcePlanningPage.js +8 -8
- package/dist/timecampus/pages/resource-planning/ResourcePlanningPage.js.map +1 -1
- package/dist/timecampus/pages/team/TeamAnalyticsPage.js +10 -10
- package/dist/timecampus/pages/team/TeamAnalyticsPage.js.map +1 -1
- package/dist/timecampus/pages/team/TeamMembersPage.js +10 -10
- package/dist/timecampus/pages/team/TeamMembersPage.js.map +1 -1
- package/dist/timecampus/pages/team/TeamPage.js +4 -4
- package/dist/timecampus/pages/team/TeamPage.js.map +1 -1
- package/dist/timecampus/pages/team-activity/TeamActivityPage.js +6 -6
- package/dist/timecampus/pages/team-activity/TeamActivityPage.js.map +1 -1
- package/dist/timecampus/pages/team-activity/TeamActivitySettingsPage.js +11 -11
- package/dist/timecampus/pages/team-activity/TeamActivitySettingsPage.js.map +1 -1
- package/dist/timecampus/pages/templates/TemplateApplicationPage.js +6 -6
- package/dist/timecampus/pages/templates/TemplateApplicationPage.js.map +1 -1
- package/dist/timecampus/pages/templates/TemplateDetailPage.js +10 -10
- package/dist/timecampus/pages/templates/TemplateDetailPage.js.map +1 -1
- package/dist/timecampus/pages/templates/TemplatesPage.js +6 -6
- package/dist/timecampus/pages/templates/TemplatesPage.js.map +1 -1
- package/dist/timecampus/pages/time/TimeEntriesPage.js +16 -16
- package/dist/timecampus/pages/time/TimeEntriesPage.js.map +1 -1
- package/dist/timecampus/pages/time/TimeTrackingPage.js +9 -9
- package/dist/timecampus/pages/time/TimeTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/time/TimerPage.js +12 -12
- package/dist/timecampus/pages/time/TimerPage.js.map +1 -1
- package/dist/timecampus/pages/time-approval/TimeApprovalPage.js +8 -8
- package/dist/timecampus/pages/time-approval/TimeApprovalPage.js.map +1 -1
- package/dist/timecampus/pages/widgets/WidgetDetailPage.js +10 -10
- package/dist/timecampus/pages/widgets/WidgetDetailPage.js.map +1 -1
- package/dist/timecampus/pages/widgets/WidgetsPage.js +7 -7
- package/dist/timecampus/pages/widgets/WidgetsPage.js.map +1 -1
- package/dist/timecampus/pages/work-patterns/WorkPatternsPage.js +9 -9
- package/dist/timecampus/pages/work-patterns/WorkPatternsPage.js.map +1 -1
- package/dist/timecampus/pages/work-patterns/WorkPatternsSettingsPage.js +10 -10
- package/dist/timecampus/pages/work-patterns/WorkPatternsSettingsPage.js.map +1 -1
- package/dist/timecampus/pages/workflows/WorkflowsPage.js +8 -8
- package/dist/timecampus/pages/workflows/WorkflowsPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -30,11 +30,11 @@ var a = class extends e {
|
|
|
30
30
|
children: [
|
|
31
31
|
/* @__PURE__ */ r(t, { className: "mb-4 h-12 w-12 text-red-500" }),
|
|
32
32
|
/* @__PURE__ */ r("h3", {
|
|
33
|
-
className: "text-lg font-medium text-
|
|
33
|
+
className: "text-lg font-medium text-text-primary",
|
|
34
34
|
children: "Something went wrong"
|
|
35
35
|
}),
|
|
36
36
|
/* @__PURE__ */ r("p", {
|
|
37
|
-
className: "mt-1 max-w-md text-sm text-
|
|
37
|
+
className: "mt-1 max-w-md text-sm text-text-secondary",
|
|
38
38
|
children: this.state.error?.message ?? "An unexpected error occurred while rendering this section."
|
|
39
39
|
}),
|
|
40
40
|
/* @__PURE__ */ i("button", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorBoundary.js","names":[],"sources":["../../../src/timecampus/components/ErrorBoundary.tsx"],"sourcesContent":["import { Component, type ReactNode, type ErrorInfo } from \"react\";\nimport { AlertTriangle, RefreshCw } from \"lucide-react\";\n\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\nexport class ErrorBoundary extends Component<\n ErrorBoundaryProps,\n ErrorBoundaryState\n> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n console.error(\"[TimeCampus ErrorBoundary]\", error, errorInfo);\n }\n\n handleReset = () => {\n this.setState({ hasError: false, error: null });\n };\n\n render() {\n if (this.state.hasError) {\n if (this.props.fallback) return this.props.fallback;\n\n return (\n <div className=\"flex flex-col items-center justify-center rounded-lg border border-dashed border-red-300 bg-red-50 p-12 text-center dark:border-red-800 dark:bg-red-900/10\">\n <AlertTriangle className=\"mb-4 h-12 w-12 text-red-500\" />\n <h3 className=\"text-lg font-medium text-
|
|
1
|
+
{"version":3,"file":"ErrorBoundary.js","names":[],"sources":["../../../src/timecampus/components/ErrorBoundary.tsx"],"sourcesContent":["import { Component, type ReactNode, type ErrorInfo } from \"react\";\nimport { AlertTriangle, RefreshCw } from \"lucide-react\";\n\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\nexport class ErrorBoundary extends Component<\n ErrorBoundaryProps,\n ErrorBoundaryState\n> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n console.error(\"[TimeCampus ErrorBoundary]\", error, errorInfo);\n }\n\n handleReset = () => {\n this.setState({ hasError: false, error: null });\n };\n\n render() {\n if (this.state.hasError) {\n if (this.props.fallback) return this.props.fallback;\n\n return (\n <div className=\"flex flex-col items-center justify-center rounded-lg border border-dashed border-red-300 bg-red-50 p-12 text-center dark:border-red-800 dark:bg-red-900/10\">\n <AlertTriangle className=\"mb-4 h-12 w-12 text-red-500\" />\n <h3 className=\"text-lg font-medium text-text-primary\">\n Something went wrong\n </h3>\n <p className=\"mt-1 max-w-md text-sm text-text-secondary\">\n {this.state.error?.message ??\n \"An unexpected error occurred while rendering this section.\"}\n </p>\n <button\n onClick={this.handleReset}\n className=\"mt-4 flex items-center gap-1.5 rounded-md bg-foreground px-4 py-2 text-sm font-medium text-background hover:opacity-90\"\n >\n <RefreshCw className=\"h-4 w-4\" /> Try Again\n </button>\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n"],"mappings":";;;;AAaA,IAAa,IAAb,cAAmC,EAGjC;CACA,YAAY,GAA2B;AAErC,EADA,MAAM,EAAM,EACZ,KAAK,QAAQ;GAAE,UAAU;GAAO,OAAO;GAAM;;CAG/C,OAAO,yBAAyB,GAAkC;AAChE,SAAO;GAAE,UAAU;GAAM;GAAO;;CAGlC,kBAAkB,GAAc,GAAsB;AACpD,UAAQ,MAAM,8BAA8B,GAAO,EAAU;;CAG/D,oBAAoB;AAClB,OAAK,SAAS;GAAE,UAAU;GAAO,OAAO;GAAM,CAAC;;CAGjD,SAAS;AAwBP,SAvBI,KAAK,MAAM,WACT,KAAK,MAAM,WAAiB,KAAK,MAAM,WAGzC,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,GAAD,EAAe,WAAU,+BAAgC,CAAA;IACzD,kBAAC,MAAD;KAAI,WAAU;eAAwC;KAEjD,CAAA;IACL,kBAAC,KAAD;KAAG,WAAU;eACV,KAAK,MAAM,OAAO,WACjB;KACA,CAAA;IACJ,kBAAC,UAAD;KACE,SAAS,KAAK;KACd,WAAU;eAFZ,CAIE,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA,EAAA,aAC1B;;IACL;OAIH,KAAK,MAAM"}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import { cn as e } from "../utils/helpers.js";
|
|
2
2
|
import { jsx as t, jsxs as n } from "react/jsx-runtime";
|
|
3
3
|
//#region src/timecampus/components/LoadingSkeleton.tsx
|
|
4
|
-
var r = ({ className: n }) => /* @__PURE__ */ t("div", { className: e("animate-pulse rounded-md bg-
|
|
4
|
+
var r = ({ className: n }) => /* @__PURE__ */ t("div", { className: e("animate-pulse rounded-md bg-bg-sunken", n) }), i = ({ variant: i = "card", count: a = 3, className: o }) => i === "table" ? /* @__PURE__ */ t("div", {
|
|
5
5
|
className: e("space-y-3", o),
|
|
6
6
|
children: /* @__PURE__ */ n("div", {
|
|
7
|
-
className: "overflow-hidden rounded-lg border border-border",
|
|
7
|
+
className: "overflow-hidden rounded-lg border border-border-subtle",
|
|
8
8
|
children: [/* @__PURE__ */ t("div", {
|
|
9
|
-
className: "border-b border-border bg-
|
|
9
|
+
className: "border-b border-border-subtle bg-bg-sunken/50 px-4 py-3",
|
|
10
10
|
children: /* @__PURE__ */ t("div", {
|
|
11
11
|
className: "flex gap-4",
|
|
12
12
|
children: Array.from({ length: 5 }).map((e, n) => /* @__PURE__ */ t(r, { className: "h-4 w-20" }, n))
|
|
13
13
|
})
|
|
14
14
|
}), Array.from({ length: a }).map((e, n) => /* @__PURE__ */ t("div", {
|
|
15
|
-
className: "flex gap-4 border-b border-border px-4 py-3 last:border-b-0",
|
|
15
|
+
className: "flex gap-4 border-b border-border-subtle px-4 py-3 last:border-b-0",
|
|
16
16
|
children: Array.from({ length: 5 }).map((e, n) => /* @__PURE__ */ t(r, { className: "h-4 w-20" }, n))
|
|
17
17
|
}, n))]
|
|
18
18
|
})
|
|
19
19
|
}) : i === "list" ? /* @__PURE__ */ t("div", {
|
|
20
20
|
className: e("space-y-2", o),
|
|
21
21
|
children: Array.from({ length: a }).map((e, i) => /* @__PURE__ */ n("div", {
|
|
22
|
-
className: "flex items-center gap-3 rounded-lg border border-border p-4",
|
|
22
|
+
className: "flex items-center gap-3 rounded-lg border border-border-subtle p-4",
|
|
23
23
|
children: [
|
|
24
24
|
/* @__PURE__ */ t(r, { className: "h-10 w-10 rounded-full" }),
|
|
25
25
|
/* @__PURE__ */ n("div", {
|
|
@@ -39,12 +39,12 @@ var r = ({ className: n }) => /* @__PURE__ */ t("div", { className: e("animate-p
|
|
|
39
39
|
/* @__PURE__ */ t("div", {
|
|
40
40
|
className: "grid gap-4 sm:grid-cols-3",
|
|
41
41
|
children: Array.from({ length: 3 }).map((e, i) => /* @__PURE__ */ n("div", {
|
|
42
|
-
className: "rounded-lg border border-border p-4",
|
|
42
|
+
className: "rounded-lg border border-border-subtle p-4",
|
|
43
43
|
children: [/* @__PURE__ */ t(r, { className: "h-3 w-20" }), /* @__PURE__ */ t(r, { className: "mt-2 h-7 w-16" })]
|
|
44
44
|
}, i))
|
|
45
45
|
}),
|
|
46
46
|
/* @__PURE__ */ n("div", {
|
|
47
|
-
className: "rounded-lg border border-border p-6",
|
|
47
|
+
className: "rounded-lg border border-border-subtle p-6",
|
|
48
48
|
children: [/* @__PURE__ */ t(r, { className: "h-5 w-1/4" }), /* @__PURE__ */ n("div", {
|
|
49
49
|
className: "mt-4 space-y-3",
|
|
50
50
|
children: [
|
|
@@ -58,7 +58,7 @@ var r = ({ className: n }) => /* @__PURE__ */ t("div", { className: e("animate-p
|
|
|
58
58
|
}) : /* @__PURE__ */ t("div", {
|
|
59
59
|
className: e("grid gap-4 sm:grid-cols-2 lg:grid-cols-3", o),
|
|
60
60
|
children: Array.from({ length: a }).map((e, i) => /* @__PURE__ */ n("div", {
|
|
61
|
-
className: "rounded-lg border border-border p-4",
|
|
61
|
+
className: "rounded-lg border border-border-subtle p-4",
|
|
62
62
|
children: [
|
|
63
63
|
/* @__PURE__ */ t(r, { className: "h-4 w-2/3" }),
|
|
64
64
|
/* @__PURE__ */ t(r, { className: "mt-2 h-3 w-1/2" }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoadingSkeleton.js","names":[],"sources":["../../../src/timecampus/components/LoadingSkeleton.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { cn } from \"../utils/helpers\";\n\ninterface SkeletonProps {\n className?: string;\n}\n\nconst Skeleton: FC<SkeletonProps> = ({ className }) => (\n <div className={cn(\"animate-pulse rounded-md bg-
|
|
1
|
+
{"version":3,"file":"LoadingSkeleton.js","names":[],"sources":["../../../src/timecampus/components/LoadingSkeleton.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { cn } from \"../utils/helpers\";\n\ninterface SkeletonProps {\n className?: string;\n}\n\nconst Skeleton: FC<SkeletonProps> = ({ className }) => (\n <div className={cn(\"animate-pulse rounded-md bg-bg-sunken\", className)} />\n);\n\ninterface LoadingSkeletonProps {\n variant?: \"card\" | \"table\" | \"list\" | \"detail\";\n count?: number;\n className?: string;\n}\n\nexport const LoadingSkeleton: FC<LoadingSkeletonProps> = ({\n variant = \"card\",\n count = 3,\n className,\n}) => {\n if (variant === \"table\") {\n return (\n <div className={cn(\"space-y-3\", className)}>\n <div className=\"overflow-hidden rounded-lg border border-border-subtle\">\n <div className=\"border-b border-border-subtle bg-bg-sunken/50 px-4 py-3\">\n <div className=\"flex gap-4\">\n {Array.from({ length: 5 }).map((_, i) => (\n <Skeleton key={i} className=\"h-4 w-20\" />\n ))}\n </div>\n </div>\n {Array.from({ length: count }).map((_, i) => (\n <div\n key={i}\n className=\"flex gap-4 border-b border-border-subtle px-4 py-3 last:border-b-0\"\n >\n {Array.from({ length: 5 }).map((_, j) => (\n <Skeleton key={j} className=\"h-4 w-20\" />\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n }\n\n if (variant === \"list\") {\n return (\n <div className={cn(\"space-y-2\", className)}>\n {Array.from({ length: count }).map((_, i) => (\n <div\n key={i}\n className=\"flex items-center gap-3 rounded-lg border border-border-subtle p-4\"\n >\n <Skeleton className=\"h-10 w-10 rounded-full\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-1/3\" />\n <Skeleton className=\"h-3 w-2/3\" />\n </div>\n <Skeleton className=\"h-6 w-16 rounded-full\" />\n </div>\n ))}\n </div>\n );\n }\n\n if (variant === \"detail\") {\n return (\n <div className={cn(\"space-y-6\", className)}>\n <div className=\"space-y-2\">\n <Skeleton className=\"h-8 w-1/3\" />\n <Skeleton className=\"h-4 w-1/2\" />\n </div>\n <div className=\"grid gap-4 sm:grid-cols-3\">\n {Array.from({ length: 3 }).map((_, i) => (\n <div key={i} className=\"rounded-lg border border-border-subtle p-4\">\n <Skeleton className=\"h-3 w-20\" />\n <Skeleton className=\"mt-2 h-7 w-16\" />\n </div>\n ))}\n </div>\n <div className=\"rounded-lg border border-border-subtle p-6\">\n <Skeleton className=\"h-5 w-1/4\" />\n <div className=\"mt-4 space-y-3\">\n <Skeleton className=\"h-4 w-full\" />\n <Skeleton className=\"h-4 w-5/6\" />\n <Skeleton className=\"h-4 w-4/6\" />\n </div>\n </div>\n </div>\n );\n }\n\n // Default: card grid\n return (\n <div className={cn(\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\", className)}>\n {Array.from({ length: count }).map((_, i) => (\n <div key={i} className=\"rounded-lg border border-border-subtle p-4\">\n <Skeleton className=\"h-4 w-2/3\" />\n <Skeleton className=\"mt-2 h-3 w-1/2\" />\n <Skeleton className=\"mt-4 h-8 w-24\" />\n <div className=\"mt-3 flex justify-between\">\n <Skeleton className=\"h-5 w-16 rounded-full\" />\n <Skeleton className=\"h-7 w-14 rounded-md\" />\n </div>\n </div>\n ))}\n </div>\n );\n};\n"],"mappings":";;;AAOA,IAAM,KAA+B,EAAE,mBACrC,kBAAC,OAAD,EAAK,WAAW,EAAG,yCAAyC,EAAU,EAAI,CAAA,EAS/D,KAA6C,EACxD,aAAU,QACV,WAAQ,GACR,mBAEI,MAAY,UAEZ,kBAAC,OAAD;CAAK,WAAW,EAAG,aAAa,EAAU;WACxC,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,OAAD;IAAK,WAAU;cACZ,MAAM,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,GAAG,MACjC,kBAAC,GAAD,EAAkB,WAAU,YAAa,EAA1B,EAA0B,CACzC;IACE,CAAA;GACF,CAAA,EACL,MAAM,KAAK,EAAE,QAAQ,GAAO,CAAC,CAAC,KAAK,GAAG,MACrC,kBAAC,OAAD;GAEE,WAAU;aAET,MAAM,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,GAAG,MACjC,kBAAC,GAAD,EAAkB,WAAU,YAAa,EAA1B,EAA0B,CACzC;GACE,EANC,EAMD,CACN,CACE;;CACF,CAAA,GAIN,MAAY,SAEZ,kBAAC,OAAD;CAAK,WAAW,EAAG,aAAa,EAAU;WACvC,MAAM,KAAK,EAAE,QAAQ,GAAO,CAAC,CAAC,KAAK,GAAG,MACrC,kBAAC,OAAD;EAEE,WAAU;YAFZ;GAIE,kBAAC,GAAD,EAAU,WAAU,0BAA2B,CAAA;GAC/C,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA,EAClC,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA,CAC9B;;GACN,kBAAC,GAAD,EAAU,WAAU,yBAA0B,CAAA;GAC1C;IATC,EASD,CACN;CACE,CAAA,GAIN,MAAY,WAEZ,kBAAC,OAAD;CAAK,WAAW,EAAG,aAAa,EAAU;WAA1C;EACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA,EAClC,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA,CAC9B;;EACN,kBAAC,OAAD;GAAK,WAAU;aACZ,MAAM,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,GAAG,MACjC,kBAAC,OAAD;IAAa,WAAU;cAAvB,CACE,kBAAC,GAAD,EAAU,WAAU,YAAa,CAAA,EACjC,kBAAC,GAAD,EAAU,WAAU,iBAAkB,CAAA,CAClC;MAHI,EAGJ,CACN;GACE,CAAA;EACN,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA,EAClC,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD,EAAU,WAAU,cAAe,CAAA;KACnC,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA;KAClC,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA;KAC9B;MACF;;EACF;KAMR,kBAAC,OAAD;CAAK,WAAW,EAAG,4CAA4C,EAAU;WACtE,MAAM,KAAK,EAAE,QAAQ,GAAO,CAAC,CAAC,KAAK,GAAG,MACrC,kBAAC,OAAD;EAAa,WAAU;YAAvB;GACE,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA;GAClC,kBAAC,GAAD,EAAU,WAAU,kBAAmB,CAAA;GACvC,kBAAC,GAAD,EAAU,WAAU,iBAAkB,CAAA;GACtC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAU,WAAU,yBAA0B,CAAA,EAC9C,kBAAC,GAAD,EAAU,WAAU,uBAAwB,CAAA,CACxC;;GACF;IARI,EAQJ,CACN;CACE,CAAA"}
|
|
@@ -6,10 +6,10 @@ var r = ({ title: r, description: i, actions: a, children: o, className: s }) =>
|
|
|
6
6
|
children: [/* @__PURE__ */ n("div", {
|
|
7
7
|
className: "mb-6 flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
|
|
8
8
|
children: [/* @__PURE__ */ n("div", { children: [/* @__PURE__ */ t("h1", {
|
|
9
|
-
className: "text-2xl font-bold text-
|
|
9
|
+
className: "text-2xl font-bold text-text-primary",
|
|
10
10
|
children: r
|
|
11
11
|
}), i && /* @__PURE__ */ t("p", {
|
|
12
|
-
className: "mt-1 text-sm text-
|
|
12
|
+
className: "mt-1 text-sm text-text-secondary",
|
|
13
13
|
children: i
|
|
14
14
|
})] }), a && /* @__PURE__ */ t("div", {
|
|
15
15
|
className: "flex items-center gap-2",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageLayout.js","names":[],"sources":["../../../src/timecampus/components/PageLayout.tsx"],"sourcesContent":["import type { FC, ReactNode } from \"react\";\nimport { cn } from \"../utils/helpers\";\n\ninterface PageLayoutProps {\n title: string;\n description?: string;\n actions?: ReactNode;\n children: ReactNode;\n className?: string;\n}\n\nexport const PageLayout: FC<PageLayoutProps> = ({\n title,\n description,\n actions,\n children,\n className,\n}) => {\n return (\n <div className={cn(\"min-h-full p-4 sm:p-6\", className)}>\n <div className=\"mb-6 flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold text-
|
|
1
|
+
{"version":3,"file":"PageLayout.js","names":[],"sources":["../../../src/timecampus/components/PageLayout.tsx"],"sourcesContent":["import type { FC, ReactNode } from \"react\";\nimport { cn } from \"../utils/helpers\";\n\ninterface PageLayoutProps {\n title: string;\n description?: string;\n actions?: ReactNode;\n children: ReactNode;\n className?: string;\n}\n\nexport const PageLayout: FC<PageLayoutProps> = ({\n title,\n description,\n actions,\n children,\n className,\n}) => {\n return (\n <div className={cn(\"min-h-full p-4 sm:p-6\", className)}>\n <div className=\"mb-6 flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">{title}</h1>\n {description && (\n <p className=\"mt-1 text-sm text-text-secondary\">{description}</p>\n )}\n </div>\n {actions && <div className=\"flex items-center gap-2\">{actions}</div>}\n </div>\n {children}\n </div>\n );\n};\n"],"mappings":";;;AAWA,IAAa,KAAmC,EAC9C,UACA,gBACA,YACA,aACA,mBAGE,kBAAC,OAAD;CAAK,WAAW,EAAG,yBAAyB,EAAU;WAAtD,CACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;GAAI,WAAU;aAAwC;GAAW,CAAA,EAChE,KACC,kBAAC,KAAD;GAAG,WAAU;aAAoC;GAAgB,CAAA,CAE/D,EAAA,CAAA,EACL,KAAW,kBAAC,OAAD;GAAK,WAAU;aAA2B;GAAc,CAAA,CAChE;KACL,EACG"}
|
|
@@ -3,18 +3,18 @@ import { ArrowDown as t, ArrowUp as n } from "lucide-react";
|
|
|
3
3
|
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
4
4
|
//#region src/timecampus/components/StatCard.tsx
|
|
5
5
|
var a = ({ title: a, value: o, icon: s, trend: c, description: l, className: u, iconBgColor: d }) => /* @__PURE__ */ r("div", {
|
|
6
|
-
className: e("rounded-xl border border-border bg-
|
|
6
|
+
className: e("rounded-xl border border-border-subtle bg-bg-surface p-4 sm:p-6", u),
|
|
7
7
|
children: /* @__PURE__ */ i("div", {
|
|
8
8
|
className: "flex items-start justify-between",
|
|
9
9
|
children: [/* @__PURE__ */ i("div", {
|
|
10
10
|
className: "flex-1 min-w-0",
|
|
11
11
|
children: [
|
|
12
12
|
/* @__PURE__ */ r("p", {
|
|
13
|
-
className: "text-sm font-medium text-
|
|
13
|
+
className: "text-sm font-medium text-text-secondary truncate",
|
|
14
14
|
children: a
|
|
15
15
|
}),
|
|
16
16
|
/* @__PURE__ */ r("p", {
|
|
17
|
-
className: "mt-2 text-2xl font-bold text-
|
|
17
|
+
className: "mt-2 text-2xl font-bold text-text-primary",
|
|
18
18
|
children: o
|
|
19
19
|
}),
|
|
20
20
|
c && /* @__PURE__ */ i("div", {
|
|
@@ -26,18 +26,18 @@ var a = ({ title: a, value: o, icon: s, trend: c, description: l, className: u,
|
|
|
26
26
|
children: [Math.abs(c.value), "%"]
|
|
27
27
|
}),
|
|
28
28
|
/* @__PURE__ */ r("span", {
|
|
29
|
-
className: "text-xs text-
|
|
29
|
+
className: "text-xs text-text-secondary",
|
|
30
30
|
children: c.label
|
|
31
31
|
})
|
|
32
32
|
]
|
|
33
33
|
}),
|
|
34
34
|
l && /* @__PURE__ */ r("p", {
|
|
35
|
-
className: "mt-1 text-xs text-
|
|
35
|
+
className: "mt-1 text-xs text-text-secondary",
|
|
36
36
|
children: l
|
|
37
37
|
})
|
|
38
38
|
]
|
|
39
39
|
}), s && /* @__PURE__ */ r("div", {
|
|
40
|
-
className: e("flex h-10 w-10 shrink-0 items-center justify-center rounded-lg", d || "bg-primary/10 text-primary"),
|
|
40
|
+
className: e("flex h-10 w-10 shrink-0 items-center justify-center rounded-lg", d || "bg-action-primary-bg/10 text-primary"),
|
|
41
41
|
children: s
|
|
42
42
|
})]
|
|
43
43
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatCard.js","names":[],"sources":["../../../src/timecampus/components/StatCard.tsx"],"sourcesContent":["import type { FC, ReactNode } from \"react\";\nimport { cn } from \"../utils/helpers\";\nimport { ArrowUp, ArrowDown } from \"lucide-react\";\n\ninterface StatCardProps {\n title: string;\n value: string | number;\n icon?: ReactNode;\n trend?: { value: number; label: string };\n description?: string;\n className?: string;\n iconBgColor?: string;\n}\n\nexport const StatCard: FC<StatCardProps> = ({\n title,\n value,\n icon,\n trend,\n description,\n className,\n iconBgColor,\n}) => {\n return (\n <div\n className={cn(\n \"rounded-xl border border-border bg-
|
|
1
|
+
{"version":3,"file":"StatCard.js","names":[],"sources":["../../../src/timecampus/components/StatCard.tsx"],"sourcesContent":["import type { FC, ReactNode } from \"react\";\nimport { cn } from \"../utils/helpers\";\nimport { ArrowUp, ArrowDown } from \"lucide-react\";\n\ninterface StatCardProps {\n title: string;\n value: string | number;\n icon?: ReactNode;\n trend?: { value: number; label: string };\n description?: string;\n className?: string;\n iconBgColor?: string;\n}\n\nexport const StatCard: FC<StatCardProps> = ({\n title,\n value,\n icon,\n trend,\n description,\n className,\n iconBgColor,\n}) => {\n return (\n <div\n className={cn(\n \"rounded-xl border border-border-subtle bg-bg-surface p-4 sm:p-6\",\n className,\n )}\n >\n <div className=\"flex items-start justify-between\">\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-secondary truncate\">\n {title}\n </p>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">\n {value}\n </p>\n {trend && (\n <div className=\"mt-2 flex items-center gap-1\">\n {trend.value >= 0 ? (\n <ArrowUp className=\"h-3 w-3 text-emerald-500\" />\n ) : (\n <ArrowDown className=\"h-3 w-3 text-red-500\" />\n )}\n <span\n className={cn(\n \"text-xs font-medium\",\n trend.value >= 0\n ? \"text-emerald-600 dark:text-emerald-400\"\n : \"text-red-600 dark:text-red-400\",\n )}\n >\n {Math.abs(trend.value)}%\n </span>\n <span className=\"text-xs text-text-secondary\">\n {trend.label}\n </span>\n </div>\n )}\n {description && (\n <p className=\"mt-1 text-xs text-text-secondary\">{description}</p>\n )}\n </div>\n {icon && (\n <div\n className={cn(\n \"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg\",\n iconBgColor || \"bg-action-primary-bg/10 text-primary\",\n )}\n >\n {icon}\n </div>\n )}\n </div>\n </div>\n );\n};\n"],"mappings":";;;;AAcA,IAAa,KAA+B,EAC1C,UACA,UACA,SACA,UACA,gBACA,cACA,qBAGE,kBAAC,OAAD;CACE,WAAW,EACT,mEACA,EACD;WAED,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,KAAD;KAAG,WAAU;eACV;KACC,CAAA;IACJ,kBAAC,KAAD;KAAG,WAAU;eACV;KACC,CAAA;IACH,KACC,kBAAC,OAAD;KAAK,WAAU;eAAf;MACG,EAAM,SAAS,IACd,kBAAC,GAAD,EAAS,WAAU,4BAA6B,CAAA,GAEhD,kBAAC,GAAD,EAAW,WAAU,wBAAyB,CAAA;MAEhD,kBAAC,QAAD;OACE,WAAW,EACT,uBACA,EAAM,SAAS,IACX,2CACA,iCACL;iBANH,CAQG,KAAK,IAAI,EAAM,MAAM,EAAC,IAClB;;MACP,kBAAC,QAAD;OAAM,WAAU;iBACb,EAAM;OACF,CAAA;MACH;;IAEP,KACC,kBAAC,KAAD;KAAG,WAAU;eAAoC;KAAgB,CAAA;IAE/D;MACL,KACC,kBAAC,OAAD;GACE,WAAW,EACT,kEACA,KAAe,uCAChB;aAEA;GACG,CAAA,CAEJ;;CACF,CAAA"}
|
|
@@ -25,7 +25,7 @@ var S = () => {
|
|
|
25
25
|
description: C("timecampus.home.description", "Overview of your time tracking and productivity"),
|
|
26
26
|
actions: /* @__PURE__ */ y("button", {
|
|
27
27
|
onClick: () => w ? E() : T(),
|
|
28
|
-
className: e("inline-flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-colors", w ? "bg-red-500 text-white hover:bg-red-600" : "bg-primary text-primary-
|
|
28
|
+
className: e("inline-flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-colors", w ? "bg-red-500 text-white hover:bg-red-600" : "bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90"),
|
|
29
29
|
children: w ? /* @__PURE__ */ b(v, { children: [
|
|
30
30
|
/* @__PURE__ */ y(h, { className: "h-4 w-4" }),
|
|
31
31
|
n(w.seconds),
|
|
@@ -71,14 +71,14 @@ var S = () => {
|
|
|
71
71
|
/* @__PURE__ */ b("div", {
|
|
72
72
|
className: "grid grid-cols-1 gap-6 lg:grid-cols-3",
|
|
73
73
|
children: [/* @__PURE__ */ b("div", {
|
|
74
|
-
className: "lg:col-span-2 rounded-xl border border-border bg-
|
|
74
|
+
className: "lg:col-span-2 rounded-xl border border-border-subtle bg-bg-surface p-6",
|
|
75
75
|
children: [/* @__PURE__ */ b("div", {
|
|
76
76
|
className: "mb-4 flex items-center justify-between",
|
|
77
77
|
children: [/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("h3", {
|
|
78
|
-
className: "text-sm font-semibold text-
|
|
78
|
+
className: "text-sm font-semibold text-text-primary",
|
|
79
79
|
children: C("timecampus.home.recentEntries.title", "Recent Time Entries")
|
|
80
80
|
}), /* @__PURE__ */ y("p", {
|
|
81
|
-
className: "text-xs text-
|
|
81
|
+
className: "text-xs text-text-secondary",
|
|
82
82
|
children: C("timecampus.home.recentEntries.description", "Your latest tracked activities")
|
|
83
83
|
})] }), /* @__PURE__ */ b("button", {
|
|
84
84
|
className: "flex items-center gap-1 text-xs text-primary hover:underline",
|
|
@@ -94,20 +94,20 @@ var S = () => {
|
|
|
94
94
|
}) : /* @__PURE__ */ b("div", {
|
|
95
95
|
className: "flex flex-col gap-3",
|
|
96
96
|
children: [M.map((e) => /* @__PURE__ */ b("div", {
|
|
97
|
-
className: "flex items-center justify-between rounded-lg border border-border p-3 transition-colors hover:bg-
|
|
97
|
+
className: "flex items-center justify-between rounded-lg border border-border-subtle p-3 transition-colors hover:bg-bg-sunken/50",
|
|
98
98
|
children: [/* @__PURE__ */ b("div", {
|
|
99
99
|
className: "min-w-0 flex-1",
|
|
100
100
|
children: [/* @__PURE__ */ y("p", {
|
|
101
|
-
className: "text-sm font-medium text-
|
|
101
|
+
className: "text-sm font-medium text-text-primary",
|
|
102
102
|
children: e.project?.name ?? C("timecampus.home.recentEntries.noProject", "No Project")
|
|
103
103
|
}), /* @__PURE__ */ y("p", {
|
|
104
|
-
className: "text-xs text-
|
|
104
|
+
className: "text-xs text-text-secondary",
|
|
105
105
|
children: e.description ?? C("timecampus.home.recentEntries.noDescription", "No description")
|
|
106
106
|
})]
|
|
107
107
|
}), /* @__PURE__ */ b("div", {
|
|
108
108
|
className: "ml-4 text-right",
|
|
109
109
|
children: [/* @__PURE__ */ y("p", {
|
|
110
|
-
className: "text-sm font-mono font-medium text-
|
|
110
|
+
className: "text-sm font-mono font-medium text-text-primary",
|
|
111
111
|
children: t((e.duration ?? 0) / 3600)
|
|
112
112
|
}), /* @__PURE__ */ y("span", {
|
|
113
113
|
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",
|
|
@@ -115,67 +115,67 @@ var S = () => {
|
|
|
115
115
|
})]
|
|
116
116
|
})]
|
|
117
117
|
}, e.id)), M.length === 0 && /* @__PURE__ */ y("p", {
|
|
118
|
-
className: "text-center text-sm text-
|
|
118
|
+
className: "text-center text-sm text-text-secondary py-4",
|
|
119
119
|
children: C("timecampus.home.recentEntries.empty", "No time entries yet")
|
|
120
120
|
})]
|
|
121
121
|
})]
|
|
122
122
|
}), /* @__PURE__ */ b("div", {
|
|
123
|
-
className: "rounded-xl border border-border bg-
|
|
123
|
+
className: "rounded-xl border border-border-subtle bg-bg-surface p-6",
|
|
124
124
|
children: [/* @__PURE__ */ b("div", {
|
|
125
125
|
className: "mb-4",
|
|
126
126
|
children: [/* @__PURE__ */ y("h3", {
|
|
127
|
-
className: "text-sm font-semibold text-
|
|
127
|
+
className: "text-sm font-semibold text-text-primary",
|
|
128
128
|
children: C("timecampus.home.summary.title", "Quick Summary")
|
|
129
129
|
}), /* @__PURE__ */ y("p", {
|
|
130
|
-
className: "text-xs text-
|
|
130
|
+
className: "text-xs text-text-secondary",
|
|
131
131
|
children: C("timecampus.home.summary.description", "Time tracking overview")
|
|
132
132
|
})]
|
|
133
133
|
}), /* @__PURE__ */ b("div", {
|
|
134
134
|
className: "flex flex-col gap-4",
|
|
135
135
|
children: [
|
|
136
136
|
/* @__PURE__ */ b("div", {
|
|
137
|
-
className: "flex items-center justify-between rounded-lg border border-border p-3",
|
|
137
|
+
className: "flex items-center justify-between rounded-lg border border-border-subtle p-3",
|
|
138
138
|
children: [/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("p", {
|
|
139
|
-
className: "text-xs font-medium text-
|
|
139
|
+
className: "text-xs font-medium text-text-secondary",
|
|
140
140
|
children: C("timecampus.home.summary.totalHours", "Total Hours")
|
|
141
141
|
}), /* @__PURE__ */ y("p", {
|
|
142
|
-
className: "mt-1 text-xl font-bold text-
|
|
142
|
+
className: "mt-1 text-xl font-bold text-text-primary",
|
|
143
143
|
children: t(j?.totalHours ?? 0)
|
|
144
|
-
})] }), /* @__PURE__ */ y(f, { className: "h-5 w-5 text-
|
|
144
|
+
})] }), /* @__PURE__ */ y(f, { className: "h-5 w-5 text-text-secondary" })]
|
|
145
145
|
}),
|
|
146
146
|
/* @__PURE__ */ b("div", {
|
|
147
|
-
className: "flex items-center justify-between rounded-lg border border-border p-3",
|
|
147
|
+
className: "flex items-center justify-between rounded-lg border border-border-subtle p-3",
|
|
148
148
|
children: [/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("p", {
|
|
149
|
-
className: "text-xs font-medium text-
|
|
149
|
+
className: "text-xs font-medium text-text-secondary",
|
|
150
150
|
children: C("timecampus.home.summary.billableHours", "Billable Hours")
|
|
151
151
|
}), /* @__PURE__ */ y("p", {
|
|
152
|
-
className: "mt-1 text-xl font-bold text-
|
|
152
|
+
className: "mt-1 text-xl font-bold text-text-primary",
|
|
153
153
|
children: t(j?.billableHours ?? 0)
|
|
154
|
-
})] }), /* @__PURE__ */ y(g, { className: "h-5 w-5 text-
|
|
154
|
+
})] }), /* @__PURE__ */ y(g, { className: "h-5 w-5 text-text-secondary" })]
|
|
155
155
|
}),
|
|
156
156
|
/* @__PURE__ */ b("div", {
|
|
157
|
-
className: "flex items-center justify-between rounded-lg border border-border p-3",
|
|
157
|
+
className: "flex items-center justify-between rounded-lg border border-border-subtle p-3",
|
|
158
158
|
children: [/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("p", {
|
|
159
|
-
className: "text-xs font-medium text-
|
|
159
|
+
className: "text-xs font-medium text-text-secondary",
|
|
160
160
|
children: C("timecampus.home.summary.activeTimers", "Active Timers")
|
|
161
161
|
}), /* @__PURE__ */ y("p", {
|
|
162
|
-
className: "mt-1 text-xl font-bold text-
|
|
162
|
+
className: "mt-1 text-xl font-bold text-text-primary",
|
|
163
163
|
children: j?.activeTimers ?? 0
|
|
164
|
-
})] }), /* @__PURE__ */ y(_, { className: "h-5 w-5 text-
|
|
164
|
+
})] }), /* @__PURE__ */ y(_, { className: "h-5 w-5 text-text-secondary" })]
|
|
165
165
|
})
|
|
166
166
|
]
|
|
167
167
|
})]
|
|
168
168
|
})]
|
|
169
169
|
}),
|
|
170
170
|
/* @__PURE__ */ b("div", {
|
|
171
|
-
className: "rounded-xl border border-border bg-
|
|
171
|
+
className: "rounded-xl border border-border-subtle bg-bg-surface p-6",
|
|
172
172
|
children: [/* @__PURE__ */ b("div", {
|
|
173
173
|
className: "mb-4",
|
|
174
174
|
children: [/* @__PURE__ */ y("h3", {
|
|
175
|
-
className: "text-sm font-semibold text-
|
|
175
|
+
className: "text-sm font-semibold text-text-primary",
|
|
176
176
|
children: C("timecampus.home.quickActions.title", "Quick Actions")
|
|
177
177
|
}), /* @__PURE__ */ y("p", {
|
|
178
|
-
className: "text-xs text-
|
|
178
|
+
className: "text-xs text-text-secondary",
|
|
179
179
|
children: C("timecampus.home.quickActions.description", "Frequently used features")
|
|
180
180
|
})]
|
|
181
181
|
}), /* @__PURE__ */ y("div", {
|
|
@@ -212,18 +212,18 @@ var S = () => {
|
|
|
212
212
|
description: C("timecampus.home.quickActions.approvals.description", "Review timesheets")
|
|
213
213
|
}
|
|
214
214
|
].map(({ label: e, icon: t, description: n }) => /* @__PURE__ */ b("button", {
|
|
215
|
-
className: "flex flex-col items-center gap-2 rounded-lg border border-border bg-
|
|
215
|
+
className: "flex flex-col items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface p-4 text-center transition-colors hover:bg-bg-sunken/50",
|
|
216
216
|
children: [
|
|
217
217
|
/* @__PURE__ */ y("div", {
|
|
218
|
-
className: "rounded-full bg-primary/10 p-3",
|
|
218
|
+
className: "rounded-full bg-action-primary-bg/10 p-3",
|
|
219
219
|
children: /* @__PURE__ */ y(t, { className: "h-5 w-5 text-primary" })
|
|
220
220
|
}),
|
|
221
221
|
/* @__PURE__ */ y("span", {
|
|
222
|
-
className: "text-sm font-medium text-
|
|
222
|
+
className: "text-sm font-medium text-text-primary",
|
|
223
223
|
children: e
|
|
224
224
|
}),
|
|
225
225
|
/* @__PURE__ */ y("span", {
|
|
226
|
-
className: "text-xs text-
|
|
226
|
+
className: "text-xs text-text-secondary",
|
|
227
227
|
children: n
|
|
228
228
|
})
|
|
229
229
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HomePage.js","names":[],"sources":["../../../src/timecampus/pages/HomePage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport {\n Clock,\n FolderOpen,\n Users,\n TrendingUp,\n Timer,\n CheckCircle,\n BarChart3,\n Play,\n ArrowRight,\n} from \"lucide-react\";\nimport { PageLayout } from \"../components/PageLayout\";\nimport { StatCard } from \"../components/StatCard\";\nimport { LoadingSkeleton } from \"../components/LoadingSkeleton\";\nimport { cn, formatHours, formatTimerDuration } from \"../utils/helpers\";\nimport { useTimeCampusStore } from \"../store/timecampusStore\";\nimport {\n useGetTimeEntryStatsQuery,\n useListTimeEntriesQuery,\n type TimeEntryFieldsFragment,\n} from \"@/generated/wspace-operations\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\n\nexport const HomePage: FC = () => {\n const { t: translate } = useI18n();\n const t = (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n };\n const { activeTimer, startTimer, stopTimer } = useTimeCampusStore();\n\n const { data: statsData, loading: statsLoading } =\n useGetTimeEntryStatsQuery();\n const { data: entriesData, loading: entriesLoading } =\n useListTimeEntriesQuery({\n variables: { limit: 4 },\n });\n\n const stats = statsData?.timeEntryStats;\n const recentEntries = entriesData?.timeEntries?.items ?? [];\n\n if (statsLoading && entriesLoading) {\n return (\n <PageLayout\n title={t(\"timecampus.home.title\", \"Dashboard\")}\n description={t(\n \"timecampus.home.description\",\n \"Overview of your time tracking and productivity\",\n )}\n >\n <LoadingSkeleton variant=\"card\" count={4} />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={t(\"timecampus.home.title\", \"Dashboard\")}\n description={t(\n \"timecampus.home.description\",\n \"Overview of your time tracking and productivity\",\n )}\n actions={\n <button\n onClick={() => (activeTimer ? stopTimer() : startTimer())}\n className={cn(\n \"inline-flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-colors\",\n activeTimer\n ? \"bg-red-500 text-white hover:bg-red-600\"\n : \"bg-primary text-primary-foreground hover:bg-primary/90\",\n )}\n >\n {activeTimer ? (\n <>\n <Timer className=\"h-4 w-4\" />\n {formatTimerDuration(activeTimer.seconds)} -{\" \"}\n {t(\"timecampus.home.actions.stop\", \"Stop\")}\n </>\n ) : (\n <>\n <Play className=\"h-4 w-4\" />\n {t(\"timecampus.home.actions.startTimer\", \"Start Timer\")}\n </>\n )}\n </button>\n }\n >\n {/* Stat Cards */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n <StatCard\n title={t(\"timecampus.home.stats.today\", \"Today\")}\n value={formatHours(stats?.totalHours ?? 0)}\n icon={<Clock className=\"h-5 w-5\" />}\n trend={{\n value: 12.5,\n label: t(\"timecampus.home.stats.vsYesterday\", \"vs yesterday\"),\n }}\n />\n <StatCard\n title={t(\"timecampus.home.stats.billable\", \"Billable\")}\n value={formatHours(stats?.billableHours ?? 0)}\n icon={<TrendingUp className=\"h-5 w-5\" />}\n description={`${stats?.totalEntries ?? 0} ${t(\"timecampus.home.stats.entries\", \"entries\")}`}\n />\n <StatCard\n title={t(\"timecampus.home.stats.activeTimers\", \"Active Timers\")}\n value={stats?.activeTimers ?? 0}\n icon={<FolderOpen className=\"h-5 w-5\" />}\n description={t(\n \"timecampus.home.stats.currentlyRunning\",\n \"Currently running\",\n )}\n />\n <StatCard\n title={t(\"timecampus.home.stats.totalEntries\", \"Entries\")}\n value={stats?.totalEntries ?? 0}\n icon={<BarChart3 className=\"h-5 w-5\" />}\n description={t(\n \"timecampus.home.stats.totalEntriesDescription\",\n \"Total time entries\",\n )}\n iconBgColor=\"bg-emerald-100 text-emerald-600 dark:bg-emerald-900/30 dark:text-emerald-400\"\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Recent Time Entries */}\n <div className=\"lg:col-span-2 rounded-xl border border-border bg-card p-6\">\n <div className=\"mb-4 flex items-center justify-between\">\n <div>\n <h3 className=\"text-sm font-semibold text-foreground\">\n {t(\n \"timecampus.home.recentEntries.title\",\n \"Recent Time Entries\",\n )}\n </h3>\n <p className=\"text-xs text-muted-foreground\">\n {t(\n \"timecampus.home.recentEntries.description\",\n \"Your latest tracked activities\",\n )}\n </p>\n </div>\n <button className=\"flex items-center gap-1 text-xs text-primary hover:underline\">\n {t(\"timecampus.home.recentEntries.viewAll\", \"View all\")}{\" \"}\n <ArrowRight className=\"h-3 w-3\" />\n </button>\n </div>\n {entriesLoading ? (\n <LoadingSkeleton variant=\"list\" count={4} />\n ) : (\n <div className=\"flex flex-col gap-3\">\n {recentEntries.map((entry: TimeEntryFieldsFragment) => (\n <div\n key={entry.id}\n className=\"flex items-center justify-between rounded-lg border border-border p-3 transition-colors hover:bg-muted/50\"\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-foreground\">\n {entry.project?.name ??\n t(\n \"timecampus.home.recentEntries.noProject\",\n \"No Project\",\n )}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {entry.description ??\n t(\n \"timecampus.home.recentEntries.noDescription\",\n \"No description\",\n )}\n </p>\n </div>\n <div className=\"ml-4 text-right\">\n <p className=\"text-sm font-mono font-medium text-foreground\">\n {formatHours((entry.duration ?? 0) / 3600)}\n </p>\n <span 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\">\n {entry.isRunning\n ? t(\n \"timecampus.home.recentEntries.status.running\",\n \"running\",\n )\n : t(\n \"timecampus.home.recentEntries.status.completed\",\n \"completed\",\n )}\n </span>\n </div>\n </div>\n ))}\n {recentEntries.length === 0 && (\n <p className=\"text-center text-sm text-muted-foreground py-4\">\n {t(\n \"timecampus.home.recentEntries.empty\",\n \"No time entries yet\",\n )}\n </p>\n )}\n </div>\n )}\n </div>\n\n {/* Quick Summary */}\n <div className=\"rounded-xl border border-border bg-card p-6\">\n <div className=\"mb-4\">\n <h3 className=\"text-sm font-semibold text-foreground\">\n {t(\"timecampus.home.summary.title\", \"Quick Summary\")}\n </h3>\n <p className=\"text-xs text-muted-foreground\">\n {t(\n \"timecampus.home.summary.description\",\n \"Time tracking overview\",\n )}\n </p>\n </div>\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center justify-between rounded-lg border border-border p-3\">\n <div>\n <p className=\"text-xs font-medium text-muted-foreground\">\n {t(\"timecampus.home.summary.totalHours\", \"Total Hours\")}\n </p>\n <p className=\"mt-1 text-xl font-bold text-foreground\">\n {formatHours(stats?.totalHours ?? 0)}\n </p>\n </div>\n <Clock className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <div className=\"flex items-center justify-between rounded-lg border border-border p-3\">\n <div>\n <p className=\"text-xs font-medium text-muted-foreground\">\n {t(\"timecampus.home.summary.billableHours\", \"Billable Hours\")}\n </p>\n <p className=\"mt-1 text-xl font-bold text-foreground\">\n {formatHours(stats?.billableHours ?? 0)}\n </p>\n </div>\n <TrendingUp className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <div className=\"flex items-center justify-between rounded-lg border border-border p-3\">\n <div>\n <p className=\"text-xs font-medium text-muted-foreground\">\n {t(\"timecampus.home.summary.activeTimers\", \"Active Timers\")}\n </p>\n <p className=\"mt-1 text-xl font-bold text-foreground\">\n {stats?.activeTimers ?? 0}\n </p>\n </div>\n <Users className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n </div>\n </div>\n </div>\n\n {/* Quick Actions */}\n <div className=\"rounded-xl border border-border bg-card p-6\">\n <div className=\"mb-4\">\n <h3 className=\"text-sm font-semibold text-foreground\">\n {t(\"timecampus.home.quickActions.title\", \"Quick Actions\")}\n </h3>\n <p className=\"text-xs text-muted-foreground\">\n {t(\n \"timecampus.home.quickActions.description\",\n \"Frequently used features\",\n )}\n </p>\n </div>\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-6\">\n {[\n {\n label: t(\n \"timecampus.home.quickActions.startTimer.label\",\n \"Start Timer\",\n ),\n icon: Play,\n description: t(\n \"timecampus.home.quickActions.startTimer.description\",\n \"Track your time\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.viewProjects.label\",\n \"View Projects\",\n ),\n icon: FolderOpen,\n description: t(\n \"timecampus.home.quickActions.viewProjects.description\",\n \"Manage projects\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.timeEntries.label\",\n \"Time Entries\",\n ),\n icon: Clock,\n description: t(\n \"timecampus.home.quickActions.timeEntries.description\",\n \"View all entries\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.teamActivity.label\",\n \"Team Activity\",\n ),\n icon: Users,\n description: t(\n \"timecampus.home.quickActions.teamActivity.description\",\n \"See team status\",\n ),\n },\n {\n label: t(\"timecampus.home.quickActions.reports.label\", \"Reports\"),\n icon: BarChart3,\n description: t(\n \"timecampus.home.quickActions.reports.description\",\n \"Generate reports\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.approvals.label\",\n \"Approvals\",\n ),\n icon: CheckCircle,\n description: t(\n \"timecampus.home.quickActions.approvals.description\",\n \"Review timesheets\",\n ),\n },\n ].map(({ label, icon: Icon, description }) => (\n <button\n key={label}\n className=\"flex flex-col items-center gap-2 rounded-lg border border-border bg-background p-4 text-center transition-colors hover:bg-muted/50\"\n >\n <div className=\"rounded-full bg-primary/10 p-3\">\n <Icon className=\"h-5 w-5 text-primary\" />\n </div>\n <span className=\"text-sm font-medium text-foreground\">\n {label}\n </span>\n <span className=\"text-xs text-muted-foreground\">\n {description}\n </span>\n </button>\n ))}\n </div>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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E,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAE,sCAAsC,gBAAgB;MACtD,CAAA,EACL,kBAAC,KAAD;MAAG,WAAU;gBACV,EACC,4CACA,2BACD;MACC,CAAA,CACA;QACN,kBAAC,OAAD;KAAK,WAAU;eACZ;MACC;OACE,OAAO,EACL,iDACA,cACD;OACD,MAAM;OACN,aAAa,EACX,uDACA,kBACD;OACF;MACD;OACE,OAAO,EACL,mDACA,gBACD;OACD,MAAM;OACN,aAAa,EACX,yDACA,kBACD;OACF;MACD;OACE,OAAO,EACL,kDACA,eACD;OACD,MAAM;OACN,aAAa,EACX,wDACA,mBACD;OACF;MACD;OACE,OAAO,EACL,mDACA,gBACD;OACD,MAAM;OACN,aAAa,EACX,yDACA,kBACD;OACF;MACD;OACE,OAAO,EAAE,8CAA8C,UAAU;OACjE,MAAM;OACN,aAAa,EACX,oDACA,mBACD;OACF;MACD;OACE,OAAO,EACL,gDACA,YACD;OACD,MAAM;OACN,aAAa,EACX,sDACA,oBACD;OACF;MACF,CAAC,KAAK,EAAE,UAAO,MAAM,GAAM,qBAC1B,kBAAC,UAAD;MAEE,WAAU;gBAFZ;OAIE,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,GAAD,EAAM,WAAU,wBAAyB,CAAA;QACrC,CAAA;OACN,kBAAC,QAAD;QAAM,WAAU;kBACb;QACI,CAAA;OACP,kBAAC,QAAD;QAAM,WAAU;kBACb;QACI,CAAA;OACA;QAZF,EAYE,CACT;KACE,CAAA,CACF;;GACK"}
|
|
1
|
+
{"version":3,"file":"HomePage.js","names":[],"sources":["../../../src/timecampus/pages/HomePage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport {\n Clock,\n FolderOpen,\n Users,\n TrendingUp,\n Timer,\n CheckCircle,\n BarChart3,\n Play,\n ArrowRight,\n} from \"lucide-react\";\nimport { PageLayout } from \"../components/PageLayout\";\nimport { StatCard } from \"../components/StatCard\";\nimport { LoadingSkeleton } from \"../components/LoadingSkeleton\";\nimport { cn, formatHours, formatTimerDuration } from \"../utils/helpers\";\nimport { useTimeCampusStore } from \"../store/timecampusStore\";\nimport {\n useGetTimeEntryStatsQuery,\n useListTimeEntriesQuery,\n type TimeEntryFieldsFragment,\n} from \"@/generated/wspace-operations\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\n\nexport const HomePage: FC = () => {\n const { t: translate } = useI18n();\n const t = (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n };\n const { activeTimer, startTimer, stopTimer } = useTimeCampusStore();\n\n const { data: statsData, loading: statsLoading } =\n useGetTimeEntryStatsQuery();\n const { data: entriesData, loading: entriesLoading } =\n useListTimeEntriesQuery({\n variables: { limit: 4 },\n });\n\n const stats = statsData?.timeEntryStats;\n const recentEntries = entriesData?.timeEntries?.items ?? [];\n\n if (statsLoading && entriesLoading) {\n return (\n <PageLayout\n title={t(\"timecampus.home.title\", \"Dashboard\")}\n description={t(\n \"timecampus.home.description\",\n \"Overview of your time tracking and productivity\",\n )}\n >\n <LoadingSkeleton variant=\"card\" count={4} />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={t(\"timecampus.home.title\", \"Dashboard\")}\n description={t(\n \"timecampus.home.description\",\n \"Overview of your time tracking and productivity\",\n )}\n actions={\n <button\n onClick={() => (activeTimer ? stopTimer() : startTimer())}\n className={cn(\n \"inline-flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-colors\",\n activeTimer\n ? \"bg-red-500 text-white hover:bg-red-600\"\n : \"bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90\",\n )}\n >\n {activeTimer ? (\n <>\n <Timer className=\"h-4 w-4\" />\n {formatTimerDuration(activeTimer.seconds)} -{\" \"}\n {t(\"timecampus.home.actions.stop\", \"Stop\")}\n </>\n ) : (\n <>\n <Play className=\"h-4 w-4\" />\n {t(\"timecampus.home.actions.startTimer\", \"Start Timer\")}\n </>\n )}\n </button>\n }\n >\n {/* Stat Cards */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n <StatCard\n title={t(\"timecampus.home.stats.today\", \"Today\")}\n value={formatHours(stats?.totalHours ?? 0)}\n icon={<Clock className=\"h-5 w-5\" />}\n trend={{\n value: 12.5,\n label: t(\"timecampus.home.stats.vsYesterday\", \"vs yesterday\"),\n }}\n />\n <StatCard\n title={t(\"timecampus.home.stats.billable\", \"Billable\")}\n value={formatHours(stats?.billableHours ?? 0)}\n icon={<TrendingUp className=\"h-5 w-5\" />}\n description={`${stats?.totalEntries ?? 0} ${t(\"timecampus.home.stats.entries\", \"entries\")}`}\n />\n <StatCard\n title={t(\"timecampus.home.stats.activeTimers\", \"Active Timers\")}\n value={stats?.activeTimers ?? 0}\n icon={<FolderOpen className=\"h-5 w-5\" />}\n description={t(\n \"timecampus.home.stats.currentlyRunning\",\n \"Currently running\",\n )}\n />\n <StatCard\n title={t(\"timecampus.home.stats.totalEntries\", \"Entries\")}\n value={stats?.totalEntries ?? 0}\n icon={<BarChart3 className=\"h-5 w-5\" />}\n description={t(\n \"timecampus.home.stats.totalEntriesDescription\",\n \"Total time entries\",\n )}\n iconBgColor=\"bg-emerald-100 text-emerald-600 dark:bg-emerald-900/30 dark:text-emerald-400\"\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Recent Time Entries */}\n <div className=\"lg:col-span-2 rounded-xl border border-border-subtle bg-bg-surface p-6\">\n <div className=\"mb-4 flex items-center justify-between\">\n <div>\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {t(\n \"timecampus.home.recentEntries.title\",\n \"Recent Time Entries\",\n )}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t(\n \"timecampus.home.recentEntries.description\",\n \"Your latest tracked activities\",\n )}\n </p>\n </div>\n <button className=\"flex items-center gap-1 text-xs text-primary hover:underline\">\n {t(\"timecampus.home.recentEntries.viewAll\", \"View all\")}{\" \"}\n <ArrowRight className=\"h-3 w-3\" />\n </button>\n </div>\n {entriesLoading ? (\n <LoadingSkeleton variant=\"list\" count={4} />\n ) : (\n <div className=\"flex flex-col gap-3\">\n {recentEntries.map((entry: TimeEntryFieldsFragment) => (\n <div\n key={entry.id}\n className=\"flex items-center justify-between rounded-lg border border-border-subtle p-3 transition-colors hover:bg-bg-sunken/50\"\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-text-primary\">\n {entry.project?.name ??\n t(\n \"timecampus.home.recentEntries.noProject\",\n \"No Project\",\n )}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {entry.description ??\n t(\n \"timecampus.home.recentEntries.noDescription\",\n \"No description\",\n )}\n </p>\n </div>\n <div className=\"ml-4 text-right\">\n <p className=\"text-sm font-mono font-medium text-text-primary\">\n {formatHours((entry.duration ?? 0) / 3600)}\n </p>\n <span 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\">\n {entry.isRunning\n ? t(\n \"timecampus.home.recentEntries.status.running\",\n \"running\",\n )\n : t(\n \"timecampus.home.recentEntries.status.completed\",\n \"completed\",\n )}\n </span>\n </div>\n </div>\n ))}\n {recentEntries.length === 0 && (\n <p className=\"text-center text-sm text-text-secondary py-4\">\n {t(\n \"timecampus.home.recentEntries.empty\",\n \"No time entries yet\",\n )}\n </p>\n )}\n </div>\n )}\n </div>\n\n {/* Quick Summary */}\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-6\">\n <div className=\"mb-4\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {t(\"timecampus.home.summary.title\", \"Quick Summary\")}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t(\n \"timecampus.home.summary.description\",\n \"Time tracking overview\",\n )}\n </p>\n </div>\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-3\">\n <div>\n <p className=\"text-xs font-medium text-text-secondary\">\n {t(\"timecampus.home.summary.totalHours\", \"Total Hours\")}\n </p>\n <p className=\"mt-1 text-xl font-bold text-text-primary\">\n {formatHours(stats?.totalHours ?? 0)}\n </p>\n </div>\n <Clock className=\"h-5 w-5 text-text-secondary\" />\n </div>\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-3\">\n <div>\n <p className=\"text-xs font-medium text-text-secondary\">\n {t(\"timecampus.home.summary.billableHours\", \"Billable Hours\")}\n </p>\n <p className=\"mt-1 text-xl font-bold text-text-primary\">\n {formatHours(stats?.billableHours ?? 0)}\n </p>\n </div>\n <TrendingUp className=\"h-5 w-5 text-text-secondary\" />\n </div>\n <div className=\"flex items-center justify-between rounded-lg border border-border-subtle p-3\">\n <div>\n <p className=\"text-xs font-medium text-text-secondary\">\n {t(\"timecampus.home.summary.activeTimers\", \"Active Timers\")}\n </p>\n <p className=\"mt-1 text-xl font-bold text-text-primary\">\n {stats?.activeTimers ?? 0}\n </p>\n </div>\n <Users className=\"h-5 w-5 text-text-secondary\" />\n </div>\n </div>\n </div>\n </div>\n\n {/* Quick Actions */}\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-6\">\n <div className=\"mb-4\">\n <h3 className=\"text-sm font-semibold text-text-primary\">\n {t(\"timecampus.home.quickActions.title\", \"Quick Actions\")}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t(\n \"timecampus.home.quickActions.description\",\n \"Frequently used features\",\n )}\n </p>\n </div>\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-6\">\n {[\n {\n label: t(\n \"timecampus.home.quickActions.startTimer.label\",\n \"Start Timer\",\n ),\n icon: Play,\n description: t(\n \"timecampus.home.quickActions.startTimer.description\",\n \"Track your time\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.viewProjects.label\",\n \"View Projects\",\n ),\n icon: FolderOpen,\n description: t(\n \"timecampus.home.quickActions.viewProjects.description\",\n \"Manage projects\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.timeEntries.label\",\n \"Time Entries\",\n ),\n icon: Clock,\n description: t(\n \"timecampus.home.quickActions.timeEntries.description\",\n \"View all entries\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.teamActivity.label\",\n \"Team Activity\",\n ),\n icon: Users,\n description: t(\n \"timecampus.home.quickActions.teamActivity.description\",\n \"See team status\",\n ),\n },\n {\n label: t(\"timecampus.home.quickActions.reports.label\", \"Reports\"),\n icon: BarChart3,\n description: t(\n \"timecampus.home.quickActions.reports.description\",\n \"Generate reports\",\n ),\n },\n {\n label: t(\n \"timecampus.home.quickActions.approvals.label\",\n \"Approvals\",\n ),\n icon: CheckCircle,\n description: t(\n \"timecampus.home.quickActions.approvals.description\",\n \"Review timesheets\",\n ),\n },\n ].map(({ label, icon: Icon, description }) => (\n <button\n key={label}\n className=\"flex flex-col items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface p-4 text-center transition-colors hover:bg-bg-sunken/50\"\n >\n <div className=\"rounded-full bg-action-primary-bg/10 p-3\">\n <Icon className=\"h-5 w-5 text-primary\" />\n </div>\n <span className=\"text-sm font-medium text-text-primary\">\n {label}\n </span>\n <span className=\"text-xs text-text-secondary\">\n {description}\n </span>\n </button>\n ))}\n </div>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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E,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAE,sCAAsC,gBAAgB;MACtD,CAAA,EACL,kBAAC,KAAD;MAAG,WAAU;gBACV,EACC,4CACA,2BACD;MACC,CAAA,CACA;QACN,kBAAC,OAAD;KAAK,WAAU;eACZ;MACC;OACE,OAAO,EACL,iDACA,cACD;OACD,MAAM;OACN,aAAa,EACX,uDACA,kBACD;OACF;MACD;OACE,OAAO,EACL,mDACA,gBACD;OACD,MAAM;OACN,aAAa,EACX,yDACA,kBACD;OACF;MACD;OACE,OAAO,EACL,kDACA,eACD;OACD,MAAM;OACN,aAAa,EACX,wDACA,mBACD;OACF;MACD;OACE,OAAO,EACL,mDACA,gBACD;OACD,MAAM;OACN,aAAa,EACX,yDACA,kBACD;OACF;MACD;OACE,OAAO,EAAE,8CAA8C,UAAU;OACjE,MAAM;OACN,aAAa,EACX,oDACA,mBACD;OACF;MACD;OACE,OAAO,EACL,gDACA,YACD;OACD,MAAM;OACN,aAAa,EACX,sDACA,oBACD;OACF;MACF,CAAC,KAAK,EAAE,UAAO,MAAM,GAAM,qBAC1B,kBAAC,UAAD;MAEE,WAAU;gBAFZ;OAIE,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,GAAD,EAAM,WAAU,wBAAyB,CAAA;QACrC,CAAA;OACN,kBAAC,QAAD;QAAM,WAAU;kBACb;QACI,CAAA;OACP,kBAAC,QAAD;QAAM,WAAU;kBACb;QACI,CAAA;OACA;QAZF,EAYE,CACT;KACE,CAAA,CACF;;GACK"}
|
|
@@ -27,33 +27,33 @@ function l() {
|
|
|
27
27
|
children: /* @__PURE__ */ s("div", {
|
|
28
28
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
29
29
|
children: p.length === 0 ? /* @__PURE__ */ s("div", {
|
|
30
|
-
className: "col-span-full p-8 text-center text-sm text-
|
|
30
|
+
className: "col-span-full p-8 text-center text-sm text-text-secondary",
|
|
31
31
|
children: "No applets available in the store yet. Store applets are managed as workspace configurations with the \"applet.store.\" key prefix."
|
|
32
32
|
}) : p.map((e) => {
|
|
33
33
|
let t = e.value, n = t.name ?? e.key.replace("applet.store.", ""), r = e.description ?? t.description ?? "";
|
|
34
34
|
t.category;
|
|
35
35
|
let l = t.rating ?? 0, u = t.downloads ?? 0;
|
|
36
36
|
return /* @__PURE__ */ c("div", {
|
|
37
|
-
className: "rounded-xl border border-border bg-
|
|
37
|
+
className: "rounded-xl border border-border-subtle bg-bg-surface p-5 transition-colors hover:bg-bg-sunken/50 cursor-pointer",
|
|
38
38
|
children: [/* @__PURE__ */ c("div", {
|
|
39
39
|
className: "flex items-start gap-3",
|
|
40
40
|
children: [/* @__PURE__ */ s("div", {
|
|
41
|
-
className: "flex h-12 w-12 items-center justify-center rounded-xl bg-primary/10",
|
|
41
|
+
className: "flex h-12 w-12 items-center justify-center rounded-xl bg-action-primary-bg/10",
|
|
42
42
|
children: /* @__PURE__ */ s(a, { className: "h-6 w-6 text-primary" })
|
|
43
43
|
}), /* @__PURE__ */ c("div", {
|
|
44
44
|
className: "flex-1",
|
|
45
45
|
children: [/* @__PURE__ */ s("p", {
|
|
46
|
-
className: "text-sm font-semibold text-
|
|
46
|
+
className: "text-sm font-semibold text-text-primary",
|
|
47
47
|
children: n
|
|
48
48
|
}), /* @__PURE__ */ s("p", {
|
|
49
|
-
className: "text-xs text-
|
|
49
|
+
className: "text-xs text-text-secondary",
|
|
50
50
|
children: r
|
|
51
51
|
})]
|
|
52
52
|
})]
|
|
53
53
|
}), /* @__PURE__ */ c("div", {
|
|
54
54
|
className: "mt-3 flex items-center justify-between",
|
|
55
55
|
children: [/* @__PURE__ */ c("div", {
|
|
56
|
-
className: "flex items-center gap-3 text-xs text-
|
|
56
|
+
className: "flex items-center gap-3 text-xs text-text-secondary",
|
|
57
57
|
children: [/* @__PURE__ */ c("div", {
|
|
58
58
|
className: "flex items-center gap-1",
|
|
59
59
|
children: [/* @__PURE__ */ s(o, { className: "h-3 w-3 fill-amber-400 text-amber-400" }), /* @__PURE__ */ s("span", { children: l })]
|
|
@@ -62,7 +62,7 @@ function l() {
|
|
|
62
62
|
children: [/* @__PURE__ */ s(i, { className: "h-3 w-3" }), /* @__PURE__ */ s("span", { children: u })]
|
|
63
63
|
})]
|
|
64
64
|
}), /* @__PURE__ */ s("button", {
|
|
65
|
-
className: "rounded-md bg-primary px-3 py-1 text-xs font-medium text-primary-
|
|
65
|
+
className: "rounded-md bg-action-primary-bg px-3 py-1 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90",
|
|
66
66
|
children: "Install"
|
|
67
67
|
})]
|
|
68
68
|
})]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppletStorePage.js","names":[],"sources":["../../../../src/timecampus/pages/applets/AppletStorePage.tsx"],"sourcesContent":["import { Puzzle, Star, Download } 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 AppletStorePage() {\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 store/available applets (key starts with 'applet.store.')\n const storeApplets = configurations.filter((c: ConfigurationFieldsFragment) =>\n c.key.startsWith(\"applet.store.\"),\n );\n\n if (loading) {\n return (\n <PageLayout\n title=\"Applet Store\"\n description=\"Browse and install applets to extend TimeCampus\"\n >\n <LoadingSkeleton variant=\"card\" count={6} />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title=\"Applet Store\"\n description=\"Browse and install applets to extend TimeCampus\"\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 applet store data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Applet Store\"\n description=\"Browse and install applets to extend TimeCampus\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {storeApplets.length === 0 ? (\n <div className=\"col-span-full p-8 text-center text-sm text-
|
|
1
|
+
{"version":3,"file":"AppletStorePage.js","names":[],"sources":["../../../../src/timecampus/pages/applets/AppletStorePage.tsx"],"sourcesContent":["import { Puzzle, Star, Download } 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 AppletStorePage() {\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 store/available applets (key starts with 'applet.store.')\n const storeApplets = configurations.filter((c: ConfigurationFieldsFragment) =>\n c.key.startsWith(\"applet.store.\"),\n );\n\n if (loading) {\n return (\n <PageLayout\n title=\"Applet Store\"\n description=\"Browse and install applets to extend TimeCampus\"\n >\n <LoadingSkeleton variant=\"card\" count={6} />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title=\"Applet Store\"\n description=\"Browse and install applets to extend TimeCampus\"\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 applet store data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Applet Store\"\n description=\"Browse and install applets to extend TimeCampus\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {storeApplets.length === 0 ? (\n <div className=\"col-span-full p-8 text-center text-sm text-text-secondary\">\n No applets available in the store yet. Store applets are managed as\n workspace configurations with the \"applet.store.\" key prefix.\n </div>\n ) : (\n storeApplets.map((applet: ConfigurationFieldsFragment) => {\n const val = applet.value as Record<string, unknown>;\n const name =\n (val.name as string) ?? applet.key.replace(\"applet.store.\", \"\");\n const description =\n applet.description ?? (val.description as string) ?? \"\";\n const category = (val.category as string) ?? \"general\";\n const rating = (val.rating as number) ?? 0;\n const downloads = (val.downloads as number) ?? 0;\n\n return (\n <div\n key={applet.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 <Puzzle 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 {description}\n </p>\n </div>\n </div>\n <div className=\"mt-3 flex items-center justify-between\">\n <div className=\"flex items-center gap-3 text-xs text-text-secondary\">\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 <Download className=\"h-3 w-3\" />\n <span>{downloads}</span>\n </div>\n </div>\n <button className=\"rounded-md bg-action-primary-bg px-3 py-1 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90\">\n Install\n </button>\n </div>\n </div>\n );\n })\n )}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;AASA,SAAgB,IAAkB;CAChC,IAAM,EAAE,iBAAc,OAAO,GAAe,EAEtC,EAAE,SAAM,YAAS,aAAU,EAA2B,EAC1D,WAAW,EAAE,OAAO,aAAoB,EACzC,CAAC,EAKI,KAHiB,GAAM,kBAAkB,EAAE,EAGb,QAAQ,MAC1C,EAAE,IAAI,WAAW,gBAAgB,CAClC;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,EAAa,WAAW,IACvB,kBAAC,OAAD;IAAK,WAAU;cAA4D;IAGrE,CAAA,GAEN,EAAa,KAAK,MAAwC;IACxD,IAAM,IAAM,EAAO,OACb,IACH,EAAI,QAAmB,EAAO,IAAI,QAAQ,iBAAiB,GAAG,EAC3D,IACJ,EAAO,eAAgB,EAAI,eAA0B;AACrC,MAAI;IACtB,IAAM,IAAU,EAAI,UAAqB,GACnC,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,EAAQ,WAAU,wBAAyB,CAAA;OACvC,CAAA,EACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBACV;QACC,CAAA,EACJ,kBAAC,KAAD;QAAG,WAAU;kBACV;QACC,CAAA,CACA;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,EAAU,WAAU,WAAY,CAAA,EAChC,kBAAC,QAAD,EAAA,UAAO,GAAiB,CAAA,CACpB;UACF;UACN,kBAAC,UAAD;OAAQ,WAAU;iBAAuH;OAEhI,CAAA,CACL;QACF;OA/BC,EAAO,GA+BR;KAER;GAEA,CAAA;EACK,CAAA"}
|