@local-civics/mgmt-ui 0.1.186 → 0.1.187
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.js +126 -70
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +127 -71
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useState, useMemo } from 'react';
|
|
3
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$4, Grid, Table as Table$k, ActionIcon, LoadingOverlay, Select, Autocomplete, Drawer, Divider, TextInput, Tooltip, Paper, Overlay, Anchor, Menu, Checkbox, createEmotionCache, MantineProvider, AppShell } from '@mantine/core';
|
|
4
|
-
import { IconChevronRight, IconChevronLeft, IconVideo, IconSwitchHorizontal, IconLogout, IconHome2, IconGauge, IconCategory2, IconRoute, IconAlbum, IconLambda, IconBuilding, IconBatteryEco, IconBooks, IconBackpack, IconClipboardCopy, IconTableExport, IconArrowLeft, IconPlaylistAdd, IconCheck, IconTrash,
|
|
4
|
+
import { IconChevronRight, IconChevronLeft, IconVideo, IconSwitchHorizontal, IconLogout, IconHome2, IconGauge, IconCategory2, IconRoute, IconAlbum, IconLambda, IconBuilding, IconBatteryEco, IconBooks, IconBackpack, IconClipboardCopy, IconTableExport, IconArrowLeft, IconPlaylistAdd, IconCheck, IconTrash, IconChevronUp, IconChevronDown, IconSelector, IconDownload, IconX, IconCloudUpload, IconInfoCircle, IconColorSwatch, IconPointer, IconScribble, IconSchool, IconPodium, IconBriefcase, IconPresentation, IconNews, IconTools, IconBrandInstagram, IconBrandLinkedin, IconBrandFacebook } from '@tabler/icons';
|
|
5
5
|
import { Link } from 'react-router-dom';
|
|
6
6
|
import { showNotification, NotificationsProvider } from '@mantine/notifications';
|
|
7
7
|
export { showNotification, updateNotification } from '@mantine/notifications';
|
|
@@ -42,7 +42,7 @@ var __objRest$2 = (source, exclude) => {
|
|
|
42
42
|
}
|
|
43
43
|
return target;
|
|
44
44
|
};
|
|
45
|
-
const useStyles$
|
|
45
|
+
const useStyles$v = createStyles((theme) => ({
|
|
46
46
|
user: {
|
|
47
47
|
display: "block",
|
|
48
48
|
width: "100%",
|
|
@@ -53,7 +53,7 @@ const useStyles$u = createStyles((theme) => ({
|
|
|
53
53
|
}));
|
|
54
54
|
function UserButton(_a) {
|
|
55
55
|
var _b = _a, { image, name, email, icon } = _b, others = __objRest$2(_b, ["image", "name", "email", "icon"]);
|
|
56
|
-
const { classes } = useStyles$
|
|
56
|
+
const { classes } = useStyles$v();
|
|
57
57
|
return /* @__PURE__ */ React.createElement(Group, __spreadValues$9({ 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)));
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -64,7 +64,7 @@ const compact = (num) => {
|
|
|
64
64
|
}).format(num || 0);
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
-
const useStyles$
|
|
67
|
+
const useStyles$u = createStyles((theme, _params, getRef) => {
|
|
68
68
|
const icon = getRef("icon");
|
|
69
69
|
return {
|
|
70
70
|
control: {
|
|
@@ -117,7 +117,7 @@ const useStyles$t = createStyles((theme, _params, getRef) => {
|
|
|
117
117
|
};
|
|
118
118
|
});
|
|
119
119
|
function LinksGroup({ icon: Icon, href, label, initiallyOpened, links, active, notifications }) {
|
|
120
|
-
const { classes, theme, cx } = useStyles$
|
|
120
|
+
const { classes, theme, cx } = useStyles$u();
|
|
121
121
|
const hasLinks = Array.isArray(links) && links.length > 0;
|
|
122
122
|
const hasActiveLinks = Array.isArray(links) && links.map((l) => !!active && active === `${label}/${l.label}`).reduce((a, b) => a || b, false);
|
|
123
123
|
const [opened, setOpened] = useState(initiallyOpened || hasActiveLinks || false);
|
|
@@ -181,7 +181,7 @@ var __spreadValues$8 = (a, b) => {
|
|
|
181
181
|
return a;
|
|
182
182
|
};
|
|
183
183
|
var __spreadProps$5 = (a, b) => __defProps$5(a, __getOwnPropDescs$5(b));
|
|
184
|
-
const useStyles$
|
|
184
|
+
const useStyles$t = createStyles((theme, _params, getRef) => {
|
|
185
185
|
const icon = getRef("icon");
|
|
186
186
|
return {
|
|
187
187
|
navbar: {
|
|
@@ -281,7 +281,7 @@ const TRIAL_PAGES = [
|
|
|
281
281
|
"Badges"
|
|
282
282
|
];
|
|
283
283
|
function Navbar(props) {
|
|
284
|
-
const { classes, cx } = useStyles$
|
|
284
|
+
const { classes, cx } = useStyles$t();
|
|
285
285
|
const [burgerOpen, setBurgerOpen] = React.useState(false);
|
|
286
286
|
const toggle = () => setBurgerOpen(!burgerOpen);
|
|
287
287
|
const links = data.map((item) => {
|
|
@@ -324,7 +324,7 @@ function Navbar(props) {
|
|
|
324
324
|
} }, /* @__PURE__ */ React.createElement(IconLogout, { className: classes.linkIcon, stroke: 1.5 }), /* @__PURE__ */ React.createElement("span", null, "Logout"))))));
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
-
const useStyles$
|
|
327
|
+
const useStyles$s = createStyles((theme) => ({
|
|
328
328
|
inner: {
|
|
329
329
|
paddingTop: theme.spacing.xl,
|
|
330
330
|
paddingBottom: theme.spacing.xl * 4
|
|
@@ -360,7 +360,7 @@ const useStyles$r = createStyles((theme) => ({
|
|
|
360
360
|
}
|
|
361
361
|
}));
|
|
362
362
|
const GettingStarted = (props) => {
|
|
363
|
-
const { classes } = useStyles$
|
|
363
|
+
const { classes } = useStyles$s();
|
|
364
364
|
return /* @__PURE__ */ React.createElement(
|
|
365
365
|
Modal,
|
|
366
366
|
{
|
|
@@ -374,7 +374,7 @@ const GettingStarted = (props) => {
|
|
|
374
374
|
);
|
|
375
375
|
};
|
|
376
376
|
|
|
377
|
-
const useStyles$
|
|
377
|
+
const useStyles$r = createStyles((theme) => ({
|
|
378
378
|
title: {
|
|
379
379
|
fontSize: 34,
|
|
380
380
|
fontWeight: 900,
|
|
@@ -415,7 +415,7 @@ const useStyles$q = createStyles((theme) => ({
|
|
|
415
415
|
}
|
|
416
416
|
}));
|
|
417
417
|
const SwitchAccount = (props) => {
|
|
418
|
-
const { classes, theme } = useStyles$
|
|
418
|
+
const { classes, theme } = useStyles$r();
|
|
419
419
|
const options = props.accounts.map((a) => {
|
|
420
420
|
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")));
|
|
421
421
|
});
|
|
@@ -432,7 +432,7 @@ const SwitchAccount = (props) => {
|
|
|
432
432
|
);
|
|
433
433
|
};
|
|
434
434
|
|
|
435
|
-
const useStyles$
|
|
435
|
+
const useStyles$q = createStyles((theme) => ({
|
|
436
436
|
root: {
|
|
437
437
|
display: "flex",
|
|
438
438
|
backgroundImage: `linear-gradient(-60deg, ${theme.colors[theme.primaryColor][4]} 0%, ${theme.colors[theme.primaryColor][7]} 100%)`,
|
|
@@ -476,7 +476,7 @@ const useStyles$p = createStyles((theme) => ({
|
|
|
476
476
|
}
|
|
477
477
|
}));
|
|
478
478
|
const StatsGroup = ({ data, footer }) => {
|
|
479
|
-
const { classes } = useStyles$
|
|
479
|
+
const { classes } = useStyles$q();
|
|
480
480
|
const stats = data.map((stat) => {
|
|
481
481
|
const value = (() => {
|
|
482
482
|
if (stat.unit === "%") {
|
|
@@ -496,7 +496,7 @@ const Tabs = (props) => {
|
|
|
496
496
|
return /* @__PURE__ */ React.createElement(Tabs$1, { value: props.value, onTabChange: props.onChange }, /* @__PURE__ */ React.createElement(Tabs$1.List, null, tabs));
|
|
497
497
|
};
|
|
498
498
|
|
|
499
|
-
const useStyles$
|
|
499
|
+
const useStyles$p = createStyles((theme) => ({
|
|
500
500
|
button: {
|
|
501
501
|
borderTopRightRadius: 0,
|
|
502
502
|
borderBottomRightRadius: 0,
|
|
@@ -511,7 +511,7 @@ const useStyles$o = createStyles((theme) => ({
|
|
|
511
511
|
}
|
|
512
512
|
}));
|
|
513
513
|
const SplitButton$4 = (props) => {
|
|
514
|
-
const { classes, theme } = useStyles$
|
|
514
|
+
const { classes, theme } = useStyles$p();
|
|
515
515
|
theme.colors[theme.primaryColor][theme.colorScheme === "dark" ? 5 : 6];
|
|
516
516
|
return /* @__PURE__ */ React.createElement(Stack$4, { spacing: "sm" }, /* @__PURE__ */ React.createElement(
|
|
517
517
|
Button,
|
|
@@ -539,7 +539,7 @@ const SplitButton$4 = (props) => {
|
|
|
539
539
|
));
|
|
540
540
|
};
|
|
541
541
|
|
|
542
|
-
const useStyles$
|
|
542
|
+
const useStyles$o = createStyles((theme) => ({
|
|
543
543
|
wrapper: {
|
|
544
544
|
display: "flex",
|
|
545
545
|
alignItems: "center",
|
|
@@ -590,7 +590,7 @@ const useStyles$n = createStyles((theme) => ({
|
|
|
590
590
|
}
|
|
591
591
|
}));
|
|
592
592
|
const PlaceholderBanner = (props) => {
|
|
593
|
-
const { classes } = useStyles$
|
|
593
|
+
const { classes } = useStyles$o();
|
|
594
594
|
const title = props.title || "Nothing to display";
|
|
595
595
|
const description = props.description || "We don't have anything to show you here just yet. Add data, check back later, or adjust your search.";
|
|
596
596
|
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 }));
|
|
@@ -662,7 +662,7 @@ function Table$i(props) {
|
|
|
662
662
|
return /* @__PURE__ */ React.createElement(ScrollArea.Autosize, { maxHeight: 600 }, /* @__PURE__ */ React.createElement(Table$k, { verticalSpacing: "sm", sx: { minWidth: 700 }, highlightOnHover: true, striped: true }, /* @__PURE__ */ React.createElement("thead", null, /* @__PURE__ */ React.createElement("tr", null, /* @__PURE__ */ React.createElement("th", null, "Lesson Name"), /* @__PURE__ */ React.createElement("th", null, "Lesson Completion"))), /* @__PURE__ */ React.createElement("tbody", null, rows)));
|
|
663
663
|
}
|
|
664
664
|
|
|
665
|
-
const useStyles$
|
|
665
|
+
const useStyles$n = createStyles((theme) => ({
|
|
666
666
|
title: {
|
|
667
667
|
fontSize: 34,
|
|
668
668
|
fontWeight: 900,
|
|
@@ -675,7 +675,7 @@ const useStyles$m = createStyles((theme) => ({
|
|
|
675
675
|
}
|
|
676
676
|
}));
|
|
677
677
|
const Badge = (props) => {
|
|
678
|
-
const { classes } = useStyles$
|
|
678
|
+
const { classes } = useStyles$n();
|
|
679
679
|
const [tab, setTab] = useState("lessons");
|
|
680
680
|
const numberOfStudents = props.students.length;
|
|
681
681
|
const numberOfBadges = numberOfStudents > 0 ? props.students.filter((u) => u.isComplete).length : 0;
|
|
@@ -773,7 +773,7 @@ function Table$h(props) {
|
|
|
773
773
|
return /* @__PURE__ */ React.createElement(ScrollArea.Autosize, { maxHeight: 600 }, /* @__PURE__ */ React.createElement(Table$k, { horizontalSpacing: 0, verticalSpacing: 0, sx: { minWidth: 700 } }, /* @__PURE__ */ React.createElement("tbody", null, rows)));
|
|
774
774
|
}
|
|
775
775
|
|
|
776
|
-
const useStyles$
|
|
776
|
+
const useStyles$m = createStyles((theme) => ({
|
|
777
777
|
title: {
|
|
778
778
|
fontSize: 34,
|
|
779
779
|
fontWeight: 900,
|
|
@@ -786,7 +786,7 @@ const useStyles$l = createStyles((theme) => ({
|
|
|
786
786
|
}
|
|
787
787
|
}));
|
|
788
788
|
const Badges = (props) => {
|
|
789
|
-
const { classes } = useStyles$
|
|
789
|
+
const { classes } = useStyles$m();
|
|
790
790
|
return /* @__PURE__ */ React.createElement(Container, { size: "lg", py: "xl" }, /* @__PURE__ */ React.createElement(Stack$4, { 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(
|
|
791
791
|
Autocomplete,
|
|
792
792
|
{
|
|
@@ -1016,7 +1016,63 @@ const SplitButton$3 = (props) => {
|
|
|
1016
1016
|
));
|
|
1017
1017
|
};
|
|
1018
1018
|
|
|
1019
|
+
function useSortableData(items, config = { key: "", direction: null }) {
|
|
1020
|
+
const [sortConfig, setSortConfig] = useState(config);
|
|
1021
|
+
const sortedItems = useMemo(() => {
|
|
1022
|
+
let sortableItems = [...items];
|
|
1023
|
+
if (sortConfig.direction !== null) {
|
|
1024
|
+
sortableItems.sort((a, b) => {
|
|
1025
|
+
const aValue = a[sortConfig.key];
|
|
1026
|
+
const bValue = b[sortConfig.key];
|
|
1027
|
+
if (aValue === bValue)
|
|
1028
|
+
return 0;
|
|
1029
|
+
if (aValue === null || aValue === void 0)
|
|
1030
|
+
return 1;
|
|
1031
|
+
if (bValue === null || bValue === void 0)
|
|
1032
|
+
return -1;
|
|
1033
|
+
if (typeof aValue === "number" && typeof bValue === "number") {
|
|
1034
|
+
return sortConfig.direction === "asc" ? aValue - bValue : bValue - aValue;
|
|
1035
|
+
}
|
|
1036
|
+
if (typeof aValue === "boolean" && typeof bValue === "boolean") {
|
|
1037
|
+
return sortConfig.direction === "asc" ? aValue === bValue ? 0 : aValue ? 1 : -1 : aValue === bValue ? 0 : aValue ? -1 : 1;
|
|
1038
|
+
}
|
|
1039
|
+
if (aValue instanceof Date && bValue instanceof Date) {
|
|
1040
|
+
return sortConfig.direction === "asc" ? aValue.getTime() - bValue.getTime() : bValue.getTime() - aValue.getTime();
|
|
1041
|
+
}
|
|
1042
|
+
return sortConfig.direction === "asc" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
return sortableItems;
|
|
1046
|
+
}, [items, sortConfig]);
|
|
1047
|
+
const requestSort = (key) => {
|
|
1048
|
+
let direction = "asc";
|
|
1049
|
+
if (sortConfig.key === key && sortConfig.direction === "asc") {
|
|
1050
|
+
direction = "desc";
|
|
1051
|
+
} else if (sortConfig.key === key && sortConfig.direction === "desc") {
|
|
1052
|
+
direction = null;
|
|
1053
|
+
}
|
|
1054
|
+
setSortConfig({ key, direction });
|
|
1055
|
+
};
|
|
1056
|
+
return { items: sortedItems, requestSort, sortConfig };
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
const useStyles$l = createStyles((theme) => ({
|
|
1060
|
+
th: { padding: "0 !important" },
|
|
1061
|
+
control: {
|
|
1062
|
+
width: "100%",
|
|
1063
|
+
padding: `${theme.spacing.xs}px ${theme.spacing.md}px`,
|
|
1064
|
+
"&:hover": {
|
|
1065
|
+
backgroundColor: theme.colorScheme === "dark" ? theme.colors.dark[6] : theme.colors.gray[0]
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
}));
|
|
1069
|
+
function Th$1({ children, reversed, sorted, onSort }) {
|
|
1070
|
+
const { classes } = useStyles$l();
|
|
1071
|
+
const Icon = sorted ? reversed ? IconChevronUp : IconChevronDown : IconSelector;
|
|
1072
|
+
return /* @__PURE__ */ React.createElement("th", { className: classes.th }, /* @__PURE__ */ React.createElement(UnstyledButton, { onClick: onSort, className: classes.control }, /* @__PURE__ */ React.createElement(Group, { position: "apart" }, /* @__PURE__ */ React.createElement(Text, { weight: 500, size: "sm" }, children), /* @__PURE__ */ React.createElement(Center, null, /* @__PURE__ */ React.createElement(Icon, { size: 14, stroke: 1.5 })))));
|
|
1073
|
+
}
|
|
1019
1074
|
function Table$b(props) {
|
|
1075
|
+
const { items: sortedItems, requestSort, sortConfig } = useSortableData(props.items);
|
|
1020
1076
|
if (props.items.length === 0) {
|
|
1021
1077
|
return /* @__PURE__ */ React.createElement(
|
|
1022
1078
|
PlaceholderBanner,
|
|
@@ -1045,7 +1101,55 @@ function Table$b(props) {
|
|
|
1045
1101
|
data: [{ value: "student", label: "Student" }, { value: "educator", label: "Educator" }]
|
|
1046
1102
|
}
|
|
1047
1103
|
))), /* @__PURE__ */ React.createElement("td", null, row.badgesEarned), /* @__PURE__ */ React.createElement("td", null, row.lessonsCompleted), /* @__PURE__ */ React.createElement("td", null, row.hasAccount && /* @__PURE__ */ React.createElement(IconCheck, { color: "green" })), /* @__PURE__ */ React.createElement("td", null, row.lastActivity ? relativeTimeFromDates(row.lastActivity) : ""), /* @__PURE__ */ React.createElement("td", null, /* @__PURE__ */ React.createElement(Group, { noWrap: true, spacing: 0, position: "right" }, !row.readonly && !!props.onDelete && /* @__PURE__ */ React.createElement(ActionIcon, { color: "red" }, /* @__PURE__ */ React.createElement(IconTrash, { onClick: () => openDeleteModal(row), size: 16, stroke: 1.5 }))))));
|
|
1048
|
-
return /* @__PURE__ */ React.createElement(ScrollArea, null, /* @__PURE__ */ React.createElement(Table$k, { verticalSpacing: 20, sx: { minWidth: 700 }, highlightOnHover: true, striped: true }, /* @__PURE__ */ React.createElement("thead", null, /* @__PURE__ */ React.createElement("tr", null, /* @__PURE__ */ React.createElement(
|
|
1104
|
+
return /* @__PURE__ */ React.createElement(ScrollArea, null, /* @__PURE__ */ React.createElement(Table$k, { verticalSpacing: 20, sx: { minWidth: 700 }, highlightOnHover: true, striped: true }, /* @__PURE__ */ React.createElement("thead", null, /* @__PURE__ */ React.createElement("tr", null, /* @__PURE__ */ React.createElement(
|
|
1105
|
+
Th$1,
|
|
1106
|
+
{
|
|
1107
|
+
sorted: sortConfig.key === "givenName",
|
|
1108
|
+
reversed: sortConfig.direction === "desc",
|
|
1109
|
+
onSort: () => requestSort("givenName")
|
|
1110
|
+
},
|
|
1111
|
+
"Name"
|
|
1112
|
+
), /* @__PURE__ */ React.createElement(
|
|
1113
|
+
Th$1,
|
|
1114
|
+
{
|
|
1115
|
+
sorted: sortConfig.key === "isAdmin",
|
|
1116
|
+
reversed: sortConfig.direction === "desc",
|
|
1117
|
+
onSort: () => requestSort("isAdmin")
|
|
1118
|
+
},
|
|
1119
|
+
"Role"
|
|
1120
|
+
), /* @__PURE__ */ React.createElement(
|
|
1121
|
+
Th$1,
|
|
1122
|
+
{
|
|
1123
|
+
sorted: sortConfig.key === "badgesEarned",
|
|
1124
|
+
reversed: sortConfig.direction === "desc",
|
|
1125
|
+
onSort: () => requestSort("badgesEarned")
|
|
1126
|
+
},
|
|
1127
|
+
"Badges Earned"
|
|
1128
|
+
), /* @__PURE__ */ React.createElement(
|
|
1129
|
+
Th$1,
|
|
1130
|
+
{
|
|
1131
|
+
sorted: sortConfig.key === "lessonsCompleted",
|
|
1132
|
+
reversed: sortConfig.direction === "desc",
|
|
1133
|
+
onSort: () => requestSort("lessonsCompleted")
|
|
1134
|
+
},
|
|
1135
|
+
"Lessons Completed"
|
|
1136
|
+
), /* @__PURE__ */ React.createElement(
|
|
1137
|
+
Th$1,
|
|
1138
|
+
{
|
|
1139
|
+
sorted: sortConfig.key === "hasAccount",
|
|
1140
|
+
reversed: sortConfig.direction === "desc",
|
|
1141
|
+
onSort: () => requestSort("hasAccount")
|
|
1142
|
+
},
|
|
1143
|
+
"Account Created?"
|
|
1144
|
+
), /* @__PURE__ */ React.createElement(
|
|
1145
|
+
Th$1,
|
|
1146
|
+
{
|
|
1147
|
+
sorted: sortConfig.key === "lastActivity",
|
|
1148
|
+
reversed: sortConfig.direction === "desc",
|
|
1149
|
+
onSort: () => requestSort("lastActivity")
|
|
1150
|
+
},
|
|
1151
|
+
"Last Active"
|
|
1152
|
+
), /* @__PURE__ */ React.createElement("th", null), " ")), /* @__PURE__ */ React.createElement("tbody", null, rows)));
|
|
1049
1153
|
}
|
|
1050
1154
|
|
|
1051
1155
|
var __defProp$7 = Object.defineProperty;
|
|
@@ -1247,46 +1351,6 @@ const DropzoneButton$1 = (props) => {
|
|
|
1247
1351
|
} }, "Select file"));
|
|
1248
1352
|
};
|
|
1249
1353
|
|
|
1250
|
-
function useSortableData(items, config = { key: "", direction: null }) {
|
|
1251
|
-
const [sortConfig, setSortConfig] = useState(config);
|
|
1252
|
-
const sortedItems = useMemo(() => {
|
|
1253
|
-
let sortableItems = [...items];
|
|
1254
|
-
if (sortConfig.direction !== null) {
|
|
1255
|
-
sortableItems.sort((a, b) => {
|
|
1256
|
-
const aValue = a[sortConfig.key];
|
|
1257
|
-
const bValue = b[sortConfig.key];
|
|
1258
|
-
if (aValue === bValue)
|
|
1259
|
-
return 0;
|
|
1260
|
-
if (aValue === null || aValue === void 0)
|
|
1261
|
-
return 1;
|
|
1262
|
-
if (bValue === null || bValue === void 0)
|
|
1263
|
-
return -1;
|
|
1264
|
-
if (typeof aValue === "number" && typeof bValue === "number") {
|
|
1265
|
-
return sortConfig.direction === "asc" ? aValue - bValue : bValue - aValue;
|
|
1266
|
-
}
|
|
1267
|
-
if (typeof aValue === "boolean" && typeof bValue === "boolean") {
|
|
1268
|
-
return sortConfig.direction === "asc" ? aValue === bValue ? 0 : aValue ? 1 : -1 : aValue === bValue ? 0 : aValue ? -1 : 1;
|
|
1269
|
-
}
|
|
1270
|
-
if (aValue instanceof Date && bValue instanceof Date) {
|
|
1271
|
-
return sortConfig.direction === "asc" ? aValue.getTime() - bValue.getTime() : bValue.getTime() - aValue.getTime();
|
|
1272
|
-
}
|
|
1273
|
-
return sortConfig.direction === "asc" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
|
|
1274
|
-
});
|
|
1275
|
-
}
|
|
1276
|
-
return sortableItems;
|
|
1277
|
-
}, [items, sortConfig]);
|
|
1278
|
-
const requestSort = (key) => {
|
|
1279
|
-
let direction = "asc";
|
|
1280
|
-
if (sortConfig.key === key && sortConfig.direction === "asc") {
|
|
1281
|
-
direction = "desc";
|
|
1282
|
-
} else if (sortConfig.key === key && sortConfig.direction === "desc") {
|
|
1283
|
-
direction = null;
|
|
1284
|
-
}
|
|
1285
|
-
setSortConfig({ key, direction });
|
|
1286
|
-
};
|
|
1287
|
-
return { items: sortedItems, requestSort, sortConfig };
|
|
1288
|
-
}
|
|
1289
|
-
|
|
1290
1354
|
const useStyles$j = createStyles((theme) => ({
|
|
1291
1355
|
th: { padding: "0 !important" },
|
|
1292
1356
|
control: {
|
|
@@ -1332,15 +1396,7 @@ function Table$a(props) {
|
|
|
1332
1396
|
onSort: () => requestSort("name")
|
|
1333
1397
|
},
|
|
1334
1398
|
"Class Name"
|
|
1335
|
-
), /* @__PURE__ */ React.createElement(
|
|
1336
|
-
Th,
|
|
1337
|
-
{
|
|
1338
|
-
sorted: sortConfig.key === "description",
|
|
1339
|
-
reversed: sortConfig.direction === "desc",
|
|
1340
|
-
onSort: () => requestSort("description")
|
|
1341
|
-
},
|
|
1342
|
-
"Description"
|
|
1343
|
-
), /* @__PURE__ */ React.createElement(
|
|
1399
|
+
), /* @__PURE__ */ React.createElement("th", { style: { padding: "7px 16px" } }, /* @__PURE__ */ React.createElement(Text, { weight: 500, size: "sm" }, "Description")), /* @__PURE__ */ React.createElement(
|
|
1344
1400
|
Th,
|
|
1345
1401
|
{
|
|
1346
1402
|
sorted: sortConfig.key === "numberOfStudents",
|