@burdenoff/microfe-technospam 2026.705.1 → 2026.705.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.
Files changed (36) hide show
  1. package/dist/technospam/components/MediaCover.js +57 -0
  2. package/dist/technospam/components/MediaCover.js.map +1 -0
  3. package/dist/technospam/components/PageLayout.js +1 -1
  4. package/dist/technospam/components/PageLayout.js.map +1 -1
  5. package/dist/technospam/components/StatCard.js +19 -11
  6. package/dist/technospam/components/StatCard.js.map +1 -1
  7. package/dist/technospam/components/StatusBadge.js +1 -1
  8. package/dist/technospam/components/StatusBadge.js.map +1 -1
  9. package/dist/technospam/components/index.js +1 -0
  10. package/dist/technospam/pages/AdminAdminDashboardPagePage.js +525 -459
  11. package/dist/technospam/pages/AdminAdminDashboardPagePage.js.map +1 -1
  12. package/dist/technospam/pages/AnalyticsAnalyticsPagePage.js +167 -127
  13. package/dist/technospam/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
  14. package/dist/technospam/pages/ApplicationsProblemDetailsPagePage.js +178 -125
  15. package/dist/technospam/pages/ApplicationsProblemDetailsPagePage.js.map +1 -1
  16. package/dist/technospam/pages/ApplicationsProblemsPagePage.js +77 -88
  17. package/dist/technospam/pages/ApplicationsProblemsPagePage.js.map +1 -1
  18. package/dist/technospam/pages/CoursesCourseDetailsPagePage.js +287 -186
  19. package/dist/technospam/pages/CoursesCourseDetailsPagePage.js.map +1 -1
  20. package/dist/technospam/pages/CoursesCoursesPagePage.js +76 -83
  21. package/dist/technospam/pages/CoursesCoursesPagePage.js.map +1 -1
  22. package/dist/technospam/pages/CoursesMyLearningPagePage.js +119 -88
  23. package/dist/technospam/pages/CoursesMyLearningPagePage.js.map +1 -1
  24. package/dist/technospam/pages/DashboardDashboardPagePage.js +232 -199
  25. package/dist/technospam/pages/DashboardDashboardPagePage.js.map +1 -1
  26. package/dist/technospam/pages/HackathonsHackathonDetailsPagePage.js +128 -106
  27. package/dist/technospam/pages/HackathonsHackathonDetailsPagePage.js.map +1 -1
  28. package/dist/technospam/pages/HackathonsHackathonsPagePage.js +71 -78
  29. package/dist/technospam/pages/HackathonsHackathonsPagePage.js.map +1 -1
  30. package/dist/technospam/pages/MentorshipMentorProfilePagePage.js +165 -110
  31. package/dist/technospam/pages/MentorshipMentorProfilePagePage.js.map +1 -1
  32. package/dist/technospam/pages/MentorshipMentorsPagePage.js +210 -156
  33. package/dist/technospam/pages/MentorshipMentorsPagePage.js.map +1 -1
  34. package/dist/technospam/pages/MentorshipSessionsPagePage.js +59 -43
  35. package/dist/technospam/pages/MentorshipSessionsPagePage.js.map +1 -1
  36. package/package.json +1 -1
@@ -0,0 +1,57 @@
1
+ import { cn as e } from "../utils/cn.js";
2
+ import { createElement as t } from "react";
3
+ import { BarChart3 as n, BrainCircuit as r, Cloud as i, Code2 as a, Database as o, Globe as s, Layers as c, Lock as l, Smartphone as u } from "lucide-react";
4
+ import { jsx as d, jsxs as f } from "react/jsx-runtime";
5
+ //#region src/technospam/components/MediaCover.tsx
6
+ var p = [
7
+ "from-accent-primary to-accent-indigo",
8
+ "from-accent-indigo to-accent-purple",
9
+ "from-accent-teal to-accent-primary",
10
+ "from-accent-purple to-accent-primary",
11
+ "from-accent-primary to-accent-teal",
12
+ "from-accent-indigo to-accent-teal"
13
+ ];
14
+ function m(e) {
15
+ let t = 0;
16
+ for (let n = 0; n < e.length; n += 1) t = t * 31 + e.charCodeAt(n) >>> 0;
17
+ return t;
18
+ }
19
+ function h(e) {
20
+ return p[m(e) % p.length];
21
+ }
22
+ var g = [
23
+ [/data|sql|postgres|database|analytics/i, o],
24
+ [/web|react|frontend|css|html|ui/i, s],
25
+ [/ai|ml|machine|neural|llm|intelligence/i, r],
26
+ [/cloud|devops|kubernetes|docker|infra/i, i],
27
+ [/security|crypto|auth/i, l],
28
+ [/mobile|ios|android|flutter/i, u],
29
+ [/architecture|system|design|scal/i, c],
30
+ [/chart|report|metric/i, n]
31
+ ];
32
+ function _(e, t = a) {
33
+ for (let [t, n] of g) if (t.test(e)) return n;
34
+ return t;
35
+ }
36
+ function v({ seed: n, icon: r, height: i = "h-28", children: a, className: o }) {
37
+ let s = t(r ?? _(n), {
38
+ className: "pointer-events-none absolute -right-4 -top-4 text-white/15",
39
+ size: 96,
40
+ strokeWidth: 1.4
41
+ });
42
+ return /* @__PURE__ */ f("div", {
43
+ className: e("relative flex items-end overflow-hidden bg-gradient-to-br p-4", h(n), i, o),
44
+ children: [
45
+ s,
46
+ /* @__PURE__ */ d("div", { className: "pointer-events-none absolute inset-0 bg-gradient-to-t from-black/25 via-transparent to-white/5" }),
47
+ a ? /* @__PURE__ */ d("div", {
48
+ className: "relative flex w-full items-end justify-between gap-2",
49
+ children: a
50
+ }) : null
51
+ ]
52
+ });
53
+ }
54
+ //#endregion
55
+ export { v as MediaCover, h as coverGradient, _ as topicIcon };
56
+
57
+ //# sourceMappingURL=MediaCover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MediaCover.js","names":[],"sources":["../../../src/technospam/components/MediaCover.tsx"],"sourcesContent":["import { createElement, type ReactNode } from 'react';\nimport {\n BarChart3,\n BrainCircuit,\n Cloud,\n Code2,\n Database,\n Globe,\n Layers,\n Lock,\n Smartphone,\n Trophy,\n type LucideIcon,\n} from 'lucide-react';\nimport { cn } from '../utils/cn';\n\n/** Vivid, on-theme gradient covers built only from tokens that exist in the theme\n * (accent-primary / accent-indigo / accent-teal / accent-purple). */\nconst GRADIENTS = [\n 'from-accent-primary to-accent-indigo',\n 'from-accent-indigo to-accent-purple',\n 'from-accent-teal to-accent-primary',\n 'from-accent-purple to-accent-primary',\n 'from-accent-primary to-accent-teal',\n 'from-accent-indigo to-accent-teal',\n];\n\nfunction hash(seed: string): number {\n let h = 0;\n for (let i = 0; i < seed.length; i += 1) h = (h * 31 + seed.charCodeAt(i)) >>> 0;\n return h;\n}\n\nexport function coverGradient(seed: string): string {\n return GRADIENTS[hash(seed) % GRADIENTS.length]!;\n}\n\nconst TOPIC_ICONS: Array<[RegExp, LucideIcon]> = [\n [/data|sql|postgres|database|analytics/i, Database],\n [/web|react|frontend|css|html|ui/i, Globe],\n [/ai|ml|machine|neural|llm|intelligence/i, BrainCircuit],\n [/cloud|devops|kubernetes|docker|infra/i, Cloud],\n [/security|crypto|auth/i, Lock],\n [/mobile|ios|android|flutter/i, Smartphone],\n [/architecture|system|design|scal/i, Layers],\n [/chart|report|metric/i, BarChart3],\n];\n\n/** Pick a topic-appropriate icon from a free-text seed (topic/title/tags). */\nexport function topicIcon(seed: string, fallback: LucideIcon = Code2): LucideIcon {\n for (const [re, Icon] of TOPIC_ICONS) if (re.test(seed)) return Icon;\n return fallback;\n}\n\nexport { Trophy };\n\n/**\n * A vivid gradient cover band with a large faint topic-icon watermark and a\n * bottom scrim for legible overlay content. Used by course / problem / hackathon\n * cards and detail heroes so media reads as bold and modern (no flat panels).\n */\nexport function MediaCover({\n seed,\n icon,\n height = 'h-28',\n children,\n className,\n}: {\n seed: string;\n icon?: LucideIcon;\n height?: string;\n children?: ReactNode;\n className?: string;\n}) {\n const iconEl = createElement(icon ?? topicIcon(seed), {\n className: 'pointer-events-none absolute -right-4 -top-4 text-white/15',\n size: 96,\n strokeWidth: 1.4,\n });\n return (\n <div\n className={cn(\n 'relative flex items-end overflow-hidden bg-gradient-to-br p-4',\n coverGradient(seed),\n height,\n className\n )}\n >\n {iconEl}\n <div className=\"pointer-events-none absolute inset-0 bg-gradient-to-t from-black/25 via-transparent to-white/5\" />\n {children ? (\n <div className=\"relative flex w-full items-end justify-between gap-2\">{children}</div>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;;;AAkBA,IAAM,IAAY;CAChB;CACA;CACA;CACA;CACA;CACA;CACD;AAED,SAAS,EAAK,GAAsB;CAClC,IAAI,IAAI;AACR,MAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAAK,EAAG,KAAK,IAAI,KAAK,EAAK,WAAW,EAAE,KAAM;AAC/E,QAAO;;AAGT,SAAgB,EAAc,GAAsB;AAClD,QAAO,EAAU,EAAK,EAAK,GAAG,EAAU;;AAG1C,IAAM,IAA2C;CAC/C,CAAC,yCAAyC,EAAS;CACnD,CAAC,mCAAmC,EAAM;CAC1C,CAAC,0CAA0C,EAAa;CACxD,CAAC,yCAAyC,EAAM;CAChD,CAAC,yBAAyB,EAAK;CAC/B,CAAC,+BAA+B,EAAW;CAC3C,CAAC,oCAAoC,EAAO;CAC5C,CAAC,wBAAwB,EAAU;CACpC;AAGD,SAAgB,EAAU,GAAc,IAAuB,GAAmB;AAChF,MAAK,IAAM,CAAC,GAAI,MAAS,EAAa,KAAI,EAAG,KAAK,EAAK,CAAE,QAAO;AAChE,QAAO;;AAUT,SAAgB,EAAW,EACzB,SACA,SACA,YAAS,QACT,aACA,gBAOC;CACD,IAAM,IAAS,EAAc,KAAQ,EAAU,EAAK,EAAE;EACpD,WAAW;EACX,MAAM;EACN,aAAa;EACd,CAAC;AACF,QACE,kBAAC,OAAD;EACE,WAAW,EACT,iEACA,EAAc,EAAK,EACnB,GACA,EACD;YANH;GAQG;GACD,kBAAC,OAAD,EAAK,WAAU,kGAAmG,CAAA;GACjH,IACC,kBAAC,OAAD;IAAK,WAAU;IAAwD;IAAe,CAAA,GACpF;GACA"}
@@ -9,7 +9,7 @@ function o({ title: o, description: s, actions: c, children: l, backPath: u, her
9
9
  return /* @__PURE__ */ i("div", {
10
10
  className: "flex h-full flex-col bg-bg-surface",
11
11
  children: [/* @__PURE__ */ i("div", {
12
- className: t("relative flex flex-col gap-4 overflow-hidden border-b border-border-seam px-6 py-5 sm:flex-row sm:items-start sm:justify-between", d ? "bg-accent-wash" : "bg-bg-surface"),
12
+ className: t("relative flex flex-col gap-4 overflow-hidden border-b border-border-seam px-6 py-5 sm:flex-row sm:items-start sm:justify-between", d ? "bg-accent-primary/12" : "bg-bg-surface"),
13
13
  children: [
14
14
  d ? /* @__PURE__ */ r(a, { intensity: "subtle" }) : null,
15
15
  /* @__PURE__ */ i("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"PageLayout.js","names":[],"sources":["../../../src/technospam/components/PageLayout.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { ArrowLeft } from 'lucide-react';\nimport { AuroraBackground } from '@burdenoff/fe-libs/ui';\nimport { useTechnoSpamNavigate } from '../providers/TechnoSpamProvider';\nimport { cn } from '../utils/cn';\n\ninterface PageLayoutProps {\n title: ReactNode;\n description?: ReactNode;\n actions?: ReactNode;\n children: ReactNode;\n backPath?: string;\n /** Render the page header with the living-glass aurora backdrop (module hero). */\n hero?: boolean;\n}\n\n/**\n * Consistent page chrome for every TechnoSpam module page: a header band\n * (optionally with the aurora hero backdrop), an optional back affordance, an\n * actions slot, and a scrollable body. Mirrors the platform page pattern so\n * TechnoSpam feels native to the shell.\n */\nexport function PageLayout({\n title,\n description,\n actions,\n children,\n backPath,\n hero = false,\n}: PageLayoutProps) {\n const navigate = useTechnoSpamNavigate();\n\n return (\n <div className=\"flex h-full flex-col bg-bg-surface\">\n <div\n className={cn(\n 'relative flex flex-col gap-4 overflow-hidden border-b border-border-seam px-6 py-5 sm:flex-row sm:items-start sm:justify-between',\n hero ? 'bg-accent-wash' : 'bg-bg-surface'\n )}\n >\n {hero ? <AuroraBackground intensity=\"subtle\" /> : null}\n <div className=\"relative flex min-w-0 flex-col gap-1\">\n {backPath ? (\n <button\n type=\"button\"\n onClick={() => navigate(backPath)}\n className=\"flex w-fit items-center gap-1 text-sm text-text-secondary transition-colors hover:text-text-primary focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <ArrowLeft size={15} />\n Back\n </button>\n ) : null}\n <h1 className=\"truncate text-xl font-semibold text-text-primary sm:text-2xl\">{title}</h1>\n {description ? (\n <p className=\"max-w-2xl text-sm text-text-secondary\">{description}</p>\n ) : null}\n </div>\n {actions ? (\n <div className=\"relative flex flex-wrap items-center gap-2\">{actions}</div>\n ) : null}\n </div>\n <div className=\"flex-1 overflow-y-auto p-6\">{children}</div>\n </div>\n );\n}\n"],"mappings":";;;;;;AAsBA,SAAgB,EAAW,EACzB,UACA,gBACA,YACA,aACA,aACA,UAAO,MACW;CAClB,IAAM,IAAW,GAAuB;AAExC,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GACE,WAAW,EACT,oIACA,IAAO,mBAAmB,gBAC3B;aAJH;IAMG,IAAO,kBAAC,GAAD,EAAkB,WAAU,UAAW,CAAA,GAAG;IAClD,kBAAC,OAAD;KAAK,WAAU;eAAf;MACG,IACC,kBAAC,UAAD;OACE,MAAK;OACL,eAAe,EAAS,EAAS;OACjC,WAAU;iBAHZ,CAKE,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA,EAAA,OAEhB;WACP;MACJ,kBAAC,MAAD;OAAI,WAAU;iBAAgE;OAAW,CAAA;MACxF,IACC,kBAAC,KAAD;OAAG,WAAU;iBAAyC;OAAgB,CAAA,GACpE;MACA;;IACL,IACC,kBAAC,OAAD;KAAK,WAAU;eAA8C;KAAc,CAAA,GACzE;IACA;MACN,kBAAC,OAAD;GAAK,WAAU;GAA8B;GAAe,CAAA,CACxD"}
1
+ {"version":3,"file":"PageLayout.js","names":[],"sources":["../../../src/technospam/components/PageLayout.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { ArrowLeft } from 'lucide-react';\nimport { AuroraBackground } from '@burdenoff/fe-libs/ui';\nimport { useTechnoSpamNavigate } from '../providers/TechnoSpamProvider';\nimport { cn } from '../utils/cn';\n\ninterface PageLayoutProps {\n title: ReactNode;\n description?: ReactNode;\n actions?: ReactNode;\n children: ReactNode;\n backPath?: string;\n /** Render the page header with the living-glass aurora backdrop (module hero). */\n hero?: boolean;\n}\n\n/**\n * Consistent page chrome for every TechnoSpam module page: a header band\n * (optionally with the aurora hero backdrop), an optional back affordance, an\n * actions slot, and a scrollable body. Mirrors the platform page pattern so\n * TechnoSpam feels native to the shell.\n */\nexport function PageLayout({\n title,\n description,\n actions,\n children,\n backPath,\n hero = false,\n}: PageLayoutProps) {\n const navigate = useTechnoSpamNavigate();\n\n return (\n <div className=\"flex h-full flex-col bg-bg-surface\">\n <div\n className={cn(\n 'relative flex flex-col gap-4 overflow-hidden border-b border-border-seam px-6 py-5 sm:flex-row sm:items-start sm:justify-between',\n hero ? 'bg-accent-primary/12' : 'bg-bg-surface'\n )}\n >\n {hero ? <AuroraBackground intensity=\"subtle\" /> : null}\n <div className=\"relative flex min-w-0 flex-col gap-1\">\n {backPath ? (\n <button\n type=\"button\"\n onClick={() => navigate(backPath)}\n className=\"flex w-fit items-center gap-1 text-sm text-text-secondary transition-colors hover:text-text-primary focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <ArrowLeft size={15} />\n Back\n </button>\n ) : null}\n <h1 className=\"truncate text-xl font-semibold text-text-primary sm:text-2xl\">{title}</h1>\n {description ? (\n <p className=\"max-w-2xl text-sm text-text-secondary\">{description}</p>\n ) : null}\n </div>\n {actions ? (\n <div className=\"relative flex flex-wrap items-center gap-2\">{actions}</div>\n ) : null}\n </div>\n <div className=\"flex-1 overflow-y-auto p-6\">{children}</div>\n </div>\n );\n}\n"],"mappings":";;;;;;AAsBA,SAAgB,EAAW,EACzB,UACA,gBACA,YACA,aACA,aACA,UAAO,MACW;CAClB,IAAM,IAAW,GAAuB;AAExC,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GACE,WAAW,EACT,oIACA,IAAO,yBAAyB,gBACjC;aAJH;IAMG,IAAO,kBAAC,GAAD,EAAkB,WAAU,UAAW,CAAA,GAAG;IAClD,kBAAC,OAAD;KAAK,WAAU;eAAf;MACG,IACC,kBAAC,UAAD;OACE,MAAK;OACL,eAAe,EAAS,EAAS;OACjC,WAAU;iBAHZ,CAKE,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA,EAAA,OAEhB;WACP;MACJ,kBAAC,MAAD;OAAI,WAAU;iBAAgE;OAAW,CAAA;MACxF,IACC,kBAAC,KAAD;OAAG,WAAU;iBAAyC;OAAgB,CAAA,GACpE;MACA;;IACL,IACC,kBAAC,OAAD;KAAK,WAAU;eAA8C;KAAc,CAAA,GACzE;IACA;MACN,kBAAC,OAAD;GAAK,WAAU;GAA8B;GAAe,CAAA,CACxD"}
@@ -2,32 +2,40 @@ import { cn as e } from "../utils/cn.js";
2
2
  import { jsx as t, jsxs as n } from "react/jsx-runtime";
3
3
  import { GlassCard as r } from "@burdenoff/fe-libs/ui";
4
4
  //#region src/technospam/components/StatCard.tsx
5
- function i({ label: i, value: a, hint: o, icon: s, className: c }) {
5
+ var i = {
6
+ blue: "bg-accent-primary/15 text-accent-primary ring-accent-primary/20",
7
+ teal: "bg-accent-teal/15 text-accent-teal ring-accent-teal/20",
8
+ purple: "bg-accent-purple/15 text-accent-purple ring-accent-purple/20",
9
+ indigo: "bg-accent-indigo/15 text-accent-indigo ring-accent-indigo/20",
10
+ green: "bg-status-success-bg-subtle text-status-success-text ring-status-success-border/30",
11
+ amber: "bg-status-warning-bg-subtle text-status-warning-text ring-status-warning-border/30"
12
+ };
13
+ function a({ label: a, value: o, hint: s, icon: c, tone: l = "blue", className: u }) {
6
14
  return /* @__PURE__ */ n(r, {
7
- className: e("flex items-start gap-3 p-4", c),
8
- children: [s ? /* @__PURE__ */ t("span", {
9
- className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-accent-wash text-accent-teal",
10
- children: /* @__PURE__ */ t(s, { size: 18 })
15
+ className: e("group flex items-start gap-3 p-4 transition-transform duration-200 hover:-translate-y-0.5", u),
16
+ children: [c ? /* @__PURE__ */ t("span", {
17
+ className: e("flex h-10 w-10 shrink-0 items-center justify-center rounded-xl ring-1 transition-transform duration-200 group-hover:scale-105", i[l]),
18
+ children: /* @__PURE__ */ t(c, { size: 19 })
11
19
  }) : null, /* @__PURE__ */ n("div", {
12
20
  className: "min-w-0",
13
21
  children: [
14
22
  /* @__PURE__ */ t("div", {
15
23
  className: "truncate text-sm text-text-secondary",
16
- children: i
24
+ children: a
17
25
  }),
18
26
  /* @__PURE__ */ t("div", {
19
- className: "text-xl font-semibold text-text-primary",
20
- children: a
27
+ className: "text-2xl font-semibold tracking-tight text-text-primary",
28
+ children: o
21
29
  }),
22
- o ? /* @__PURE__ */ t("div", {
30
+ s ? /* @__PURE__ */ t("div", {
23
31
  className: "mt-0.5 truncate text-xs text-text-muted",
24
- children: o
32
+ children: s
25
33
  }) : null
26
34
  ]
27
35
  })]
28
36
  });
29
37
  }
30
38
  //#endregion
31
- export { i as StatCard };
39
+ export { a as StatCard };
32
40
 
33
41
  //# sourceMappingURL=StatCard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"StatCard.js","names":[],"sources":["../../../src/technospam/components/StatCard.tsx"],"sourcesContent":["import type { LucideIcon } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\n\ninterface StatCardProps {\n label: string;\n value: string | number;\n hint?: string;\n icon?: LucideIcon;\n className?: string;\n}\n\n/** Compact metric tile used across dashboards and module overviews. */\nexport function StatCard({ label, value, hint, icon: Icon, className }: StatCardProps) {\n return (\n <GlassCard className={cn('flex items-start gap-3 p-4', className)}>\n {Icon ? (\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-accent-wash text-accent-teal\">\n <Icon size={18} />\n </span>\n ) : null}\n <div className=\"min-w-0\">\n <div className=\"truncate text-sm text-text-secondary\">{label}</div>\n <div className=\"text-xl font-semibold text-text-primary\">{value}</div>\n {hint ? <div className=\"mt-0.5 truncate text-xs text-text-muted\">{hint}</div> : null}\n </div>\n </GlassCard>\n );\n}\n"],"mappings":";;;;AAaA,SAAgB,EAAS,EAAE,UAAO,UAAO,SAAM,MAAM,GAAM,gBAA4B;AACrF,QACE,kBAAC,GAAD;EAAW,WAAW,EAAG,8BAA8B,EAAU;YAAjE,CACG,IACC,kBAAC,QAAD;GAAM,WAAU;aACd,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA;GACb,CAAA,GACL,MACJ,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eAAwC;KAAY,CAAA;IACnE,kBAAC,OAAD;KAAK,WAAU;eAA2C;KAAY,CAAA;IACrE,IAAO,kBAAC,OAAD;KAAK,WAAU;eAA2C;KAAW,CAAA,GAAG;IAC5E;KACI"}
1
+ {"version":3,"file":"StatCard.js","names":[],"sources":["../../../src/technospam/components/StatCard.tsx"],"sourcesContent":["import type { LucideIcon } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\n\n/** Tinted icon-chip tones, all built from tokens that exist in the theme. */\nexport type StatTone = 'blue' | 'teal' | 'purple' | 'indigo' | 'green' | 'amber';\n\nconst TONE: Record<StatTone, string> = {\n blue: 'bg-accent-primary/15 text-accent-primary ring-accent-primary/20',\n teal: 'bg-accent-teal/15 text-accent-teal ring-accent-teal/20',\n purple: 'bg-accent-purple/15 text-accent-purple ring-accent-purple/20',\n indigo: 'bg-accent-indigo/15 text-accent-indigo ring-accent-indigo/20',\n green: 'bg-status-success-bg-subtle text-status-success-text ring-status-success-border/30',\n amber: 'bg-status-warning-bg-subtle text-status-warning-text ring-status-warning-border/30',\n};\n\ninterface StatCardProps {\n label: string;\n value: string | number;\n hint?: string;\n icon?: LucideIcon;\n tone?: StatTone;\n className?: string;\n}\n\n/**\n * Compact metric tile used across dashboards and module overviews. The icon sits\n * in a softly-tinted, ringed chip so a row of tiles reads as a colourful,\n * modern stat strip rather than a flat list.\n */\nexport function StatCard({\n label,\n value,\n hint,\n icon: Icon,\n tone = 'blue',\n className,\n}: StatCardProps) {\n return (\n <GlassCard\n className={cn(\n 'group flex items-start gap-3 p-4 transition-transform duration-200 hover:-translate-y-0.5',\n className\n )}\n >\n {Icon ? (\n <span\n className={cn(\n 'flex h-10 w-10 shrink-0 items-center justify-center rounded-xl ring-1 transition-transform duration-200 group-hover:scale-105',\n TONE[tone]\n )}\n >\n <Icon size={19} />\n </span>\n ) : null}\n <div className=\"min-w-0\">\n <div className=\"truncate text-sm text-text-secondary\">{label}</div>\n <div className=\"text-2xl font-semibold tracking-tight text-text-primary\">{value}</div>\n {hint ? <div className=\"mt-0.5 truncate text-xs text-text-muted\">{hint}</div> : null}\n </div>\n </GlassCard>\n );\n}\n"],"mappings":";;;;AAOA,IAAM,IAAiC;CACrC,MAAM;CACN,MAAM;CACN,QAAQ;CACR,QAAQ;CACR,OAAO;CACP,OAAO;CACR;AAgBD,SAAgB,EAAS,EACvB,UACA,UACA,SACA,MAAM,GACN,UAAO,QACP,gBACgB;AAChB,QACE,kBAAC,GAAD;EACE,WAAW,EACT,6FACA,EACD;YAJH,CAMG,IACC,kBAAC,QAAD;GACE,WAAW,EACT,iIACA,EAAK,GACN;aAED,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA;GACb,CAAA,GACL,MACJ,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eAAwC;KAAY,CAAA;IACnE,kBAAC,OAAD;KAAK,WAAU;eAA2D;KAAY,CAAA;IACrF,IAAO,kBAAC,OAAD;KAAK,WAAU;eAA2C;KAAW,CAAA,GAAG;IAC5E;KACI"}
@@ -4,7 +4,7 @@ import { Badge as n } from "@burdenoff/fe-libs/ui";
4
4
  //#region src/technospam/components/StatusBadge.tsx
5
5
  var r = {
6
6
  neutral: "bg-bg-sunken text-text-secondary border-border-seam",
7
- info: "bg-accent-wash text-accent-primary border-accent-primary/30",
7
+ info: "bg-accent-primary/12 text-accent-primary border-accent-primary/30",
8
8
  success: "bg-status-success-bg-subtle text-status-success-text border-status-success-border",
9
9
  warning: "bg-status-warning-bg-subtle text-status-warning-text border-status-warning-border",
10
10
  danger: "bg-status-error-bg-subtle text-status-error-text border-status-error-border"
@@ -1 +1 @@
1
- {"version":3,"file":"StatusBadge.js","names":[],"sources":["../../../src/technospam/components/StatusBadge.tsx"],"sourcesContent":["import { Badge } from '@burdenoff/fe-libs/ui';\nimport { humanizeEnum } from '../utils/format';\n\ntype Tone = 'neutral' | 'info' | 'success' | 'warning' | 'danger';\n\nconst TONE_CLASS: Record<Tone, string> = {\n neutral: 'bg-bg-sunken text-text-secondary border-border-seam',\n info: 'bg-accent-wash text-accent-primary border-accent-primary/30',\n success: 'bg-status-success-bg-subtle text-status-success-text border-status-success-border',\n warning: 'bg-status-warning-bg-subtle text-status-warning-text border-status-warning-border',\n danger: 'bg-status-error-bg-subtle text-status-error-text border-status-error-border',\n};\n\n/** Maps any Tec* status enum to a semantic tone. Unknown values fall back to neutral. */\nconst STATUS_TONE: Record<string, Tone> = {\n // course / problem\n DRAFT: 'neutral',\n PUBLISHED: 'success',\n ARCHIVED: 'warning',\n // enrollment\n ENROLLED: 'info',\n IN_PROGRESS: 'info',\n COMPLETED: 'success',\n DROPPED: 'warning',\n // certificate\n ISSUED: 'success',\n REVOKED: 'danger',\n // submission verdict\n PENDING: 'neutral',\n ACCEPTED: 'success',\n WRONG_ANSWER: 'danger',\n TIME_LIMIT_EXCEEDED: 'warning',\n RUNTIME_ERROR: 'danger',\n COMPILE_ERROR: 'danger',\n // mentor\n ACTIVE: 'success',\n PAUSED: 'warning',\n INACTIVE: 'neutral',\n // session\n REQUESTED: 'info',\n CONFIRMED: 'success',\n CANCELLED: 'danger',\n NO_SHOW: 'danger',\n // hackathon\n REGISTRATION_OPEN: 'success',\n JUDGING: 'info',\n // team\n SUBMITTED: 'success',\n DISQUALIFIED: 'danger',\n WINNER: 'success',\n};\n\nconst DIFFICULTY_TONE: Record<string, Tone> = {\n EASY: 'success',\n MEDIUM: 'warning',\n HARD: 'danger',\n BEGINNER: 'success',\n INTERMEDIATE: 'info',\n ADVANCED: 'warning',\n EXPERT: 'danger',\n};\n\nexport function StatusBadge({\n status,\n kind = 'status',\n}: {\n status?: string | null;\n kind?: 'status' | 'level';\n}) {\n if (!status) return null;\n const tone = (kind === 'level' ? DIFFICULTY_TONE[status] : STATUS_TONE[status]) ?? 'neutral';\n return (\n <Badge variant=\"outline\" className={TONE_CLASS[tone]}>\n {humanizeEnum(status)}\n </Badge>\n );\n}\n"],"mappings":";;;;AAKA,IAAM,IAAmC;CACvC,SAAS;CACT,MAAM;CACN,SAAS;CACT,SAAS;CACT,QAAQ;CACT,EAGK,IAAoC;CAExC,OAAO;CACP,WAAW;CACX,UAAU;CAEV,UAAU;CACV,aAAa;CACb,WAAW;CACX,SAAS;CAET,QAAQ;CACR,SAAS;CAET,SAAS;CACT,UAAU;CACV,cAAc;CACd,qBAAqB;CACrB,eAAe;CACf,eAAe;CAEf,QAAQ;CACR,QAAQ;CACR,UAAU;CAEV,WAAW;CACX,WAAW;CACX,WAAW;CACX,SAAS;CAET,mBAAmB;CACnB,SAAS;CAET,WAAW;CACX,cAAc;CACd,QAAQ;CACT,EAEK,IAAwC;CAC5C,MAAM;CACN,QAAQ;CACR,MAAM;CACN,UAAU;CACV,cAAc;CACd,UAAU;CACV,QAAQ;CACT;AAED,SAAgB,EAAY,EAC1B,WACA,UAAO,YAIN;AAGD,QAFK,IAGH,kBAAC,GAAD;EAAO,SAAQ;EAAU,WAAW,GAFxB,MAAS,UAAU,EAAgB,KAAU,EAAY,OAAY;YAG9E,EAAa,EAAO;EACf,CAAA,GALU"}
1
+ {"version":3,"file":"StatusBadge.js","names":[],"sources":["../../../src/technospam/components/StatusBadge.tsx"],"sourcesContent":["import { Badge } from '@burdenoff/fe-libs/ui';\nimport { humanizeEnum } from '../utils/format';\n\ntype Tone = 'neutral' | 'info' | 'success' | 'warning' | 'danger';\n\nconst TONE_CLASS: Record<Tone, string> = {\n neutral: 'bg-bg-sunken text-text-secondary border-border-seam',\n info: 'bg-accent-primary/12 text-accent-primary border-accent-primary/30',\n success: 'bg-status-success-bg-subtle text-status-success-text border-status-success-border',\n warning: 'bg-status-warning-bg-subtle text-status-warning-text border-status-warning-border',\n danger: 'bg-status-error-bg-subtle text-status-error-text border-status-error-border',\n};\n\n/** Maps any Tec* status enum to a semantic tone. Unknown values fall back to neutral. */\nconst STATUS_TONE: Record<string, Tone> = {\n // course / problem\n DRAFT: 'neutral',\n PUBLISHED: 'success',\n ARCHIVED: 'warning',\n // enrollment\n ENROLLED: 'info',\n IN_PROGRESS: 'info',\n COMPLETED: 'success',\n DROPPED: 'warning',\n // certificate\n ISSUED: 'success',\n REVOKED: 'danger',\n // submission verdict\n PENDING: 'neutral',\n ACCEPTED: 'success',\n WRONG_ANSWER: 'danger',\n TIME_LIMIT_EXCEEDED: 'warning',\n RUNTIME_ERROR: 'danger',\n COMPILE_ERROR: 'danger',\n // mentor\n ACTIVE: 'success',\n PAUSED: 'warning',\n INACTIVE: 'neutral',\n // session\n REQUESTED: 'info',\n CONFIRMED: 'success',\n CANCELLED: 'danger',\n NO_SHOW: 'danger',\n // hackathon\n REGISTRATION_OPEN: 'success',\n JUDGING: 'info',\n // team\n SUBMITTED: 'success',\n DISQUALIFIED: 'danger',\n WINNER: 'success',\n};\n\nconst DIFFICULTY_TONE: Record<string, Tone> = {\n EASY: 'success',\n MEDIUM: 'warning',\n HARD: 'danger',\n BEGINNER: 'success',\n INTERMEDIATE: 'info',\n ADVANCED: 'warning',\n EXPERT: 'danger',\n};\n\nexport function StatusBadge({\n status,\n kind = 'status',\n}: {\n status?: string | null;\n kind?: 'status' | 'level';\n}) {\n if (!status) return null;\n const tone = (kind === 'level' ? DIFFICULTY_TONE[status] : STATUS_TONE[status]) ?? 'neutral';\n return (\n <Badge variant=\"outline\" className={TONE_CLASS[tone]}>\n {humanizeEnum(status)}\n </Badge>\n );\n}\n"],"mappings":";;;;AAKA,IAAM,IAAmC;CACvC,SAAS;CACT,MAAM;CACN,SAAS;CACT,SAAS;CACT,QAAQ;CACT,EAGK,IAAoC;CAExC,OAAO;CACP,WAAW;CACX,UAAU;CAEV,UAAU;CACV,aAAa;CACb,WAAW;CACX,SAAS;CAET,QAAQ;CACR,SAAS;CAET,SAAS;CACT,UAAU;CACV,cAAc;CACd,qBAAqB;CACrB,eAAe;CACf,eAAe;CAEf,QAAQ;CACR,QAAQ;CACR,UAAU;CAEV,WAAW;CACX,WAAW;CACX,WAAW;CACX,SAAS;CAET,mBAAmB;CACnB,SAAS;CAET,WAAW;CACX,cAAc;CACd,QAAQ;CACT,EAEK,IAAwC;CAC5C,MAAM;CACN,QAAQ;CACR,MAAM;CACN,UAAU;CACV,cAAc;CACd,UAAU;CACV,QAAQ;CACT;AAED,SAAgB,EAAY,EAC1B,WACA,UAAO,YAIN;AAGD,QAFK,IAGH,kBAAC,GAAD;EAAO,SAAQ;EAAU,WAAW,GAFxB,MAAS,UAAU,EAAgB,KAAU,EAAY,OAAY;YAG9E,EAAa,EAAO;EACf,CAAA,GALU"}
@@ -1,5 +1,6 @@
1
1
  import "./PageLayout.js";
2
2
  import "./StatCard.js";
3
+ import "./MediaCover.js";
3
4
  import "./StatusBadge.js";
4
5
  import "./LoadMore.js";
5
6
  import "./StateViews.js";