@local-civics/mgmt-ui 0.1.212 → 0.1.213

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/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { useState, useMemo } from 'react';
3
- import { createStyles, Group, Avatar, Text, Box, Badge as Badge$1, ThemeIcon, Collapse, Navbar as Navbar$1, Center, Image, Code, Burger, ScrollArea, Modal, Loader, Container, Button, Title, UnstyledButton, Card, SimpleGrid, Tabs as Tabs$1, Stack as Stack$5, Grid, ActionIcon, LoadingOverlay, Select, Table as Table$l, Autocomplete, Drawer, Divider, TextInput, Tooltip, Paper, Overlay, Anchor, Menu, Checkbox, createEmotionCache, MantineProvider, AppShell, Accordion } from '@mantine/core';
4
- import { IconChevronRight, IconChevronLeft, IconVideo, IconSwitchHorizontal, IconLogout, IconHome2, IconGauge, IconCategory2, IconRoute, IconAlbum, IconLambda, IconClipboard, IconBuilding, IconBatteryEco, IconBooks, IconBackpack, IconClipboardCopy, IconTableExport, IconArrowLeft, IconPlaylistAdd, IconCheck, IconTrash, IconDownload, IconX, IconCloudUpload, IconInfoCircle, IconColorSwatch, IconPointer, IconChevronDown, IconScribble, IconSchool, IconPodium, IconBriefcase, IconPresentation, IconNews, IconTools, IconBrandInstagram, IconBrandLinkedin, IconBrandFacebook } from '@tabler/icons';
3
+ import { IconChevronRight, IconVideo, IconSwitchHorizontal, IconLogout, IconHome2, IconGauge, IconCategory2, IconRoute, IconAlbum, IconLambda, IconClipboard, IconBuilding, IconBatteryEco, IconBooks, IconBackpack, IconClipboardCopy, IconTableExport, IconArrowLeft, IconSearch, IconCheck, IconTrash, IconPlus, IconLink, IconDownload, IconCloudUpload, IconInfoCircle, IconPlaylistAdd, IconColorSwatch, IconPointer, IconChevronDown, IconX, IconScribble, IconSchool, IconPodium, IconBriefcase, IconPresentation, IconNews, IconTools, IconBrandInstagram, IconBrandLinkedin, IconBrandFacebook } from '@tabler/icons';
4
+ import { Avatar, createStyles, Modal, Center, Loader, Container, Group, Button, Title, Text, UnstyledButton, Card, ScrollArea, SimpleGrid, Tabs as Tabs$1, Stack as Stack$5, Image, Grid, Badge as Badge$1, ActionIcon, LoadingOverlay, Select, Table as Table$l, Drawer, Divider, TextInput, Tooltip, Autocomplete, Paper, ThemeIcon, Overlay, Anchor, Box, Menu, Checkbox, createEmotionCache, MantineProvider, AppShell, Accordion } from '@mantine/core';
5
5
  import { Link } from 'react-router-dom';
6
6
  import { showNotification, NotificationsProvider } from '@mantine/notifications';
7
7
  export { showNotification, updateNotification } from '@mantine/notifications';
@@ -14,47 +14,46 @@ import AvatarInit from 'avatar-initials';
14
14
  import { Chart } from 'react-charts';
15
15
  import { useUncontrolled } from '@mantine/hooks';
16
16
 
17
- var __defProp$f = Object.defineProperty;
18
- var __getOwnPropSymbols$f = Object.getOwnPropertySymbols;
19
- var __hasOwnProp$f = Object.prototype.hasOwnProperty;
20
- var __propIsEnum$f = Object.prototype.propertyIsEnumerable;
21
- var __defNormalProp$f = (obj, key, value) => key in obj ? __defProp$f(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
22
- var __spreadValues$f = (a, b) => {
23
- for (var prop in b || (b = {}))
24
- if (__hasOwnProp$f.call(b, prop))
25
- __defNormalProp$f(a, prop, b[prop]);
26
- if (__getOwnPropSymbols$f)
27
- for (var prop of __getOwnPropSymbols$f(b)) {
28
- if (__propIsEnum$f.call(b, prop))
29
- __defNormalProp$f(a, prop, b[prop]);
30
- }
31
- return a;
32
- };
33
- var __objRest$2 = (source, exclude) => {
34
- var target = {};
35
- for (var prop in source)
36
- if (__hasOwnProp$f.call(source, prop) && exclude.indexOf(prop) < 0)
37
- target[prop] = source[prop];
38
- if (source != null && __getOwnPropSymbols$f)
39
- for (var prop of __getOwnPropSymbols$f(source)) {
40
- if (exclude.indexOf(prop) < 0 && __propIsEnum$f.call(source, prop))
41
- target[prop] = source[prop];
17
+ function styleInject(css, ref) {
18
+ if ( ref === void 0 ) ref = {};
19
+ var insertAt = ref.insertAt;
20
+
21
+ if (!css || typeof document === 'undefined') { return; }
22
+
23
+ var head = document.head || document.getElementsByTagName('head')[0];
24
+ var style = document.createElement('style');
25
+ style.type = 'text/css';
26
+
27
+ if (insertAt === 'top') {
28
+ if (head.firstChild) {
29
+ head.insertBefore(style, head.firstChild);
30
+ } else {
31
+ head.appendChild(style);
42
32
  }
43
- return target;
44
- };
45
- const useStyles$v = createStyles((theme) => ({
46
- user: {
47
- display: "block",
48
- width: "100%",
49
- padding: theme.spacing.md,
50
- cursor: "default",
51
- color: theme.colorScheme === "dark" ? theme.colors.dark[0] : theme.black
33
+ } else {
34
+ head.appendChild(style);
52
35
  }
53
- }));
54
- function UserButton(_a) {
55
- var _b = _a, { image, name, email, icon } = _b, others = __objRest$2(_b, ["image", "name", "email", "icon"]);
56
- const { classes } = useStyles$v();
57
- return /* @__PURE__ */ React.createElement(Group, __spreadValues$f({ className: classes.user }, others), /* @__PURE__ */ React.createElement(Avatar, { src: image, radius: "xl" }), /* @__PURE__ */ React.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ React.createElement(Text, { size: "sm", weight: 500 }, name), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", size: "xs" }, email)));
36
+
37
+ if (style.styleSheet) {
38
+ style.styleSheet.cssText = css;
39
+ } else {
40
+ style.appendChild(document.createTextNode(css));
41
+ }
42
+ }
43
+
44
+ var css_248z = "@font-face{font-family:ProximaNova;src:url(https://cdn.localcivics.io/fonts/ProximaNova.otf) format(\"opentype\")}@font-face{font-family:ProximaNova;font-weight:700;src:url(https://cdn.localcivics.io/fonts/ProximaNovaBold.otf) format(\"opentype\")}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.\\!relative{position:relative!important}.m-3{margin:.75rem}.mx-auto{margin-left:auto;margin-right:auto}.mt-1{margin-top:.25rem}.mt-6{margin-top:1.5rem}.mt-2{margin-top:.5rem}.mt-1\\.5{margin-top:.375rem}.ml-\\[29px\\]{margin-left:29px}.mt-0\\.5{margin-top:.125rem}.mt-0{margin-top:0}.block{display:block}.inline{display:inline}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-full{height:100%}.h-8{height:2rem}.h-7{height:1.75rem}.h-screen{height:100vh}.h-\\[30px\\]{height:30px}.w-full{width:100%}.w-max{width:-moz-max-content;width:max-content}.w-8{width:2rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-7{width:1.75rem}.w-screen{width:100vw}.w-\\[230px\\]{width:230px}.w-24{width:6rem}.w-\\[30px\\]{width:30px}.min-w-0{min-width:0}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.rotate-90{--tw-rotate:90deg}.rotate-90,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.grid-cols-\\[2\\.2fr_1\\.2fr_1fr_1\\.2fr_1fr_0\\.6fr\\]{grid-template-columns:2.2fr 1.2fr 1fr 1.2fr 1fr .6fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-5{gap:1.25rem}.gap-2\\.5{gap:.625rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-1{gap:.25rem}.gap-1\\.5{gap:.375rem}.gap-3{gap:.75rem}.gap-0\\.5{gap:.125rem}.gap-0{gap:0}.gap-x-10{-moz-column-gap:2.5rem;column-gap:2.5rem}.gap-y-4{row-gap:1rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-y-1\\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.375rem*var(--tw-space-y-reverse));margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.overscroll-none{overscroll-behavior:none}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded-xl{border-radius:.75rem}.rounded-lg{border-radius:.5rem}.rounded-full{border-radius:9999px}.rounded-md{border-radius:.375rem}.rounded-2xl{border-radius:1rem}.rounded-\\[10px\\]{border-radius:10px}.rounded-\\[8px\\]{border-radius:8px}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-l{border-left-width:1px}.border-none{border-style:none}.border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity))}.border-slate-100{--tw-border-opacity:1;border-color:rgb(241 245 249/var(--tw-border-opacity))}.border-sky-blue-400\\/30{border-color:rgba(59,208,242,.3)}.border-mint-400\\/30{border-color:rgba(30,226,175,.3)}.border-gold-400\\/30{border-color:rgba(255,212,77,.3)}.border-transparent{border-color:transparent}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-transparent{background-color:transparent}.bg-dark-blue-400{--tw-bg-opacity:1;background-color:rgb(35 42 58/var(--tw-bg-opacity))}.bg-mint-400\\/20{background-color:rgba(30,226,175,.2)}.bg-gold-400\\/15{background-color:rgba(255,212,77,.15)}.bg-sky-blue-400\\/15{background-color:rgba(59,208,242,.15)}.bg-sky-blue-400\\/25{background-color:rgba(59,208,242,.25)}.bg-mint-400\\/15{background-color:rgba(30,226,175,.15)}.bg-mint-400\\/25{background-color:rgba(30,226,175,.25)}.bg-gold-400\\/25{background-color:rgba(255,212,77,.25)}.bg-slate-50{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.from-gold-400{--tw-gradient-from:#ffd44d;--tw-gradient-to:rgba(255,212,77,0);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-dark-blue-600{--tw-gradient-from:#0a0f2e;--tw-gradient-to:rgba(10,15,46,0);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-sky-blue-400\\/15{--tw-gradient-from:rgba(59,208,242,.15);--tw-gradient-to:rgba(59,208,242,0);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.via-dark-blue-400{--tw-gradient-to:rgba(35,42,58,0);--tw-gradient-stops:var(--tw-gradient-from),#232a3a,var(--tw-gradient-to)}.to-\\[\\#f5c300\\]{--tw-gradient-to:#f5c300}.to-sky-blue-400{--tw-gradient-to:#3bd0f2}.to-mint-400\\/15{--tw-gradient-to:rgba(30,226,175,.15)}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-8{padding:2rem}.p-4{padding:1rem}.p-2\\.5{padding:.625rem}.p-2{padding:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-8{padding-bottom:2rem;padding-top:2rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-4{padding-bottom:1rem;padding-top:1rem}.px-3\\.5{padding-left:.875rem;padding-right:.875rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-2\\.5{padding-bottom:.625rem;padding-top:.625rem}.py-3\\.5{padding-bottom:.875rem;padding-top:.875rem}.px-2\\.5{padding-left:.625rem;padding-right:.625rem}.py-1\\.5{padding-bottom:.375rem;padding-top:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.px-8{padding-left:2rem;padding-right:2rem}.py-6{padding-bottom:1.5rem;padding-top:1.5rem}.py-0\\.5{padding-bottom:.125rem;padding-top:.125rem}.py-0{padding-bottom:0;padding-top:0}.pl-2\\.5{padding-left:.625rem}.pl-2{padding-left:.5rem}.text-center{text-align:center}.font-proxima{font-family:ProximaNova}.text-2xl{font-size:1.5rem;line-height:2rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-\\[10px\\]{font-size:10px}.text-\\[10\\.5px\\]{font-size:10.5px}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\\[11px\\]{font-size:11px}.text-\\[11\\.5px\\]{font-size:11.5px}.font-extrabold{font-weight:800}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-black{font-weight:900}.uppercase{text-transform:uppercase}.leading-relaxed{line-height:1.625}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.text-dark-blue-400{--tw-text-opacity:1;color:rgb(35 42 58/var(--tw-text-opacity))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity))}.text-sky-blue-400{--tw-text-opacity:1;color:rgb(59 208 242/var(--tw-text-opacity))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-mint-400{--tw-text-opacity:1;color:rgb(30 226 175/var(--tw-text-opacity))}.text-slate-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity))}.text-white\\/70{color:hsla(0,0%,100%,.7)}.text-gold-400{--tw-text-opacity:1;color:rgb(255 212 77/var(--tw-text-opacity))}.underline{text-decoration-line:underline}.no-underline{text-decoration-line:none}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow-\\[0_3px_12px_rgba\\(255\\2c 212\\2c 77\\2c 0\\.35\\)\\],.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\\[0_3px_12px_rgba\\(255\\2c 212\\2c 77\\2c 0\\.35\\)\\]{--tw-shadow:0 3px 12px rgba(255,212,77,.35);--tw-shadow-colored:0 3px 12px var(--tw-shadow-color)}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-\\[0_2px_10px_rgba\\(30\\2c 226\\2c 175\\2c 0\\.15\\)\\]{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\\[0_2px_10px_rgba\\(30\\2c 226\\2c 175\\2c 0\\.15\\)\\]{--tw-shadow:0 2px 10px rgba(30,226,175,.15);--tw-shadow-colored:0 2px 10px var(--tw-shadow-color)}.outline-none{outline:2px solid transparent;outline-offset:2px}.outline{outline-style:solid}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-colors{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-transform{transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}*,:after,:before{border-style:solid;border-width:0}.placeholder\\:text-slate-400::-moz-placeholder{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity))}.placeholder\\:text-slate-400::placeholder{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity))}.hover\\:bg-slate-50:hover{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity))}.hover\\:bg-red-50:hover{--tw-bg-opacity:1;background-color:rgb(254 242 242/var(--tw-bg-opacity))}.hover\\:text-red-500:hover{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity))}.hover\\:text-slate-500:hover{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity))}.disabled\\:opacity-50:disabled{opacity:.5}";
45
+ styleInject(css_248z);
46
+
47
+ function UserButton({ image, name, email }) {
48
+ return /* @__PURE__ */ React.createElement("div", { className: "m-3 flex items-center gap-2.5 rounded-xl border border-mint-400/30 bg-gradient-to-r from-sky-blue-400/15 to-mint-400/15 p-2.5 shadow-[0_2px_10px_rgba(30,226,175,0.15)]" }, /* @__PURE__ */ React.createElement(
49
+ Avatar,
50
+ {
51
+ src: image,
52
+ radius: "xl",
53
+ size: 32,
54
+ styles: { placeholder: { color: "#232A3A", backgroundColor: "rgba(30,226,175,0.2)" } }
55
+ }
56
+ ), /* @__PURE__ */ React.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ React.createElement("div", { className: "truncate text-xs font-bold text-dark-blue-400" }, name), /* @__PURE__ */ React.createElement("div", { className: "truncate text-[10px] text-slate-500" }, email)));
58
57
  }
59
58
 
60
59
  const compact = (num) => {
@@ -64,217 +63,96 @@ const compact = (num) => {
64
63
  }).format(num || 0);
65
64
  };
66
65
 
67
- const useStyles$u = createStyles((theme, _params, getRef) => {
68
- const icon = getRef("icon");
69
- return {
70
- control: {
71
- fontWeight: 500,
72
- width: "100%",
73
- padding: `${theme.spacing.xs}px ${theme.spacing.md}px`,
74
- color: theme.colorScheme === "dark" ? theme.colors.dark[0] : theme.black,
75
- fontSize: theme.fontSizes.sm,
76
- "&:hover": {
77
- backgroundColor: theme.colorScheme === "dark" ? theme.colors.dark[7] : theme.colors.gray[0],
78
- color: theme.colorScheme === "dark" ? theme.white : theme.black
79
- }
80
- },
81
- controlButton: {
82
- cursor: "pointer"
83
- },
84
- badge: {
85
- pointerEvents: "none"
86
- },
87
- link: {
88
- fontWeight: 500,
89
- display: "block",
90
- textDecoration: "none",
91
- padding: `${theme.spacing.xs}px ${theme.spacing.md}px`,
92
- paddingLeft: 31,
93
- marginLeft: 30,
94
- fontSize: theme.fontSizes.sm,
95
- color: theme.colorScheme === "dark" ? theme.colors.dark[0] : theme.colors.gray[7],
96
- borderLeft: `1px solid ${theme.colorScheme === "dark" ? theme.colors.dark[4] : theme.colors.gray[3]}`,
97
- "&:hover": {
98
- backgroundColor: theme.colorScheme === "dark" ? theme.colors.dark[7] : theme.colors.gray[0],
99
- color: theme.colorScheme === "dark" ? theme.white : theme.black
100
- }
101
- },
102
- linkActive: {
103
- "&, &:hover": {
104
- backgroundColor: theme.fn.variant({ variant: "light", color: theme.primaryColor }).background,
105
- color: theme.fn.variant({ variant: "light", color: theme.primaryColor }).color,
106
- [`& .${icon}`]: {
107
- color: theme.fn.variant({ variant: "light", color: theme.primaryColor }).color
108
- }
109
- }
110
- },
111
- chevron: {
112
- transition: "transform 200ms ease"
113
- },
114
- linkIcon: {
115
- ref: icon
116
- }
117
- };
118
- });
119
- function LinksGroup({ icon: Icon, href, label, initiallyOpened, links, active, notifications }) {
120
- const { classes, theme, cx } = useStyles$u();
66
+ const ACCENT_CLASSNAMES = {
67
+ cyan: {
68
+ row: "bg-sky-blue-400/15 border-sky-blue-400/30",
69
+ chip: "bg-sky-blue-400/25",
70
+ icon: "text-sky-blue-400",
71
+ pill: "bg-sky-blue-400/15 text-dark-blue-400"
72
+ },
73
+ mint: {
74
+ row: "bg-mint-400/15 border-mint-400/30",
75
+ chip: "bg-mint-400/25",
76
+ icon: "text-mint-400",
77
+ pill: "bg-mint-400/15 text-dark-blue-400"
78
+ },
79
+ gold: {
80
+ row: "bg-gold-400/15 border-gold-400/30",
81
+ chip: "bg-gold-400/25",
82
+ icon: "text-gold-400",
83
+ pill: "bg-gold-400/15 text-dark-blue-400"
84
+ }
85
+ };
86
+ function LinksGroup({ icon: Icon, href, label, accent = "cyan", initiallyOpened, links, active, notifications }) {
121
87
  const hasLinks = Array.isArray(links) && links.length > 0;
122
88
  const hasActiveLinks = Array.isArray(links) && links.map((l) => !!active && active === `${label}/${l.label}`).reduce((a, b) => a || b, false);
123
89
  const [opened, setOpened] = useState(initiallyOpened || hasActiveLinks || false);
124
90
  React.useEffect(() => {
125
91
  setOpened(hasActiveLinks);
126
92
  }, [hasActiveLinks]);
127
- const ChevronIcon = theme.dir === "ltr" ? IconChevronRight : IconChevronLeft;
93
+ const isActive = !!active && !hasLinks && label === active;
94
+ const accentClasses = ACCENT_CLASSNAMES[accent];
128
95
  const items = (hasLinks ? links : []).map((link) => {
96
+ const linkActive = !!active && active === `${label}/${link.label}`;
129
97
  return /* @__PURE__ */ React.createElement(
130
- Box,
98
+ Link,
131
99
  {
132
- className: cx(classes.link, { [classes.linkActive]: !!active && active === `${label}/${link.label}` }),
133
- key: link.label
100
+ key: link.label,
101
+ to: link.href,
102
+ className: `flex items-center justify-between gap-2 rounded-[8px] border px-3 py-2 text-xs no-underline transition-colors ${linkActive ? `${accentClasses.row} font-bold text-dark-blue-400` : "border-transparent font-medium text-slate-500 hover:bg-slate-50"}`
134
103
  },
135
- /* @__PURE__ */ React.createElement(Group, { position: "apart", spacing: 0 }, /* @__PURE__ */ React.createElement(Text, { component: Link, to: link.href }, link.label), !!link.notifications && /* @__PURE__ */ React.createElement(Badge$1, { size: "sm", variant: "filled", className: classes.badge }, compact(link.notifications)))
104
+ link.label,
105
+ !!link.notifications && /* @__PURE__ */ React.createElement("span", { className: `rounded-full px-2 py-0.5 text-[10px] font-bold ${accentClasses.pill}` }, compact(link.notifications))
136
106
  );
137
107
  });
138
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
139
- Group,
108
+ const rowInner = /* @__PURE__ */ React.createElement("div", { className: "flex flex-1 items-center gap-2.5" }, /* @__PURE__ */ React.createElement("div", { className: `flex h-[30px] w-[30px] shrink-0 items-center justify-center rounded-lg ${isActive ? accentClasses.chip : "bg-slate-50"}` }, /* @__PURE__ */ React.createElement(Icon, { size: 14, stroke: isActive ? 2.2 : 1.75, className: isActive ? accentClasses.icon : "text-slate-400" })), /* @__PURE__ */ React.createElement("span", { className: `flex-1 text-xs ${isActive ? "font-bold text-dark-blue-400" : "font-medium text-slate-500"}` }, label));
109
+ return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(
110
+ "div",
140
111
  {
141
- className: cx(classes.control, {
142
- [classes.linkActive]: !!active && !hasLinks && label === active,
143
- [classes.controlButton]: hasLinks
144
- }),
145
- onClick: () => setOpened((o) => !o),
146
- position: "apart",
147
- spacing: 0
112
+ onClick: () => hasLinks && setOpened((o) => !o),
113
+ className: `flex items-center gap-2.5 rounded-[10px] border px-3.5 py-2.5 transition-colors ${isActive ? accentClasses.row : "border-transparent hover:bg-slate-50"} ${hasLinks ? "cursor-pointer" : ""}`
148
114
  },
149
- /* @__PURE__ */ React.createElement(Box, { sx: { display: "flex", alignItems: "center" } }, /* @__PURE__ */ React.createElement(ThemeIcon, { variant: "light", size: 30 }, /* @__PURE__ */ React.createElement(Icon, { className: classes.linkIcon, size: 18 })), /* @__PURE__ */ React.createElement(Box, { ml: "md" }, /* @__PURE__ */ React.createElement(Text, { component: Link, to: href }, label))),
150
- !!notifications && /* @__PURE__ */ React.createElement(Badge$1, { size: "sm", variant: "filled", className: classes.badge }, compact(notifications)),
115
+ hasLinks ? rowInner : /* @__PURE__ */ React.createElement(Link, { to: href, className: "flex flex-1 items-center gap-2.5 no-underline" }, rowInner),
116
+ !!notifications && /* @__PURE__ */ React.createElement("span", { className: `rounded-full px-2 py-0.5 text-[10px] font-bold ${accentClasses.pill}` }, compact(notifications)),
151
117
  hasLinks && /* @__PURE__ */ React.createElement(
152
- ChevronIcon,
118
+ IconChevronRight,
153
119
  {
154
- className: classes.chevron,
155
- size: 14,
156
- stroke: 1.5,
157
- style: {
158
- transform: opened ? `rotate(${theme.dir === "rtl" ? -90 : 90}deg)` : "none"
159
- }
120
+ size: 13,
121
+ stroke: 2.2,
122
+ className: `shrink-0 text-slate-300 transition-transform ${opened ? "rotate-90" : ""}`
160
123
  }
161
124
  )
162
- ), hasLinks ? /* @__PURE__ */ React.createElement(Collapse, { in: opened }, items) : null);
125
+ ), hasLinks && opened && /* @__PURE__ */ React.createElement("div", { className: "ml-[29px] mt-0.5 flex flex-col gap-0.5 border-l border-slate-100 pl-2.5" }, items));
163
126
  }
164
127
 
165
- var __defProp$e = Object.defineProperty;
166
- var __defProps$a = Object.defineProperties;
167
- var __getOwnPropDescs$a = Object.getOwnPropertyDescriptors;
168
- var __getOwnPropSymbols$e = Object.getOwnPropertySymbols;
169
- var __hasOwnProp$e = Object.prototype.hasOwnProperty;
170
- var __propIsEnum$e = Object.prototype.propertyIsEnumerable;
171
- var __defNormalProp$e = (obj, key, value) => key in obj ? __defProp$e(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
172
- var __spreadValues$e = (a, b) => {
128
+ var __defProp$d = Object.defineProperty;
129
+ var __defProps$9 = Object.defineProperties;
130
+ var __getOwnPropDescs$9 = Object.getOwnPropertyDescriptors;
131
+ var __getOwnPropSymbols$d = Object.getOwnPropertySymbols;
132
+ var __hasOwnProp$d = Object.prototype.hasOwnProperty;
133
+ var __propIsEnum$d = Object.prototype.propertyIsEnumerable;
134
+ var __defNormalProp$d = (obj, key, value) => key in obj ? __defProp$d(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
135
+ var __spreadValues$d = (a, b) => {
173
136
  for (var prop in b || (b = {}))
174
- if (__hasOwnProp$e.call(b, prop))
175
- __defNormalProp$e(a, prop, b[prop]);
176
- if (__getOwnPropSymbols$e)
177
- for (var prop of __getOwnPropSymbols$e(b)) {
178
- if (__propIsEnum$e.call(b, prop))
179
- __defNormalProp$e(a, prop, b[prop]);
137
+ if (__hasOwnProp$d.call(b, prop))
138
+ __defNormalProp$d(a, prop, b[prop]);
139
+ if (__getOwnPropSymbols$d)
140
+ for (var prop of __getOwnPropSymbols$d(b)) {
141
+ if (__propIsEnum$d.call(b, prop))
142
+ __defNormalProp$d(a, prop, b[prop]);
180
143
  }
181
144
  return a;
182
145
  };
183
- var __spreadProps$a = (a, b) => __defProps$a(a, __getOwnPropDescs$a(b));
184
- const useStyles$t = createStyles((theme, _params, getRef) => {
185
- const icon = getRef("icon");
186
- return {
187
- navbar: {
188
- backgroundColor: theme.colorScheme === "dark" ? theme.colors.dark[6] : theme.white
189
- },
190
- navHeader: {
191
- [`@media (max-width: ${theme.breakpoints.sm}px)`]: {
192
- height: 71,
193
- position: "absolute",
194
- top: 0
195
- }
196
- },
197
- navBody: {
198
- [`@media (max-width: ${theme.breakpoints.sm}px)`]: {
199
- display: "none"
200
- }
201
- },
202
- burger: {
203
- [theme.fn.largerThan("sm")]: {
204
- display: "none"
205
- }
206
- },
207
- header: {
208
- padding: theme.spacing.md,
209
- paddingTop: 0,
210
- marginLeft: -theme.spacing.md,
211
- marginRight: -theme.spacing.md,
212
- color: theme.colorScheme === "dark" ? theme.white : theme.black,
213
- borderBottom: `1px solid ${theme.colorScheme === "dark" ? theme.colors.dark[4] : theme.colors.gray[3]}`
214
- },
215
- link: __spreadProps$a(__spreadValues$e({}, theme.fn.focusStyles()), {
216
- display: "flex",
217
- alignItems: "center",
218
- textDecoration: "none",
219
- fontSize: theme.fontSizes.sm,
220
- color: theme.colorScheme === "dark" ? theme.colors.dark[1] : theme.colors.gray[7],
221
- padding: `${theme.spacing.xs}px ${theme.spacing.sm}px`,
222
- borderRadius: theme.radius.sm,
223
- fontWeight: 500,
224
- "&:hover": {
225
- backgroundColor: theme.colorScheme === "dark" ? theme.colors.dark[6] : theme.colors.gray[0],
226
- color: theme.colorScheme === "dark" ? theme.white : theme.black,
227
- [`& .${icon}`]: {
228
- color: theme.colorScheme === "dark" ? theme.white : theme.black
229
- }
230
- }
231
- }),
232
- linkIcon: {
233
- ref: icon,
234
- color: theme.colorScheme === "dark" ? theme.colors.dark[2] : theme.colors.gray[6],
235
- marginRight: theme.spacing.sm
236
- },
237
- links: {
238
- marginLeft: -theme.spacing.md,
239
- marginRight: -theme.spacing.md
240
- },
241
- user: {
242
- margin: theme.spacing.md,
243
- marginLeft: 0,
244
- marginRight: 0
245
- },
246
- linksInner: {
247
- paddingBottom: theme.spacing.xl
248
- },
249
- footer: {
250
- paddingTop: theme.spacing.md,
251
- paddingBottom: theme.spacing.md,
252
- borderTop: `1px solid ${theme.colorScheme === "dark" ? theme.colors.dark[4] : theme.colors.gray[2]}`
253
- },
254
- active: {
255
- "&, &:hover": {
256
- backgroundColor: theme.fn.variant({ variant: "light", color: theme.primaryColor }).background,
257
- color: theme.fn.variant({ variant: "light", color: theme.primaryColor }).color
258
- }
259
- }
260
- };
261
- });
146
+ var __spreadProps$9 = (a, b) => __defProps$9(a, __getOwnPropDescs$9(b));
262
147
  const data = [
263
- { label: "Home", icon: IconHome2 },
264
- { label: "Dashboard", icon: IconGauge },
265
- { label: "Classes", icon: IconCategory2 },
266
- { label: "Pathways", icon: IconRoute },
267
- { label: "Badges", icon: IconAlbum },
268
- { label: "Lessons", icon: IconLambda },
269
- { label: "File Locker", icon: IconClipboard },
270
- {
271
- label: "Organization",
272
- icon: IconBuilding,
273
- links: [
274
- { label: "Overview" },
275
- { label: "People" }
276
- ]
277
- }
148
+ { label: "Home", icon: IconHome2, accent: "cyan" },
149
+ { label: "Dashboard", icon: IconGauge, accent: "mint" },
150
+ { label: "Classes", icon: IconCategory2, accent: "gold" },
151
+ { label: "Pathways", icon: IconRoute, accent: "cyan" },
152
+ { label: "Badges", icon: IconAlbum, accent: "mint" },
153
+ { label: "Lessons", icon: IconLambda, accent: "gold" },
154
+ { label: "File Locker", icon: IconClipboard, accent: "cyan" },
155
+ { label: "Organization", icon: IconBuilding, accent: "gold", links: [{ label: "Overview" }, { label: "People" }] }
278
156
  ];
279
157
  const TRIAL_PAGES = [
280
158
  "Home",
@@ -282,9 +160,6 @@ const TRIAL_PAGES = [
282
160
  "Badges"
283
161
  ];
284
162
  function Navbar(props) {
285
- const { classes, cx } = useStyles$t();
286
- const [burgerOpen, setBurgerOpen] = React.useState(false);
287
- const toggle = () => setBurgerOpen(!burgerOpen);
288
163
  const links = data.map((item) => {
289
164
  const context = props.links[item.label] || { notifications: 0, href: "" };
290
165
  if (context.hidden || props.trial && TRIAL_PAGES.indexOf(item.label) === -1) {
@@ -295,37 +170,32 @@ function Navbar(props) {
295
170
  }
296
171
  return /* @__PURE__ */ React.createElement(
297
172
  LinksGroup,
298
- __spreadProps$a(__spreadValues$e(__spreadValues$e({
173
+ __spreadProps$9(__spreadValues$d(__spreadValues$d({
299
174
  key: item.label,
300
175
  active: props.active
301
176
  }, item), context), {
302
177
  links: (item.links || []).map((link) => {
303
- return __spreadValues$e(__spreadValues$e({}, link), props.links[`${item.label}/${link.label}`] || { notifications: 0, href: "" });
178
+ return __spreadValues$d(__spreadValues$d({}, link), props.links[`${item.label}/${link.label}`] || { notifications: 0, href: "" });
304
179
  })
305
180
  })
306
181
  );
307
182
  });
308
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Navbar$1, { width: { sm: 300 }, p: "md", className: cx(classes.navbar, { [classes.navHeader]: !burgerOpen }) }, /* @__PURE__ */ React.createElement(Navbar$1.Section, { className: classes.header }, /* @__PURE__ */ React.createElement(Group, { position: "apart" }, /* @__PURE__ */ React.createElement(Center, null, /* @__PURE__ */ React.createElement(Avatar, { color: "blue", radius: "sm" }, /* @__PURE__ */ React.createElement("div", { style: { width: 15, marginLeft: "auto", marginRight: "auto" } }, /* @__PURE__ */ React.createElement(Image, { fit: "contain", src: "https://cdn.localcivics.io/brand/l.png" })))), /* @__PURE__ */ React.createElement(Group, { position: "apart" }, /* @__PURE__ */ React.createElement(Code, { sx: { fontWeight: 700 } }, props.version), !!props.trial && /* @__PURE__ */ React.createElement(Badge$1, { color: "violet", radius: "xs" }, "Trial"), /* @__PURE__ */ React.createElement(Burger, { opened: burgerOpen, onClick: toggle, className: classes.burger, size: "sm" })))), /* @__PURE__ */ React.createElement("div", { className: cx({ [classes.navBody]: !burgerOpen }) }, !props.loading && /* @__PURE__ */ React.createElement(
309
- UserButton,
310
- {
311
- className: classes.user,
312
- image: props.image,
313
- name: props.name,
314
- email: props.email
315
- }
316
- ), /* @__PURE__ */ React.createElement(Navbar$1.Section, { grow: true, className: classes.links, component: ScrollArea }, /* @__PURE__ */ React.createElement("div", { className: classes.linksInner }, links)), !props.loading && /* @__PURE__ */ React.createElement(Navbar$1.Section, { className: classes.footer }, props.trial && /* @__PURE__ */ React.createElement("a", { href: "#", className: classes.link, onClick: (event) => {
317
- event.preventDefault();
318
- props.onGettingStarted();
319
- } }, /* @__PURE__ */ React.createElement(IconVideo, { className: classes.linkIcon, stroke: 1.5 }), /* @__PURE__ */ React.createElement("span", null, "Getting started")), !!props.onSwitchAccounts && /* @__PURE__ */ React.createElement("a", { href: "#", className: classes.link, onClick: (event) => {
320
- event.preventDefault();
321
- props.onSwitchAccounts && props.onSwitchAccounts();
322
- } }, /* @__PURE__ */ React.createElement(IconSwitchHorizontal, { className: classes.linkIcon, stroke: 1.5 }), /* @__PURE__ */ React.createElement("span", null, "Change account")), /* @__PURE__ */ React.createElement("a", { href: "#", className: classes.link, onClick: (event) => {
323
- event.preventDefault();
324
- props.onLogout();
325
- } }, /* @__PURE__ */ React.createElement(IconLogout, { className: classes.linkIcon, stroke: 1.5 }), /* @__PURE__ */ React.createElement("span", null, "Logout"))))));
183
+ return /* @__PURE__ */ React.createElement("nav", { className: "flex h-full w-[230px] shrink-0 flex-col border-r border-slate-200 bg-white" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-between border-b border-slate-100 p-4" }, /* @__PURE__ */ React.createElement("div", { className: "w-24" }, /* @__PURE__ */ React.createElement("img", { className: "w-full object-contain", src: "https://cdn.localcivics.io/brand/localcivics.png", alt: "Logo" })), !!props.trial && /* @__PURE__ */ React.createElement("span", { className: "rounded-full bg-gold-400/15 px-2.5 py-1 text-[10px] font-bold text-dark-blue-400" }, "Trial")), !props.loading && /* @__PURE__ */ React.createElement(UserButton, { image: props.image, name: props.name, email: props.email }), /* @__PURE__ */ React.createElement("div", { className: "flex flex-1 flex-col gap-0.5 overflow-y-auto p-2.5" }, links), !props.loading && /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-0.5 border-t border-slate-200 p-2.5" }, props.trial && /* @__PURE__ */ React.createElement(UtilLink, { label: "Getting started", icon: IconVideo, onClick: props.onGettingStarted }), !!props.onSwitchAccounts && /* @__PURE__ */ React.createElement(UtilLink, { label: "Change account", icon: IconSwitchHorizontal, onClick: props.onSwitchAccounts }), /* @__PURE__ */ React.createElement(UtilLink, { label: "Logout", icon: IconLogout, onClick: props.onLogout })));
326
184
  }
185
+ const UtilLink = (props) => {
186
+ const Icon = props.icon;
187
+ return /* @__PURE__ */ React.createElement(
188
+ "div",
189
+ {
190
+ onClick: props.onClick,
191
+ className: "flex cursor-pointer items-center gap-2.5 rounded-[10px] px-3.5 py-2 text-slate-400 hover:bg-slate-50 hover:text-slate-500"
192
+ },
193
+ /* @__PURE__ */ React.createElement(Icon, { size: 13, stroke: 1.75 }),
194
+ /* @__PURE__ */ React.createElement("span", { className: "text-[11.5px]" }, props.label)
195
+ );
196
+ };
327
197
 
328
- const useStyles$s = createStyles((theme) => ({
198
+ const useStyles$o = createStyles((theme) => ({
329
199
  inner: {
330
200
  paddingTop: theme.spacing.xl,
331
201
  paddingBottom: theme.spacing.xl * 4
@@ -361,7 +231,7 @@ const useStyles$s = createStyles((theme) => ({
361
231
  }
362
232
  }));
363
233
  const GettingStarted = (props) => {
364
- const { classes } = useStyles$s();
234
+ const { classes } = useStyles$o();
365
235
  return /* @__PURE__ */ React.createElement(
366
236
  Modal,
367
237
  {
@@ -375,7 +245,7 @@ const GettingStarted = (props) => {
375
245
  );
376
246
  };
377
247
 
378
- const useStyles$r = createStyles((theme) => ({
248
+ const useStyles$n = createStyles((theme) => ({
379
249
  title: {
380
250
  fontSize: 34,
381
251
  fontWeight: 900,
@@ -416,7 +286,7 @@ const useStyles$r = createStyles((theme) => ({
416
286
  }
417
287
  }));
418
288
  const SwitchAccount = (props) => {
419
- const { classes, theme } = useStyles$r();
289
+ const { classes, theme } = useStyles$n();
420
290
  const options = props.accounts.map((a) => {
421
291
  return /* @__PURE__ */ React.createElement(UnstyledButton, { onClick: () => props.onClick && props.onClick(a.accountId), key: a.accountId, p: theme.spacing.md }, /* @__PURE__ */ React.createElement(Card, { withBorder: true, shadow: "md", radius: "md", className: classes.card, p: "xl" }, a.isAdmin && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(IconBatteryEco, { size: 50, stroke: 2, color: theme.fn.primaryColor() })), a.isGroupAdmin && !a.isAdmin && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(IconBooks, { size: 50, stroke: 2, color: theme.fn.primaryColor() })), !a.isAdmin && !a.isGroupAdmin && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(IconBackpack, { size: 50, stroke: 2, color: theme.fn.primaryColor() })), /* @__PURE__ */ React.createElement(Text, { size: "lg", weight: 500, className: classes.cardTitle, mt: "md" }, a.name), /* @__PURE__ */ React.createElement(Text, { size: "sm", color: "dimmed", mt: "sm" }, a.isAdmin ? "Admin" : a.isGroupAdmin ? "Educator" : "Student")));
422
292
  });
@@ -433,51 +303,7 @@ const SwitchAccount = (props) => {
433
303
  );
434
304
  };
435
305
 
436
- const useStyles$q = createStyles((theme) => ({
437
- root: {
438
- display: "flex",
439
- backgroundImage: `linear-gradient(-60deg, ${theme.colors[theme.primaryColor][4]} 0%, ${theme.colors[theme.primaryColor][7]} 100%)`,
440
- padding: theme.spacing.xl * 1.5,
441
- borderRadius: theme.radius.md
442
- },
443
- title: {
444
- color: theme.white,
445
- textTransform: "uppercase",
446
- fontWeight: 700,
447
- fontSize: theme.fontSizes.sm
448
- },
449
- count: {
450
- color: theme.white,
451
- fontSize: 32,
452
- lineHeight: 1,
453
- fontWeight: 700,
454
- marginBottom: theme.spacing.md,
455
- fontFamily: `Greycliff CF, ${theme.fontFamily}`
456
- },
457
- description: {
458
- color: theme.colors[theme.primaryColor][0],
459
- fontSize: theme.fontSizes.sm,
460
- marginTop: 5
461
- },
462
- stat: {
463
- flex: 1,
464
- "& + &": {
465
- paddingLeft: theme.spacing.xl,
466
- marginLeft: theme.spacing.xl,
467
- borderLeft: `1px solid ${theme.colors[theme.primaryColor][3]}`,
468
- [theme.fn.smallerThan("sm")]: {
469
- paddingLeft: 0,
470
- marginLeft: 0,
471
- borderLeft: 0,
472
- paddingTop: theme.spacing.xl,
473
- marginTop: theme.spacing.xl,
474
- borderTop: `1px solid ${theme.colors[theme.primaryColor][3]}`
475
- }
476
- }
477
- }
478
- }));
479
306
  const StatsGroup = ({ data, footer }) => {
480
- const { classes } = useStyles$q();
481
307
  const stats = data.map((stat) => {
482
308
  const value = (() => {
483
309
  if (stat.unit === "%") {
@@ -486,9 +312,9 @@ const StatsGroup = ({ data, footer }) => {
486
312
  return stat.value;
487
313
  })();
488
314
  const safeValue = Number.isFinite(value) ? value : 0;
489
- return /* @__PURE__ */ React.createElement("div", { key: stat.title, className: classes.stat }, /* @__PURE__ */ React.createElement(Text, { className: classes.count }, safeValue.toLocaleString(), stat.unit), /* @__PURE__ */ React.createElement(Text, { className: classes.title }, stat.title));
315
+ return /* @__PURE__ */ React.createElement("div", { key: stat.title }, /* @__PURE__ */ React.createElement("div", { className: "text-3xl font-black text-white" }, safeValue.toLocaleString(), stat.unit), /* @__PURE__ */ React.createElement("div", { className: "mt-1.5 text-[11px] font-bold uppercase tracking-wide text-white/70" }, stat.title));
490
316
  });
491
- return /* @__PURE__ */ React.createElement("div", { className: classes.root }, stats, footer);
317
+ return /* @__PURE__ */ React.createElement("div", { className: "flex flex-wrap gap-x-10 gap-y-4 rounded-2xl bg-gradient-to-br from-dark-blue-600 via-dark-blue-400 to-sky-blue-400 px-8 py-6" }, stats, footer);
492
318
  };
493
319
 
494
320
  const Tabs = (props) => {
@@ -497,7 +323,7 @@ const Tabs = (props) => {
497
323
  return /* @__PURE__ */ React.createElement(Tabs$1, { value: props.value, onTabChange: props.onChange }, /* @__PURE__ */ React.createElement(Tabs$1.List, null, tabs));
498
324
  };
499
325
 
500
- const useStyles$p = createStyles((theme) => ({
326
+ const useStyles$m = createStyles((theme) => ({
501
327
  button: {
502
328
  borderTopRightRadius: 0,
503
329
  borderBottomRightRadius: 0,
@@ -511,8 +337,8 @@ const useStyles$p = createStyles((theme) => ({
511
337
  borderLeft: `1px solid ${theme.colorScheme === "dark" ? theme.colors.dark[7] : theme.white}`
512
338
  }
513
339
  }));
514
- const SplitButton$5 = (props) => {
515
- const { classes, theme } = useStyles$p();
340
+ const SplitButton$4 = (props) => {
341
+ const { classes, theme } = useStyles$m();
516
342
  theme.colors[theme.primaryColor][theme.colorScheme === "dark" ? 5 : 6];
517
343
  return /* @__PURE__ */ React.createElement(Stack$5, { spacing: "sm" }, /* @__PURE__ */ React.createElement(
518
344
  Button,
@@ -540,7 +366,7 @@ const SplitButton$5 = (props) => {
540
366
  ));
541
367
  };
542
368
 
543
- const useStyles$o = createStyles((theme) => ({
369
+ const useStyles$l = createStyles((theme) => ({
544
370
  wrapper: {
545
371
  display: "flex",
546
372
  alignItems: "center",
@@ -591,7 +417,7 @@ const useStyles$o = createStyles((theme) => ({
591
417
  }
592
418
  }));
593
419
  const PlaceholderBanner = (props) => {
594
- const { classes } = useStyles$o();
420
+ const { classes } = useStyles$l();
595
421
  const title = props.title || "Nothing to display";
596
422
  const description = props.description || "We don't have anything to show you here just yet. Add data, check back later, or adjust your search.";
597
423
  return /* @__PURE__ */ React.createElement("div", { className: classes.wrapper }, /* @__PURE__ */ React.createElement("div", { className: classes.body }, /* @__PURE__ */ React.createElement(Title, { className: classes.title }, props.loading ? "Loading..." : title), /* @__PURE__ */ React.createElement(Text, { size: "sm", color: "dimmed" }, props.loading ? "Hold on, we're loading your data." : description)), /* @__PURE__ */ React.createElement(Image, { src: `https://cdn.localcivics.io/illustrations/${props.icon}.svg`, className: classes.image }));
@@ -643,28 +469,28 @@ function useSortableData(items, config = { key: "", direction: null }) {
643
469
  return { items: sortedItems, requestSort, sortConfig };
644
470
  }
645
471
 
646
- var __defProp$d = Object.defineProperty;
647
- var __defProps$9 = Object.defineProperties;
648
- var __getOwnPropDescs$9 = Object.getOwnPropertyDescriptors;
649
- var __getOwnPropSymbols$d = Object.getOwnPropertySymbols;
650
- var __hasOwnProp$d = Object.prototype.hasOwnProperty;
651
- var __propIsEnum$d = Object.prototype.propertyIsEnumerable;
652
- var __defNormalProp$d = (obj, key, value) => key in obj ? __defProp$d(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
653
- var __spreadValues$d = (a, b) => {
472
+ var __defProp$c = Object.defineProperty;
473
+ var __defProps$8 = Object.defineProperties;
474
+ var __getOwnPropDescs$8 = Object.getOwnPropertyDescriptors;
475
+ var __getOwnPropSymbols$c = Object.getOwnPropertySymbols;
476
+ var __hasOwnProp$c = Object.prototype.hasOwnProperty;
477
+ var __propIsEnum$c = Object.prototype.propertyIsEnumerable;
478
+ var __defNormalProp$c = (obj, key, value) => key in obj ? __defProp$c(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
479
+ var __spreadValues$c = (a, b) => {
654
480
  for (var prop in b || (b = {}))
655
- if (__hasOwnProp$d.call(b, prop))
656
- __defNormalProp$d(a, prop, b[prop]);
657
- if (__getOwnPropSymbols$d)
658
- for (var prop of __getOwnPropSymbols$d(b)) {
659
- if (__propIsEnum$d.call(b, prop))
660
- __defNormalProp$d(a, prop, b[prop]);
481
+ if (__hasOwnProp$c.call(b, prop))
482
+ __defNormalProp$c(a, prop, b[prop]);
483
+ if (__getOwnPropSymbols$c)
484
+ for (var prop of __getOwnPropSymbols$c(b)) {
485
+ if (__propIsEnum$c.call(b, prop))
486
+ __defNormalProp$c(a, prop, b[prop]);
661
487
  }
662
488
  return a;
663
489
  };
664
- var __spreadProps$9 = (a, b) => __defProps$9(a, __getOwnPropDescs$9(b));
490
+ var __spreadProps$8 = (a, b) => __defProps$8(a, __getOwnPropDescs$8(b));
665
491
  function Table$k(props) {
666
492
  const preparedItems = React.useMemo(() => {
667
- return props.items.map((item) => __spreadProps$9(__spreadValues$d({}, item), {
493
+ return props.items.map((item) => __spreadProps$8(__spreadValues$c({}, item), {
668
494
  status: item.isComplete ? 1 : 0
669
495
  }));
670
496
  }, [props.items]);
@@ -761,7 +587,7 @@ function Table$j(props) {
761
587
  ));
762
588
  }
763
589
 
764
- const useStyles$n = createStyles((theme) => ({
590
+ const useStyles$k = createStyles((theme) => ({
765
591
  title: {
766
592
  fontSize: 34,
767
593
  fontWeight: 900,
@@ -774,7 +600,7 @@ const useStyles$n = createStyles((theme) => ({
774
600
  }
775
601
  }));
776
602
  const Badge = (props) => {
777
- const { classes } = useStyles$n();
603
+ const { classes } = useStyles$k();
778
604
  const [tab, setTab] = useState("lessons");
779
605
  const numberOfStudents = props.students.length;
780
606
  const numberOfBadges = numberOfStudents > 0 ? props.students.filter((u) => u.isComplete).length : 0;
@@ -788,7 +614,7 @@ const Badge = (props) => {
788
614
  },
789
615
  "Back"
790
616
  )), /* @__PURE__ */ React.createElement(Group, null, /* @__PURE__ */ React.createElement(Stack$5, { spacing: 0 }, /* @__PURE__ */ React.createElement(Title, { order: 2, className: classes.title, mt: "md" }, props.displayName || "Badge"), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", className: classes.description, mt: "sm" }, props.description || "No description")), !props.trial && /* @__PURE__ */ React.createElement(Stack$5, { ml: "auto" }, /* @__PURE__ */ React.createElement(
791
- SplitButton$5,
617
+ SplitButton$4,
792
618
  {
793
619
  href: props.href,
794
620
  onCopyLinkClick: props.onCopyLinkClick,
@@ -841,65 +667,34 @@ const Badge = (props) => {
841
667
  };
842
668
 
843
669
  function Table$i(props) {
670
+ if (props.loading) {
671
+ return /* @__PURE__ */ React.createElement("div", { className: "text-sm text-slate-400" }, "Loading\u2026");
672
+ }
844
673
  if (props.items.length === 0) {
845
- return /* @__PURE__ */ React.createElement(
846
- PlaceholderBanner,
847
- {
848
- title: "No badges to display",
849
- description: "We don't have any badges to show you just yet.",
850
- loading: props.loading,
851
- icon: "badges"
852
- }
853
- );
674
+ return /* @__PURE__ */ React.createElement("div", { className: "rounded-xl border border-slate-200 bg-white p-8 text-center text-sm text-slate-400 shadow-sm" }, "No badges to display.");
854
675
  }
855
- const rows = props.items.map((row) => /* @__PURE__ */ React.createElement("tr", { key: row.badgeId }, /* @__PURE__ */ React.createElement("td", null, /* @__PURE__ */ React.createElement(
856
- UnstyledButton,
676
+ return /* @__PURE__ */ React.createElement("div", { className: "overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm" }, props.items.map((row, i) => /* @__PURE__ */ React.createElement(
677
+ Link,
857
678
  {
858
- component: Link,
679
+ key: row.badgeId,
859
680
  to: row.href,
860
- sx: (theme) => ({
861
- display: "block",
862
- width: "100%",
863
- padding: theme.spacing.md,
864
- color: theme.colorScheme === "dark" ? theme.colors.dark[0] : theme.black,
865
- "&:hover": {
866
- backgroundColor: theme.colorScheme === "dark" ? theme.colors.dark[8] : theme.colors.gray[1]
867
- }
868
- })
681
+ className: `block px-5 py-4 no-underline hover:bg-slate-50 ${i < props.items.length - 1 ? "border-b border-slate-100" : ""}`
869
682
  },
870
- /* @__PURE__ */ React.createElement(Group, null, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Text, { size: "sm", weight: 500 }, row.name), /* @__PURE__ */ React.createElement(Text, { size: "xs", color: "dimmed" }, row.description)))
871
- ))));
872
- return /* @__PURE__ */ React.createElement(ScrollArea.Autosize, { maxHeight: 600 }, /* @__PURE__ */ React.createElement(Table$l, { horizontalSpacing: 0, verticalSpacing: 0, sx: { minWidth: 700 } }, /* @__PURE__ */ React.createElement("tbody", null, rows)));
683
+ /* @__PURE__ */ React.createElement("div", { className: "text-sm font-bold text-dark-blue-400" }, row.name),
684
+ row.description && /* @__PURE__ */ React.createElement("div", { className: "mt-1 text-xs leading-relaxed text-slate-500" }, row.description)
685
+ )));
873
686
  }
874
687
 
875
- const useStyles$m = createStyles((theme) => ({
876
- title: {
877
- fontSize: 34,
878
- fontWeight: 900,
879
- [theme.fn.smallerThan("sm")]: {
880
- fontSize: 24
881
- }
882
- },
883
- description: {
884
- maxWidth: 600
885
- }
886
- }));
887
688
  const Badges = (props) => {
888
- const { classes } = useStyles$m();
889
- return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$5, { spacing: "md" }, /* @__PURE__ */ React.createElement(Grid, null, /* @__PURE__ */ React.createElement(Grid.Col, { sm: "auto" }, /* @__PURE__ */ React.createElement(Badge$1, { variant: "filled", size: "lg" }, "Badges"), /* @__PURE__ */ React.createElement(Title, { order: 2, className: classes.title, mt: "md" }, "Badges and micro-credentials"), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", className: classes.description, mt: "sm" }, "Key milestones that reflect skill development, micro-credentials, or academic progress"))), /* @__PURE__ */ React.createElement(
890
- Autocomplete,
689
+ return /* @__PURE__ */ React.createElement("div", { className: "mx-auto flex max-w-4xl flex-col gap-5 px-4 py-8" }, /* @__PURE__ */ React.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ React.createElement("h1", { className: "text-2xl font-extrabold tracking-tight text-dark-blue-400" }, "Badges and micro-credentials"), /* @__PURE__ */ React.createElement("p", { className: "text-sm text-slate-500" }, "Project-sized skills acquisition and standards alignment.")), /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2.5 rounded-xl border border-slate-200 bg-white px-4 py-3 shadow-sm" }, /* @__PURE__ */ React.createElement(IconSearch, { size: 15, stroke: 1.75, className: "text-slate-400" }), /* @__PURE__ */ React.createElement(
690
+ "input",
891
691
  {
692
+ type: "text",
892
693
  placeholder: "Search for a badge that fits your needs",
893
- data: props.badges.map((item) => item.name),
894
- onChange: props.onAutocompleteChange
895
- }
896
- ), /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(LoadingOverlay, { visible: props.loading, overlayBlur: 2 }), /* @__PURE__ */ React.createElement(
897
- Table$i,
898
- {
899
- loading: props.loading,
900
- items: props.badges
694
+ onChange: (e) => props.onAutocompleteChange(e.target.value),
695
+ className: "flex-1 border-none bg-transparent text-sm text-dark-blue-400 outline-none placeholder:text-slate-400"
901
696
  }
902
- ))));
697
+ )), /* @__PURE__ */ React.createElement(Table$i, { loading: props.loading, items: props.badges }));
903
698
  };
904
699
 
905
700
  function Table$h(props) {
@@ -1090,142 +885,57 @@ const Dashboard = (props) => {
1090
885
  )))))));
1091
886
  };
1092
887
 
1093
- const SplitButton$4 = (props) => {
1094
- return /* @__PURE__ */ React.createElement(Stack$5, { spacing: "sm" }, /* @__PURE__ */ React.createElement(
1095
- Button,
1096
- {
1097
- leftIcon: /* @__PURE__ */ React.createElement(IconPlaylistAdd, { size: 14 }),
1098
- onClick: props.onAddMembersClick
1099
- },
1100
- "Add students"
1101
- ), /* @__PURE__ */ React.createElement(
1102
- Button,
1103
- {
1104
- leftIcon: /* @__PURE__ */ React.createElement(IconClipboardCopy, { size: 14 }),
1105
- onClick: props.onCopyClassLinkClick
1106
- },
1107
- "Copy link"
1108
- ), /* @__PURE__ */ React.createElement(
1109
- Button,
1110
- {
1111
- leftIcon: /* @__PURE__ */ React.createElement(IconTableExport, { size: 14 }),
1112
- onClick: props.onExportDataClick
1113
- },
1114
- "Export data (.csv)"
1115
- ));
1116
- };
1117
-
1118
- var __defProp$c = Object.defineProperty;
1119
- var __defProps$8 = Object.defineProperties;
1120
- var __getOwnPropDescs$8 = Object.getOwnPropertyDescriptors;
1121
- var __getOwnPropSymbols$c = Object.getOwnPropertySymbols;
1122
- var __hasOwnProp$c = Object.prototype.hasOwnProperty;
1123
- var __propIsEnum$c = Object.prototype.propertyIsEnumerable;
1124
- var __defNormalProp$c = (obj, key, value) => key in obj ? __defProp$c(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1125
- var __spreadValues$c = (a, b) => {
1126
- for (var prop in b || (b = {}))
1127
- if (__hasOwnProp$c.call(b, prop))
1128
- __defNormalProp$c(a, prop, b[prop]);
1129
- if (__getOwnPropSymbols$c)
1130
- for (var prop of __getOwnPropSymbols$c(b)) {
1131
- if (__propIsEnum$c.call(b, prop))
1132
- __defNormalProp$c(a, prop, b[prop]);
1133
- }
1134
- return a;
1135
- };
1136
- var __spreadProps$8 = (a, b) => __defProps$8(a, __getOwnPropDescs$8(b));
888
+ const openDeleteModal = (student, onDelete) => openConfirmModal({
889
+ title: `Remove "${student.givenName && student.familyName ? `${student.givenName} ${student.familyName}` : student.email}" from this class?`,
890
+ centered: true,
891
+ children: /* @__PURE__ */ React.createElement(Text, { size: "sm" }, "Click confirm if you want to remove the student from this specific class. This will NOT remove the student from the Tech Platform."),
892
+ labels: { confirm: "Remove Student", cancel: "Cancel" },
893
+ confirmProps: { color: "red" },
894
+ onConfirm: () => onDelete(student)
895
+ });
1137
896
  function Table$c(props) {
1138
- const preparedItems = React.useMemo(() => {
1139
- return props.items.map((item) => __spreadProps$8(__spreadValues$c({}, item), {
1140
- fullName: item.givenName && item.familyName ? `${item.givenName} ${item.familyName}`.toLowerCase() : item.email.toLowerCase()
1141
- }));
1142
- }, [props.items]);
1143
- console.groupEnd();
1144
- const { items: sortedItems, requestSort, sortConfig } = useSortableData(preparedItems);
897
+ if (props.loading) {
898
+ return /* @__PURE__ */ React.createElement("div", { className: "text-sm text-slate-400" }, "Loading\u2026");
899
+ }
1145
900
  if (props.items.length === 0) {
901
+ return /* @__PURE__ */ React.createElement("div", { className: "rounded-xl border border-slate-200 bg-white p-8 text-center text-sm text-slate-400 shadow-sm" }, "You have not rostered any students yet.");
902
+ }
903
+ return /* @__PURE__ */ React.createElement("div", { className: "overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm" }, /* @__PURE__ */ React.createElement("div", { className: "grid grid-cols-[2.2fr_1.2fr_1fr_1.2fr_1fr_0.6fr] gap-3 border-b border-slate-100 px-5 py-3 text-[10px] font-bold uppercase tracking-wide text-slate-400" }, /* @__PURE__ */ React.createElement("div", null, "Name"), /* @__PURE__ */ React.createElement("div", null, "Role"), /* @__PURE__ */ React.createElement("div", null, "Badges Earned"), /* @__PURE__ */ React.createElement("div", null, "Lessons Completed"), /* @__PURE__ */ React.createElement("div", null, "Account Created?"), /* @__PURE__ */ React.createElement("div", null)), props.items.map((row, i) => {
904
+ var _a, _b;
905
+ const name = row.givenName && row.familyName ? `${row.givenName} ${row.familyName}` : row.email;
906
+ const initials = (((_a = row.givenName) == null ? void 0 : _a[0]) || row.email[0] || "?") + (((_b = row.familyName) == null ? void 0 : _b[0]) || "");
1146
907
  return /* @__PURE__ */ React.createElement(
1147
- PlaceholderBanner,
908
+ "div",
1148
909
  {
1149
- title: "No members to display",
1150
- description: "You have not rostered any students yet.",
1151
- loading: props.loading,
1152
- icon: "groups"
1153
- }
1154
- );
1155
- }
1156
- const sortStatus = {
1157
- columnAccessor: sortConfig.key,
1158
- direction: sortConfig.direction === "desc" ? "desc" : "asc"
1159
- };
1160
- const openDeleteModal = (student) => openConfirmModal({
1161
- title: `Remove "${student.givenName && student.familyName ? `${student.givenName} ${student.familyName}` : student.email}" from this class?`,
1162
- centered: true,
1163
- children: /* @__PURE__ */ React.createElement(Text, { size: "sm" }, "Click confirm if you want to remove the student from this specific class. This will NOT remove the student from the Tech Platform."),
1164
- labels: { confirm: "Remove Student", cancel: "Cancel" },
1165
- confirmProps: { color: "red" },
1166
- onConfirm: () => props.onDelete && props.onDelete(student)
1167
- });
1168
- return /* @__PURE__ */ React.createElement(ScrollArea, null, /* @__PURE__ */ React.createElement(
1169
- DataTable,
1170
- {
1171
- verticalSpacing: 20,
1172
- sx: { minWidth: 700 },
1173
- highlightOnHover: true,
1174
- striped: true,
1175
- records: sortedItems,
1176
- idAccessor: "email",
1177
- sortStatus,
1178
- onSortStatusChange: (status) => requestSort(status.columnAccessor),
1179
- columns: [
1180
- {
1181
- accessor: "fullName",
1182
- title: "Name",
1183
- sortable: true,
1184
- render: (row) => /* @__PURE__ */ React.createElement(UnstyledButton, { component: Link, to: row.href }, /* @__PURE__ */ React.createElement(Group, { spacing: "sm" }, /* @__PURE__ */ React.createElement(Avatar, { size: 40, src: row.avatar, radius: 40 }), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Text, { size: "sm", weight: 500 }, row.givenName && row.familyName ? `${row.givenName} ${row.familyName}` : row.email), /* @__PURE__ */ React.createElement(Text, { size: "xs", color: "dimmed" }, row.email))))
1185
- },
1186
- {
1187
- accessor: "isAdmin",
1188
- title: "Role",
1189
- sortable: true,
1190
- render: (row) => /* @__PURE__ */ React.createElement(Box, { maw: 150 }, /* @__PURE__ */ React.createElement(
1191
- Select,
1192
- {
1193
- size: "sm",
1194
- disabled: row.readonly,
1195
- value: row.isAdmin ? "educator" : "student",
1196
- onChange: (value) => props.onRoleChange && props.onRoleChange(row, value),
1197
- data: [
1198
- { label: "Student", value: "student" },
1199
- { label: "Educator", value: "educator" }
1200
- ]
1201
- }
1202
- ))
1203
- },
1204
- {
1205
- accessor: "badgesEarned",
1206
- title: "Badges Earned",
1207
- sortable: true
1208
- },
910
+ key: row.email,
911
+ className: `grid grid-cols-[2.2fr_1.2fr_1fr_1.2fr_1fr_0.6fr] items-center gap-3 px-5 py-3.5 ${i < props.items.length - 1 ? "border-b border-slate-100" : ""}`
912
+ },
913
+ /* @__PURE__ */ React.createElement(Link, { to: row.href, className: "flex min-w-0 items-center gap-2.5 no-underline" }, row.avatar ? /* @__PURE__ */ React.createElement("img", { className: "h-8 w-8 shrink-0 rounded-full object-cover", src: row.avatar, alt: name }) : /* @__PURE__ */ React.createElement("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-mint-400/20 text-[10px] font-bold text-dark-blue-400" }, initials.toUpperCase()), /* @__PURE__ */ React.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ React.createElement("div", { className: "truncate text-xs font-bold text-dark-blue-400" }, name), /* @__PURE__ */ React.createElement("div", { className: "truncate text-[10.5px] text-slate-400" }, row.email))),
914
+ /* @__PURE__ */ React.createElement(
915
+ "select",
1209
916
  {
1210
- accessor: "lessonsCompleted",
1211
- title: "Lessons Completed",
1212
- sortable: true
917
+ disabled: row.readonly,
918
+ value: row.isAdmin ? "educator" : "student",
919
+ onChange: (e) => props.onRoleChange && props.onRoleChange(row, e.target.value),
920
+ className: "w-fit rounded-lg border border-slate-200 bg-white px-2.5 py-1.5 text-xs font-medium text-slate-600 disabled:opacity-50"
1213
921
  },
922
+ /* @__PURE__ */ React.createElement("option", { value: "student" }, "Student"),
923
+ /* @__PURE__ */ React.createElement("option", { value: "educator" }, "Educator")
924
+ ),
925
+ /* @__PURE__ */ React.createElement("div", { className: "text-xs font-bold text-dark-blue-400" }, row.badgesEarned),
926
+ /* @__PURE__ */ React.createElement("div", { className: "text-xs font-bold text-dark-blue-400" }, row.lessonsCompleted),
927
+ /* @__PURE__ */ React.createElement("div", null, row.hasAccount && /* @__PURE__ */ React.createElement(IconCheck, { size: 16, stroke: 3, className: "text-mint-400" })),
928
+ /* @__PURE__ */ React.createElement("div", null, !row.readonly && !!props.onDelete && /* @__PURE__ */ React.createElement(
929
+ "button",
1214
930
  {
1215
- accessor: "hasAccount",
1216
- title: "Account Created?",
1217
- sortable: true,
1218
- render: (row) => row.hasAccount ? /* @__PURE__ */ React.createElement(IconCheck, { color: "green" }) : null
931
+ type: "button",
932
+ onClick: () => openDeleteModal(row, props.onDelete),
933
+ className: "flex h-7 w-7 items-center justify-center rounded-md text-slate-300 hover:bg-red-50 hover:text-red-500"
1219
934
  },
1220
- {
1221
- accessor: "actions",
1222
- title: "",
1223
- textAlignment: "right",
1224
- render: (row) => /* @__PURE__ */ React.createElement(Group, { noWrap: true, spacing: 0, position: "right" }, !row.readonly && !!props.onDelete && /* @__PURE__ */ React.createElement(ActionIcon, { color: "red", onClick: () => openDeleteModal(row) }, /* @__PURE__ */ React.createElement(IconTrash, { size: 16, stroke: 1.5 })))
1225
- }
1226
- ]
1227
- }
1228
- ));
935
+ /* @__PURE__ */ React.createElement(IconTrash, { size: 14, stroke: 1.75 })
936
+ ))
937
+ );
938
+ }));
1229
939
  }
1230
940
 
1231
941
  var __defProp$b = Object.defineProperty;
@@ -1247,112 +957,46 @@ var __spreadValues$b = (a, b) => {
1247
957
  return a;
1248
958
  };
1249
959
  var __spreadProps$7 = (a, b) => __defProps$7(a, __getOwnPropDescs$7(b));
1250
- const useStyles$l = createStyles((theme) => ({
1251
- title: {
1252
- fontSize: 34,
1253
- fontWeight: 900,
1254
- [theme.fn.smallerThan("sm")]: {
1255
- fontSize: 24
1256
- }
1257
- },
1258
- description: {
1259
- maxWidth: 600
1260
- },
1261
- autocomplete: {
1262
- maxWidth: 400
1263
- },
1264
- wrapper: {
1265
- position: "relative",
1266
- marginBottom: 30
1267
- },
1268
- dropzone: {
1269
- borderWidth: 1,
1270
- paddingBottom: 50
1271
- },
1272
- icon: {
1273
- color: theme.colorScheme === "dark" ? theme.colors.dark[3] : theme.colors.gray[4]
1274
- },
1275
- control: {
1276
- position: "absolute",
1277
- width: 250,
1278
- left: "calc(50% - 125px)",
1279
- bottom: -20
1280
- }
1281
- }));
1282
960
  const Class = (props) => {
1283
- const { classes } = useStyles$l();
1284
- const form = useForm({
1285
- initialValues: {
1286
- classId: "",
1287
- userId: "",
1288
- email: "",
1289
- givenName: "",
1290
- familyName: "",
1291
- avatar: "",
1292
- role: "",
1293
- readonly: false,
1294
- lastActivity: null,
1295
- hasAccount: false,
1296
- lessonsCompleted: 0,
1297
- badgesEarned: 0,
1298
- href: "",
1299
- isAdmin: false
1300
- },
1301
- validate: {
1302
- email: (value) => /^\S+@\S+$/.test(value) && props.members.filter((u) => u.email === value).length === 0 ? null : "Invalid email"
1303
- }
1304
- });
1305
961
  const [opened, setOpened] = useState(false);
1306
962
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
1307
963
  Drawer,
1308
964
  {
1309
965
  opened,
1310
966
  onClose: () => setOpened(false),
1311
- title: /* @__PURE__ */ React.createElement(Title, { size: "h5" }, "Add students"),
967
+ title: "Add students",
1312
968
  padding: "xl",
1313
969
  size: "xl"
1314
970
  },
1315
- /* @__PURE__ */ React.createElement(Stack$5, { spacing: "md" }, /* @__PURE__ */ React.createElement(DropzoneButton$1, __spreadProps$7(__spreadValues$b({}, props), { close: () => setOpened(false) })), /* @__PURE__ */ React.createElement(Divider, { label: "or", labelPosition: "center", my: "md", variant: "dashed" }), /* @__PURE__ */ React.createElement("form", { onSubmit: form.onSubmit(() => {
1316
- const values = form.values;
1317
- form.reset();
1318
- setOpened(false);
1319
- props.onCreateMembers && props.onCreateMembers([values]);
1320
- }) }, /* @__PURE__ */ React.createElement(Stack$5, null, /* @__PURE__ */ React.createElement(
1321
- TextInput,
1322
- __spreadValues$b({
1323
- withAsterisk: true,
1324
- label: "Email",
1325
- placeholder: "Email"
1326
- }, form.getInputProps("email"))
1327
- ), /* @__PURE__ */ React.createElement(Group, { grow: true }, /* @__PURE__ */ React.createElement(
1328
- TextInput,
1329
- __spreadValues$b({
1330
- label: "Given name",
1331
- placeholder: "Given name"
1332
- }, form.getInputProps("givenName"))
1333
- ), /* @__PURE__ */ React.createElement(
1334
- TextInput,
1335
- __spreadValues$b({
1336
- label: "Family name",
1337
- placeholder: "Family name"
1338
- }, form.getInputProps("familyName"))
1339
- )), /* @__PURE__ */ React.createElement(Button, { type: "submit", fullWidth: true, mt: "md" }, "Submit"))))
1340
- ), /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$5, { spacing: "md" }, /* @__PURE__ */ React.createElement(Grid, null, /* @__PURE__ */ React.createElement(Grid.Col, { sm: "auto" }, /* @__PURE__ */ React.createElement(UnstyledButton, { onClick: props.onBackClick }, /* @__PURE__ */ React.createElement(
1341
- Badge$1,
971
+ /* @__PURE__ */ React.createElement(DropzoneButton$1, __spreadProps$7(__spreadValues$b({}, props), { close: () => setOpened(false) }))
972
+ ), /* @__PURE__ */ React.createElement("div", { className: "mx-auto flex max-w-5xl flex-col gap-5 px-4 py-8" }, /* @__PURE__ */ React.createElement("div", { className: "flex flex-wrap items-start justify-between gap-4" }, /* @__PURE__ */ React.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React.createElement("div", { onClick: props.onBackClick, className: "flex w-max cursor-pointer items-center gap-1 text-xs font-bold text-sky-blue-400" }, /* @__PURE__ */ React.createElement(IconArrowLeft, { size: 13, stroke: 2.5 }), "Back"), /* @__PURE__ */ React.createElement("h1", { className: "text-2xl font-extrabold tracking-tight text-dark-blue-400" }, props.displayName || "Class"), /* @__PURE__ */ React.createElement("p", { className: "text-sm text-slate-500" }, props.description || "No description")), !props.loading && /* @__PURE__ */ React.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React.createElement(
973
+ "button",
1342
974
  {
1343
- variant: "filled",
1344
- leftSection: /* @__PURE__ */ React.createElement(ActionIcon, { color: "blue", size: "xs", radius: "xl", variant: "filled" }, /* @__PURE__ */ React.createElement(IconArrowLeft, { size: 14 })),
1345
- size: "lg"
975
+ type: "button",
976
+ onClick: () => setOpened(true),
977
+ className: "flex items-center gap-1.5 rounded-lg border border-slate-200 bg-white px-3.5 py-2 text-xs font-bold text-slate-600 hover:bg-slate-50"
1346
978
  },
1347
- "Back"
1348
- )), /* @__PURE__ */ React.createElement(Title, { order: 2, className: classes.title, mt: "md" }, props.displayName || "Class"), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", className: classes.description, mt: "sm" }, props.description || "No description")), /* @__PURE__ */ React.createElement(Grid.Col, { sm: "content" }, !props.loading && /* @__PURE__ */ React.createElement(
1349
- SplitButton$4,
979
+ /* @__PURE__ */ React.createElement(IconPlus, { size: 13, stroke: 2 }),
980
+ "Add students"
981
+ ), /* @__PURE__ */ React.createElement(
982
+ "button",
1350
983
  {
1351
- onAddMembersClick: () => setOpened(true),
1352
- onCopyClassLinkClick: props.onCopyLinkClick,
1353
- onExportDataClick: props.onExportDataClick
1354
- }
1355
- ))), /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(LoadingOverlay, { visible: props.loading, overlayBlur: 2 }), /* @__PURE__ */ React.createElement(Stack$5, { spacing: "sm" }, /* @__PURE__ */ React.createElement(StatsGroup, { data: [
984
+ type: "button",
985
+ onClick: props.onCopyLinkClick,
986
+ className: "flex items-center gap-1.5 rounded-lg border border-slate-200 bg-white px-3.5 py-2 text-xs font-bold text-slate-600 hover:bg-slate-50"
987
+ },
988
+ /* @__PURE__ */ React.createElement(IconLink, { size: 13, stroke: 2 }),
989
+ "Copy class link"
990
+ ), /* @__PURE__ */ React.createElement(
991
+ "button",
992
+ {
993
+ type: "button",
994
+ onClick: props.onExportDataClick,
995
+ className: "flex items-center gap-1.5 rounded-lg bg-gradient-to-r from-gold-400 to-[#f5c300] px-3.5 py-2 text-xs font-bold text-dark-blue-400 shadow-[0_3px_12px_rgba(255,212,77,0.35)]"
996
+ },
997
+ /* @__PURE__ */ React.createElement(IconDownload, { size: 13, stroke: 2 }),
998
+ "Export data (.csv)"
999
+ ))), /* @__PURE__ */ React.createElement(StatsGroup, { data: [
1356
1000
  {
1357
1001
  title: "# OF STUDENTS",
1358
1002
  value: props.members.filter((a) => !a.isAdmin).length
@@ -1378,10 +1022,30 @@ const Class = (props) => {
1378
1022
  onDelete: props.onDeleteMember,
1379
1023
  onRoleChange: props.onChangeUserRole
1380
1024
  }
1381
- ))))));
1025
+ )));
1382
1026
  };
1383
1027
  const DropzoneButton$1 = (props) => {
1384
- const { classes, theme } = useStyles$l();
1028
+ const form = useForm({
1029
+ initialValues: {
1030
+ classId: "",
1031
+ userId: "",
1032
+ email: "",
1033
+ givenName: "",
1034
+ familyName: "",
1035
+ avatar: "",
1036
+ role: "",
1037
+ readonly: false,
1038
+ lastActivity: null,
1039
+ hasAccount: false,
1040
+ lessonsCompleted: 0,
1041
+ badgesEarned: 0,
1042
+ href: "",
1043
+ isAdmin: false
1044
+ },
1045
+ validate: {
1046
+ email: (value) => /^\S+@\S+$/.test(value) && props.members.filter((u) => u.email === value).length === 0 ? null : "Invalid email"
1047
+ }
1048
+ });
1385
1049
  const openRef = React.useRef(null);
1386
1050
  const [loading, setLoading] = React.useState(false);
1387
1051
  const onDrop = React.useCallback((acceptedFiles) => {
@@ -1402,29 +1066,59 @@ const DropzoneButton$1 = (props) => {
1402
1066
  });
1403
1067
  });
1404
1068
  }, []);
1405
- return /* @__PURE__ */ React.createElement("div", { className: classes.wrapper }, /* @__PURE__ */ React.createElement(
1069
+ return /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-4" }, /* @__PURE__ */ React.createElement(
1406
1070
  Dropzone,
1407
1071
  {
1408
1072
  loading,
1409
1073
  openRef,
1410
1074
  onDrop,
1411
- className: classes.dropzone,
1412
- radius: "md",
1413
1075
  accept: [MIME_TYPES.csv],
1414
1076
  maxSize: 5 * 1024 ** 2
1415
1077
  },
1416
- /* @__PURE__ */ React.createElement("div", { style: { pointerEvents: "none" } }, /* @__PURE__ */ React.createElement(Group, { position: "center" }, /* @__PURE__ */ React.createElement(Dropzone.Accept, null, /* @__PURE__ */ React.createElement(IconDownload, { size: 50, color: theme.colors[theme.primaryColor][6], stroke: 1.5 })), /* @__PURE__ */ React.createElement(Dropzone.Reject, null, /* @__PURE__ */ React.createElement(IconX, { size: 50, color: theme.colors.red[6], stroke: 1.5 })), /* @__PURE__ */ React.createElement(Dropzone.Idle, null, /* @__PURE__ */ React.createElement(
1417
- IconCloudUpload,
1418
- {
1419
- size: 50,
1420
- color: theme.colorScheme === "dark" ? theme.colors.dark[0] : theme.black,
1421
- stroke: 1.5
1422
- }
1423
- ))), /* @__PURE__ */ React.createElement(Text, { align: "center", weight: 700, size: "lg", mt: "xl" }, /* @__PURE__ */ React.createElement(Dropzone.Accept, null, "Drop files here"), /* @__PURE__ */ React.createElement(Dropzone.Reject, null, "Csv file less than 5mb"), /* @__PURE__ */ React.createElement(Dropzone.Idle, null, "Upload multiple")), /* @__PURE__ */ React.createElement(Text, { align: "center", size: "sm", mt: "xs", color: "dimmed" }, "Drag'n'drop files here to upload. We can accept only ", /* @__PURE__ */ React.createElement("i", null, ".csv"), " files that are less than 5mb in size."))
1424
- ), /* @__PURE__ */ React.createElement(Button, { className: classes.control, size: "md", radius: "xl", onClick: () => {
1425
- var _a;
1426
- return (_a = openRef.current) == null ? void 0 : _a.call(openRef);
1427
- } }, "Select file"));
1078
+ /* @__PURE__ */ React.createElement("div", { style: { pointerEvents: "none" } }, /* @__PURE__ */ React.createElement(Group, { position: "center" }, /* @__PURE__ */ React.createElement(IconCloudUpload, { size: 50, stroke: 1.5 })), /* @__PURE__ */ React.createElement("p", { className: "mt-6 text-center text-lg font-bold text-dark-blue-400" }, "Upload multiple"), /* @__PURE__ */ React.createElement("p", { className: "mt-2 text-center text-sm text-slate-400" }, "Drag'n'drop files here to upload. We can accept only ", /* @__PURE__ */ React.createElement("i", null, ".csv"), " files that are less than 5mb in size."))
1079
+ ), /* @__PURE__ */ React.createElement("div", { className: "flex justify-center" }, /* @__PURE__ */ React.createElement(
1080
+ "button",
1081
+ {
1082
+ type: "button",
1083
+ onClick: () => {
1084
+ var _a;
1085
+ return (_a = openRef.current) == null ? void 0 : _a.call(openRef);
1086
+ },
1087
+ className: "rounded-full bg-dark-blue-400 px-6 py-2.5 text-xs font-bold text-white"
1088
+ },
1089
+ "Select file"
1090
+ )), /* @__PURE__ */ React.createElement(Divider, { label: "or", labelPosition: "center", my: "md", variant: "dashed" }), /* @__PURE__ */ React.createElement("form", { onSubmit: form.onSubmit(() => {
1091
+ const values = form.values;
1092
+ form.reset();
1093
+ props.close();
1094
+ props.onCreateMembers && props.onCreateMembers([values]);
1095
+ }) }, /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-3" }, /* @__PURE__ */ React.createElement(
1096
+ TextInput,
1097
+ __spreadValues$b({
1098
+ withAsterisk: true,
1099
+ label: "Email",
1100
+ placeholder: "Email"
1101
+ }, form.getInputProps("email"))
1102
+ ), /* @__PURE__ */ React.createElement(Group, { grow: true }, /* @__PURE__ */ React.createElement(
1103
+ TextInput,
1104
+ __spreadValues$b({
1105
+ label: "Given name",
1106
+ placeholder: "Given name"
1107
+ }, form.getInputProps("givenName"))
1108
+ ), /* @__PURE__ */ React.createElement(
1109
+ TextInput,
1110
+ __spreadValues$b({
1111
+ label: "Family name",
1112
+ placeholder: "Family name"
1113
+ }, form.getInputProps("familyName"))
1114
+ )), /* @__PURE__ */ React.createElement(
1115
+ "button",
1116
+ {
1117
+ type: "submit",
1118
+ className: "mt-2 rounded-lg bg-dark-blue-400 px-4 py-2.5 text-xs font-bold text-white"
1119
+ },
1120
+ "Submit"
1121
+ ))));
1428
1122
  };
1429
1123
 
1430
1124
  function Table$b(props) {
@@ -1509,7 +1203,7 @@ var __spreadValues$a = (a, b) => {
1509
1203
  }
1510
1204
  return a;
1511
1205
  };
1512
- const useStyles$k = createStyles((theme) => ({
1206
+ const useStyles$j = createStyles((theme) => ({
1513
1207
  title: {
1514
1208
  fontSize: 34,
1515
1209
  fontWeight: 900,
@@ -1522,7 +1216,7 @@ const useStyles$k = createStyles((theme) => ({
1522
1216
  }
1523
1217
  }));
1524
1218
  const Classes = (props) => {
1525
- const { classes } = useStyles$k();
1219
+ const { classes } = useStyles$j();
1526
1220
  const form = useForm({
1527
1221
  initialValues: {
1528
1222
  classId: "",
@@ -1593,7 +1287,7 @@ const Classes = (props) => {
1593
1287
  ))))));
1594
1288
  };
1595
1289
 
1596
- const useStyles$j = createStyles((theme) => ({
1290
+ const useStyles$i = createStyles((theme) => ({
1597
1291
  title: {
1598
1292
  fontSize: 34,
1599
1293
  fontWeight: 900,
@@ -1607,7 +1301,7 @@ const useStyles$j = createStyles((theme) => ({
1607
1301
  }
1608
1302
  }));
1609
1303
  const UserInfo = (props) => {
1610
- const { classes } = useStyles$j();
1304
+ const { classes } = useStyles$i();
1611
1305
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Title, { className: classes.title }, props.name), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", className: classes.description, mt: "xs" }, props.impactStatement));
1612
1306
  };
1613
1307
 
@@ -1745,7 +1439,7 @@ const Student = (props) => {
1745
1439
  ))))));
1746
1440
  };
1747
1441
 
1748
- const useStyles$i = createStyles((theme, props) => {
1442
+ const useStyles$h = createStyles((theme, props) => {
1749
1443
  const from = props.from || "blue";
1750
1444
  const to = props.to || "green";
1751
1445
  return {
@@ -1773,7 +1467,7 @@ const useStyles$i = createStyles((theme, props) => {
1773
1467
  };
1774
1468
  });
1775
1469
  function CardGradient(props) {
1776
- const { classes } = useStyles$i(props);
1470
+ const { classes } = useStyles$h(props);
1777
1471
  const from = props.from || "blue";
1778
1472
  const to = props.to || "green";
1779
1473
  const icon = props.icon || /* @__PURE__ */ React.createElement(IconColorSwatch, { size: 28, stroke: 1.5 });
@@ -1817,7 +1511,7 @@ var __objRest$1 = (source, exclude) => {
1817
1511
  }
1818
1512
  return target;
1819
1513
  };
1820
- const useStyles$h = createStyles((theme) => ({
1514
+ const useStyles$g = createStyles((theme) => ({
1821
1515
  card: {
1822
1516
  height: 240,
1823
1517
  backgroundSize: "cover",
@@ -1862,7 +1556,7 @@ const TenantBanner = (_a) => {
1862
1556
  "className",
1863
1557
  "code"
1864
1558
  ]);
1865
- const { classes, cx, theme } = useStyles$h();
1559
+ const { classes, cx, theme } = useStyles$g();
1866
1560
  const handleCopy = async () => {
1867
1561
  if (!code)
1868
1562
  return;
@@ -2002,7 +1696,7 @@ function Table$7(props) {
2002
1696
  ));
2003
1697
  }
2004
1698
 
2005
- const useStyles$g = createStyles((theme) => ({
1699
+ const useStyles$f = createStyles((theme) => ({
2006
1700
  button: {
2007
1701
  borderTopRightRadius: 0,
2008
1702
  borderBottomRightRadius: 0,
@@ -2017,7 +1711,7 @@ const useStyles$g = createStyles((theme) => ({
2017
1711
  }
2018
1712
  }));
2019
1713
  const SplitButton$3 = (props) => {
2020
- const { classes, theme } = useStyles$g();
1714
+ const { classes, theme } = useStyles$f();
2021
1715
  theme.colors[theme.primaryColor][theme.colorScheme === "dark" ? 5 : 6];
2022
1716
  return /* @__PURE__ */ React.createElement(Stack$5, { spacing: "sm" }, /* @__PURE__ */ React.createElement(
2023
1717
  Button,
@@ -2195,7 +1889,7 @@ function Stack$2(props) {
2195
1889
  }
2196
1890
  const truncateWithEllipses = (text, max) => text.substr(0, max - 1) + (text.length > max ? "&hellip;" : "");
2197
1891
 
2198
- const useStyles$f = createStyles((theme) => ({
1892
+ const useStyles$e = createStyles((theme) => ({
2199
1893
  title: {
2200
1894
  fontSize: 34,
2201
1895
  fontWeight: 900,
@@ -2208,7 +1902,7 @@ const useStyles$f = createStyles((theme) => ({
2208
1902
  }
2209
1903
  }));
2210
1904
  const Lesson = (props) => {
2211
- const { classes } = useStyles$f();
1905
+ const { classes } = useStyles$e();
2212
1906
  const [tab, setTab] = useState("question");
2213
1907
  const numberOfStudents = props.students.length;
2214
1908
  const numberOfLessons = numberOfStudents > 0 ? props.students.filter((u) => u.isComplete).length : 0;
@@ -2352,7 +2046,7 @@ function Table$5(props) {
2352
2046
  return /* @__PURE__ */ React.createElement(ScrollArea.Autosize, { maxHeight: 600 }, /* @__PURE__ */ React.createElement(Table$l, { horizontalSpacing: 0, verticalSpacing: 0, sx: { minWidth: 700 } }, /* @__PURE__ */ React.createElement("tbody", null, rows)));
2353
2047
  }
2354
2048
 
2355
- const useStyles$e = createStyles((theme) => ({
2049
+ const useStyles$d = createStyles((theme) => ({
2356
2050
  title: {
2357
2051
  fontSize: 34,
2358
2052
  fontWeight: 900,
@@ -2365,7 +2059,7 @@ const useStyles$e = createStyles((theme) => ({
2365
2059
  }
2366
2060
  }));
2367
2061
  const Lessons = (props) => {
2368
- const { classes } = useStyles$e();
2062
+ const { classes } = useStyles$d();
2369
2063
  return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$5, { spacing: "md" }, /* @__PURE__ */ React.createElement(Grid, null, /* @__PURE__ */ React.createElement(Grid.Col, { sm: "auto" }, /* @__PURE__ */ React.createElement(Badge$1, { variant: "filled", size: "lg" }, "Lessons"), /* @__PURE__ */ React.createElement(Title, { order: 2, className: classes.title, mt: "md" }, "Lessons"), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", className: classes.description, mt: "sm" }, "Bite-sized activities and learning experiences accelerating students achievement"))), /* @__PURE__ */ React.createElement(
2370
2064
  Autocomplete,
2371
2065
  {
@@ -2382,7 +2076,7 @@ const Lessons = (props) => {
2382
2076
  ))));
2383
2077
  };
2384
2078
 
2385
- const useStyles$d = createStyles((theme) => ({
2079
+ const useStyles$c = createStyles((theme) => ({
2386
2080
  title: {
2387
2081
  fontSize: 22,
2388
2082
  fontWeight: 900,
@@ -2401,7 +2095,7 @@ const useStyles$d = createStyles((theme) => ({
2401
2095
  }
2402
2096
  }));
2403
2097
  function AccessCode(props) {
2404
- const { classes } = useStyles$d();
2098
+ const { classes } = useStyles$c();
2405
2099
  return /* @__PURE__ */ React.createElement(Container, { mx: "0", px: "0", size: 460, my: 30 }, /* @__PURE__ */ React.createElement(Title, { className: classes.title }, "Access code"), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", size: "sm" }, "Grant access to join your organization"), /* @__PURE__ */ React.createElement(Paper, { withBorder: true, shadow: "md", p: 30, radius: "md", mt: "xl" }, /* @__PURE__ */ React.createElement(TextInput, { value: props.value, readOnly: true }), /* @__PURE__ */ React.createElement(Group, { position: "apart", mt: "lg", className: classes.controls }, /* @__PURE__ */ React.createElement(
2406
2100
  Anchor,
2407
2101
  {
@@ -2429,7 +2123,7 @@ const monthNames = [
2429
2123
  "November",
2430
2124
  "December"
2431
2125
  ];
2432
- const useStyles$c = createStyles((theme) => ({
2126
+ const useStyles$b = createStyles((theme) => ({
2433
2127
  title: {
2434
2128
  fontSize: 34,
2435
2129
  fontWeight: 900,
@@ -2459,7 +2153,7 @@ const useStyles$c = createStyles((theme) => ({
2459
2153
  }
2460
2154
  }));
2461
2155
  const Organization = (props) => {
2462
- const { classes } = useStyles$c();
2156
+ const { classes } = useStyles$b();
2463
2157
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$5, { spacing: "md" }, /* @__PURE__ */ React.createElement(Grid, null, /* @__PURE__ */ React.createElement(Grid.Col, { sm: "auto" }, /* @__PURE__ */ React.createElement(UnstyledButton, { onClick: props.onBackClick }, /* @__PURE__ */ React.createElement(
2464
2158
  Badge$1,
2465
2159
  {
@@ -2485,7 +2179,7 @@ const Organization = (props) => {
2485
2179
  ] }))))));
2486
2180
  };
2487
2181
 
2488
- const useStyles$b = createStyles((theme) => ({
2182
+ const useStyles$a = createStyles((theme) => ({
2489
2183
  button: {
2490
2184
  borderTopRightRadius: 0,
2491
2185
  borderBottomRightRadius: 0,
@@ -2500,7 +2194,7 @@ const useStyles$b = createStyles((theme) => ({
2500
2194
  }
2501
2195
  }));
2502
2196
  const SplitButton$2 = (props) => {
2503
- const { classes, theme } = useStyles$b();
2197
+ const { classes, theme } = useStyles$a();
2504
2198
  const menuIconColor = theme.colors[theme.primaryColor][theme.colorScheme === "dark" ? 5 : 6];
2505
2199
  const hasMenu = !!props.withOrganizationLink;
2506
2200
  return /* @__PURE__ */ React.createElement(Group, { noWrap: true, spacing: 0 }, /* @__PURE__ */ React.createElement(
@@ -2581,7 +2275,7 @@ var __spreadValues$7 = (a, b) => {
2581
2275
  return a;
2582
2276
  };
2583
2277
  var __spreadProps$5 = (a, b) => __defProps$5(a, __getOwnPropDescs$5(b));
2584
- const useStyles$a = createStyles((theme) => ({
2278
+ const useStyles$9 = createStyles((theme) => ({
2585
2279
  title: {
2586
2280
  fontSize: 34,
2587
2281
  fontWeight: 900,
@@ -2611,7 +2305,7 @@ const useStyles$a = createStyles((theme) => ({
2611
2305
  }
2612
2306
  }));
2613
2307
  const People = (props) => {
2614
- const { classes } = useStyles$a();
2308
+ const { classes } = useStyles$9();
2615
2309
  const form = useForm({
2616
2310
  initialValues: {
2617
2311
  userId: "",
@@ -2715,7 +2409,7 @@ const People = (props) => {
2715
2409
  ))))));
2716
2410
  };
2717
2411
  const DropzoneButton = (props) => {
2718
- const { classes, theme } = useStyles$a();
2412
+ const { classes, theme } = useStyles$9();
2719
2413
  const openRef = React.useRef(null);
2720
2414
  const [loading, setLoading] = React.useState(false);
2721
2415
  const onDrop = React.useCallback((acceptedFiles) => {
@@ -2761,7 +2455,7 @@ const DropzoneButton = (props) => {
2761
2455
  } }, "Select file"));
2762
2456
  };
2763
2457
 
2764
- const useStyles$9 = createStyles((theme) => ({
2458
+ const useStyles$8 = createStyles((theme) => ({
2765
2459
  form: {
2766
2460
  backgroundColor: theme.white,
2767
2461
  padding: theme.spacing.xl,
@@ -2824,7 +2518,7 @@ const useStyles$9 = createStyles((theme) => ({
2824
2518
  }
2825
2519
  }));
2826
2520
  const StartAnonymousLesson = (props) => {
2827
- const { classes } = useStyles$9();
2521
+ const { classes } = useStyles$8();
2828
2522
  const [name, setName] = React.useState("");
2829
2523
  return /* @__PURE__ */ React.createElement("div", { className: classes.wrapper }, /* @__PURE__ */ React.createElement(Container, null, /* @__PURE__ */ React.createElement(SimpleGrid, { maw: 960, cols: 2, spacing: 15, breakpoints: [{ maxWidth: "sm", cols: 1 }] }, /* @__PURE__ */ React.createElement("div", { className: classes.content }, /* @__PURE__ */ React.createElement(Badge$1, { color: "violet" }, "Community"), /* @__PURE__ */ React.createElement(Title, { className: classes.title }, props.title), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", mt: "md" }, props.description), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", mt: "md" }, "You are now part of ", `${props.educatorName}'s`, " Class")), /* @__PURE__ */ React.createElement("div", { className: classes.form }, /* @__PURE__ */ React.createElement(
2830
2524
  TextInput,
@@ -2881,7 +2575,7 @@ function TaskCard(props) {
2881
2575
  ));
2882
2576
  }
2883
2577
 
2884
- const useStyles$8 = createStyles((theme) => ({
2578
+ const useStyles$7 = createStyles((theme) => ({
2885
2579
  action: {
2886
2580
  backgroundColor: "inherit",
2887
2581
  ":hover": {
@@ -2900,7 +2594,7 @@ const useStyles$8 = createStyles((theme) => ({
2900
2594
  }
2901
2595
  }));
2902
2596
  const TrialHome = (props) => {
2903
- const { classes } = useStyles$8();
2597
+ const { classes } = useStyles$7();
2904
2598
  return /* @__PURE__ */ React.createElement(Container, { size: "lg" }, /* @__PURE__ */ React.createElement(Badge$1, null, props.daysRemaining, " day", props.daysRemaining !== 1 ? "s" : "", " left"), /* @__PURE__ */ React.createElement(
2905
2599
  Button,
2906
2600
  {
@@ -2960,7 +2654,7 @@ var __objRest = (source, exclude) => {
2960
2654
  }
2961
2655
  return target;
2962
2656
  };
2963
- const useStyles$7 = createStyles((theme, { checked }) => ({
2657
+ const useStyles$6 = createStyles((theme, { checked }) => ({
2964
2658
  button: {
2965
2659
  display: "flex",
2966
2660
  alignItems: "center",
@@ -3002,7 +2696,7 @@ function ImageCheckbox(_a) {
3002
2696
  finalValue: false,
3003
2697
  onChange
3004
2698
  });
3005
- const { classes, cx } = useStyles$7({ checked: value });
2699
+ const { classes, cx } = useStyles$6({ checked: value });
3006
2700
  return /* @__PURE__ */ React.createElement(
3007
2701
  UnstyledButton,
3008
2702
  __spreadProps$4(__spreadValues$5({}, others), {
@@ -3063,7 +2757,7 @@ var __spreadValues$4 = (a, b) => {
3063
2757
  return a;
3064
2758
  };
3065
2759
  var __spreadProps$3 = (a, b) => __defProps$3(a, __getOwnPropDescs$3(b));
3066
- const useStyles$6 = createStyles((theme) => ({
2760
+ const useStyles$5 = createStyles((theme) => ({
3067
2761
  wrapper: {
3068
2762
  minHeight: "100%",
3069
2763
  boxSizing: "border-box",
@@ -3126,7 +2820,7 @@ const OPTIONS = [
3126
2820
  { description: "project-based learning", title: "Project-Based Learning", icon: IconTools }
3127
2821
  ];
3128
2822
  const TrialRegistration = (props) => {
3129
- const { classes } = useStyles$6();
2823
+ const { classes } = useStyles$5();
3130
2824
  const [firstName, setFirstName] = React.useState("");
3131
2825
  const [lastName, setLastName] = React.useState("");
3132
2826
  const [organization, setOrganization] = React.useState({ organizationId: "", displayName: "" });
@@ -3241,7 +2935,7 @@ var __spreadValues$3 = (a, b) => {
3241
2935
  return a;
3242
2936
  };
3243
2937
  var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b));
3244
- const useStyles$5 = createStyles((theme, props) => ({
2938
+ const useStyles$4 = createStyles((theme, props) => ({
3245
2939
  footer: {
3246
2940
  paddingTop: theme.spacing.md,
3247
2941
  paddingBottom: theme.spacing.md,
@@ -3328,7 +3022,7 @@ const useStyles$5 = createStyles((theme, props) => ({
3328
3022
  }
3329
3023
  }));
3330
3024
  const App = (props) => {
3331
- const { classes } = useStyles$5(props);
3025
+ const { classes } = useStyles$4(props);
3332
3026
  const account = useAccount(props.account, props.accounts, props.onAccountChange);
3333
3027
  return /* @__PURE__ */ React.createElement(
3334
3028
  AppShell,
@@ -3424,58 +3118,26 @@ const useAccount = (account, accounts, onAccountChange) => {
3424
3118
  };
3425
3119
 
3426
3120
  function Table$3(props) {
3121
+ if (props.loading) {
3122
+ return /* @__PURE__ */ React.createElement("div", { className: "text-sm text-slate-400" }, "Loading\u2026");
3123
+ }
3427
3124
  if (props.items.length === 0) {
3428
- return /* @__PURE__ */ React.createElement(
3429
- PlaceholderBanner,
3430
- {
3431
- title: "No pathway items to display",
3432
- description: "We don't have any pathway items to show you just yet.",
3433
- loading: props.loading,
3434
- icon: "badges"
3435
- }
3436
- );
3125
+ return /* @__PURE__ */ React.createElement("div", { className: "rounded-xl border border-slate-200 bg-white p-8 text-center text-sm text-slate-400 shadow-sm" }, "No pathways to display.");
3437
3126
  }
3438
- const rows = props.items.map((row) => /* @__PURE__ */ React.createElement("tr", { key: row.badgeId }, /* @__PURE__ */ React.createElement("td", null, /* @__PURE__ */ React.createElement(
3439
- UnstyledButton,
3127
+ return /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-3" }, props.items.map((row) => /* @__PURE__ */ React.createElement(
3128
+ Link,
3440
3129
  {
3441
- component: Link,
3130
+ key: row.badgeId,
3442
3131
  to: row.href,
3443
- sx: (theme) => ({
3444
- display: "block",
3445
- width: "100%",
3446
- padding: theme.spacing.md,
3447
- color: theme.colorScheme === "dark" ? theme.colors.dark[0] : theme.black,
3448
- "&:hover": {
3449
- backgroundColor: theme.colorScheme === "dark" ? theme.colors.dark[8] : theme.colors.gray[1]
3450
- }
3451
- })
3132
+ className: "flex items-center gap-4 rounded-xl border border-slate-200 bg-white p-4 no-underline shadow-sm hover:bg-slate-50"
3452
3133
  },
3453
- /* @__PURE__ */ React.createElement(Group, null, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(Text, { size: "sm", weight: 500 }, row.name), /* @__PURE__ */ React.createElement(Text, { size: "xs", color: "dimmed" }, row.description)))
3454
- ))));
3455
- return /* @__PURE__ */ React.createElement(ScrollArea.Autosize, { maxHeight: 600 }, /* @__PURE__ */ React.createElement(Table$l, { horizontalSpacing: 0, verticalSpacing: 0, sx: { minWidth: 700 } }, /* @__PURE__ */ React.createElement("tbody", null, rows)));
3134
+ /* @__PURE__ */ React.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ React.createElement("div", { className: "text-sm font-bold text-dark-blue-400" }, row.name), row.description && /* @__PURE__ */ React.createElement("div", { className: "mt-1 text-xs leading-relaxed text-slate-500" }, row.description)),
3135
+ /* @__PURE__ */ React.createElement(IconChevronRight, { size: 16, stroke: 2, className: "shrink-0 text-slate-300" })
3136
+ )));
3456
3137
  }
3457
3138
 
3458
- const useStyles$4 = createStyles((theme) => ({
3459
- title: {
3460
- fontSize: 34,
3461
- fontWeight: 900,
3462
- [theme.fn.smallerThan("sm")]: {
3463
- fontSize: 24
3464
- }
3465
- },
3466
- description: {
3467
- maxWidth: 600
3468
- }
3469
- }));
3470
3139
  const Pathways = (props) => {
3471
- const { classes } = useStyles$4();
3472
- return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$5, { spacing: "md" }, /* @__PURE__ */ React.createElement(Grid, null, /* @__PURE__ */ React.createElement(Grid.Col, { sm: "auto" }, /* @__PURE__ */ React.createElement(Badge$1, { variant: "filled", size: "lg" }, "Pathways"), /* @__PURE__ */ React.createElement(Title, { order: 2, className: classes.title, mt: "md" }, "Pathways"), /* @__PURE__ */ React.createElement(Text, { color: "dimmed", className: classes.description, mt: "sm" }, "Explore all your unique pathway requirements in one clear space"))), /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React.createElement(LoadingOverlay, { visible: props.loading, overlayBlur: 2 }), /* @__PURE__ */ React.createElement(
3473
- Table$3,
3474
- {
3475
- loading: props.loading,
3476
- items: props.pathways
3477
- }
3478
- ))));
3140
+ return /* @__PURE__ */ React.createElement("div", { className: "mx-auto flex max-w-4xl flex-col gap-5 px-4 py-8" }, /* @__PURE__ */ React.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ React.createElement("h1", { className: "text-2xl font-extrabold tracking-tight text-dark-blue-400" }, "Pathways"), /* @__PURE__ */ React.createElement("p", { className: "text-sm text-slate-500" }, "Explore all your unique pathway requirements in one clear space")), /* @__PURE__ */ React.createElement(Table$3, { loading: props.loading, items: props.pathways }));
3479
3141
  };
3480
3142
 
3481
3143
  const useStyles$3 = createStyles((theme) => ({