@burdenoff/microfe-timecampus 2026.608.1 → 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
|
@@ -11,7 +11,7 @@ function d() {
|
|
|
11
11
|
title: "Reports",
|
|
12
12
|
description: "Generate and view time tracking reports",
|
|
13
13
|
actions: /* @__PURE__ */ u("button", {
|
|
14
|
-
className: "inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-
|
|
14
|
+
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",
|
|
15
15
|
children: [/* @__PURE__ */ l(c, { className: "h-4 w-4" }), "Generate Report"]
|
|
16
16
|
}),
|
|
17
17
|
children: /* @__PURE__ */ l(n, {
|
|
@@ -60,25 +60,25 @@ function d() {
|
|
|
60
60
|
title: "Reports",
|
|
61
61
|
description: "Generate and view time tracking reports",
|
|
62
62
|
actions: /* @__PURE__ */ u("button", {
|
|
63
|
-
className: "inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-
|
|
63
|
+
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",
|
|
64
64
|
children: [/* @__PURE__ */ l(c, { className: "h-4 w-4" }), "Generate Report"]
|
|
65
65
|
}),
|
|
66
66
|
children: /* @__PURE__ */ l("div", {
|
|
67
|
-
className: "rounded-xl border border-border bg-
|
|
67
|
+
className: "rounded-xl border border-border-subtle bg-bg-surface",
|
|
68
68
|
children: /* @__PURE__ */ l("div", {
|
|
69
69
|
className: "divide-y divide-border",
|
|
70
70
|
children: S.length === 0 ? /* @__PURE__ */ l("div", {
|
|
71
|
-
className: "p-8 text-center text-sm text-
|
|
71
|
+
className: "p-8 text-center text-sm text-text-secondary",
|
|
72
72
|
children: "No report data available yet."
|
|
73
73
|
}) : S.map((e) => /* @__PURE__ */ u("div", {
|
|
74
|
-
className: "flex items-center justify-between p-4 hover:bg-
|
|
74
|
+
className: "flex items-center justify-between p-4 hover:bg-bg-sunken/50 transition-colors",
|
|
75
75
|
children: [/* @__PURE__ */ u("div", {
|
|
76
76
|
className: "flex items-center gap-3",
|
|
77
|
-
children: [/* @__PURE__ */ l(s, { className: "h-5 w-5 text-
|
|
78
|
-
className: "text-sm font-medium text-
|
|
77
|
+
children: [/* @__PURE__ */ l(s, { className: "h-5 w-5 text-text-secondary" }), /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("p", {
|
|
78
|
+
className: "text-sm font-medium text-text-primary",
|
|
79
79
|
children: e.name
|
|
80
80
|
}), /* @__PURE__ */ l("p", {
|
|
81
|
-
className: "text-xs text-
|
|
81
|
+
className: "text-xs text-text-secondary",
|
|
82
82
|
children: e.period
|
|
83
83
|
})] })]
|
|
84
84
|
}), /* @__PURE__ */ u("div", {
|
|
@@ -87,8 +87,8 @@ function d() {
|
|
|
87
87
|
className: "inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-400",
|
|
88
88
|
children: e.status
|
|
89
89
|
}), /* @__PURE__ */ l("button", {
|
|
90
|
-
className: "rounded-md p-1.5 hover:bg-
|
|
91
|
-
children: /* @__PURE__ */ l(o, { className: "h-4 w-4 text-
|
|
90
|
+
className: "rounded-md p-1.5 hover:bg-bg-sunken",
|
|
91
|
+
children: /* @__PURE__ */ l(o, { className: "h-4 w-4 text-text-secondary" })
|
|
92
92
|
})]
|
|
93
93
|
})]
|
|
94
94
|
}, e.id))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReportsPage.js","names":[],"sources":["../../../../src/timecampus/pages/dashboard/ReportsPage.tsx"],"sourcesContent":["import { FileText, Plus, Download } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useGetTimeEntryStatsQuery,\n useGetWorkPatternSummaryQuery,\n useGetFocusScoreSummaryQuery,\n} from \"@/generated/wspace-operations\";\n\nexport function ReportsPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const {\n data: statsData,\n loading: statsLoading,\n error: statsError,\n } = useGetTimeEntryStatsQuery({\n skip: !workspaceId,\n });\n\n const { data: patternData, loading: patternLoading } =\n useGetWorkPatternSummaryQuery({\n skip: !workspaceId,\n });\n\n const { data: focusData, loading: focusLoading } =\n useGetFocusScoreSummaryQuery({\n skip: !workspaceId,\n });\n\n const stats = statsData?.timeEntryStats;\n const pattern = patternData?.workPatternSummary;\n const focus = focusData?.focusScoreSummary;\n\n const isLoading = statsLoading || patternLoading || focusLoading;\n\n if (isLoading) {\n return (\n <PageLayout\n title=\"Reports\"\n description=\"Generate and view time tracking reports\"\n actions={\n <button className=\"inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-
|
|
1
|
+
{"version":3,"file":"ReportsPage.js","names":[],"sources":["../../../../src/timecampus/pages/dashboard/ReportsPage.tsx"],"sourcesContent":["import { FileText, Plus, Download } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useGetTimeEntryStatsQuery,\n useGetWorkPatternSummaryQuery,\n useGetFocusScoreSummaryQuery,\n} from \"@/generated/wspace-operations\";\n\nexport function ReportsPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const {\n data: statsData,\n loading: statsLoading,\n error: statsError,\n } = useGetTimeEntryStatsQuery({\n skip: !workspaceId,\n });\n\n const { data: patternData, loading: patternLoading } =\n useGetWorkPatternSummaryQuery({\n skip: !workspaceId,\n });\n\n const { data: focusData, loading: focusLoading } =\n useGetFocusScoreSummaryQuery({\n skip: !workspaceId,\n });\n\n const stats = statsData?.timeEntryStats;\n const pattern = patternData?.workPatternSummary;\n const focus = focusData?.focusScoreSummary;\n\n const isLoading = statsLoading || patternLoading || focusLoading;\n\n if (isLoading) {\n return (\n <PageLayout\n title=\"Reports\"\n description=\"Generate and view time tracking reports\"\n actions={\n <button className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\">\n <Plus className=\"h-4 w-4\" />\n Generate Report\n </button>\n }\n >\n <LoadingSkeleton variant=\"list\" count={4} />\n </PageLayout>\n );\n }\n\n if (statsError) {\n return (\n <PageLayout\n title=\"Reports\"\n description=\"Generate and view time tracking reports\"\n >\n <div className=\"rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-600 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400\">\n Failed to load reports data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n // Build dynamic reports from available analytics data\n const reports = [\n ...(stats\n ? [\n {\n id: \"time-summary\",\n name: \"Time Tracking Summary\",\n type: \"time\",\n period: `${Math.round(stats.totalHours)}h total · ${stats.totalEntries} entries`,\n status: \"ready\" as const,\n },\n {\n id: \"billable-summary\",\n name: \"Billable Hours Report\",\n type: \"billing\",\n period: `${Math.round(stats.billableHours)}h billable · ${stats.activeTimers} active`,\n status: \"ready\" as const,\n },\n ]\n : []),\n ...(pattern\n ? [\n {\n id: \"work-pattern\",\n name: \"Work Pattern Analysis\",\n type: \"team\",\n period: `${pattern.averageFocusHours.toFixed(1)}h avg focus · ${Math.round(pattern.averageProductivity)}% productivity`,\n status: \"ready\" as const,\n },\n ]\n : []),\n ...(focus\n ? [\n {\n id: \"focus-score\",\n name: \"Focus Score Report\",\n type: \"productivity\",\n period: `Avg: ${Math.round(focus.averageScore)} · High: ${Math.round(focus.highestScore)} · Low: ${Math.round(focus.lowestScore)}`,\n status: \"ready\" as const,\n },\n ]\n : []),\n ];\n\n return (\n <PageLayout\n title=\"Reports\"\n description=\"Generate and view time tracking reports\"\n actions={\n <button className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\">\n <Plus className=\"h-4 w-4\" />\n Generate Report\n </button>\n }\n >\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface\">\n <div className=\"divide-y divide-border\">\n {reports.length === 0 ? (\n <div className=\"p-8 text-center text-sm text-text-secondary\">\n No report data available yet.\n </div>\n ) : (\n reports.map((report) => (\n <div\n key={report.id}\n className=\"flex items-center justify-between p-4 hover:bg-bg-sunken/50 transition-colors\"\n >\n <div className=\"flex items-center gap-3\">\n <FileText className=\"h-5 w-5 text-text-secondary\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {report.name}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {report.period}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-3\">\n <span className=\"inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-400\">\n {report.status}\n </span>\n <button className=\"rounded-md p-1.5 hover:bg-bg-sunken\">\n <Download className=\"h-4 w-4 text-text-secondary\" />\n </button>\n </div>\n </div>\n ))\n )}\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;AAUA,SAAgB,IAAc;CAC5B,IAAM,EAAE,iBAAc,OAAO,GAAe,EAEtC,EACJ,MAAM,GACN,SAAS,GACT,OAAO,MACL,EAA0B,EAC5B,MAAM,CAAC,GACR,CAAC,EAEI,EAAE,MAAM,GAAa,SAAS,MAClC,EAA8B,EAC5B,MAAM,CAAC,GACR,CAAC,EAEE,EAAE,MAAM,GAAW,SAAS,MAChC,EAA6B,EAC3B,MAAM,CAAC,GACR,CAAC,EAEE,IAAQ,GAAW,gBACnB,IAAU,GAAa,oBACvB,IAAQ,GAAW;AAIzB,KAFkB,KAAgB,KAAkB,EAGlD,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SACE,kBAAC,UAAD;GAAQ,WAAU;aAAlB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,kBAErB;;YAGX,kBAAC,GAAD;GAAiB,SAAQ;GAAO,OAAO;GAAK,CAAA;EACjC,CAAA;AAIjB,KAAI,EACF,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,OAAD;GAAK,WAAU;aAA+H;GAExI,CAAA;EACK,CAAA;CAKjB,IAAM,IAAU;EACd,GAAI,IACA,CACE;GACE,IAAI;GACJ,MAAM;GACN,MAAM;GACN,QAAQ,GAAG,KAAK,MAAM,EAAM,WAAW,CAAC,YAAY,EAAM,aAAa;GACvE,QAAQ;GACT,EACD;GACE,IAAI;GACJ,MAAM;GACN,MAAM;GACN,QAAQ,GAAG,KAAK,MAAM,EAAM,cAAc,CAAC,eAAe,EAAM,aAAa;GAC7E,QAAQ;GACT,CACF,GACD,EAAE;EACN,GAAI,IACA,CACE;GACE,IAAI;GACJ,MAAM;GACN,MAAM;GACN,QAAQ,GAAG,EAAQ,kBAAkB,QAAQ,EAAE,CAAC,gBAAgB,KAAK,MAAM,EAAQ,oBAAoB,CAAC;GACxG,QAAQ;GACT,CACF,GACD,EAAE;EACN,GAAI,IACA,CACE;GACE,IAAI;GACJ,MAAM;GACN,MAAM;GACN,QAAQ,QAAQ,KAAK,MAAM,EAAM,aAAa,CAAC,WAAW,KAAK,MAAM,EAAM,aAAa,CAAC,UAAU,KAAK,MAAM,EAAM,YAAY;GAChI,QAAQ;GACT,CACF,GACD,EAAE;EACP;AAED,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SACE,kBAAC,UAAD;GAAQ,WAAU;aAAlB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,kBAErB;;YAGX,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAQ,WAAW,IAClB,kBAAC,OAAD;KAAK,WAAU;eAA8C;KAEvD,CAAA,GAEN,EAAQ,KAAK,MACX,kBAAC,OAAD;KAEE,WAAU;eAFZ,CAIE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EAAU,WAAU,+BAAgC,CAAA,EACpD,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAO;OACN,CAAA,EACJ,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAO;OACN,CAAA,CACA,EAAA,CAAA,CACF;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OAAM,WAAU;iBACb,EAAO;OACH,CAAA,EACP,kBAAC,UAAD;OAAQ,WAAU;iBAChB,kBAAC,GAAD,EAAU,WAAU,+BAAgC,CAAA;OAC7C,CAAA,CACL;QACF;OAtBC,EAAO,GAsBR,CACN;IAEA,CAAA;GACF,CAAA;EACK,CAAA"}
|
|
@@ -20,7 +20,7 @@ function u() {
|
|
|
20
20
|
title: "Email Analytics",
|
|
21
21
|
description: "Insights into email time management",
|
|
22
22
|
children: /* @__PURE__ */ c("div", {
|
|
23
|
-
className: "rounded-xl border border-
|
|
23
|
+
className: "rounded-xl border border-status-error-border/50 bg-status-error-bg/10 p-4 text-sm text-status-error-text",
|
|
24
24
|
children: "Failed to load email analytics. Please try again later."
|
|
25
25
|
})
|
|
26
26
|
});
|
|
@@ -53,14 +53,14 @@ function u() {
|
|
|
53
53
|
})
|
|
54
54
|
]
|
|
55
55
|
}), /* @__PURE__ */ l("div", {
|
|
56
|
-
className: "rounded-xl border border-border bg-
|
|
56
|
+
className: "rounded-xl border border-border-subtle bg-bg-surface p-6",
|
|
57
57
|
children: [/* @__PURE__ */ c("h3", {
|
|
58
|
-
className: "mb-4 text-sm font-semibold text-
|
|
58
|
+
className: "mb-4 text-sm font-semibold text-text-primary",
|
|
59
59
|
children: "Email Volume & Response Time"
|
|
60
60
|
}), /* @__PURE__ */ c("div", {
|
|
61
|
-
className: "flex h-48 items-center justify-center rounded-lg border border-dashed border-border",
|
|
61
|
+
className: "flex h-48 items-center justify-center rounded-lg border border-dashed border-border-subtle",
|
|
62
62
|
children: /* @__PURE__ */ c("p", {
|
|
63
|
-
className: "text-sm text-
|
|
63
|
+
className: "text-sm text-text-secondary",
|
|
64
64
|
children: "Chart will render here"
|
|
65
65
|
})
|
|
66
66
|
})]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmailAnalyticsPage.js","names":[],"sources":["../../../../src/timecampus/pages/email-tracking/EmailAnalyticsPage.tsx"],"sourcesContent":["import { BarChart3, Mail, Clock } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { StatCard } from \"../../components/StatCard\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport { useGetEmailTrackingStatsQuery } from \"@/generated/wspace-operations\";\n\nexport function EmailAnalyticsPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n const { data, loading, error } = useGetEmailTrackingStatsQuery({\n skip: !workspaceId,\n });\n\n const stats = data?.emailTrackingStats;\n\n if (loading) {\n return (\n <PageLayout\n title=\"Email Analytics\"\n description=\"Insights into email time management\"\n >\n <LoadingSkeleton variant=\"card\" count={4} />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title=\"Email Analytics\"\n description=\"Insights into email time management\"\n >\n <div className=\"rounded-xl border border-
|
|
1
|
+
{"version":3,"file":"EmailAnalyticsPage.js","names":[],"sources":["../../../../src/timecampus/pages/email-tracking/EmailAnalyticsPage.tsx"],"sourcesContent":["import { BarChart3, Mail, Clock } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { StatCard } from \"../../components/StatCard\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport { useGetEmailTrackingStatsQuery } from \"@/generated/wspace-operations\";\n\nexport function EmailAnalyticsPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n const { data, loading, error } = useGetEmailTrackingStatsQuery({\n skip: !workspaceId,\n });\n\n const stats = data?.emailTrackingStats;\n\n if (loading) {\n return (\n <PageLayout\n title=\"Email Analytics\"\n description=\"Insights into email time management\"\n >\n <LoadingSkeleton variant=\"card\" count={4} />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title=\"Email Analytics\"\n description=\"Insights into email time management\"\n >\n <div className=\"rounded-xl border border-status-error-border/50 bg-status-error-bg/10 p-4 text-sm text-status-error-text\">\n Failed to load email analytics. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n const totalMinutes = Math.round((stats?.totalDuration ?? 0) / 60);\n const hours = Math.floor(totalMinutes / 60);\n const minutes = totalMinutes % 60;\n const timeOnEmail = hours > 0 ? `${hours}h ${minutes}m` : `${minutes}m`;\n const avgResponse =\n stats?.averageResponseTime != null\n ? `${Math.round(stats.averageResponseTime)} min`\n : \"--\";\n const totalEmails = String(stats?.totalEmails ?? 0);\n const importantRatio = stats?.totalEmails\n ? Math.round((stats.importantCount / stats.totalEmails) * 100)\n : 0;\n\n return (\n <PageLayout\n title=\"Email Analytics\"\n description=\"Insights into email time management\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatCard\n title=\"Emails Today\"\n value={totalEmails}\n icon={<Mail className=\"h-5 w-5\" />}\n />\n <StatCard\n title=\"Time on Email\"\n value={timeOnEmail}\n icon={<Clock className=\"h-5 w-5\" />}\n />\n <StatCard\n title=\"Avg. Response\"\n value={avgResponse}\n description=\"Target: 15 min\"\n />\n <StatCard\n title=\"Email Score\"\n value={`${importantRatio}%`}\n icon={<BarChart3 className=\"h-5 w-5\" />}\n />\n </div>\n\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-6\">\n <h3 className=\"mb-4 text-sm font-semibold text-text-primary\">\n Email Volume & Response Time\n </h3>\n <div className=\"flex h-48 items-center justify-center rounded-lg border border-dashed border-border-subtle\">\n <p className=\"text-sm text-text-secondary\">\n Chart will render here\n </p>\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;AAOA,SAAgB,IAAqB;CACnC,IAAM,EAAE,iBAAc,OAAO,GAAe,EACtC,EAAE,SAAM,YAAS,aAAU,EAA8B,EAC7D,MAAM,CAAC,GACR,CAAC,EAEI,IAAQ,GAAM;AAEpB,KAAI,EACF,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,GAAD;GAAiB,SAAQ;GAAO,OAAO;GAAK,CAAA;EACjC,CAAA;AAIjB,KAAI,EACF,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,OAAD;GAAK,WAAU;aAA2G;GAEpH,CAAA;EACK,CAAA;CAIjB,IAAM,IAAe,KAAK,OAAO,GAAO,iBAAiB,KAAK,GAAG,EAC3D,IAAQ,KAAK,MAAM,IAAe,GAAG,EACrC,IAAU,IAAe,IACzB,IAAc,IAAQ,IAAI,GAAG,EAAM,IAAI,EAAQ,KAAK,GAAG,EAAQ,IAC/D,IACJ,GAAO,uBAAuB,OAE1B,OADA,GAAG,KAAK,MAAM,EAAM,oBAAoB,CAAC,OAEzC,IAAc,OAAO,GAAO,eAAe,EAAE,EAC7C,IAAiB,GAAO,cAC1B,KAAK,MAAO,EAAM,iBAAiB,EAAM,cAAe,IAAI,GAC5D;AAEJ,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAFd,CAIE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,GAAD;KACE,OAAM;KACN,OAAO;KACP,MAAM,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA;KAClC,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO;KACP,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;KACnC,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO;KACP,aAAY;KACZ,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,GAAG,EAAe;KACzB,MAAM,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;KACvC,CAAA;IACE;MAEN,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,MAAD;IAAI,WAAU;cAA+C;IAExD,CAAA,EACL,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,KAAD;KAAG,WAAU;eAA8B;KAEvC,CAAA;IACA,CAAA,CACF;KACK"}
|
|
@@ -48,7 +48,7 @@ function p() {
|
|
|
48
48
|
title: "Email Settings",
|
|
49
49
|
description: "Configure email tracking preferences",
|
|
50
50
|
children: /* @__PURE__ */ l("div", {
|
|
51
|
-
className: "rounded-xl border border-
|
|
51
|
+
className: "rounded-xl border border-status-error-border/50 bg-status-error-bg/10 p-4 text-sm text-status-error-text",
|
|
52
52
|
children: "Failed to load settings. Please try again later."
|
|
53
53
|
})
|
|
54
54
|
}) : /* @__PURE__ */ l(t, {
|
|
@@ -57,9 +57,9 @@ function p() {
|
|
|
57
57
|
children: /* @__PURE__ */ u("div", {
|
|
58
58
|
className: "mx-auto max-w-2xl space-y-6",
|
|
59
59
|
children: [/* @__PURE__ */ u("div", {
|
|
60
|
-
className: "rounded-xl border border-border bg-
|
|
60
|
+
className: "rounded-xl border border-border-subtle bg-bg-surface p-6",
|
|
61
61
|
children: [/* @__PURE__ */ u("h3", {
|
|
62
|
-
className: "mb-4 flex items-center gap-2 text-sm font-semibold text-
|
|
62
|
+
className: "mb-4 flex items-center gap-2 text-sm font-semibold text-text-primary",
|
|
63
63
|
children: [/* @__PURE__ */ l(c, { className: "h-4 w-4" }), "Tracking Configuration"]
|
|
64
64
|
}), /* @__PURE__ */ u("div", {
|
|
65
65
|
className: "space-y-3",
|
|
@@ -67,10 +67,10 @@ function p() {
|
|
|
67
67
|
/* @__PURE__ */ u("label", {
|
|
68
68
|
className: "flex items-center justify-between",
|
|
69
69
|
children: [/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("span", {
|
|
70
|
-
className: "text-sm font-medium text-
|
|
70
|
+
className: "text-sm font-medium text-text-primary",
|
|
71
71
|
children: "Auto-track emails"
|
|
72
72
|
}), /* @__PURE__ */ l("p", {
|
|
73
|
-
className: "text-xs text-
|
|
73
|
+
className: "text-xs text-text-secondary",
|
|
74
74
|
children: "Automatically track time spent reading and responding"
|
|
75
75
|
})] }), /* @__PURE__ */ l("input", {
|
|
76
76
|
type: "checkbox",
|
|
@@ -79,16 +79,16 @@ function p() {
|
|
|
79
79
|
...t,
|
|
80
80
|
autoTrack: e.target.checked
|
|
81
81
|
})),
|
|
82
|
-
className: "h-4 w-4 rounded border-border"
|
|
82
|
+
className: "h-4 w-4 rounded border-border-subtle"
|
|
83
83
|
})]
|
|
84
84
|
}),
|
|
85
85
|
/* @__PURE__ */ u("label", {
|
|
86
86
|
className: "flex items-center justify-between",
|
|
87
87
|
children: [/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("span", {
|
|
88
|
-
className: "text-sm font-medium text-
|
|
88
|
+
className: "text-sm font-medium text-text-primary",
|
|
89
89
|
children: "Categorize by project"
|
|
90
90
|
}), /* @__PURE__ */ l("p", {
|
|
91
|
-
className: "text-xs text-
|
|
91
|
+
className: "text-xs text-text-secondary",
|
|
92
92
|
children: "Link emails to projects automatically"
|
|
93
93
|
})] }), /* @__PURE__ */ l("input", {
|
|
94
94
|
type: "checkbox",
|
|
@@ -97,16 +97,16 @@ function p() {
|
|
|
97
97
|
...t,
|
|
98
98
|
categorizeByProject: e.target.checked
|
|
99
99
|
})),
|
|
100
|
-
className: "h-4 w-4 rounded border-border"
|
|
100
|
+
className: "h-4 w-4 rounded border-border-subtle"
|
|
101
101
|
})]
|
|
102
102
|
}),
|
|
103
103
|
/* @__PURE__ */ u("label", {
|
|
104
104
|
className: "flex items-center justify-between",
|
|
105
105
|
children: [/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("span", {
|
|
106
|
-
className: "text-sm font-medium text-
|
|
106
|
+
className: "text-sm font-medium text-text-primary",
|
|
107
107
|
children: "Response time alerts"
|
|
108
108
|
}), /* @__PURE__ */ l("p", {
|
|
109
|
-
className: "text-xs text-
|
|
109
|
+
className: "text-xs text-text-secondary",
|
|
110
110
|
children: "Notify when response time exceeds threshold"
|
|
111
111
|
})] }), /* @__PURE__ */ l("input", {
|
|
112
112
|
type: "checkbox",
|
|
@@ -115,7 +115,7 @@ function p() {
|
|
|
115
115
|
...t,
|
|
116
116
|
responseTimeAlerts: e.target.checked
|
|
117
117
|
})),
|
|
118
|
-
className: "h-4 w-4 rounded border-border"
|
|
118
|
+
className: "h-4 w-4 rounded border-border-subtle"
|
|
119
119
|
})]
|
|
120
120
|
})
|
|
121
121
|
]
|
|
@@ -125,7 +125,7 @@ function p() {
|
|
|
125
125
|
children: /* @__PURE__ */ l("button", {
|
|
126
126
|
onClick: x,
|
|
127
127
|
disabled: v,
|
|
128
|
-
className: "rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-
|
|
128
|
+
className: "rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50",
|
|
129
129
|
children: v ? "Saving..." : "Save Settings"
|
|
130
130
|
})
|
|
131
131
|
})]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmailSettingsPage.js","names":[],"sources":["../../../../src/timecampus/pages/email-tracking/EmailSettingsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from \"react\";\nimport { Settings } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListConfigurationsQuery,\n useSetConfigurationMutation,\n type ConfigurationFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nconst EMAIL_SETTINGS_KEY = \"timecampus.email.settings\";\n\ninterface EmailSettings {\n autoTrack: boolean;\n categorizeByProject: boolean;\n responseTimeAlerts: boolean;\n}\n\nconst DEFAULT_SETTINGS: EmailSettings = {\n autoTrack: true,\n categorizeByProject: true,\n responseTimeAlerts: false,\n};\n\nexport function EmailSettingsPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n const { data, loading, error } = useListConfigurationsQuery({\n variables: { scope: \"WORKSPACE\" as never, limit: 100 },\n skip: !workspaceId,\n });\n\n const [setConfiguration, { loading: saving }] = useSetConfigurationMutation();\n const [settings, setSettings] = useState<EmailSettings>(DEFAULT_SETTINGS);\n\n useEffect(() => {\n if (data?.configurations) {\n const emailConfig = data.configurations.find(\n (c: ConfigurationFieldsFragment) => c.key === EMAIL_SETTINGS_KEY,\n );\n if (emailConfig?.value) {\n const val = emailConfig.value as Partial<EmailSettings>;\n setSettings({\n autoTrack: val.autoTrack ?? DEFAULT_SETTINGS.autoTrack,\n categorizeByProject:\n val.categorizeByProject ?? DEFAULT_SETTINGS.categorizeByProject,\n responseTimeAlerts:\n val.responseTimeAlerts ?? DEFAULT_SETTINGS.responseTimeAlerts,\n });\n }\n }\n }, [data]);\n\n const handleSave = useCallback(async () => {\n await setConfiguration({\n variables: {\n input: {\n key: EMAIL_SETTINGS_KEY,\n value: settings as unknown as Record<string, unknown>,\n description: \"Email tracking settings\",\n scope: \"WORKSPACE\" as never,\n },\n },\n });\n }, [setConfiguration, settings]);\n\n if (loading) {\n return (\n <PageLayout\n title=\"Email Settings\"\n description=\"Configure email tracking preferences\"\n >\n <LoadingSkeleton variant=\"detail\" />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title=\"Email Settings\"\n description=\"Configure email tracking preferences\"\n >\n <div className=\"rounded-xl border border-
|
|
1
|
+
{"version":3,"file":"EmailSettingsPage.js","names":[],"sources":["../../../../src/timecampus/pages/email-tracking/EmailSettingsPage.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from \"react\";\nimport { Settings } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListConfigurationsQuery,\n useSetConfigurationMutation,\n type ConfigurationFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nconst EMAIL_SETTINGS_KEY = \"timecampus.email.settings\";\n\ninterface EmailSettings {\n autoTrack: boolean;\n categorizeByProject: boolean;\n responseTimeAlerts: boolean;\n}\n\nconst DEFAULT_SETTINGS: EmailSettings = {\n autoTrack: true,\n categorizeByProject: true,\n responseTimeAlerts: false,\n};\n\nexport function EmailSettingsPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n const { data, loading, error } = useListConfigurationsQuery({\n variables: { scope: \"WORKSPACE\" as never, limit: 100 },\n skip: !workspaceId,\n });\n\n const [setConfiguration, { loading: saving }] = useSetConfigurationMutation();\n const [settings, setSettings] = useState<EmailSettings>(DEFAULT_SETTINGS);\n\n useEffect(() => {\n if (data?.configurations) {\n const emailConfig = data.configurations.find(\n (c: ConfigurationFieldsFragment) => c.key === EMAIL_SETTINGS_KEY,\n );\n if (emailConfig?.value) {\n const val = emailConfig.value as Partial<EmailSettings>;\n setSettings({\n autoTrack: val.autoTrack ?? DEFAULT_SETTINGS.autoTrack,\n categorizeByProject:\n val.categorizeByProject ?? DEFAULT_SETTINGS.categorizeByProject,\n responseTimeAlerts:\n val.responseTimeAlerts ?? DEFAULT_SETTINGS.responseTimeAlerts,\n });\n }\n }\n }, [data]);\n\n const handleSave = useCallback(async () => {\n await setConfiguration({\n variables: {\n input: {\n key: EMAIL_SETTINGS_KEY,\n value: settings as unknown as Record<string, unknown>,\n description: \"Email tracking settings\",\n scope: \"WORKSPACE\" as never,\n },\n },\n });\n }, [setConfiguration, settings]);\n\n if (loading) {\n return (\n <PageLayout\n title=\"Email Settings\"\n description=\"Configure email tracking preferences\"\n >\n <LoadingSkeleton variant=\"detail\" />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title=\"Email Settings\"\n description=\"Configure email tracking preferences\"\n >\n <div className=\"rounded-xl border border-status-error-border/50 bg-status-error-bg/10 p-4 text-sm text-status-error-text\">\n Failed to load settings. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Email Settings\"\n description=\"Configure email tracking preferences\"\n >\n <div className=\"mx-auto max-w-2xl space-y-6\">\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-6\">\n <h3 className=\"mb-4 flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <Settings className=\"h-4 w-4\" />\n Tracking Configuration\n </h3>\n <div className=\"space-y-3\">\n <label className=\"flex items-center justify-between\">\n <div>\n <span className=\"text-sm font-medium text-text-primary\">\n Auto-track emails\n </span>\n <p className=\"text-xs text-text-secondary\">\n Automatically track time spent reading and responding\n </p>\n </div>\n <input\n type=\"checkbox\"\n checked={settings.autoTrack}\n onChange={(e) =>\n setSettings((s) => ({ ...s, autoTrack: e.target.checked }))\n }\n className=\"h-4 w-4 rounded border-border-subtle\"\n />\n </label>\n <label className=\"flex items-center justify-between\">\n <div>\n <span className=\"text-sm font-medium text-text-primary\">\n Categorize by project\n </span>\n <p className=\"text-xs text-text-secondary\">\n Link emails to projects automatically\n </p>\n </div>\n <input\n type=\"checkbox\"\n checked={settings.categorizeByProject}\n onChange={(e) =>\n setSettings((s) => ({\n ...s,\n categorizeByProject: e.target.checked,\n }))\n }\n className=\"h-4 w-4 rounded border-border-subtle\"\n />\n </label>\n <label className=\"flex items-center justify-between\">\n <div>\n <span className=\"text-sm font-medium text-text-primary\">\n Response time alerts\n </span>\n <p className=\"text-xs text-text-secondary\">\n Notify when response time exceeds threshold\n </p>\n </div>\n <input\n type=\"checkbox\"\n checked={settings.responseTimeAlerts}\n onChange={(e) =>\n setSettings((s) => ({\n ...s,\n responseTimeAlerts: e.target.checked,\n }))\n }\n className=\"h-4 w-4 rounded border-border-subtle\"\n />\n </label>\n </div>\n </div>\n <div className=\"flex justify-end\">\n <button\n onClick={handleSave}\n disabled={saving}\n className=\"rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50\"\n >\n {saving ? \"Saving...\" : \"Save Settings\"}\n </button>\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -15,31 +15,31 @@ function d() {
|
|
|
15
15
|
title: "Email Tracking",
|
|
16
16
|
description: "Track time spent on emails",
|
|
17
17
|
actions: /* @__PURE__ */ u("button", {
|
|
18
|
-
className: "inline-flex items-center gap-1.5 rounded-md border border-border px-3 py-2 text-sm font-medium text-
|
|
18
|
+
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",
|
|
19
19
|
children: [/* @__PURE__ */ l(s, { className: "h-4 w-4" }), "Filter"]
|
|
20
20
|
}),
|
|
21
21
|
children: p ? /* @__PURE__ */ l(a, {
|
|
22
22
|
variant: "list",
|
|
23
23
|
count: 4
|
|
24
24
|
}) : m ? /* @__PURE__ */ l("div", {
|
|
25
|
-
className: "rounded-xl border border-
|
|
25
|
+
className: "rounded-xl border border-status-error-border/50 bg-status-error-bg/10 p-4 text-sm text-status-error-text",
|
|
26
26
|
children: "Failed to load email entries. Please try again later."
|
|
27
27
|
}) : /* @__PURE__ */ l("div", {
|
|
28
|
-
className: "rounded-xl border border-border bg-
|
|
28
|
+
className: "rounded-xl border border-border-subtle bg-bg-surface",
|
|
29
29
|
children: /* @__PURE__ */ l("div", {
|
|
30
30
|
className: "divide-y divide-border",
|
|
31
31
|
children: h.length === 0 ? /* @__PURE__ */ l("div", {
|
|
32
|
-
className: "p-8 text-center text-sm text-
|
|
32
|
+
className: "p-8 text-center text-sm text-text-secondary",
|
|
33
33
|
children: "No email entries found."
|
|
34
34
|
}) : h.map((e) => /* @__PURE__ */ u("div", {
|
|
35
|
-
className: "flex items-center justify-between p-4 hover:bg-
|
|
35
|
+
className: "flex items-center justify-between p-4 hover:bg-bg-sunken/50 transition-colors cursor-pointer",
|
|
36
36
|
children: [/* @__PURE__ */ u("div", {
|
|
37
37
|
className: "flex items-center gap-3",
|
|
38
|
-
children: [/* @__PURE__ */ l(c, { className: `h-5 w-5 ${e.isImportant ? "text-primary" : "text-
|
|
39
|
-
className: `text-sm ${e.isImportant ? "font-semibold text-
|
|
38
|
+
children: [/* @__PURE__ */ l(c, { className: `h-5 w-5 ${e.isImportant ? "text-primary" : "text-text-secondary"}` }), /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("p", {
|
|
39
|
+
className: `text-sm ${e.isImportant ? "font-semibold text-text-primary" : "font-medium text-text-primary"}`,
|
|
40
40
|
children: e.subject ?? "(No subject)"
|
|
41
41
|
}), /* @__PURE__ */ u("p", {
|
|
42
|
-
className: "text-xs text-
|
|
42
|
+
className: "text-xs text-text-secondary",
|
|
43
43
|
children: [
|
|
44
44
|
e.sender ?? "Unknown",
|
|
45
45
|
" ·",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmailTrackingPage.js","names":[],"sources":["../../../../src/timecampus/pages/email-tracking/EmailTrackingPage.tsx"],"sourcesContent":["import { Mail, Filter } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport {\n getStatusColor,\n getPriorityColor,\n formatRelativeTime,\n} from \"../../utils/helpers\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListEmailTimeEntriesQuery,\n type EmailTimeEntryFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function EmailTrackingPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n const { data, loading, error } = useListEmailTimeEntriesQuery({\n variables: { limit: 50 },\n skip: !workspaceId,\n });\n\n const emails = data?.emailTimeEntries ?? [];\n\n return (\n <PageLayout\n title=\"Email Tracking\"\n description=\"Track time spent on emails\"\n actions={\n <button className=\"inline-flex items-center gap-1.5 rounded-md border border-border px-3 py-2 text-sm font-medium text-
|
|
1
|
+
{"version":3,"file":"EmailTrackingPage.js","names":[],"sources":["../../../../src/timecampus/pages/email-tracking/EmailTrackingPage.tsx"],"sourcesContent":["import { Mail, Filter } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport {\n getStatusColor,\n getPriorityColor,\n formatRelativeTime,\n} from \"../../utils/helpers\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListEmailTimeEntriesQuery,\n type EmailTimeEntryFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function EmailTrackingPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n const { data, loading, error } = useListEmailTimeEntriesQuery({\n variables: { limit: 50 },\n skip: !workspaceId,\n });\n\n const emails = data?.emailTimeEntries ?? [];\n\n return (\n <PageLayout\n title=\"Email Tracking\"\n description=\"Track time spent on emails\"\n actions={\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 }\n >\n {loading ? (\n <LoadingSkeleton variant=\"list\" count={4} />\n ) : error ? (\n <div className=\"rounded-xl border border-status-error-border/50 bg-status-error-bg/10 p-4 text-sm text-status-error-text\">\n Failed to load email entries. Please try again later.\n </div>\n ) : (\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface\">\n <div className=\"divide-y divide-border\">\n {emails.length === 0 ? (\n <div className=\"p-8 text-center text-sm text-text-secondary\">\n No email entries found.\n </div>\n ) : (\n emails.map((email: EmailTimeEntryFieldsFragment) => (\n <div\n key={email.id}\n className=\"flex items-center justify-between p-4 hover:bg-bg-sunken/50 transition-colors cursor-pointer\"\n >\n <div className=\"flex items-center gap-3\">\n <Mail\n className={`h-5 w-5 ${email.isImportant ? \"text-primary\" : \"text-text-secondary\"}`}\n />\n <div>\n <p\n className={`text-sm ${email.isImportant ? \"font-semibold text-text-primary\" : \"font-medium text-text-primary\"}`}\n >\n {email.subject ?? \"(No subject)\"}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {email.sender ?? \"Unknown\"} ·{\" \"}\n {formatRelativeTime(email.date)} · ~\n {email.duration ?? 0}min\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <span\n className={`inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${getPriorityColor(email.isImportant ? \"high\" : \"low\")}`}\n >\n {email.isImportant ? \"high\" : \"normal\"}\n </span>\n <span\n className={`inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${getStatusColor(email.category ?? \"active\")}`}\n >\n {email.category ?? \"uncategorized\"}\n </span>\n </div>\n </div>\n ))\n )}\n </div>\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;AAcA,SAAgB,IAAoB;CAClC,IAAM,EAAE,iBAAc,OAAO,GAAe,EACtC,EAAE,SAAM,YAAS,aAAU,EAA6B;EAC5D,WAAW,EAAE,OAAO,IAAI;EACxB,MAAM,CAAC;EACR,CAAC,EAEI,IAAS,GAAM,oBAAoB,EAAE;AAE3C,QACE,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SACE,kBAAC,UAAD;GAAQ,WAAU;aAAlB,CACE,kBAAC,GAAD,EAAQ,WAAU,WAAY,CAAA,EAAA,SAEvB;;YAGV,IACC,kBAAC,GAAD;GAAiB,SAAQ;GAAO,OAAO;GAAK,CAAA,GAC1C,IACF,kBAAC,OAAD;GAAK,WAAU;aAA2G;GAEpH,CAAA,GAEN,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAO,WAAW,IACjB,kBAAC,OAAD;KAAK,WAAU;eAA8C;KAEvD,CAAA,GAEN,EAAO,KAAK,MACV,kBAAC,OAAD;KAEE,WAAU;eAFZ,CAIE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EACE,WAAW,WAAW,EAAM,cAAc,iBAAiB,yBAC3D,CAAA,EACF,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;OACE,WAAW,WAAW,EAAM,cAAc,oCAAoC;iBAE7E,EAAM,WAAW;OAChB,CAAA,EACJ,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG,EAAM,UAAU;QAAU;QAAU;QACpC,EAAmB,EAAM,KAAK;QAAC;QAC/B,EAAM,YAAY;QAAE;QACnB;SACA,EAAA,CAAA,CACF;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OACE,WAAW,4DAA4D,EAAiB,EAAM,cAAc,SAAS,MAAM;iBAE1H,EAAM,cAAc,SAAS;OACzB,CAAA,EACP,kBAAC,QAAD;OACE,WAAW,4DAA4D,EAAe,EAAM,YAAY,SAAS;iBAEhH,EAAM,YAAY;OACd,CAAA,CACH;QACF;OAhCC,EAAM,GAgCP,CACN;IAEA,CAAA;GACF,CAAA;EAEG,CAAA"}
|
|
@@ -27,7 +27,7 @@ function m() {
|
|
|
27
27
|
title: "Expense Tracking",
|
|
28
28
|
description: "Track and manage work expenses",
|
|
29
29
|
actions: /* @__PURE__ */ p("button", {
|
|
30
|
-
className: "inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-
|
|
30
|
+
className: "inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
|
|
31
31
|
children: [/* @__PURE__ */ f(u, { className: "h-4 w-4" }), "Add Expense"]
|
|
32
32
|
}),
|
|
33
33
|
children: [/* @__PURE__ */ p("div", {
|
|
@@ -56,21 +56,21 @@ function m() {
|
|
|
56
56
|
})
|
|
57
57
|
]
|
|
58
58
|
}), /* @__PURE__ */ f("div", {
|
|
59
|
-
className: "rounded-xl border border-border bg-
|
|
59
|
+
className: "rounded-xl border border-border-subtle bg-bg-surface",
|
|
60
60
|
children: /* @__PURE__ */ p("div", {
|
|
61
61
|
className: "divide-y divide-border",
|
|
62
62
|
children: [x.length === 0 && !g && /* @__PURE__ */ f("div", {
|
|
63
|
-
className: "p-4 text-center text-sm text-
|
|
63
|
+
className: "p-4 text-center text-sm text-text-secondary",
|
|
64
64
|
children: "No expenses recorded yet."
|
|
65
65
|
}), x.map((e) => /* @__PURE__ */ p("div", {
|
|
66
|
-
className: "flex items-center justify-between p-4 hover:bg-
|
|
66
|
+
className: "flex items-center justify-between p-4 hover:bg-bg-sunken/50 transition-colors",
|
|
67
67
|
children: [/* @__PURE__ */ p("div", {
|
|
68
68
|
className: "flex items-center gap-3",
|
|
69
|
-
children: [/* @__PURE__ */ f(d, { className: "h-5 w-5 text-
|
|
70
|
-
className: "text-sm font-medium text-
|
|
69
|
+
children: [/* @__PURE__ */ f(d, { className: "h-5 w-5 text-text-secondary" }), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("p", {
|
|
70
|
+
className: "text-sm font-medium text-text-primary",
|
|
71
71
|
children: e.description ?? "Untitled expense"
|
|
72
72
|
}), /* @__PURE__ */ p("p", {
|
|
73
|
-
className: "text-xs text-
|
|
73
|
+
className: "text-xs text-text-secondary",
|
|
74
74
|
children: [
|
|
75
75
|
e.category,
|
|
76
76
|
" ·",
|
|
@@ -84,7 +84,7 @@ function m() {
|
|
|
84
84
|
}), /* @__PURE__ */ p("div", {
|
|
85
85
|
className: "flex items-center gap-3",
|
|
86
86
|
children: [/* @__PURE__ */ f("p", {
|
|
87
|
-
className: "text-sm font-medium text-
|
|
87
|
+
className: "text-sm font-medium text-text-primary",
|
|
88
88
|
children: t(e.amount)
|
|
89
89
|
}), /* @__PURE__ */ f("span", {
|
|
90
90
|
className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${r(e.status)}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpenseTrackingPage.js","names":[],"sources":["../../../../src/timecampus/pages/expense-tracking/ExpenseTrackingPage.tsx"],"sourcesContent":["import { Receipt, Plus, DollarSign } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { StatCard } from \"../../components/StatCard\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport {\n getStatusColor,\n formatCurrency,\n formatDate,\n} from \"../../utils/helpers\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListExpensesQuery,\n useGetExpenseStatsQuery,\n type ExpenseFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function ExpenseTrackingPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const {\n data: expensesData,\n loading: expensesLoading,\n error: expensesError,\n } = useListExpensesQuery({\n variables: { workspaceId },\n });\n const {\n data: statsData,\n loading: statsLoading,\n error: statsError,\n } = useGetExpenseStatsQuery({\n variables: { workspaceId },\n });\n\n const expenses = expensesData?.expenses ?? [];\n const stats = statsData?.expenseStats;\n\n if (expensesLoading && statsLoading) {\n return (\n <PageLayout\n title=\"Expense Tracking\"\n description=\"Track and manage work expenses\"\n >\n <LoadingSkeleton variant=\"list\" count={4} />\n </PageLayout>\n );\n }\n\n if (expensesError && statsError) {\n return (\n <PageLayout\n title=\"Expense Tracking\"\n description=\"Track and manage work expenses\"\n >\n <div className=\"rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-600 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400\">\n Failed to load expense data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Expense Tracking\"\n description=\"Track and manage work expenses\"\n actions={\n <button className=\"inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-
|
|
1
|
+
{"version":3,"file":"ExpenseTrackingPage.js","names":[],"sources":["../../../../src/timecampus/pages/expense-tracking/ExpenseTrackingPage.tsx"],"sourcesContent":["import { Receipt, Plus, DollarSign } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { StatCard } from \"../../components/StatCard\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport {\n getStatusColor,\n formatCurrency,\n formatDate,\n} from \"../../utils/helpers\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListExpensesQuery,\n useGetExpenseStatsQuery,\n type ExpenseFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nexport function ExpenseTrackingPage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const {\n data: expensesData,\n loading: expensesLoading,\n error: expensesError,\n } = useListExpensesQuery({\n variables: { workspaceId },\n });\n const {\n data: statsData,\n loading: statsLoading,\n error: statsError,\n } = useGetExpenseStatsQuery({\n variables: { workspaceId },\n });\n\n const expenses = expensesData?.expenses ?? [];\n const stats = statsData?.expenseStats;\n\n if (expensesLoading && statsLoading) {\n return (\n <PageLayout\n title=\"Expense Tracking\"\n description=\"Track and manage work expenses\"\n >\n <LoadingSkeleton variant=\"list\" count={4} />\n </PageLayout>\n );\n }\n\n if (expensesError && statsError) {\n return (\n <PageLayout\n title=\"Expense Tracking\"\n description=\"Track and manage work expenses\"\n >\n <div className=\"rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-600 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400\">\n Failed to load expense data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Expense Tracking\"\n description=\"Track and manage work expenses\"\n actions={\n <button className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\">\n <Plus className=\"h-4 w-4\" />\n Add Expense\n </button>\n }\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatCard\n title=\"Total This Month\"\n value={formatCurrency(stats?.totalAmount ?? 0)}\n icon={<DollarSign className=\"h-5 w-5\" />}\n />\n <StatCard\n title=\"Pending\"\n value={String(stats?.pendingCount ?? 0)}\n description=\"expenses awaiting approval\"\n />\n <StatCard\n title=\"Approved\"\n value={String(stats?.approvedCount ?? 0)}\n description=\"expenses approved\"\n />\n <StatCard\n title=\"Average\"\n value={formatCurrency(stats?.averageAmount ?? 0)}\n icon={<Receipt className=\"h-5 w-5\" />}\n description=\"per expense\"\n />\n </div>\n\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface\">\n <div className=\"divide-y divide-border\">\n {expenses.length === 0 && !expensesLoading && (\n <div className=\"p-4 text-center text-sm text-text-secondary\">\n No expenses recorded yet.\n </div>\n )}\n {expenses.map((expense: ExpenseFieldsFragment) => (\n <div\n key={expense.id}\n className=\"flex items-center justify-between p-4 hover:bg-bg-sunken/50 transition-colors\"\n >\n <div className=\"flex items-center gap-3\">\n <Receipt className=\"h-5 w-5 text-text-secondary\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {expense.description ?? \"Untitled expense\"}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {expense.category} ·{\" \"}\n {expense.projectId ?? \"No project\"} ·{\" \"}\n {formatDate(expense.date)}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-3\">\n <p className=\"text-sm font-medium text-text-primary\">\n {formatCurrency(expense.amount)}\n </p>\n <span\n className={`inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${getStatusColor(expense.status)}`}\n >\n {expense.status}\n </span>\n </div>\n </div>\n ))}\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;AAgBA,SAAgB,IAAsB;CACpC,IAAM,EAAE,iBAAc,OAAO,GAAe,EAEtC,EACJ,MAAM,GACN,SAAS,GACT,OAAO,MACL,EAAqB,EACvB,WAAW,EAAE,gBAAa,EAC3B,CAAC,EACI,EACJ,MAAM,GACN,SAAS,GACT,OAAO,MACL,EAAwB,EAC1B,WAAW,EAAE,gBAAa,EAC3B,CAAC,EAEI,IAAW,GAAc,YAAY,EAAE,EACvC,IAAQ,GAAW;AA0BzB,QAxBI,KAAmB,IAEnB,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,GAAD;GAAiB,SAAQ;GAAO,OAAO;GAAK,CAAA;EACjC,CAAA,GAIb,KAAiB,IAEjB,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;YAEZ,kBAAC,OAAD;GAAK,WAAU;aAA+H;GAExI,CAAA;EACK,CAAA,GAKf,kBAAC,GAAD;EACE,OAAM;EACN,aAAY;EACZ,SACE,kBAAC,UAAD;GAAQ,WAAU;aAAlB,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAAA,cAErB;;YAPb,CAUE,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,EAAe,GAAO,eAAe,EAAE;KAC9C,MAAM,kBAAC,GAAD,EAAY,WAAU,WAAY,CAAA;KACxC,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,OAAO,GAAO,gBAAgB,EAAE;KACvC,aAAY;KACZ,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,OAAO,GAAO,iBAAiB,EAAE;KACxC,aAAY;KACZ,CAAA;IACF,kBAAC,GAAD;KACE,OAAM;KACN,OAAO,EAAe,GAAO,iBAAiB,EAAE;KAChD,MAAM,kBAAC,GAAD,EAAS,WAAU,WAAY,CAAA;KACrC,aAAY;KACZ,CAAA;IACE;MAEN,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,EAAS,WAAW,KAAK,CAAC,KACzB,kBAAC,OAAD;KAAK,WAAU;eAA8C;KAEvD,CAAA,EAEP,EAAS,KAAK,MACb,kBAAC,OAAD;KAEE,WAAU;eAFZ,CAIE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EAAS,WAAU,+BAAgC,CAAA,EACnD,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAQ,eAAe;OACtB,CAAA,EACJ,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG,EAAQ;QAAS;QAAU;QAC3B,EAAQ,aAAa;QAAa;QAAU;QAC5C,EAAW,EAAQ,KAAK;QACvB;SACA,EAAA,CAAA,CACF;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAe,EAAQ,OAAO;OAC7B,CAAA,EACJ,kBAAC,QAAD;OACE,WAAW,4DAA4D,EAAe,EAAQ,OAAO;iBAEpG,EAAQ;OACJ,CAAA,CACH;QACF;OA1BC,EAAQ,GA0BT,CACN,CACE;;GACF,CAAA,CACK"}
|
|
@@ -55,7 +55,7 @@ function m() {
|
|
|
55
55
|
title: "Focus Score",
|
|
56
56
|
description: "Measure and improve your focus",
|
|
57
57
|
children: /* @__PURE__ */ d("div", {
|
|
58
|
-
className: "rounded-xl border border-
|
|
58
|
+
className: "rounded-xl border border-status-error-border/50 bg-status-error-bg/10 p-4 text-sm text-status-error-text",
|
|
59
59
|
children: "Failed to load focus score data. Please try again later."
|
|
60
60
|
})
|
|
61
61
|
}) : /* @__PURE__ */ f(t, {
|
|
@@ -93,12 +93,12 @@ function m() {
|
|
|
93
93
|
})
|
|
94
94
|
]
|
|
95
95
|
}), /* @__PURE__ */ f("div", {
|
|
96
|
-
className: "rounded-xl border border-border bg-
|
|
96
|
+
className: "rounded-xl border border-border-subtle bg-bg-surface p-6",
|
|
97
97
|
children: [/* @__PURE__ */ d("h3", {
|
|
98
|
-
className: "mb-4 text-sm font-semibold text-
|
|
98
|
+
className: "mb-4 text-sm font-semibold text-text-primary",
|
|
99
99
|
children: "Focus Components"
|
|
100
100
|
}), k.length === 0 ? /* @__PURE__ */ d("div", {
|
|
101
|
-
className: "flex h-32 items-center justify-center text-sm text-
|
|
101
|
+
className: "flex h-32 items-center justify-center text-sm text-text-secondary",
|
|
102
102
|
children: "No focus score recorded today."
|
|
103
103
|
}) : /* @__PURE__ */ d("div", {
|
|
104
104
|
className: "space-y-4",
|
|
@@ -107,14 +107,14 @@ function m() {
|
|
|
107
107
|
children: [/* @__PURE__ */ f("div", {
|
|
108
108
|
className: "flex items-center justify-between text-sm",
|
|
109
109
|
children: [/* @__PURE__ */ d("span", {
|
|
110
|
-
className: "font-medium text-
|
|
110
|
+
className: "font-medium text-text-primary",
|
|
111
111
|
children: e.label
|
|
112
112
|
}), /* @__PURE__ */ f("span", {
|
|
113
|
-
className: "text-
|
|
113
|
+
className: "text-text-secondary",
|
|
114
114
|
children: [e.score, "%"]
|
|
115
115
|
})]
|
|
116
116
|
}), /* @__PURE__ */ d("div", {
|
|
117
|
-
className: "h-2.5 w-full rounded-full bg-
|
|
117
|
+
className: "h-2.5 w-full rounded-full bg-bg-sunken",
|
|
118
118
|
children: /* @__PURE__ */ d("div", {
|
|
119
119
|
className: `h-2.5 rounded-full ${e.color}`,
|
|
120
120
|
style: { width: `${e.score}%` }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FocusScorePage.js","names":[],"sources":["../../../../src/timecampus/pages/focus-score/FocusScorePage.tsx"],"sourcesContent":["import { Brain, Target, Zap, Shield } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { StatCard } from \"../../components/StatCard\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListFocusScoresQuery,\n useGetFocusScoreSummaryQuery,\n useGetTodayFocusScoreQuery,\n type FocusScoreFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nconst COMPONENT_COLORS: Record<string, string> = {\n deepWork: \"bg-blue-500\",\n consistency: \"bg-emerald-500\",\n taskCompletion: \"bg-violet-500\",\n distractionResistance: \"bg-amber-500\",\n energyManagement: \"bg-rose-500\",\n};\n\nexport function FocusScorePage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const {\n data: scoresData,\n loading: scoresLoading,\n error: scoresError,\n } = useListFocusScoresQuery({\n variables: { limit: 30 },\n skip: !workspaceId,\n });\n\n const {\n data: summaryData,\n loading: summaryLoading,\n error: summaryError,\n } = useGetFocusScoreSummaryQuery({\n skip: !workspaceId,\n });\n\n const {\n data: todayData,\n loading: todayLoading,\n error: todayError,\n } = useGetTodayFocusScoreQuery({\n skip: !workspaceId,\n });\n\n const loading = scoresLoading || summaryLoading || todayLoading;\n const error = scoresError || summaryError || todayError;\n const today = todayData?.todayFocusScore;\n const summary = summaryData?.focusScoreSummary;\n const scores = scoresData?.focusScores ?? [];\n\n // Build focus components from today's score\n const focusComponents = today\n ? [\n {\n label: \"Deep Work\",\n score: today.deepWorkScore ?? 0,\n color: COMPONENT_COLORS.deepWork,\n },\n {\n label: \"Consistency\",\n score: today.consistencyScore ?? 0,\n color: COMPONENT_COLORS.consistency,\n },\n {\n label: \"Task Completion\",\n score: today.taskCompletionScore ?? 0,\n color: COMPONENT_COLORS.taskCompletion,\n },\n {\n label: \"Distraction Resistance\",\n score: today.distractionResistanceScore ?? 0,\n color: COMPONENT_COLORS.distractionResistance,\n },\n {\n label: \"Energy Management\",\n score: today.energyManagementScore ?? 0,\n color: COMPONENT_COLORS.energyManagement,\n },\n ]\n : [];\n\n // Calculate stats\n const overallScore =\n today?.overallScore != null ? `${today.overallScore}/100` : \"--\";\n const completedSessions = scores.filter(\n (s: FocusScoreFieldsFragment) => s.overallScore >= 70,\n ).length;\n const totalFocusMinutes = scores.reduce(\n (sum: number, s: FocusScoreFieldsFragment) => sum + (s.overallScore ?? 0),\n 0,\n );\n const totalFocusHours = Math.floor(totalFocusMinutes / 60);\n const totalFocusMins = totalFocusMinutes % 60;\n const focusTimeDisplay =\n totalFocusHours > 0\n ? `${totalFocusHours}h ${totalFocusMins}m`\n : `${totalFocusMins}m`;\n const trendValue =\n summary?.trend === \"up\" ? 7 : summary?.trend === \"down\" ? -5 : 0;\n\n // Longest streak from highest score\n const highestScore =\n summary?.highestScore != null ? `${summary.highestScore}` : \"--\";\n\n if (loading) {\n return (\n <PageLayout\n title=\"Focus Score\"\n description=\"Measure and improve your focus\"\n >\n <LoadingSkeleton variant=\"card\" count={4} />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title=\"Focus Score\"\n description=\"Measure and improve your focus\"\n >\n <div className=\"rounded-xl border border-
|
|
1
|
+
{"version":3,"file":"FocusScorePage.js","names":[],"sources":["../../../../src/timecampus/pages/focus-score/FocusScorePage.tsx"],"sourcesContent":["import { Brain, Target, Zap, Shield } from \"lucide-react\";\nimport { PageLayout } from \"../../components/PageLayout\";\nimport { StatCard } from \"../../components/StatCard\";\nimport { LoadingSkeleton } from \"../../components/LoadingSkeleton\";\nimport { useTimeCampus } from \"../../providers/TimeCampusProvider\";\nimport {\n useListFocusScoresQuery,\n useGetFocusScoreSummaryQuery,\n useGetTodayFocusScoreQuery,\n type FocusScoreFieldsFragment,\n} from \"@/generated/wspace-operations\";\n\nconst COMPONENT_COLORS: Record<string, string> = {\n deepWork: \"bg-blue-500\",\n consistency: \"bg-emerald-500\",\n taskCompletion: \"bg-violet-500\",\n distractionResistance: \"bg-amber-500\",\n energyManagement: \"bg-rose-500\",\n};\n\nexport function FocusScorePage() {\n const { workspaceId = \"\" } = useTimeCampus();\n\n const {\n data: scoresData,\n loading: scoresLoading,\n error: scoresError,\n } = useListFocusScoresQuery({\n variables: { limit: 30 },\n skip: !workspaceId,\n });\n\n const {\n data: summaryData,\n loading: summaryLoading,\n error: summaryError,\n } = useGetFocusScoreSummaryQuery({\n skip: !workspaceId,\n });\n\n const {\n data: todayData,\n loading: todayLoading,\n error: todayError,\n } = useGetTodayFocusScoreQuery({\n skip: !workspaceId,\n });\n\n const loading = scoresLoading || summaryLoading || todayLoading;\n const error = scoresError || summaryError || todayError;\n const today = todayData?.todayFocusScore;\n const summary = summaryData?.focusScoreSummary;\n const scores = scoresData?.focusScores ?? [];\n\n // Build focus components from today's score\n const focusComponents = today\n ? [\n {\n label: \"Deep Work\",\n score: today.deepWorkScore ?? 0,\n color: COMPONENT_COLORS.deepWork,\n },\n {\n label: \"Consistency\",\n score: today.consistencyScore ?? 0,\n color: COMPONENT_COLORS.consistency,\n },\n {\n label: \"Task Completion\",\n score: today.taskCompletionScore ?? 0,\n color: COMPONENT_COLORS.taskCompletion,\n },\n {\n label: \"Distraction Resistance\",\n score: today.distractionResistanceScore ?? 0,\n color: COMPONENT_COLORS.distractionResistance,\n },\n {\n label: \"Energy Management\",\n score: today.energyManagementScore ?? 0,\n color: COMPONENT_COLORS.energyManagement,\n },\n ]\n : [];\n\n // Calculate stats\n const overallScore =\n today?.overallScore != null ? `${today.overallScore}/100` : \"--\";\n const completedSessions = scores.filter(\n (s: FocusScoreFieldsFragment) => s.overallScore >= 70,\n ).length;\n const totalFocusMinutes = scores.reduce(\n (sum: number, s: FocusScoreFieldsFragment) => sum + (s.overallScore ?? 0),\n 0,\n );\n const totalFocusHours = Math.floor(totalFocusMinutes / 60);\n const totalFocusMins = totalFocusMinutes % 60;\n const focusTimeDisplay =\n totalFocusHours > 0\n ? `${totalFocusHours}h ${totalFocusMins}m`\n : `${totalFocusMins}m`;\n const trendValue =\n summary?.trend === \"up\" ? 7 : summary?.trend === \"down\" ? -5 : 0;\n\n // Longest streak from highest score\n const highestScore =\n summary?.highestScore != null ? `${summary.highestScore}` : \"--\";\n\n if (loading) {\n return (\n <PageLayout\n title=\"Focus Score\"\n description=\"Measure and improve your focus\"\n >\n <LoadingSkeleton variant=\"card\" count={4} />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title=\"Focus Score\"\n description=\"Measure and improve your focus\"\n >\n <div className=\"rounded-xl border border-status-error-border/50 bg-status-error-bg/10 p-4 text-sm text-status-error-text\">\n Failed to load focus score data. Please try again later.\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Focus Score\"\n description=\"Measure and improve your focus\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatCard\n title=\"Overall Score\"\n value={overallScore}\n icon={<Brain className=\"h-5 w-5\" />}\n trend={\n trendValue !== 0\n ? { value: trendValue, label: \"vs last week\" }\n : undefined\n }\n iconBgColor=\"bg-violet-100 text-violet-600 dark:bg-violet-900/30 dark:text-violet-400\"\n />\n <StatCard\n title=\"Focus Sessions\"\n value={String(completedSessions)}\n icon={<Target className=\"h-5 w-5\" />}\n description=\"Completed today\"\n />\n <StatCard\n title=\"Total Focus Time\"\n value={focusTimeDisplay}\n icon={<Zap className=\"h-5 w-5\" />}\n />\n <StatCard\n title=\"Highest Score\"\n value={highestScore}\n icon={<Shield className=\"h-5 w-5\" />}\n description=\"Personal best\"\n />\n </div>\n\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-6\">\n <h3 className=\"mb-4 text-sm font-semibold text-text-primary\">\n Focus Components\n </h3>\n {focusComponents.length === 0 ? (\n <div className=\"flex h-32 items-center justify-center text-sm text-text-secondary\">\n No focus score recorded today.\n </div>\n ) : (\n <div className=\"space-y-4\">\n {focusComponents.map((component) => (\n <div key={component.label} className=\"space-y-1\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"font-medium text-text-primary\">\n {component.label}\n </span>\n <span className=\"text-text-secondary\">\n {component.score}%\n </span>\n </div>\n <div className=\"h-2.5 w-full rounded-full bg-bg-sunken\">\n <div\n className={`h-2.5 rounded-full ${component.color}`}\n style={{ width: `${component.score}%` }}\n />\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|