@burdenoff/microfe-crewfoundry 2026.624.1 → 2026.625.2
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/crewfoundry/pages/AdminAdminPagePage.js +100 -76
- package/dist/crewfoundry/pages/AdminAdminPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js +118 -94
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js +105 -81
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +134 -110
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +121 -97
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +28 -15
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js +74 -54
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsDirectoryPagePage.js +87 -69
- package/dist/crewfoundry/pages/CommunicationsDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js +99 -80
- package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +87 -68
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js +31 -15
- package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js +81 -61
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +71 -51
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js +82 -58
- package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js +46 -39
- package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +80 -62
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js +104 -80
- package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +219 -151
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js +183 -142
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardExecutiveDashboardPage.js +121 -97
- package/dist/crewfoundry/pages/DashboardExecutiveDashboardPage.js.map +1 -1
- package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js +57 -46
- package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +91 -67
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +112 -93
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +55 -48
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +70 -50
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +140 -97
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobsPagePage.js +101 -85
- package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +68 -48
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js +99 -71
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +97 -73
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrPayrollPagePage.js +100 -76
- package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +93 -69
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +65 -45
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +93 -75
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +117 -72
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +66 -54
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js +36 -20
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js +90 -66
- package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPagePage.js +81 -57
- package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +90 -65
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +33 -17
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +83 -59
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js +68 -48
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js +80 -60
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js +153 -118
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +42 -37
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +67 -47
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +104 -85
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js +76 -57
- package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +78 -60
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js +138 -93
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +98 -53
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js +69 -49
- package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +84 -65
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js +76 -52
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js +58 -40
- package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js +85 -65
- package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js +36 -29
- package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js +108 -73
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +43 -27
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js +67 -47
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +108 -63
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +83 -64
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js +185 -144
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +40 -24
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LearningCoursesPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/LearningCoursesPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Badge,\n
|
|
1
|
+
{"version":3,"file":"LearningCoursesPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/LearningCoursesPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Badge,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n Input,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { BookOpen, Search, Star, Users } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nexport function LearningCoursesPagePage() {\n const { courses } = useCrewFoundryStore();\n const [search, setSearch] = useState('');\n const filtered = courses.filter((c) =>\n `${c.title} ${c.category} ${c.instructor}`.toLowerCase().includes(search.toLowerCase())\n );\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Course Catalog</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">{courses.length} courses available</p>\n <PagePurpose className=\"mt-1\">Browse the course catalog — find training to grow your team's skills and enroll in the programs that fit your goals.</PagePurpose>\n </div>\n <div className=\"relative max-w-sm\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary\" />\n <Input\n placeholder=\"Search courses...\"\n className=\"pl-9\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n </div>\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {filtered.length === 0 ? (\n <div className=\"col-span-full\">\n <IllustratedEmptyState illustration=\"empty-search\" title=\"No courses found\" description=\"Try a different search term to find training.\" />\n </div>\n ) : (\n filtered.map((course, _idx) => (\n <GlassCard key={course.id} treatment={_idx === 0 ? 'glass' : 'plain'} glow={_idx === 0} className=\"hover:shadow-md transition-shadow cursor-pointer\">\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {course.category}\n </Badge>\n <Badge\n variant={\n course.level === 'beginner'\n ? 'secondary'\n : course.level === 'intermediate'\n ? 'default'\n : 'destructive'\n }\n className=\"text-[10px]\"\n >\n {course.level}\n </Badge>\n </div>\n <CardTitle className=\"text-base mt-2\">{course.title}</CardTitle>\n <CardDescription>\n {course.instructor} · {course.duration} · {course.modules} modules\n </CardDescription>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-text-secondary mb-3\">{course.description}</p>\n <div className=\"flex flex-wrap gap-1 mb-3\">\n {course.skills.map((s) => (\n <Badge key={s} variant=\"outline\" className=\"text-[9px]\">\n {s}\n </Badge>\n ))}\n </div>\n <div className=\"flex items-center justify-between text-xs text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 text-status-warning-text\" />\n {course.rating}\n </span>\n <span className=\"flex items-center gap-1\">\n <Users className=\"h-3 w-3\" />\n {course.enrolled} enrolled\n </span>\n <span>{Math.round((course.completed / course.enrolled) * 100)}% completion</span>\n </div>\n </CardContent>\n </GlassCard>\n )))}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;AAgBA,SAAgB,IAA0B;CACxC,IAAM,EAAE,eAAY,GAAqB,EACnC,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,IAAW,EAAQ,QAAQ,MAC/B,GAAG,EAAE,MAAM,GAAG,EAAE,SAAS,GAAG,EAAE,aAAa,aAAa,CAAC,SAAS,EAAO,aAAa,CAAC,CACxF;AAED,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD,EAAA,UAAA;IACE,kBAAC,MAAD;KAAI,WAAU;eACZ,kBAAC,GAAD,EAAA,UAAc,kBAA6B,CAAA;KACxC,CAAA;IACL,kBAAC,KAAD;KAAG,WAAU;eAAb,CAA4C,EAAQ,QAAO,qBAAsB;;IACjF,kBAAC,GAAD;KAAa,WAAU;eAAO;KAAuI,CAAA;IACjK,EAAA,CAAA;GACN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAQ,WAAU,wEAAyE,CAAA,EAC3F,kBAAC,GAAD;KACE,aAAY;KACZ,WAAU;KACV,OAAO;KACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;KAC1C,CAAA,CACE;;GACN,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAS,WAAW,IACnB,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD;MAAuB,cAAa;MAAe,OAAM;MAAmB,aAAY;MAAkD,CAAA;KACtI,CAAA,GAEN,EAAS,KAAK,GAAQ,MACtB,kBAAC,GAAD;KAA2B,WAAW,MAAS,IAAI,UAAU;KAAS,MAAM,MAAS;KAAG,WAAU;eAAlG,CACE,kBAAC,GAAD,EAAA,UAAA;MACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QAAO,SAAQ;QAAU,WAAU;kBAChC,EAAO;QACF,CAAA,EACR,kBAAC,GAAD;QACE,SACE,EAAO,UAAU,aACb,cACA,EAAO,UAAU,iBACf,YACA;QAER,WAAU;kBAET,EAAO;QACF,CAAA,CACJ;;MACN,kBAAC,GAAD;OAAW,WAAU;iBAAkB,EAAO;OAAkB,CAAA;MAChE,kBAAC,GAAD,EAAA,UAAA;OACG,EAAO;OAAW;OAAI,EAAO;OAAS;OAAI,EAAO;OAAQ;OAC1C,EAAA,CAAA;MACP,EAAA,CAAA,EACb,kBAAC,GAAD,EAAA,UAAA;MACE,kBAAC,KAAD;OAAG,WAAU;iBAAoC,EAAO;OAAgB,CAAA;MACxE,kBAAC,OAAD;OAAK,WAAU;iBACZ,EAAO,OAAO,KAAK,MAClB,kBAAC,GAAD;QAAe,SAAQ;QAAU,WAAU;kBACxC;QACK,EAFI,EAEJ,CACR;OACE,CAAA;MACN,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,QAAD;SAAM,WAAU;mBAAhB,CACE,kBAAC,GAAD,EAAM,WAAU,oCAAqC,CAAA,EACpD,EAAO,OACH;;QACP,kBAAC,QAAD;SAAM,WAAU;mBAAhB;UACE,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;UAC5B,EAAO;UAAS;UACZ;;QACP,kBAAC,QAAD,EAAA,UAAA,CAAO,KAAK,MAAO,EAAO,YAAY,EAAO,WAAY,IAAI,EAAC,eAAmB,EAAA,CAAA;QAC7E;;MACM,EAAA,CAAA,CACJ;OA7CI,EAAO,GA6CX,CACZ;IACE,CAAA;GACF"}
|
|
@@ -2,80 +2,104 @@ import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
|
2
2
|
import { useMemo as t } from "react";
|
|
3
3
|
import { Clock as n, GraduationCap as r, Star as i, Users as a } from "lucide-react";
|
|
4
4
|
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
5
|
-
import { Badge as c, Card as l, CardContent as u, CardDescription as d, CardHeader as f, CardTitle as p } from "@burdenoff/fe-libs/ui";
|
|
5
|
+
import { Badge as c, Card as l, CardContent as u, CardDescription as d, CardHeader as f, CardTitle as p, GlassCard as m, GradientText as h, PagePurpose as g } from "@burdenoff/fe-libs/ui";
|
|
6
6
|
//#region src/crewfoundry/pages/LearningLearningAnalyticsPagePage.tsx
|
|
7
|
-
var
|
|
8
|
-
function
|
|
9
|
-
let { courses:
|
|
10
|
-
month: (/* @__PURE__ */ new Date(
|
|
7
|
+
var _ = (/* @__PURE__ */ new Date("2026-03-01T00:00:00Z")).getTime();
|
|
8
|
+
function v() {
|
|
9
|
+
let { courses: v } = e(), y = v.reduce((e, t) => e + t.enrolled, 0), b = v.reduce((e, t) => e + t.completed, 0), x = (v.reduce((e, t) => e + t.rating, 0) / Math.max(v.length, 1)).toFixed(1), S = t(() => v.slice(0, 6).map((e, t) => ({
|
|
10
|
+
month: (/* @__PURE__ */ new Date(_ - (5 - t) * 864e5 * 30)).toLocaleString("en-US", { month: "short" }),
|
|
11
11
|
hours: Math.round((e.completed + Math.max(e.modules, 1)) * 2.2),
|
|
12
12
|
completions: e.completed,
|
|
13
13
|
enrollments: e.enrolled
|
|
14
|
-
})), [
|
|
14
|
+
})), [v]), C = Math.max(1, ...S.map((e) => e.hours)), w = S.reduce((e, t) => e + t.hours, 0), T = v.reduce((e, t) => (e[t.category] = (e[t.category] || 0) + t.enrolled, e), {});
|
|
15
15
|
return /* @__PURE__ */ s("div", {
|
|
16
16
|
className: "space-y-6 p-6",
|
|
17
17
|
children: [
|
|
18
|
-
/* @__PURE__ */ s("div", { children: [
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
/* @__PURE__ */ s("div", { children: [
|
|
19
|
+
/* @__PURE__ */ o("h1", {
|
|
20
|
+
className: "text-2xl font-semibold",
|
|
21
|
+
children: /* @__PURE__ */ o(h, { children: "Learning Analytics" })
|
|
22
|
+
}),
|
|
23
|
+
/* @__PURE__ */ o("p", {
|
|
24
|
+
className: "text-sm text-text-secondary",
|
|
25
|
+
children: "Training metrics and engagement insights"
|
|
26
|
+
}),
|
|
27
|
+
/* @__PURE__ */ o(g, {
|
|
28
|
+
className: "mt-1",
|
|
29
|
+
children: "See how learning is landing across your organization — completion rates, popular courses, and skill growth to guide your L&D strategy."
|
|
30
|
+
})
|
|
31
|
+
] }),
|
|
25
32
|
/* @__PURE__ */ s("div", {
|
|
26
33
|
className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
|
|
27
34
|
children: [
|
|
28
|
-
/* @__PURE__ */ s(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
className: "
|
|
46
|
-
children:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
className: "
|
|
63
|
-
children: [/* @__PURE__ */
|
|
64
|
-
className: "
|
|
65
|
-
children:
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
children:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
})
|
|
35
|
+
/* @__PURE__ */ s(m, {
|
|
36
|
+
treatment: "glass",
|
|
37
|
+
glow: !0,
|
|
38
|
+
className: "border-border-seam",
|
|
39
|
+
children: [/* @__PURE__ */ s(f, {
|
|
40
|
+
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
41
|
+
children: [/* @__PURE__ */ o(p, {
|
|
42
|
+
className: "text-sm font-medium",
|
|
43
|
+
children: "Total Enrollments"
|
|
44
|
+
}), /* @__PURE__ */ o(a, { className: "h-4 w-4 text-text-secondary" })]
|
|
45
|
+
}), /* @__PURE__ */ o(u, { children: /* @__PURE__ */ o("div", {
|
|
46
|
+
className: "text-2xl font-bold tabular-nums",
|
|
47
|
+
children: y
|
|
48
|
+
}) })]
|
|
49
|
+
}),
|
|
50
|
+
/* @__PURE__ */ s(m, {
|
|
51
|
+
treatment: "metric",
|
|
52
|
+
className: "border-border-seam",
|
|
53
|
+
children: [/* @__PURE__ */ s(f, {
|
|
54
|
+
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
55
|
+
children: [/* @__PURE__ */ o(p, {
|
|
56
|
+
className: "text-sm font-medium",
|
|
57
|
+
children: "Completions"
|
|
58
|
+
}), /* @__PURE__ */ o(r, { className: "h-4 w-4 text-status-success-text" })]
|
|
59
|
+
}), /* @__PURE__ */ s(u, { children: [/* @__PURE__ */ o("div", {
|
|
60
|
+
className: "text-2xl font-bold tabular-nums",
|
|
61
|
+
children: b
|
|
62
|
+
}), /* @__PURE__ */ s("p", {
|
|
63
|
+
className: "text-xs text-text-secondary",
|
|
64
|
+
children: [Math.round(b / Math.max(y, 1) * 100), "% rate"]
|
|
65
|
+
})] })]
|
|
66
|
+
}),
|
|
67
|
+
/* @__PURE__ */ s(m, {
|
|
68
|
+
treatment: "metric",
|
|
69
|
+
className: "border-border-seam",
|
|
70
|
+
children: [/* @__PURE__ */ s(f, {
|
|
71
|
+
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
72
|
+
children: [/* @__PURE__ */ o(p, {
|
|
73
|
+
className: "text-sm font-medium",
|
|
74
|
+
children: "Avg Rating"
|
|
75
|
+
}), /* @__PURE__ */ o(i, { className: "h-4 w-4 text-status-warning-text" })]
|
|
76
|
+
}), /* @__PURE__ */ o(u, { children: /* @__PURE__ */ s("div", {
|
|
77
|
+
className: "text-2xl font-bold tabular-nums",
|
|
78
|
+
children: [x, "/5"]
|
|
79
|
+
}) })]
|
|
80
|
+
}),
|
|
81
|
+
/* @__PURE__ */ s(m, {
|
|
82
|
+
treatment: "metric",
|
|
83
|
+
className: "border-border-seam",
|
|
84
|
+
children: [/* @__PURE__ */ s(f, {
|
|
85
|
+
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
86
|
+
children: [/* @__PURE__ */ o(p, {
|
|
87
|
+
className: "text-sm font-medium",
|
|
88
|
+
children: "Training Hours"
|
|
89
|
+
}), /* @__PURE__ */ o(n, { className: "h-4 w-4 text-text-secondary" })]
|
|
90
|
+
}), /* @__PURE__ */ s(u, { children: [/* @__PURE__ */ o("div", {
|
|
91
|
+
className: "text-2xl font-bold tabular-nums",
|
|
92
|
+
children: w.toLocaleString()
|
|
93
|
+
}), /* @__PURE__ */ o("p", {
|
|
94
|
+
className: "text-xs text-text-secondary",
|
|
95
|
+
children: "Recent 6-month trend"
|
|
96
|
+
})] })]
|
|
97
|
+
})
|
|
74
98
|
]
|
|
75
99
|
}),
|
|
76
100
|
/* @__PURE__ */ s(l, { children: [/* @__PURE__ */ s(f, { children: [/* @__PURE__ */ o(p, { children: "Monthly Training Activity" }), /* @__PURE__ */ o(d, { children: "Hours and completions over time" })] }), /* @__PURE__ */ o(u, {
|
|
77
101
|
className: "space-y-3",
|
|
78
|
-
children:
|
|
102
|
+
children: S.map((e) => /* @__PURE__ */ s("div", {
|
|
79
103
|
className: "flex items-center gap-3",
|
|
80
104
|
children: [
|
|
81
105
|
/* @__PURE__ */ o("span", {
|
|
@@ -86,7 +110,7 @@ function h() {
|
|
|
86
110
|
className: "h-4 flex-1 overflow-hidden rounded bg-bg-sunken",
|
|
87
111
|
children: /* @__PURE__ */ o("div", {
|
|
88
112
|
className: "h-4 rounded bg-action-primary-bg",
|
|
89
|
-
style: { width: `${Math.round(e.hours /
|
|
113
|
+
style: { width: `${Math.round(e.hours / C * 100)}%` }
|
|
90
114
|
})
|
|
91
115
|
}),
|
|
92
116
|
/* @__PURE__ */ s("span", {
|
|
@@ -105,7 +129,7 @@ function h() {
|
|
|
105
129
|
className: "grid gap-4 md:grid-cols-2",
|
|
106
130
|
children: [/* @__PURE__ */ s(l, { children: [/* @__PURE__ */ o(f, { children: /* @__PURE__ */ o(p, { children: "Category Distribution" }) }), /* @__PURE__ */ o(u, {
|
|
107
131
|
className: "space-y-3",
|
|
108
|
-
children: Object.entries(
|
|
132
|
+
children: Object.entries(T).sort(([, e], [, t]) => t - e).map(([e, t]) => /* @__PURE__ */ s("div", {
|
|
109
133
|
className: "flex items-center justify-between",
|
|
110
134
|
children: [/* @__PURE__ */ o("span", {
|
|
111
135
|
className: "text-sm",
|
|
@@ -118,7 +142,7 @@ function h() {
|
|
|
118
142
|
}), /* @__PURE__ */ s(c, {
|
|
119
143
|
variant: "outline",
|
|
120
144
|
className: "text-[10px]",
|
|
121
|
-
children: [Math.round(t / Math.max(
|
|
145
|
+
children: [Math.round(t / Math.max(y, 1) * 100), "%"]
|
|
122
146
|
})]
|
|
123
147
|
})]
|
|
124
148
|
}, e))
|
|
@@ -139,7 +163,7 @@ function h() {
|
|
|
139
163
|
children: "Rating"
|
|
140
164
|
})
|
|
141
165
|
]
|
|
142
|
-
}),
|
|
166
|
+
}), v.map((e) => /* @__PURE__ */ s("div", {
|
|
143
167
|
className: "grid grid-cols-4 gap-2 border-b py-2 text-sm last:border-0",
|
|
144
168
|
children: [
|
|
145
169
|
/* @__PURE__ */ o("span", {
|
|
@@ -156,7 +180,7 @@ function h() {
|
|
|
156
180
|
}),
|
|
157
181
|
/* @__PURE__ */ s("div", {
|
|
158
182
|
className: "flex items-center justify-end gap-1",
|
|
159
|
-
children: [/* @__PURE__ */ o(i, { className: "h-3 w-3 text-
|
|
183
|
+
children: [/* @__PURE__ */ o(i, { className: "h-3 w-3 text-status-warning-text" }), e.rating]
|
|
160
184
|
})
|
|
161
185
|
]
|
|
162
186
|
}, e.id))] })] })]
|
|
@@ -165,6 +189,6 @@ function h() {
|
|
|
165
189
|
});
|
|
166
190
|
}
|
|
167
191
|
//#endregion
|
|
168
|
-
export {
|
|
192
|
+
export { v as LearningLearningAnalyticsPagePage };
|
|
169
193
|
|
|
170
194
|
//# sourceMappingURL=LearningLearningAnalyticsPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LearningLearningAnalyticsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/LearningLearningAnalyticsPagePage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { Clock, GraduationCap, Star, Users } from 'lucide-react';\nimport {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from '@burdenoff/fe-libs/ui';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\ntype MonthlyLearning = {\n month: string;\n hours: number;\n completions: number;\n enrollments: number;\n};\n\nconst BASE_TS = new Date('2026-03-01T00:00:00Z').getTime();\n\nexport function LearningLearningAnalyticsPagePage() {\n const { courses } = useCrewFoundryStore();\n\n const totalEnrolled = courses.reduce((sum, course) => sum + course.enrolled, 0);\n const totalCompleted = courses.reduce((sum, course) => sum + course.completed, 0);\n const avgRating = (\n courses.reduce((sum, course) => sum + course.rating, 0) / Math.max(courses.length, 1)\n ).toFixed(1);\n\n const monthlyLearning = useMemo<MonthlyLearning[]>(() => {\n return courses.slice(0, 6).map((course, index) => {\n const month = new Date(BASE_TS - (5 - index) * 86400000 * 30).toLocaleString('en-US', {\n month: 'short',\n });\n return {\n month,\n hours: Math.round((course.completed + Math.max(course.modules, 1)) * 2.2),\n completions: course.completed,\n enrollments: course.enrolled,\n };\n });\n }, [courses]);\n\n const maxHours = Math.max(1, ...monthlyLearning.map((item) => item.hours));\n const totalHours = monthlyLearning.reduce((sum, item) => sum + item.hours, 0);\n\n const categoryDistribution = courses.reduce<Record<string, number>>((acc, course) => {\n acc[course.category] = (acc[course.category] || 0) + course.enrolled;\n return acc;\n }, {});\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">Learning Analytics</h1>\n <p className=\"text-sm text-text-secondary\">Training metrics and engagement insights</p>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Enrollments</CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold\">{totalEnrolled}</div>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Completions</CardTitle>\n <GraduationCap className=\"h-4 w-4 text-green-500\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold\">{totalCompleted}</div>\n <p className=\"text-xs text-text-secondary\">\n {Math.round((totalCompleted / Math.max(totalEnrolled, 1)) * 100)}% rate\n </p>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Avg Rating</CardTitle>\n <Star className=\"h-4 w-4 text-yellow-500\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold\">{avgRating}/5</div>\n </CardContent>\n </Card>\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Training Hours</CardTitle>\n <Clock className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold\">{totalHours.toLocaleString()}</div>\n <p className=\"text-xs text-text-secondary\">Recent 6-month trend</p>\n </CardContent>\n </Card>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Monthly Training Activity</CardTitle>\n <CardDescription>Hours and completions over time</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {monthlyLearning.map((item) => (\n <div key={`${item.month}-${item.hours}`} className=\"flex items-center gap-3\">\n <span className=\"w-10 text-sm text-text-secondary\">{item.month}</span>\n <div className=\"h-4 flex-1 overflow-hidden rounded bg-bg-sunken\">\n <div\n className=\"h-4 rounded bg-action-primary-bg\"\n style={{ width: `${Math.round((item.hours / maxHours) * 100)}%` }}\n />\n </div>\n <span className=\"w-16 text-right text-sm font-medium\">{item.hours}h</span>\n <Badge variant=\"default\" className=\"text-[10px]\">\n {item.completions} done\n </Badge>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n <Card>\n <CardHeader>\n <CardTitle>Category Distribution</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(categoryDistribution)\n .sort(([, a], [, b]) => b - a)\n .map(([category, count]) => (\n <div key={category} className=\"flex items-center justify-between\">\n <span className=\"text-sm\">{category}</span>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium\">{count}</span>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {Math.round((count / Math.max(totalEnrolled, 1)) * 100)}%\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <CardTitle>Course Performance</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"mb-2 grid grid-cols-4 gap-2 border-b pb-2 text-xs font-medium text-text-secondary\">\n <span>Course</span>\n <span className=\"text-right\">Enrolled</span>\n <span className=\"text-right\">Completed</span>\n <span className=\"text-right\">Rating</span>\n </div>\n {courses.map((course) => (\n <div\n key={course.id}\n className=\"grid grid-cols-4 gap-2 border-b py-2 text-sm last:border-0\"\n >\n <span className=\"truncate font-medium\">{course.title}</span>\n <span className=\"text-right\">{course.enrolled}</span>\n <span className=\"text-right\">{course.completed}</span>\n <div className=\"flex items-center justify-end gap-1\">\n <Star className=\"h-3 w-3 text-yellow-500\" />\n {course.rating}\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;AAmBA,IAAM,qBAAU,IAAI,KAAK,uBAAuB,EAAC,SAAS;AAE1D,SAAgB,IAAoC;CAClD,IAAM,EAAE,eAAY,GAAqB,EAEnC,IAAgB,EAAQ,QAAQ,GAAK,MAAW,IAAM,EAAO,UAAU,EAAE,EACzE,IAAiB,EAAQ,QAAQ,GAAK,MAAW,IAAM,EAAO,WAAW,EAAE,EAC3E,KACJ,EAAQ,QAAQ,GAAK,MAAW,IAAM,EAAO,QAAQ,EAAE,GAAG,KAAK,IAAI,EAAQ,QAAQ,EAAE,EACrF,QAAQ,EAAE,EAEN,IAAkB,QACf,EAAQ,MAAM,GAAG,EAAE,CAAC,KAAK,GAAQ,OAI/B;EACL,wBAJY,IAAI,KAAK,KAAW,IAAI,KAAS,QAAW,GAAG,EAAC,eAAe,SAAS,EACpF,OAAO,SACR,CAAC;EAGA,OAAO,KAAK,OAAO,EAAO,YAAY,KAAK,IAAI,EAAO,SAAS,EAAE,IAAI,IAAI;EACzE,aAAa,EAAO;EACpB,aAAa,EAAO;EACrB,EACD,EACD,CAAC,EAAQ,CAAC,EAEP,IAAW,KAAK,IAAI,GAAG,GAAG,EAAgB,KAAK,MAAS,EAAK,MAAM,CAAC,EACpE,IAAa,EAAgB,QAAQ,GAAK,MAAS,IAAM,EAAK,OAAO,EAAE,EAEvE,IAAuB,EAAQ,QAAgC,GAAK,OACxE,EAAI,EAAO,aAAa,EAAI,EAAO,aAAa,KAAK,EAAO,UACrD,IACN,EAAE,CAAC;AAEN,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;IAAI,WAAU;cAAyB;IAAuB,CAAA,EAC9D,kBAAC,KAAD;IAAG,WAAU;cAA8B;IAA4C,CAAA,CACnF,EAAA,CAAA;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAY,WAAU;gBAAtB,CACE,kBAAC,GAAD;OAAW,WAAU;iBAAsB;OAA6B,CAAA,EACxE,kBAAC,GAAD,EAAO,WAAU,+BAAgC,CAAA,CACtC;SACb,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;MAAK,WAAU;gBAAsB;MAAoB,CAAA,EAC7C,CAAA,CACT,EAAA,CAAA;KACP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAY,WAAU;gBAAtB,CACE,kBAAC,GAAD;OAAW,WAAU;iBAAsB;OAAuB,CAAA,EAClE,kBAAC,GAAD,EAAe,WAAU,0BAA2B,CAAA,CACzC;SACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAsB;MAAqB,CAAA,EAC1D,kBAAC,KAAD;MAAG,WAAU;gBAAb,CACG,KAAK,MAAO,IAAiB,KAAK,IAAI,GAAe,EAAE,GAAI,IAAI,EAAC,SAC/D;QACQ,EAAA,CAAA,CACT,EAAA,CAAA;KACP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAY,WAAU;gBAAtB,CACE,kBAAC,GAAD;OAAW,WAAU;iBAAsB;OAAsB,CAAA,EACjE,kBAAC,GAAD,EAAM,WAAU,2BAA4B,CAAA,CACjC;SACb,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CAAqC,GAAU,KAAQ;SAC3C,CAAA,CACT,EAAA,CAAA;KACP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;MAAY,WAAU;gBAAtB,CACE,kBAAC,GAAD;OAAW,WAAU;iBAAsB;OAA0B,CAAA,EACrE,kBAAC,GAAD,EAAO,WAAU,+BAAgC,CAAA,CACtC;SACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAsB,EAAW,gBAAgB;MAAO,CAAA,EACvE,kBAAC,KAAD;MAAG,WAAU;gBAA8B;MAAwB,CAAA,CACvD,EAAA,CAAA,CACT,EAAA,CAAA;KACH;;GAEN,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAW,6BAAqC,CAAA,EAChD,kBAAC,GAAD,EAAA,UAAiB,mCAAiD,CAAA,CACvD,EAAA,CAAA,EACb,kBAAC,GAAD;IAAa,WAAU;cACpB,EAAgB,KAAK,MACpB,kBAAC,OAAD;KAAyC,WAAU;eAAnD;MACE,kBAAC,QAAD;OAAM,WAAU;iBAAoC,EAAK;OAAa,CAAA;MACtE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,OAAD;QACE,WAAU;QACV,OAAO,EAAE,OAAO,GAAG,KAAK,MAAO,EAAK,QAAQ,IAAY,IAAI,CAAC,IAAI;QACjE,CAAA;OACE,CAAA;MACN,kBAAC,QAAD;OAAM,WAAU;iBAAhB,CAAuD,EAAK,OAAM,IAAQ;;MAC1E,kBAAC,GAAD;OAAO,SAAQ;OAAU,WAAU;iBAAnC,CACG,EAAK,aAAY,QACZ;;MACJ;OAZI,GAAG,EAAK,MAAM,GAAG,EAAK,QAY1B,CACN;IACU,CAAA,CACT,EAAA,CAAA;GAEP,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAW,yBAAiC,CAAA,EACjC,CAAA,EACb,kBAAC,GAAD;KAAa,WAAU;eACpB,OAAO,QAAQ,EAAqB,CAClC,MAAM,GAAG,IAAI,GAAG,OAAO,IAAI,EAAE,CAC7B,KAAK,CAAC,GAAU,OACf,kBAAC,OAAD;MAAoB,WAAU;gBAA9B,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAW;OAAgB,CAAA,EAC3C,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,QAAD;QAAM,WAAU;kBAAuB;QAAa,CAAA,EACpD,kBAAC,GAAD;QAAO,SAAQ;QAAU,WAAU;kBAAnC,CACG,KAAK,MAAO,IAAQ,KAAK,IAAI,GAAe,EAAE,GAAI,IAAI,EAAC,IAClD;UACJ;SACF;QARI,EAQJ,CACN;KACQ,CAAA,CACT,EAAA,CAAA,EACP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAW,sBAA8B,CAAA,EAC9B,CAAA,EACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,QAAD,EAAA,UAAM,UAAa,CAAA;MACnB,kBAAC,QAAD;OAAM,WAAU;iBAAa;OAAe,CAAA;MAC5C,kBAAC,QAAD;OAAM,WAAU;iBAAa;OAAgB,CAAA;MAC7C,kBAAC,QAAD;OAAM,WAAU;iBAAa;OAAa,CAAA;MACtC;QACL,EAAQ,KAAK,MACZ,kBAAC,OAAD;KAEE,WAAU;eAFZ;MAIE,kBAAC,QAAD;OAAM,WAAU;iBAAwB,EAAO;OAAa,CAAA;MAC5D,kBAAC,QAAD;OAAM,WAAU;iBAAc,EAAO;OAAgB,CAAA;MACrD,kBAAC,QAAD;OAAM,WAAU;iBAAc,EAAO;OAAiB,CAAA;MACtD,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD,EAAM,WAAU,2BAA4B,CAAA,EAC3C,EAAO,OACJ;;MACF;OAVC,EAAO,GAUR,CACN,CACU,EAAA,CAAA,CACT,EAAA,CAAA,CACH;;GACF"}
|
|
1
|
+
{"version":3,"file":"LearningLearningAnalyticsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/LearningLearningAnalyticsPagePage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { Clock, GraduationCap, Star, Users } from 'lucide-react';\nimport {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\ntype MonthlyLearning = {\n month: string;\n hours: number;\n completions: number;\n enrollments: number;\n};\n\nconst BASE_TS = new Date('2026-03-01T00:00:00Z').getTime();\n\nexport function LearningLearningAnalyticsPagePage() {\n const { courses } = useCrewFoundryStore();\n\n const totalEnrolled = courses.reduce((sum, course) => sum + course.enrolled, 0);\n const totalCompleted = courses.reduce((sum, course) => sum + course.completed, 0);\n const avgRating = (\n courses.reduce((sum, course) => sum + course.rating, 0) / Math.max(courses.length, 1)\n ).toFixed(1);\n\n const monthlyLearning = useMemo<MonthlyLearning[]>(() => {\n return courses.slice(0, 6).map((course, index) => {\n const month = new Date(BASE_TS - (5 - index) * 86400000 * 30).toLocaleString('en-US', {\n month: 'short',\n });\n return {\n month,\n hours: Math.round((course.completed + Math.max(course.modules, 1)) * 2.2),\n completions: course.completed,\n enrollments: course.enrolled,\n };\n });\n }, [courses]);\n\n const maxHours = Math.max(1, ...monthlyLearning.map((item) => item.hours));\n const totalHours = monthlyLearning.reduce((sum, item) => sum + item.hours, 0);\n\n const categoryDistribution = courses.reduce<Record<string, number>>((acc, course) => {\n acc[course.category] = (acc[course.category] || 0) + course.enrolled;\n return acc;\n }, {});\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Learning Analytics</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Training metrics and engagement insights</p>\n <PagePurpose className=\"mt-1\">See how learning is landing across your organization — completion rates, popular courses, and skill growth to guide your L&D strategy.</PagePurpose>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Enrollments</CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{totalEnrolled}</div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Completions</CardTitle>\n <GraduationCap className=\"h-4 w-4 text-status-success-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{totalCompleted}</div>\n <p className=\"text-xs text-text-secondary\">\n {Math.round((totalCompleted / Math.max(totalEnrolled, 1)) * 100)}% rate\n </p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Avg Rating</CardTitle>\n <Star className=\"h-4 w-4 text-status-warning-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{avgRating}/5</div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Training Hours</CardTitle>\n <Clock className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{totalHours.toLocaleString()}</div>\n <p className=\"text-xs text-text-secondary\">Recent 6-month trend</p>\n </CardContent>\n </GlassCard>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Monthly Training Activity</CardTitle>\n <CardDescription>Hours and completions over time</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {monthlyLearning.map((item) => (\n <div key={`${item.month}-${item.hours}`} className=\"flex items-center gap-3\">\n <span className=\"w-10 text-sm text-text-secondary\">{item.month}</span>\n <div className=\"h-4 flex-1 overflow-hidden rounded bg-bg-sunken\">\n <div\n className=\"h-4 rounded bg-action-primary-bg\"\n style={{ width: `${Math.round((item.hours / maxHours) * 100)}%` }}\n />\n </div>\n <span className=\"w-16 text-right text-sm font-medium\">{item.hours}h</span>\n <Badge variant=\"default\" className=\"text-[10px]\">\n {item.completions} done\n </Badge>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n <Card>\n <CardHeader>\n <CardTitle>Category Distribution</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(categoryDistribution)\n .sort(([, a], [, b]) => b - a)\n .map(([category, count]) => (\n <div key={category} className=\"flex items-center justify-between\">\n <span className=\"text-sm\">{category}</span>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium\">{count}</span>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {Math.round((count / Math.max(totalEnrolled, 1)) * 100)}%\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <CardTitle>Course Performance</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"mb-2 grid grid-cols-4 gap-2 border-b pb-2 text-xs font-medium text-text-secondary\">\n <span>Course</span>\n <span className=\"text-right\">Enrolled</span>\n <span className=\"text-right\">Completed</span>\n <span className=\"text-right\">Rating</span>\n </div>\n {courses.map((course) => (\n <div\n key={course.id}\n className=\"grid grid-cols-4 gap-2 border-b py-2 text-sm last:border-0\"\n >\n <span className=\"truncate font-medium\">{course.title}</span>\n <span className=\"text-right\">{course.enrolled}</span>\n <span className=\"text-right\">{course.completed}</span>\n <div className=\"flex items-center justify-end gap-1\">\n <Star className=\"h-3 w-3 text-status-warning-text\" />\n {course.rating}\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,66 +1,90 @@
|
|
|
1
1
|
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
2
|
import { BookOpen as t, GraduationCap as n, Star as r, TrendingUp as i, Users as a } from "lucide-react";
|
|
3
3
|
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
4
|
-
import { Badge as c, Card as l, CardContent as u, CardDescription as d, CardHeader as f, CardTitle as p } from "@burdenoff/fe-libs/ui";
|
|
4
|
+
import { Badge as c, Card as l, CardContent as u, CardDescription as d, CardHeader as f, CardTitle as p, GlassCard as m, GradientText as h, PagePurpose as g } from "@burdenoff/fe-libs/ui";
|
|
5
5
|
//#region src/crewfoundry/pages/LearningLearningPagePage.tsx
|
|
6
|
-
function
|
|
7
|
-
let { courses:
|
|
6
|
+
function _() {
|
|
7
|
+
let { courses: _, learningPaths: v } = e(), y = _.reduce((e, t) => e + t.enrolled, 0), b = _.reduce((e, t) => e + t.completed, 0);
|
|
8
8
|
return /* @__PURE__ */ s("div", {
|
|
9
9
|
className: "space-y-6 p-6",
|
|
10
10
|
children: [
|
|
11
|
-
/* @__PURE__ */ s("div", { children: [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
/* @__PURE__ */ s("div", { children: [
|
|
12
|
+
/* @__PURE__ */ o("h1", {
|
|
13
|
+
className: "text-2xl font-semibold",
|
|
14
|
+
children: /* @__PURE__ */ o(h, { children: "Learning & Development" })
|
|
15
|
+
}),
|
|
16
|
+
/* @__PURE__ */ o("p", {
|
|
17
|
+
className: "text-sm text-text-secondary",
|
|
18
|
+
children: "Explore courses, learning paths, and grow your skills"
|
|
19
|
+
}),
|
|
20
|
+
/* @__PURE__ */ o(g, {
|
|
21
|
+
className: "mt-1",
|
|
22
|
+
children: "Your learning home — discover courses, continue where you left off, and keep developing the skills your role needs."
|
|
23
|
+
})
|
|
24
|
+
] }),
|
|
18
25
|
/* @__PURE__ */ s("div", {
|
|
19
26
|
className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
|
|
20
27
|
children: [
|
|
21
|
-
/* @__PURE__ */ s(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
className: "
|
|
42
|
-
children:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
className: "
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
className: "
|
|
56
|
-
children: [/* @__PURE__ */
|
|
57
|
-
className: "
|
|
58
|
-
children:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
children:
|
|
63
|
-
|
|
28
|
+
/* @__PURE__ */ s(m, {
|
|
29
|
+
treatment: "glass",
|
|
30
|
+
glow: !0,
|
|
31
|
+
className: "border-border-seam",
|
|
32
|
+
children: [/* @__PURE__ */ s(f, {
|
|
33
|
+
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
34
|
+
children: [/* @__PURE__ */ o(p, {
|
|
35
|
+
className: "text-sm font-medium",
|
|
36
|
+
children: "Courses"
|
|
37
|
+
}), /* @__PURE__ */ o(t, { className: "h-4 w-4 text-text-secondary" })]
|
|
38
|
+
}), /* @__PURE__ */ s(u, { children: [/* @__PURE__ */ o("div", {
|
|
39
|
+
className: "text-2xl font-bold tabular-nums",
|
|
40
|
+
children: _.length
|
|
41
|
+
}), /* @__PURE__ */ o("p", {
|
|
42
|
+
className: "text-xs text-text-secondary",
|
|
43
|
+
children: "Active courses"
|
|
44
|
+
})] })]
|
|
45
|
+
}),
|
|
46
|
+
/* @__PURE__ */ s(m, {
|
|
47
|
+
treatment: "metric",
|
|
48
|
+
className: "border-border-seam",
|
|
49
|
+
children: [/* @__PURE__ */ s(f, {
|
|
50
|
+
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
51
|
+
children: [/* @__PURE__ */ o(p, {
|
|
52
|
+
className: "text-sm font-medium",
|
|
53
|
+
children: "Enrolled"
|
|
54
|
+
}), /* @__PURE__ */ o(a, { className: "h-4 w-4 text-text-secondary" })]
|
|
55
|
+
}), /* @__PURE__ */ o(u, { children: /* @__PURE__ */ o("div", {
|
|
56
|
+
className: "text-2xl font-bold tabular-nums",
|
|
57
|
+
children: y
|
|
58
|
+
}) })]
|
|
59
|
+
}),
|
|
60
|
+
/* @__PURE__ */ s(m, {
|
|
61
|
+
treatment: "metric",
|
|
62
|
+
className: "border-border-seam",
|
|
63
|
+
children: [/* @__PURE__ */ s(f, {
|
|
64
|
+
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
65
|
+
children: [/* @__PURE__ */ o(p, {
|
|
66
|
+
className: "text-sm font-medium",
|
|
67
|
+
children: "Completed"
|
|
68
|
+
}), /* @__PURE__ */ o(n, { className: "h-4 w-4 text-status-success-text" })]
|
|
69
|
+
}), /* @__PURE__ */ o(u, { children: /* @__PURE__ */ o("div", {
|
|
70
|
+
className: "text-2xl font-bold tabular-nums",
|
|
71
|
+
children: b
|
|
72
|
+
}) })]
|
|
73
|
+
}),
|
|
74
|
+
/* @__PURE__ */ s(m, {
|
|
75
|
+
treatment: "metric",
|
|
76
|
+
className: "border-border-seam",
|
|
77
|
+
children: [/* @__PURE__ */ s(f, {
|
|
78
|
+
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
79
|
+
children: [/* @__PURE__ */ o(p, {
|
|
80
|
+
className: "text-sm font-medium",
|
|
81
|
+
children: "Paths"
|
|
82
|
+
}), /* @__PURE__ */ o(i, { className: "h-4 w-4 text-text-secondary" })]
|
|
83
|
+
}), /* @__PURE__ */ o(u, { children: /* @__PURE__ */ o("div", {
|
|
84
|
+
className: "text-2xl font-bold tabular-nums",
|
|
85
|
+
children: v.length
|
|
86
|
+
}) })]
|
|
87
|
+
})
|
|
64
88
|
]
|
|
65
89
|
}),
|
|
66
90
|
/* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("h2", {
|
|
@@ -68,7 +92,7 @@ function m() {
|
|
|
68
92
|
children: "Featured Courses"
|
|
69
93
|
}), /* @__PURE__ */ o("div", {
|
|
70
94
|
className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3",
|
|
71
|
-
children:
|
|
95
|
+
children: _.slice(0, 3).map((e) => /* @__PURE__ */ s(l, { children: [/* @__PURE__ */ s(f, { children: [/* @__PURE__ */ o(p, {
|
|
72
96
|
className: "text-base",
|
|
73
97
|
children: e.title
|
|
74
98
|
}), /* @__PURE__ */ s(d, { children: [
|
|
@@ -84,7 +108,7 @@ function m() {
|
|
|
84
108
|
className: "flex items-center justify-between",
|
|
85
109
|
children: [/* @__PURE__ */ s("div", {
|
|
86
110
|
className: "flex items-center gap-1",
|
|
87
|
-
children: [/* @__PURE__ */ o(r, { className: "h-3 w-3 text-
|
|
111
|
+
children: [/* @__PURE__ */ o(r, { className: "h-3 w-3 text-status-warning-text" }), /* @__PURE__ */ o("span", {
|
|
88
112
|
className: "text-sm",
|
|
89
113
|
children: e.rating
|
|
90
114
|
})]
|
|
@@ -117,7 +141,7 @@ function m() {
|
|
|
117
141
|
children: "Learning Paths"
|
|
118
142
|
}), /* @__PURE__ */ o("div", {
|
|
119
143
|
className: "grid gap-4 md:grid-cols-3",
|
|
120
|
-
children:
|
|
144
|
+
children: v.map((e) => /* @__PURE__ */ s(l, { children: [/* @__PURE__ */ s(f, { children: [/* @__PURE__ */ o(p, {
|
|
121
145
|
className: "text-base",
|
|
122
146
|
children: e.title
|
|
123
147
|
}), /* @__PURE__ */ o(d, { children: e.description })] }), /* @__PURE__ */ s(u, { children: [/* @__PURE__ */ s("div", {
|
|
@@ -149,6 +173,6 @@ function m() {
|
|
|
149
173
|
});
|
|
150
174
|
}
|
|
151
175
|
//#endregion
|
|
152
|
-
export {
|
|
176
|
+
export { _ as LearningLearningPagePage };
|
|
153
177
|
|
|
154
178
|
//# sourceMappingURL=LearningLearningPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LearningLearningPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/LearningLearningPagePage.tsx"],"sourcesContent":["import {\n Badge,\n
|
|
1
|
+
{"version":3,"file":"LearningLearningPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/LearningLearningPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { Award, BookOpen, GraduationCap, Star, TrendingUp, Users } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nexport function LearningLearningPagePage() {\n const { courses, learningPaths } = useCrewFoundryStore();\n const totalEnrolled = courses.reduce((s, c) => s + c.enrolled, 0);\n const totalCompleted = courses.reduce((s, c) => s + c.completed, 0);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Learning & Development</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Explore courses, learning paths, and grow your skills\n </p>\n <PagePurpose className=\"mt-1\">Your learning home — discover courses, continue where you left off, and keep developing the skills your role needs.</PagePurpose>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Courses</CardTitle>\n <BookOpen className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{courses.length}</div>\n <p className=\"text-xs text-text-secondary\">Active courses</p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Enrolled</CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{totalEnrolled}</div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Completed</CardTitle>\n <GraduationCap className=\"h-4 w-4 text-status-success-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{totalCompleted}</div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Paths</CardTitle>\n <TrendingUp className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{learningPaths.length}</div>\n </CardContent>\n </GlassCard>\n </div>\n <div>\n <h2 className=\"text-lg font-medium mb-3\">Featured Courses</h2>\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {courses.slice(0, 3).map((course) => (\n <Card key={course.id}>\n <CardHeader>\n <CardTitle className=\"text-base\">{course.title}</CardTitle>\n <CardDescription>\n {course.instructor} · {course.duration}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-text-secondary mb-3\">{course.description}</p>\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 text-status-warning-text\" />\n <span className=\"text-sm\">{course.rating}</span>\n </div>\n <div className=\"flex gap-1\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {course.level}\n </Badge>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {course.category}\n </Badge>\n </div>\n </div>\n <div className=\"mt-2 text-xs text-text-secondary\">\n {course.enrolled} enrolled · {course.completed} completed\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n </div>\n <div>\n <h2 className=\"text-lg font-medium mb-3\">Learning Paths</h2>\n <div className=\"grid gap-4 md:grid-cols-3\">\n {learningPaths.map((path) => (\n <Card key={path.id}>\n <CardHeader>\n <CardTitle className=\"text-base\">{path.title}</CardTitle>\n <CardDescription>{path.description}</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"flex items-center justify-between text-sm text-text-secondary\">\n <span>\n {path.courses.length} courses · {path.duration}\n </span>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {path.level}\n </Badge>\n </div>\n <div className=\"mt-2 space-y-1\">\n <div className=\"flex justify-between text-xs\">\n <span>{path.enrolled} enrolled</span>\n <span>{path.completionRate}%</span>\n </div>\n <div className=\"h-2 bg-bg-sunken rounded overflow-hidden\">\n <div\n className=\"h-2 bg-action-primary-bg rounded\"\n style={{ width: `${path.completionRate}%` }}\n />\n </div>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|