diff --git a/vingo/database/days.go b/vingo/database/days.go
index 3187cb9..73daecc 100644
--- a/vingo/database/days.go
+++ b/vingo/database/days.go
@@ -1,57 +1,43 @@
package database
-import "time"
+import (
+ "time"
-type Day struct {
- Id int
- Date time.Time
-}
+ "gorm.io/gorm"
+)
func CreateDays(first_day time.Time, last_day time.Time) error {
- tx, err := db.Begin()
- if err != nil {
- return err
- }
-
- defer tx.Rollback()
-
- for d := first_day; !d.After(last_day); d = d.AddDate(0, 0, 1) {
- // Ignore weekends
- if d.Weekday() == time.Saturday || d.Weekday() == time.Sunday {
- continue
+ err := gorm_db.Transaction(func(tx *gorm.DB) error {
+ for d := first_day; !d.After(last_day); d = d.AddDate(0, 0, 1) {
+ // Ignore weekends
+ if d.Weekday() == time.Saturday || d.Weekday() == time.Sunday {
+ continue
+ }
+
+ if err := tx.Create(&StreakDay{Date: d}).Error; err != nil {
+ return err
+ }
}
- _, err := db.Exec("INSERT INTO days (date) VALUES ($1);", d)
- if err != nil {
- return err
- }
- }
+ return nil
+ })
- if err = tx.Commit(); err != nil {
+ if err != nil {
return err
}
return nil
}
-func GetDays() ([]Day, error) {
- rows, err := db.Query("SELECT id, date FROM days ORDER BY date;")
- if err != nil {
- return nil, err
- }
-
- days := make([]Day, 0)
- for rows.Next() {
- var day Day
- rows.Scan(&day.Id, &day.Date)
- days = append(days, day)
- }
+func GetDays() ([]StreakDay, error) {
+ var days []StreakDay
+ err := gorm_db.Find(&days).Error
- return days, nil
+ return days, err
}
func DeleteDay(dayId string) error {
- _, err := db.Exec("DELETE FROM days WHERE id = $1;", dayId)
+ _, err := db.Exec("DELETE FROM streak_days WHERE id = $1;", dayId)
if err != nil {
return err
}
diff --git a/vingo/database/db.go b/vingo/database/db.go
index 157c7ae..f8dd8c5 100644
--- a/vingo/database/db.go
+++ b/vingo/database/db.go
@@ -30,7 +30,7 @@ func OpenDatabase(db_string string) {
log.Fatal(err)
}
- err = new_db.AutoMigrate(&User{}, &Card{}, &Scan{}, &Day{}, &Settings{}, &Season{})
+ err = new_db.AutoMigrate(&User{}, &Card{}, &Scan{}, &StreakDay{}, &Settings{}, &Season{})
if err != nil {
log.Println("Error migrating database")
log.Fatal(err)
diff --git a/vingo/database/models.go b/vingo/database/models.go
index ce66161..7c49878 100644
--- a/vingo/database/models.go
+++ b/vingo/database/models.go
@@ -68,3 +68,14 @@ type Scan struct {
CardSerial string `json:"cardSerial" gorm:"index"`
Card Card `json:"-" gorm:"foreignKey:CardSerial;references:Serial"`
}
+
+type Season struct {
+ BaseModel
+ StartDate time.Time `json:"startDate"`
+ EndDate time.Time `json:"endDate"`
+}
+
+type StreakDay struct {
+ BaseModel
+ Date time.Time `json:"date"`
+}
diff --git a/vingo/database/seasons.go b/vingo/database/seasons.go
new file mode 100644
index 0000000..4cd36ab
--- /dev/null
+++ b/vingo/database/seasons.go
@@ -0,0 +1,11 @@
+package database
+
+func (Season) GetAll() ([]Season, error) {
+ var seasons []Season
+ result := gorm_db.Find(&seasons)
+ return seasons, result.Error
+}
+
+func (s Season) Create() error {
+ return gorm_db.Create(s).Error
+}
diff --git a/vingo/database/settings.go b/vingo/database/settings.go
index c26f98b..b3d284e 100644
--- a/vingo/database/settings.go
+++ b/vingo/database/settings.go
@@ -1,17 +1,26 @@
package database
-func CreateSettings(user_id int) error {
- _, err := db.Exec("INSERT INTO settings (user_id) VALUES ($1) ON CONFLICT DO NOTHING;", user_id)
- return err
-}
+import "log"
func GetSettings(user_id int) (*Settings, error) {
- var settings Settings
- result := gorm_db.First(&settings, "user_id = ?", user_id)
- return &settings, result.Error
+ var user User
+ result := gorm_db.Preload("Settings").First(&user, user_id)
+ log.Println(user)
+ return &user.Settings, result.Error
}
func UpdateSettings(user_id int, settings Settings) error {
- _, err := db.Exec("UPDATE settings SET scan_in_out = $1, leaderboard = $2, public = $3 WHERE user_id = $4;", settings.ScanInOut, settings.Leaderboard, settings.Public, user_id)
- return err
+ var user User
+ if err := gorm_db.Preload("Settings").First(&user, user_id).Error; err != nil {
+ return err
+ }
+
+ user.Settings.ScanInOut = settings.ScanInOut
+ user.Settings.Leaderboard = settings.Leaderboard
+ user.Settings.Public = settings.Public
+ if err := gorm_db.Save(&user.Settings).Error; err != nil {
+ return err
+ }
+
+ return nil
}
diff --git a/vingo/database/users.go b/vingo/database/users.go
index 123d93d..c46c9b7 100644
--- a/vingo/database/users.go
+++ b/vingo/database/users.go
@@ -15,7 +15,7 @@ func CreateUserIfNew(user_id int, username string) error {
func GetUser(user_id int) (*User, error) {
var user User
- result := gorm_db.First(&user, user_id)
+ result := gorm_db.Preload("Settings").First(&user, user_id)
return &user, result.Error
}
diff --git a/vingo/handlers/cards.go b/vingo/handlers/cards.go
index accd969..1d4bd1d 100644
--- a/vingo/handlers/cards.go
+++ b/vingo/handlers/cards.go
@@ -26,7 +26,7 @@ func (Cards) StartRegister(c *fiber.Ctx) error {
logger.Println("Card registration started by user", registering_user)
- return c.Status(200).JSON(map[string]bool{})
+ return c.SendStatus(200)
}
func (Cards) Get(c *fiber.Ctx) error {
@@ -68,5 +68,5 @@ func (Cards) Update(c *fiber.Ctx) error {
return c.Status(500).SendString("Error updating card name")
}
- return c.Status(200).JSON(map[string]bool{})
+ return c.SendStatus(200)
}
diff --git a/vingo/handlers/days.go b/vingo/handlers/days.go
index c4e4fc6..2b0eba8 100644
--- a/vingo/handlers/days.go
+++ b/vingo/handlers/days.go
@@ -7,35 +7,46 @@ import (
"github.com/gofiber/fiber/v2"
)
-func DaysRegister(c *fiber.Ctx) error {
- form_start_date := c.FormValue("start_date")
- form_end_date := c.FormValue("end_date")
-
- start_date, start_err := time.Parse("2006-01-02", form_start_date)
- end_date, end_err := time.Parse("2006-01-02", form_end_date)
- if start_err != nil || end_err != nil {
- logger.Println("Error parsing dates:", start_err, end_err)
- return c.Status(400).SendString("Error parsing dates")
+type Days struct{}
+
+type DaysBody struct {
+ StartDate time.Time `json:"startDate"`
+ EndDate time.Time `json:"endDate"`
+}
+
+func (Days) CreateMultiple(c *fiber.Ctx) error {
+ payload := new(DaysBody)
+ if err := c.BodyParser(payload); err != nil {
+ logger.Println("Error parsing body:", err)
+ return c.Status(400).SendString("Error parsing body")
}
- logger.Println("Registering days from", start_date, "to", end_date)
- err := database.CreateDays(start_date, end_date)
+ err := database.CreateDays(payload.StartDate, payload.EndDate)
if err != nil {
logger.Println("Error creating days:", err)
return c.Status(500).SendString("Error creating days")
}
- return c.Redirect("/days")
+ return c.SendStatus(200)
}
-func DaysDelete(c *fiber.Ctx) error {
+func (Days) Delete(c *fiber.Ctx) error {
day_id := c.Params("id")
- logger.Println("Deleting day", day_id)
err := database.DeleteDay(day_id)
if err != nil {
logger.Println("Error deleting day:", err)
return c.Status(500).SendString("Error deleting day")
}
- return c.Redirect("/days")
+ return c.SendStatus(200)
+}
+
+func (Days) All(c *fiber.Ctx) error {
+ days, err := database.GetDays()
+ if err != nil {
+ logger.Println("Error getting days:", err)
+ return c.Status(500).SendString("Error getting days")
+ }
+
+ return c.JSON(days)
}
diff --git a/vingo/handlers/seasons.go b/vingo/handlers/seasons.go
new file mode 100644
index 0000000..bcfed09
--- /dev/null
+++ b/vingo/handlers/seasons.go
@@ -0,0 +1,36 @@
+package handlers
+
+import (
+ "vingo/database"
+
+ "github.com/gofiber/fiber/v2"
+)
+
+type Seasons struct{}
+
+func (Seasons) Get(c *fiber.Ctx) error {
+ seasons, err := database.Season{}.GetAll()
+ if err != nil {
+ logger.Println(err)
+ return c.Status(500).SendString("Error getting seasons")
+ }
+
+ return c.JSON(seasons)
+}
+
+func (Seasons) Create(c *fiber.Ctx) error {
+ season := database.Season{}
+ err := c.BodyParser(&season)
+ if err != nil {
+ logger.Println(err)
+ return c.Status(400).SendString("Invalid payload")
+ }
+
+ err = season.Create()
+ if err != nil {
+ logger.Println(err)
+ return c.Status(500).SendString("Error creating season")
+ }
+
+ return c.SendStatus(200)
+}
diff --git a/vingo/handlers/settings.go b/vingo/handlers/settings.go
index dbbeb53..9cccef5 100644
--- a/vingo/handlers/settings.go
+++ b/vingo/handlers/settings.go
@@ -18,8 +18,13 @@ func (Settings) Update(c *fiber.Ctx) error {
return c.Status(400).SendString("Invalid payload")
}
+ err = database.UpdateSettings(user.Id, settings)
+ if err != nil {
+ logger.Println(err)
+ return c.Status(500).SendString("Error updating settings")
+ }
+
sess, _ := store.Get(c)
- database.UpdateSettings(user.Id, settings)
user, _ = database.GetUser(user.Id)
sess.Set(STORE_USER, &user)
sess.Save()
diff --git a/vingo/main.go b/vingo/main.go
index ab8e540..8a6405c 100644
--- a/vingo/main.go
+++ b/vingo/main.go
@@ -56,8 +56,9 @@ func main() {
admin := api.Group("/admin", handlers.IsAdmin)
{
- admin.Post("/days", handlers.DaysRegister)
- admin.Post("/days/:id", handlers.DaysDelete)
+ admin.Get("/days", handlers.Days{}.All)
+ admin.Post("/days", handlers.Days{}.CreateMultiple)
+ admin.Delete("/days/:id", handlers.Days{}.Delete)
}
}
diff --git a/vinvoor/.gitignore b/vinvoor/.gitignore
index 3bb6b40..fc04cb3 100644
--- a/vinvoor/.gitignore
+++ b/vinvoor/.gitignore
@@ -27,3 +27,5 @@ dist-ssr
bin/
pkg/
.env
+
+test.js
diff --git a/vinvoor/.tool-versions b/vinvoor/.tool-versions
index dcf61b7..72c81fc 100644
--- a/vinvoor/.tool-versions
+++ b/vinvoor/.tool-versions
@@ -1 +1 @@
-nodejs 22.2.0
+nodejs 20.15.1
diff --git a/vinvoor/Dockerfile b/vinvoor/Dockerfile
index c48e4cd..e3c8a11 100644
--- a/vinvoor/Dockerfile
+++ b/vinvoor/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:22.2.0-alpine3.19 as build-stage
+FROM node:20.15.1-alpine3.20 as build-stage
WORKDIR /app
diff --git a/vinvoor/Dockerfile.dev b/vinvoor/Dockerfile.dev
index 5bb0f50..78607c3 100644
--- a/vinvoor/Dockerfile.dev
+++ b/vinvoor/Dockerfile.dev
@@ -1,4 +1,4 @@
-FROM node:22.2.0-alpine3.19
+FROM node:20.15.1-alpine3.20
WORKDIR /frontend
diff --git a/vinvoor/package.json b/vinvoor/package.json
index fdfbba9..95435df 100644
--- a/vinvoor/package.json
+++ b/vinvoor/package.json
@@ -16,17 +16,18 @@
"@fontsource/roboto": "^5.0.13",
"@mui/icons-material": "^5.15.19",
"@mui/material": "^5.15.19",
+ "@mui/x-date-pickers": "^7.11.0",
"@types/js-cookie": "^3.0.6",
"@types/react-router-dom": "^5.3.3",
"@types/react-router-hash-link": "^2.4.9",
"apexcharts": "^3.50.0",
+ "dayjs": "^1.11.12",
"js-cookie": "^3.0.5",
"material-ui-confirm": "^3.0.16",
"mdi-material-ui": "^7.9.1",
"notistack": "^3.0.1",
"react": "^18.2.0",
"react-apexcharts": "^1.4.1",
- "react-device-detect": "^2.2.3",
"react-dom": "^18.2.0",
"react-router-dom": "^6.23.1",
"react-router-hash-link": "^2.4.3",
diff --git a/vinvoor/src/App.tsx b/vinvoor/src/App.tsx
index 76278d2..e8882c3 100644
--- a/vinvoor/src/App.tsx
+++ b/vinvoor/src/App.tsx
@@ -4,7 +4,7 @@ import { Navigate, Outlet, useOutlet } from "react-router-dom";
import { LoadingSkeleton } from "./components/LoadingSkeleton";
import { NavBar } from "./navbar/NavBar";
import { Overview } from "./overview/Overview";
-import { UserContext } from "./user/UserProvider";
+import { UserContext } from "./providers/UserProvider";
import { WelcomePage } from "./WelcomePage";
export const App = () => {
diff --git a/vinvoor/src/WelcomePage.tsx b/vinvoor/src/WelcomePage.tsx
index e4a7e28..ea06511 100644
--- a/vinvoor/src/WelcomePage.tsx
+++ b/vinvoor/src/WelcomePage.tsx
@@ -29,26 +29,21 @@ export const WelcomePage = () => {
>
Welcome to Vinvoor!
Log in to start scanning
-
- Log in with Zauth
-
-
-
+
+
+ Log in with Zauth
+
+
+
+
);
};
-
-//
-//
-//
diff --git a/vinvoor/src/cards/CardsAdd.tsx b/vinvoor/src/cards/CardsAdd.tsx
index fa5eb00..b64a134 100644
--- a/vinvoor/src/cards/CardsAdd.tsx
+++ b/vinvoor/src/cards/CardsAdd.tsx
@@ -73,7 +73,7 @@ export const CardsAdd = () => {
await postApi(REGISTER_ENDPOINT)
.then(() => (started = true))
.catch((error) => {
- if (isResponseNot200Error(error))
+ if (isResponseNot200Error(error)) {
error.response
.json()
.then((response: CardPostResponse) => {
@@ -86,7 +86,7 @@ export const CardsAdd = () => {
variant: "error",
});
});
- else throw new Error(error);
+ } else throw new Error(error);
});
}
@@ -95,29 +95,36 @@ export const CardsAdd = () => {
if (started) {
setRegistering(true);
- const id = randomInt().toString();
- enqueueSnackbar(requestSuccess, {
- variant: "info",
- persist: true,
- key: id,
- });
+ let id: string | undefined;
+
+ if (!(response.registering && response.isCurrentUser)) {
+ id = randomInt().toString();
+ enqueueSnackbar(requestSuccess, {
+ variant: "info",
+ persist: true,
+ key: id,
+ });
+ }
checkCardsChange()
.then((scanned) => {
- closeSnackbar(id);
setRegistering(false);
- if (scanned) {
- enqueueSnackbar(registerSucces, {
- variant: "success",
- });
- getApi(
- "cards",
- convertCardJSON
- ).then((cards) => setCards(cards));
- } else
- enqueueSnackbar(registerFail, {
- variant: "error",
- });
+ if (id) {
+ closeSnackbar(id);
+
+ if (scanned) {
+ enqueueSnackbar(registerSucces, {
+ variant: "success",
+ });
+ getApi(
+ "cards",
+ convertCardJSON
+ ).then((cards) => setCards(cards));
+ } else
+ enqueueSnackbar(registerFail, {
+ variant: "error",
+ });
+ }
})
.finally(() => setProgressProps(defaultProgressProps));
}
diff --git a/vinvoor/src/cards/CardsDelete.tsx b/vinvoor/src/cards/CardsDelete.tsx
index fa63fcd..2fd8e29 100644
--- a/vinvoor/src/cards/CardsDelete.tsx
+++ b/vinvoor/src/cards/CardsDelete.tsx
@@ -1,23 +1,27 @@
import DeleteIcon from "@mui/icons-material/Delete";
import { IconButton, Link, Tooltip, Typography } from "@mui/material";
import { useConfirm } from "material-ui-confirm";
+import { useSnackbar } from "notistack";
import { FC } from "react";
interface CardDeleteProps {
selected: readonly string[];
}
+const deletePressed = "Not implemented yet :'(";
+
export const CardsDelete: FC = ({ selected }) => {
const confirm = useConfirm();
+ const { enqueueSnackbar } = useSnackbar();
const numSelected = selected.length;
const title = `Delete card${numSelected > 1 ? "s" : ""}`;
const content = (
-
- ` Are you sure you want to delete ${numSelected} card$
+
+ Are you sure you want to delete {numSelected} card
{numSelected > 1 ? "s" : ""}? Unfortunately, this feature isn't
available yet. Let's convince Hannes to add this feature by signing
- this petition!`
+ this petition!
);
@@ -26,7 +30,7 @@ export const CardsDelete: FC = ({ selected }) => {
title: title,
description: content,
confirmationText: "Delete",
- }).then(() => console.log("Card deleted!"));
+ }).then(() => enqueueSnackbar(deletePressed, { variant: "error" }));
};
return (
diff --git a/vinvoor/src/cards/CardsTable.tsx b/vinvoor/src/cards/CardsTable.tsx
index 512e777..ae828dd 100644
--- a/vinvoor/src/cards/CardsTable.tsx
+++ b/vinvoor/src/cards/CardsTable.tsx
@@ -20,8 +20,8 @@ const getComparator = (
order: TableOrder,
orderBy: Key
): ((
- a: { [key in Key]: number | string | Date },
- b: { [key in Key]: number | string | Date }
+ a: Record,
+ b: Record
) => number) => {
return order === "desc"
? (a, b) => descendingComparator(a, b, orderBy)
diff --git a/vinvoor/src/cards/CardsTableBody.tsx b/vinvoor/src/cards/CardsTableBody.tsx
index 1d01ef7..53702b8 100644
--- a/vinvoor/src/cards/CardsTableBody.tsx
+++ b/vinvoor/src/cards/CardsTableBody.tsx
@@ -68,17 +68,16 @@ export const CardsTableBody: FC = ({
(cards) => setCards(cards)
);
})
- .catch((error) => {
- enqueueSnackbar(nameSaveFailure, { variant: "error" });
- console.log(error);
- });
+ .catch(() =>
+ enqueueSnackbar(nameSaveFailure, { variant: "error" })
+ );
})
.catch(() => {}); // Required otherwise the confirm dialog will throw an error in the console
};
const editButton = (id: number, name: string) => (
handleEditClick(id, name)}>
-
+
);
diff --git a/vinvoor/src/cards/CardsTableHead.tsx b/vinvoor/src/cards/CardsTableHead.tsx
index 9c651c0..1604fea 100644
--- a/vinvoor/src/cards/CardsTableHead.tsx
+++ b/vinvoor/src/cards/CardsTableHead.tsx
@@ -57,7 +57,9 @@ export const CardsTableHead: FC = ({
direction={orderBy === headCell.id ? order : "asc"}
onClick={createSortHandler(headCell.id)}
>
- {headCell.label}
+
+ {headCell.label}
+
))}
diff --git a/vinvoor/src/cards/CardsTableToolbar.tsx b/vinvoor/src/cards/CardsTableToolbar.tsx
index f9dc865..8c55b24 100644
--- a/vinvoor/src/cards/CardsTableToolbar.tsx
+++ b/vinvoor/src/cards/CardsTableToolbar.tsx
@@ -37,7 +37,11 @@ export const CardsTableToolbar: FC = ({ selected }) => {
>
) : (
<>
-
+
Cards
diff --git a/vinvoor/src/components/BrowserView.tsx b/vinvoor/src/components/BrowserView.tsx
new file mode 100644
index 0000000..bdee5ac
--- /dev/null
+++ b/vinvoor/src/components/BrowserView.tsx
@@ -0,0 +1,25 @@
+import { useMediaQuery, useTheme } from "@mui/material";
+import { FC, useEffect } from "react";
+
+interface BrowserViewProps {
+ onMobileView?: () => void;
+ onBrowserView?: () => void;
+ children: React.ReactNode;
+}
+
+export const BrowserView: FC = ({
+ onMobileView,
+ onBrowserView,
+ children,
+}) => {
+ const theme = useTheme();
+ const isMobileView = useMediaQuery(theme.breakpoints.down("md"));
+
+ // Only run callbacks after the component has rendered
+ useEffect(() => {
+ if (isMobileView) onMobileView?.();
+ else onBrowserView?.();
+ }, [isMobileView]);
+
+ return isMobileView ? null : <>{children}>;
+};
diff --git a/vinvoor/src/components/DarkModeToggle.tsx b/vinvoor/src/components/DarkModeToggle.tsx
index ab4833e..602a635 100644
--- a/vinvoor/src/components/DarkModeToggle.tsx
+++ b/vinvoor/src/components/DarkModeToggle.tsx
@@ -1,14 +1,13 @@
import { DarkModeOutlined, LightModeOutlined } from "@mui/icons-material";
import { IconButton, Tooltip } from "@mui/material";
import { useContext } from "react";
-import { ThemeContext } from "../theme/ThemeProvider";
+import { ThemeContext } from "../providers/ThemeProvider";
export const DarkModeToggle = () => {
- const { themeMode, toggleTheme } = useContext(ThemeContext);
+ const { themeMode, setTheme } = useContext(ThemeContext);
- const handleThemeChange = () => {
- toggleTheme();
- };
+ const handleThemeChange = () =>
+ setTheme(themeMode === "light" ? "dark" : "light");
return (
{
);
};
+``
diff --git a/vinvoor/src/components/LoadingSkeleton.tsx b/vinvoor/src/components/LoadingSkeleton.tsx
index 04ff32e..4c20e9a 100644
--- a/vinvoor/src/components/LoadingSkeleton.tsx
+++ b/vinvoor/src/components/LoadingSkeleton.tsx
@@ -11,9 +11,5 @@ export const LoadingSkeleton: FC = ({
children,
...props
}) => {
- return loading ? (
-
- ) : (
- children
- );
+ return loading ? : children;
};
diff --git a/vinvoor/src/hooks/useFetch.ts b/vinvoor/src/hooks/useFetch.ts
index c26ac0b..eee5f03 100644
--- a/vinvoor/src/hooks/useFetch.ts
+++ b/vinvoor/src/hooks/useFetch.ts
@@ -1,5 +1,12 @@
-import { Dispatch, SetStateAction, useEffect, useState } from "react";
-import { getApi } from "../util/fetch";
+import {
+ Dispatch,
+ SetStateAction,
+ useContext,
+ useEffect,
+ useState,
+} from "react";
+import { UserContext } from "../providers/UserProvider";
+import { getApi, isResponseNot200Error } from "../util/fetch";
interface useFetchResult {
loading: boolean;
@@ -14,10 +21,25 @@ export const useFetch = (
const [loading, setLoading] = useState(true);
const [error, setError] = useState(undefined);
+ const { setUserState } = useContext(UserContext);
+
useEffect(() => {
getApi(endpoint, convertData)
.then((data) => setData(data))
- .catch((error) => setError(error))
+ .catch((error) => {
+ if (
+ isResponseNot200Error(error) &&
+ error.response.status === 401
+ ) {
+ setUserState({
+ user: undefined,
+ loading: false,
+ error: error,
+ });
+ }
+
+ setError(error);
+ })
.finally(() => setLoading(false));
}, [endpoint]);
diff --git a/vinvoor/src/leaderboard/Leaderboard.tsx b/vinvoor/src/leaderboard/Leaderboard.tsx
index ca9ebb6..ccd6c94 100644
--- a/vinvoor/src/leaderboard/Leaderboard.tsx
+++ b/vinvoor/src/leaderboard/Leaderboard.tsx
@@ -20,7 +20,7 @@ export const Leaderboard = () => {
diff --git a/vinvoor/src/leaderboard/LeaderboardTableBody.tsx b/vinvoor/src/leaderboard/LeaderboardTableBody.tsx
index 7f94e90..4c9d6f2 100644
--- a/vinvoor/src/leaderboard/LeaderboardTableBody.tsx
+++ b/vinvoor/src/leaderboard/LeaderboardTableBody.tsx
@@ -5,16 +5,11 @@ import {
TableRow,
Typography,
} from "@mui/material";
-import { alpha } from "@mui/material/styles";
-import {
- ArrowDownBoldHexagonOutline,
- ArrowUpBoldHexagonOutline,
- Minus,
-} from "mdi-material-ui";
+import { alpha, Theme, useTheme } from "@mui/material/styles";
import { FC, useContext } from "react";
+import { UserContext } from "../providers/UserProvider";
import { TableHeadCell } from "../types/general";
import { leaderboardHeadCells, LeaderboardItem } from "../types/leaderboard";
-import { UserContext } from "../user/UserProvider";
import FirstPlaceIcon from "/first_place.svg";
import SecondPlaceIcon from "/second_place.svg";
import ThirdPlaceIcon from "/third_place.svg";
@@ -23,43 +18,61 @@ interface LeaderboardTableBodyProps {
leaderboardItems: readonly LeaderboardItem[];
}
+const leaderboardColors = [
+ (theme: Theme) => theme.leaderboard.first,
+ (theme: Theme) => theme.leaderboard.second,
+ (theme: Theme) => theme.leaderboard.third,
+];
+
+const leaderboardText = [
+ { fontSize: "30px", fontWeight: "bold" },
+ { fontSize: "25px", fontWeight: "bold" },
+ { fontSize: "18px", fontWeight: "bold" },
+];
+
+const getLeaderboardColor = (index: number, theme: Theme) =>
+ leaderboardColors[index]
+ ? { backgroundColor: leaderboardColors[index](theme) }
+ : {};
+
+const getLeaderboardText = (index: number) => leaderboardText[index] || {};
+
const getPositionChange = (positionChange: number) => {
- let icon: JSX.Element | null = null;
+ let color = "text.primary";
+ let prefix = "";
if (positionChange > 0) {
- icon = ;
+ color = "success.light";
+ prefix = "+";
} else if (positionChange < 0) {
- icon = ;
- } else {
- icon = ;
+ color = "error.light";
}
return (
- <>
- {icon}
- {positionChange}
- >
+
+ {prefix}
+ {positionChange !== 0 && positionChange}
+
);
};
const getPosition = (position: number) => {
switch (position) {
case 1:
- // return ;
return (
-
+
);
case 2:
return (
-
+
);
case 3:
return (
-
+
);
@@ -78,13 +91,22 @@ const getCell = (
case "position":
return getPosition(row[headCell.id]);
default:
- return {row[headCell.id]};
+ return (
+
+ {row[headCell.id]}
+
+ );
}
};
export const LeaderboardTableBody: FC = ({
leaderboardItems: rows,
}) => {
+ const theme = useTheme();
const {
userState: { user },
} = useContext(UserContext);
@@ -108,6 +130,7 @@ export const LeaderboardTableBody: FC = ({
theme.palette.action.activatedOpacity
),
}),
+ ...getLeaderboardColor(index, theme),
}}
>
{leaderboardHeadCells.map((headCell) => (
diff --git a/vinvoor/src/leaderboard/LeaderboardTableToolbar.tsx b/vinvoor/src/leaderboard/LeaderboardTableToolbar.tsx
index 44f9103..6d9ff5a 100644
--- a/vinvoor/src/leaderboard/LeaderboardTableToolbar.tsx
+++ b/vinvoor/src/leaderboard/LeaderboardTableToolbar.tsx
@@ -2,7 +2,7 @@ import { MoveDown } from "@mui/icons-material";
import { Button, Toolbar, Typography } from "@mui/material";
import { FC, useContext } from "react";
import { HashLink } from "react-router-hash-link";
-import { UserContext } from "../user/UserProvider";
+import { UserContext } from "../providers/UserProvider";
interface LeaderboardTableToolbarProps {}
diff --git a/vinvoor/src/main.tsx b/vinvoor/src/main.tsx
index f45b059..0621eee 100644
--- a/vinvoor/src/main.tsx
+++ b/vinvoor/src/main.tsx
@@ -4,7 +4,6 @@ import "@fontsource/roboto/500.css";
import "@fontsource/roboto/700.css";
import { CssBaseline } from "@mui/material";
import { ConfirmProvider } from "material-ui-confirm";
-import { SnackbarProvider } from "notistack";
import React from "react";
import ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
@@ -13,11 +12,14 @@ import { App } from "./App.tsx";
import { Cards } from "./cards/Cards.tsx";
import { ErrorPage } from "./errors/ErrorPage.tsx";
import { Leaderboard } from "./leaderboard/Leaderboard.tsx";
+import { CustomSnackbarProvider } from "./providers/CustomSnackbarProvider.tsx";
+import { ThemeProvider } from "./providers/ThemeProvider.tsx";
+import { UserProvider } from "./providers/UserProvider.tsx";
import { Scans } from "./scans/Scans.tsx";
-import { ThemeProvider } from "./theme/ThemeProvider";
+import { Admin } from "./settings/admin/Admin.tsx";
+import { SettingsOverview } from "./settings/SettingsOverview.tsx";
import { Login } from "./user/Login.tsx";
import { Logout } from "./user/Logout.tsx";
-import { UserProvider } from "./user/UserProvider.tsx";
const router = createBrowserRouter([
{
@@ -47,8 +49,12 @@ const router = createBrowserRouter([
},
{
path: "settings",
-
- }
+ element: ,
+ },
+ {
+ path: "admin",
+ element: ,
+ },
],
},
]);
@@ -59,14 +65,9 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
-
+
-
+
diff --git a/vinvoor/src/navbar/NavBar.tsx b/vinvoor/src/navbar/NavBar.tsx
index a07435d..b4413da 100644
--- a/vinvoor/src/navbar/NavBar.tsx
+++ b/vinvoor/src/navbar/NavBar.tsx
@@ -1,12 +1,13 @@
-import LeaderboardIcon from "@mui/icons-material/Leaderboard";
+import { LeaderboardOutlined } from "@mui/icons-material";
import { AppBar, Box, Container, Toolbar } from "@mui/material";
import {
+ CogOutline,
CreditCardMultipleOutline,
CreditCardScanOutline,
} from "mdi-material-ui";
import { useContext } from "react";
import { DarkModeToggle } from "../components/DarkModeToggle";
-import { UserContext } from "../user/UserProvider";
+import { UserContext } from "../providers/UserProvider";
import { NavBarLogo } from "./NavBarLogo";
import { NavBarPages } from "./NavBarPages";
import { NavBarSandwich } from "./NavBarSandwich";
@@ -20,10 +21,12 @@ export interface PageIcon {
const navBarPages: PageIcon[] = [
{ page: "Scans", icon: },
{ page: "Cards", icon: },
- { page: "Leaderboard", icon: },
+ { page: "Leaderboard", icon: },
];
-const userMenuPages: PageIcon[] = [];
+const userMenuPages: PageIcon[] = [
+ { page: "Settings", icon: },
+];
export const NavBar = () => {
const {
@@ -36,13 +39,7 @@ export const NavBar = () => {
};
return (
-
+
{/* Display either the ZeSS logo or a sandwich menu */}
diff --git a/vinvoor/src/navbar/NavBarLogo.tsx b/vinvoor/src/navbar/NavBarLogo.tsx
index 015a46d..12c86b3 100644
--- a/vinvoor/src/navbar/NavBarLogo.tsx
+++ b/vinvoor/src/navbar/NavBarLogo.tsx
@@ -1,22 +1,45 @@
import { Box, Button, SxProps, Theme, Typography } from "@mui/material";
import { HexagonSlice6 } from "mdi-material-ui";
-import { FC } from "react";
+import { FC, useContext } from "react";
import { UnstyledLink } from "../components/UnstyledLink";
+import { ThemeContext } from "../providers/ThemeProvider";
interface NavBarLogoProps {
sx?: SxProps;
}
+const CLICK_AMOUNT = 10;
+const CLICK_TIME_MS = 1000;
+
+let pressedAmount = 0;
+let startTimePress = 0;
+
export const NavBarLogo: FC = ({ sx }) => {
+ const { setTheme } = useContext(ThemeContext);
+ const handleClick = () => {
+ if (pressedAmount < CLICK_AMOUNT) {
+ if (pressedAmount === 0) startTimePress = Date.now();
+
+ pressedAmount++;
+
+ if (
+ pressedAmount === CLICK_AMOUNT &&
+ Date.now() - startTimePress <= CLICK_TIME_MS
+ )
+ setTheme("hidden");
+ }
+ };
+
return (
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+ ) : (
+
+
+ You don't have any scans.
+
+
+ Start scanning to see some data!
+
+
+ )}
);
};
-
-// Current height of the heatmap is calculated using ref's and calculus
-// TODO: Change it as it is very very very very very very ugly ^^
diff --git a/vinvoor/src/overview/checkin/CheckIn.tsx b/vinvoor/src/overview/checkin/CheckIn.tsx
index d174615..4f53b22 100644
--- a/vinvoor/src/overview/checkin/CheckIn.tsx
+++ b/vinvoor/src/overview/checkin/CheckIn.tsx
@@ -7,31 +7,28 @@ import { ScanContext } from "../Overview";
export const CheckIn = () => {
const { scans } = useContext(ScanContext);
- const checkedIn =
- scans.length > 0 &&
- isTheSameDay(scans[scans.length - 1].scanTime, new Date());
+ const checkedIn = isTheSameDay(
+ scans[scans.length - 1].scanTime,
+ new Date()
+ );
return checkedIn ? (
,
- }}
+ icon={}
>
Checked in
- Nice of you to stop by!
+ Nice of you to stop by !
) : (
,
- }}
+ icon={}
>
Not checked in
- We miss you!
+ We miss you !
);
};
diff --git a/vinvoor/src/overview/days/Days.tsx b/vinvoor/src/overview/days/Days.tsx
index d0f1dab..fb97935 100644
--- a/vinvoor/src/overview/days/Days.tsx
+++ b/vinvoor/src/overview/days/Days.tsx
@@ -1,3 +1,4 @@
+import { useTheme } from "@mui/material";
import { ApexOptions } from "apexcharts";
import { useContext } from "react";
import Chart from "react-apexcharts";
@@ -9,17 +10,34 @@ const getDayCount = (scans: readonly Scan[]) => {
scans.forEach((scan) => {
days[scan.scanTime.getDay() - 1]++;
});
- return days.slice(0, -2);
+ return days.slice(0, -2) as ApexNonAxisChartSeries;
};
export const Days = () => {
+ const theme = useTheme();
const { scans } = useContext(ScanContext);
const state = {
options: {
labels: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
+ colors: [
+ theme.days.color0,
+ theme.days.color1,
+ theme.days.color2,
+ theme.days.color3,
+ theme.days.color4,
+ ],
fill: {
- opacity: 1,
+ opacity: 0.9,
+ type: "gradient",
+ gradient: {
+ shade: "dark",
+ type: "vertical",
+ shadeIntensity: 0.2,
+ },
+ },
+ stroke: {
+ show: false,
},
yaxis: {
show: false,
@@ -40,14 +58,6 @@ export const Days = () => {
},
},
},
- theme: {
- monochrome: {
- enabled: true,
- color: "#ff7f00",
- shadeTo: "light",
- shadeIntensity: 1,
- },
- },
} as ApexOptions,
series: getDayCount(scans),
};
diff --git a/vinvoor/src/overview/heatmap/Day.tsx b/vinvoor/src/overview/heatmap/Day.tsx
new file mode 100644
index 0000000..4f0a3a5
--- /dev/null
+++ b/vinvoor/src/overview/heatmap/Day.tsx
@@ -0,0 +1,195 @@
+import { useTheme } from "@mui/material";
+import { FC, useContext, useMemo } from "react";
+import { ScanContext } from "../Overview";
+import "./heatmap.css";
+import { Rect } from "./Rect";
+import { DayData, HeatmapVariant } from "./types";
+import {
+ DATE_FORMATTER,
+ DAYS_IN_WEEK,
+ formatData,
+ getColumnCountMonths,
+ getMondayIndexedDay,
+ isDayVariant,
+ MILLISECONDS_IN_DAY,
+ styleMonth,
+ WEEKS_IN_MONTH,
+} from "./utils";
+
+interface DayProps {
+ startDate: Date;
+ endDate: Date;
+ columnCount: number;
+ transform: string;
+ isSmallView: boolean;
+ variant: HeatmapVariant;
+}
+
+export const Day: FC = ({
+ startDate,
+ endDate,
+ columnCount,
+ transform,
+ isSmallView,
+ variant,
+}) => {
+ const theme = useTheme();
+ const { scans } = useContext(ScanContext);
+
+ const data = useMemo(() => {
+ const normalizedScans = [...scans];
+ normalizedScans.forEach((scan) => scan.scanTime.setHours(0, 0, 0, 0));
+ const formattedScans = formatData(normalizedScans);
+
+ const start = new Date(
+ startDate.getTime() -
+ startDate.getDay() * MILLISECONDS_IN_DAY +
+ MILLISECONDS_IN_DAY
+ );
+
+ const startDates = [
+ ...Array(getColumnCountMonths(startDate, endDate)),
+ ].map((_, idx) => {
+ const newStartDate = new Date(startDate);
+ if (idx === 0) {
+ while (newStartDate.getDay() !== 1) {
+ newStartDate.setDate(newStartDate.getDate() - 1);
+ }
+ } else {
+ newStartDate.setMonth(newStartDate.getMonth() + idx);
+ newStartDate.setDate(1);
+ while (newStartDate.getDay() !== 1) {
+ newStartDate.setDate(newStartDate.getDate() + 1);
+ }
+ }
+
+ return newStartDate;
+ });
+
+ const endWeek = new Date(
+ endDate.getTime() +
+ MILLISECONDS_IN_DAY *
+ (DAYS_IN_WEEK -
+ (getMondayIndexedDay(endDate) % DAYS_IN_WEEK))
+ );
+
+ return {
+ data: formattedScans,
+ start,
+ endWeek,
+ startDates,
+ };
+ }, [scans, startDate, endDate]);
+
+ return (
+
+ {[...Array(columnCount)].map((_, idx) => {
+ return (
+
+ {isDayVariant(variant)
+ ? [...Array(DAYS_IN_WEEK)].map((_, cidx) => {
+ const currentDate = new Date(
+ data.start.getTime() +
+ MILLISECONDS_IN_DAY *
+ (idx * DAYS_IN_WEEK + cidx)
+ );
+
+ if (
+ currentDate.getTime() <
+ startDate.getTime()
+ )
+ return null;
+
+ if (currentDate.getTime() > endDate.getTime())
+ return null;
+
+ let colors = theme.heatmap.colorInActive;
+ if (data.data[currentDate.getTime()])
+ colors = theme.heatmap.colorActive;
+
+ const dataTooltipContent = `${
+ data.data[currentDate.getTime()]
+ ? "Present"
+ : "Absent"
+ } on ${DATE_FORMATTER.format(currentDate)}`;
+
+ return (
+
+ );
+ })
+ : [...Array(WEEKS_IN_MONTH)].map((_, cidx) => {
+ const currentDate = new Date(
+ data.startDates[idx].getTime() +
+ MILLISECONDS_IN_DAY *
+ cidx *
+ DAYS_IN_WEEK
+ );
+
+ // Week is no longer in the month
+ if (
+ currentDate.getMonth() >
+ startDate.getMonth() + idx &&
+ getMondayIndexedDay(currentDate) <=
+ currentDate.getDate() - 1
+ )
+ return null;
+
+ // Week is after end date
+ if (
+ currentDate.getTime() >=
+ data.endWeek.getTime()
+ )
+ return null;
+
+ const count = [...Array(DAYS_IN_WEEK)]
+ .map(
+ (_, i) =>
+ new Date(
+ currentDate.getTime() +
+ i * MILLISECONDS_IN_DAY
+ )
+ )
+ .filter(
+ (date) =>
+ date.getTime() <=
+ endDate.getTime() &&
+ data.data[date.getTime()]
+ ).length;
+
+ const colors =
+ styleMonth[Math.min(count, 5)](theme); // Can be higher than 5 if multiple scans in a day or scanned during the weekend
+
+ const dataTooltipContent = `${count} scan${
+ count !== 1 ? "s" : ""
+ } in the week of ${DATE_FORMATTER.format(
+ currentDate
+ )}`;
+
+ return (
+
+ );
+ })}
+
+ );
+ })}
+
+ );
+};
diff --git a/vinvoor/src/overview/heatmap/Heatmap.tsx b/vinvoor/src/overview/heatmap/Heatmap.tsx
index 0189a5f..4066bfd 100644
--- a/vinvoor/src/overview/heatmap/Heatmap.tsx
+++ b/vinvoor/src/overview/heatmap/Heatmap.tsx
@@ -1,257 +1,64 @@
-import { Box } from "@mui/material";
-import { FC, useContext } from "react";
-import { MILLISECONDS_IN_ONE_DAY, shiftDate } from "../../util/util";
-import { ScanContext } from "../Overview";
-import "./heatmap.css";
+import { useMediaQuery, useTheme } from "@mui/material";
+import { FC } from "react";
+import { Day } from "./Day";
+import { LabelsMonth } from "./LabelsMonth";
+import { HeatmapVariant } from "./types";
import {
- dateTimeFormat,
DAYS_IN_WEEK,
- getColumnCount,
- getEmpty,
- getHeight,
- getMonthLabelCoordinates,
- getSquareCoordinates,
- getTransformForAllWeeks,
- getTransformForColumn,
- getTransformForMonthLabels,
- getWidth,
- MONTH_LABELS,
- SQUARE_SIZE,
+ getColumnCountDays,
+ getColumnCountMonths,
+ isDayVariant,
+ LEFT_PAD,
+ RECT_SIZE,
+ SPACE,
+ TOP_PAD,
+ WEEKS_IN_MONTH,
} from "./utils";
-export interface HeatmapItem {
- date: Date;
- count: number;
-}
-
-export enum HeatmapVariant {
- DAYS,
- MONTHS,
-}
-
interface HeatmapProps {
startDate: Date;
endDate: Date;
variant: HeatmapVariant;
- maxHeight: number;
}
-const getAllValues = (
- days: readonly Date[],
- startDate: Date,
- endDate: Date,
- variant: HeatmapVariant
-): HeatmapItem[] => {
- const values: readonly HeatmapItem[] = days.map((date) => ({
- date,
- count: 1,
- }));
- if (variant === HeatmapVariant.DAYS) {
- return Array.from(
- {
- length:
- (endDate.getTime() - startDate.getTime()) /
- MILLISECONDS_IN_ONE_DAY +
- 1,
- },
- (_, i) => {
- const date = shiftDate(startDate, i);
- return (
- values.find((v) => v.date.getTime() === date.getTime()) || {
- date,
- count: 0,
- }
- );
- }
- );
- } else {
- return Array.from(
- {
- length: getColumnCount(startDate, endDate, HeatmapVariant.DAYS),
- },
- (_, i) => {
- const start = shiftDate(startDate, i * DAYS_IN_WEEK);
- const count = Array.from({
- length: DAYS_IN_WEEK,
- }).reduce((sum, _, j) => {
- const date = shiftDate(start, j);
- const value = values.find(
- (v) => v.date.getTime() === date.getTime()
- );
- return sum + (value ? value.count : 0);
- }, 0);
-
- return { date: start, count };
- }
- );
- }
-};
-
-const getWeeksInMonth = (
- values: HeatmapItem[],
- startDate: Date
-): { [key: number]: number } => {
- const startYear = values[0].date.getFullYear();
- return values.reduce(
- (acc, value) => {
- const index =
- (value.date.getFullYear() - startYear) * 12 +
- value.date.getMonth() -
- startDate.getMonth();
- acc[index] = (acc[index] || 0) + 1;
- return acc;
- },
- {
- [startDate.getMonth()]: getEmpty(
- values[0].date,
- HeatmapVariant.MONTHS
- ),
- } as {
- [key: number]: number;
- }
- );
-};
-
-const getClassNameForValue = (value: HeatmapItem, variant: HeatmapVariant) => {
- if (variant === HeatmapVariant.DAYS) {
- if (value.count > 0) return `color-active`;
-
- return `color-inactive`;
- } else {
- if (value.count <= 5) return `color-${value.count}`;
-
- return "color-5";
- }
-};
-
-const getTooltipDataAttrsForDate = (
- value: HeatmapItem,
- variant: HeatmapVariant
-) => ({
- "data-tooltip-id": "heatmap",
- "data-tooltip-content":
- variant === HeatmapVariant.DAYS
- ? getTooltipDataAttrsForDays(value)
- : getTooltipDataAttrsForMonths(value),
-});
+export const Heatmap: FC = ({ startDate, endDate, variant }) => {
+ const theme = useTheme();
+ const isSmallView = useMediaQuery(theme.breakpoints.down("lg"));
-const getTooltipDataAttrsForDays = (value: HeatmapItem) =>
- `${value.count > 0 ? "Present" : "Absent"} on ${dateTimeFormat.format(
- value.date
- )}`;
-
-const getTooltipDataAttrsForMonths = (value: HeatmapItem) =>
- `${value.count} scan${
- value.count !== 1 ? "s" : ""
- } on the week of ${dateTimeFormat.format(value.date)}`;
-
-export const Heatmap: FC = ({
- startDate,
- endDate,
- variant,
- maxHeight,
-}) => {
- const { scans } = useContext(ScanContext);
- const days = scans.map((scan) => scan.scanTime);
-
- days.forEach((date) => date.setHours(0, 0, 0, 0));
startDate.setHours(0, 0, 0, 0);
endDate.setHours(0, 0, 0, 0);
- const values = getAllValues(days, startDate, endDate, variant);
-
- const viewBox = `0 0 ${getWidth(startDate, endDate, variant)} ${getHeight(
- variant
- )}`;
-
- const weeksInMonth =
- variant === HeatmapVariant.MONTHS
- ? getWeeksInMonth(values, startDate)
- : {}; // Amount of weeks in each month
-
- const columns = getColumnCount(startDate, endDate, variant); // Amount of columns of squares
- const emptyStart = getEmpty(startDate, variant); // Amount of empty squares at the start
- const emptyEnd = getEmpty(endDate, variant); // Amount of empty squares at the end
-
- let valueIndex = 0;
- const renderSquare = (row: number, column: number) => {
- if (column === 0 && row < emptyStart) return null;
-
- if (variant === HeatmapVariant.DAYS)
- if (column === columns - 1 && row > emptyEnd) return null;
-
- const value = values[valueIndex++];
-
- const [x, y] = getSquareCoordinates(row);
-
- return (
-
- );
- };
-
- const renderColumn = (column: number) => (
-
- {[
- ...Array(
- variant === HeatmapVariant.DAYS
- ? DAYS_IN_WEEK
- : weeksInMonth[column]
- ).keys(),
- ].map((row) => renderSquare(row, column))}
-
- );
-
- const renderColumns = () =>
- [...Array(columns).keys()].map((column) => renderColumn(column));
-
- const renderMonthLabels = () => {
- if (variant === HeatmapVariant.DAYS) {
- return [...Array(columns).keys()].map((column) => {
- const endOfWeek = shiftDate(startDate, column * DAYS_IN_WEEK);
- const [x, y] = getMonthLabelCoordinates(column);
-
- return endOfWeek.getDate() >= 1 &&
- endOfWeek.getDate() <= DAYS_IN_WEEK ? (
-
- {MONTH_LABELS[endOfWeek.getMonth()]}
-
- ) : null;
- });
- } else {
- return [...Array(columns).keys()].map((column) => {
- if (column % 2 === 1) {
- return null;
- }
-
- const [x, y] = getMonthLabelCoordinates(column);
-
- return (
-
- {MONTH_LABELS[startDate.getMonth() + column]}
-
- );
- });
- }
- };
+ const columnCount = isDayVariant(variant)
+ ? getColumnCountDays(startDate, endDate)
+ : getColumnCountMonths(startDate, endDate);
return (
-
-
-
+
);
};
diff --git a/vinvoor/src/overview/heatmap/LabelsMonth.tsx b/vinvoor/src/overview/heatmap/LabelsMonth.tsx
new file mode 100644
index 0000000..6beb9c7
--- /dev/null
+++ b/vinvoor/src/overview/heatmap/LabelsMonth.tsx
@@ -0,0 +1,102 @@
+import { useTheme } from "@mui/material/styles";
+import { FC, useMemo } from "react";
+import { DayLabel, HeatmapVariant, LabelData, MonthLabel } from "./types";
+import {
+ DAYS_IN_WEEK,
+ FONT_SIZE,
+ getColumnCountDays,
+ getColumnCountMonths,
+ isDayVariant,
+ LEFT_PAD,
+ MILLISECONDS_IN_DAY,
+ MONTH_LABELS,
+ MONTH_RECT_Y,
+ RECT_SIZE,
+ SPACE,
+} from "./utils";
+
+interface LablesMonthProps {
+ startDate: Date;
+ endDate: Date;
+ isSmallView: boolean;
+ variant: HeatmapVariant;
+}
+
+export const LabelsMonth: FC = ({
+ startDate,
+ endDate,
+ isSmallView,
+ variant,
+}) => {
+ const theme = useTheme();
+
+ const data = useMemo(() => {
+ const day = [
+ ...Array(getColumnCountDays(startDate, endDate) * DAYS_IN_WEEK),
+ ]
+ .map((_, idx) => {
+ if ((idx / DAYS_IN_WEEK) % 1 === 0) {
+ const date = new Date(
+ startDate.getTime() + idx * MILLISECONDS_IN_DAY
+ );
+ const month = date.getMonth();
+
+ return {
+ col: idx / 7,
+ month,
+ monthStr: MONTH_LABELS[month],
+ };
+ }
+ return {} as DayLabel;
+ })
+ .filter((item) => Object.keys(item).length)
+ .filter((item, idx, list) =>
+ list[idx - 1] ? list[idx - 1]!.month !== item!.month : true
+ );
+
+ const month = [...Array(getColumnCountMonths(startDate, endDate))]
+ .map((_, idx) => {
+ const date = new Date(startDate);
+ date.setMonth(date.getMonth() + idx);
+
+ return { monthStr: MONTH_LABELS[date.getMonth()] };
+ })
+ .filter((_, idx) => idx % 2 === 0);
+ return {
+ day,
+ month,
+ };
+ }, [startDate, endDate]);
+
+ return (
+ <>
+ {(isDayVariant(variant)
+ ? (data.day as DayLabel[])
+ : (data.month as MonthLabel[])
+ ).map((item, idx) => {
+ return (
+
+ {item.monthStr}
+
+ );
+ })}
+ >
+ );
+};
diff --git a/vinvoor/src/overview/heatmap/Rect.tsx b/vinvoor/src/overview/heatmap/Rect.tsx
new file mode 100644
index 0000000..550f025
--- /dev/null
+++ b/vinvoor/src/overview/heatmap/Rect.tsx
@@ -0,0 +1,36 @@
+import { FC } from "react";
+import { HeatmapRectStyle } from "../../theme";
+import { RECT_RADIUS, RECT_SIZE, RECT_STROKE, SPACE } from "./utils";
+
+interface RectProps {
+ idx: number;
+ cidx: number;
+ isSmallView: boolean;
+ colors: HeatmapRectStyle;
+ dataTooltipContent: string;
+}
+
+export const Rect: FC = ({
+ idx,
+ cidx,
+ isSmallView,
+ colors,
+ dataTooltipContent,
+}) => {
+ return (
+
+ );
+};
diff --git a/vinvoor/src/overview/heatmap/heatmap.css b/vinvoor/src/overview/heatmap/heatmap.css
index 231fe10..d4f8cad 100644
--- a/vinvoor/src/overview/heatmap/heatmap.css
+++ b/vinvoor/src/overview/heatmap/heatmap.css
@@ -1,66 +1,3 @@
-.heatmap text {
- font-size: 10px;
- fill: #aaa;
-}
-
-.heatmap rect:hover {
- stroke-width: 1px;
- stroke-opacity: 0;
-}
-
-/*
- Gradients for months variant
-*/
-
-.heatmap .color-0 {
- fill: #eeeeee;
- stroke-width: 1px;
- stroke: #fcce9f;
-}
-.heatmap .color-1 {
- fill: #fcce9f;
- stroke-width: 1px;
- stroke: #fcbb79;
-}
-
-.heatmap .color-2 {
- fill: #fcbb79;
- stroke-width: 1px;
- stroke: #fa922a;
-}
-.heatmap .color-3 {
- fill: #fa922a;
- stroke-width: 1px;
- stroke: #ff7f00;
-}
-
-.heatmap .color-4 {
- fill: #ff7f00;
- stroke-width: 1px;
- stroke: #ba5f02;
-}
-.heatmap .color-5 {
- fill: #ba5f02;
- stroke-width: 1px;
- stroke: #934b01;
-}
-
-/*
- Active or not active for days variant
-*/
-
-.heatmap .color-inactive {
- fill: #eeeeee;
- stroke-width: 1px;
- stroke: #fcce9f;
-}
-
-.heatmap .color-active {
- fill: #ff7f00;
- stroke-width: 1px;
- stroke: #ba5f02;
-}
-
@keyframes createBox {
from {
width: 0;
@@ -71,6 +8,6 @@
}
}
-.rect {
- animation: createBox 1s;
+.rect:hover {
+ stroke-opacity: 0;
}
diff --git a/vinvoor/src/overview/heatmap/types.ts b/vinvoor/src/overview/heatmap/types.ts
new file mode 100644
index 0000000..3f933bc
--- /dev/null
+++ b/vinvoor/src/overview/heatmap/types.ts
@@ -0,0 +1,31 @@
+export enum HeatmapVariant {
+ DAYS,
+ MONTHS,
+}
+
+export interface HeatmapValue {
+ date: Date;
+ count: number; // Could be used in the future for check in and out
+}
+
+export interface DayData {
+ data: Record; // Each scan
+ start: Date; // Start brought back to the beginning of the week
+ endWeek: Date; // First day of the week after the end date
+ startDates: Record; // Start of each week for each month
+}
+
+export interface DayLabel {
+ col: number;
+ month: number;
+ monthStr: string;
+}
+
+export interface MonthLabel {
+ monthStr: string;
+}
+
+export interface LabelData {
+ day: DayLabel[];
+ month: MonthLabel[];
+}
diff --git a/vinvoor/src/overview/heatmap/utils.ts b/vinvoor/src/overview/heatmap/utils.ts
index efe2d1a..94443b9 100644
--- a/vinvoor/src/overview/heatmap/utils.ts
+++ b/vinvoor/src/overview/heatmap/utils.ts
@@ -1,13 +1,71 @@
-// Exports
+import { Theme } from "@mui/material";
+import { Scan } from "../../types/scans";
+import { HeatmapValue, HeatmapVariant } from "./types";
+
+export const getColumnCountDays = (startDate: Date, endDate: Date) => {
+ const startOfWeek = new Date(startDate);
+ startOfWeek.setDate(startOfWeek.getDate() - startOfWeek.getDay());
+
+ const endOfWeek = new Date(endDate);
+ if (endOfWeek.getDay() === 0)
+ endOfWeek.setDate(endOfWeek.getDate() - endOfWeek.getDay());
+ else endOfWeek.setDate(endOfWeek.getDate() - endOfWeek.getDay() + 6);
+
+ return Math.ceil(
+ (endOfWeek.getTime() - startOfWeek.getTime()) /
+ (DAYS_IN_WEEK * MILLISECONDS_IN_DAY)
+ );
+};
+
+export const getColumnCountMonths = (startDate: Date, endDate: Date) => {
+ return (
+ (endDate.getFullYear() - startDate.getFullYear()) * 12 +
+ endDate.getMonth() -
+ startDate.getMonth() +
+ 1
+ );
+};
+
+export const getMondayIndexedDay = (date: Date) => (date.getDay() + 6) % 7;
+
+export const formatData = (scans: Scan[]) => {
+ const result: Record = {};
+ scans.forEach((scan) => {
+ result[scan.scanTime.getTime()] = {
+ date: scan.scanTime,
+ count: 1,
+ };
+ });
-import { MILLISECONDS_IN_ONE_DAY } from "../../util/util";
-import { HeatmapVariant } from "./Heatmap";
+ return result;
+};
+
+export const isDayVariant = (variant: HeatmapVariant) =>
+ variant === HeatmapVariant.DAYS;
+
+export const styleMonth = [
+ (theme: Theme) => theme.heatmap.color0,
+ (theme: Theme) => theme.heatmap.color1,
+ (theme: Theme) => theme.heatmap.color2,
+ (theme: Theme) => theme.heatmap.color3,
+ (theme: Theme) => theme.heatmap.color4,
+ (theme: Theme) => theme.heatmap.color5,
+];
// Constants
-export const DAYS_IN_WEEK = 7;
-export const WEEKS_IN_MONTH = 5;
-export const SQUARE_SIZE = 10;
+// Size
+
+export const RECT_SIZE = (isSmallView: boolean) => (isSmallView ? 5 : 20);
+export const RECT_RADIUS = (isSmallView: boolean) => (isSmallView ? 1 : 4);
+export const RECT_STROKE = (isSmallView: boolean) => (isSmallView ? 1 : 2);
+export const SPACE = (isSmallView: boolean) => (isSmallView ? 2 : 10);
+export const TOP_PAD = (isSmallView: boolean) => (isSmallView ? 8 : 25);
+export const LEFT_PAD = (isSmallView: boolean) => (isSmallView ? 2 : 5);
+export const MONTH_RECT_Y = (isSmallView: boolean) => (isSmallView ? 5 : 15);
+export const FONT_SIZE = (isSmallView: boolean) => (isSmallView ? 4 : 15);
+
+// Month labels
export const MONTH_LABELS = [
"Jan",
@@ -23,79 +81,17 @@ export const MONTH_LABELS = [
"Nov",
"Dec",
];
-export const dateTimeFormat = new Intl.DateTimeFormat("en-GB", {
+
+// Formatter
+
+export const DATE_FORMATTER = new Intl.DateTimeFormat("en-GB", {
year: "2-digit",
month: "short",
day: "numeric",
});
-// Labels
-
-export const getMonthLabelSize = () => SQUARE_SIZE + MONTH_LABEL_GUTTER_SIZE;
-
-export const getMonthLabelCoordinates = (column: number) => [
- column * getSquareSize(),
- getMonthLabelSize() - MONTH_LABEL_GUTTER_SIZE,
-];
-
-// Transforms
+// Consts
-export const getTransformForColumn = (column: number) =>
- `translate(${column * getSquareSize() + GUTTERSIZE}, 0)`;
-
-export const getTransformForAllWeeks = () =>
- `translate(0, ${getMonthLabelSize()})`;
-
-export const getTransformForMonthLabels = () => `translate(0, 0)`;
-
-export const getWidth = (
- startDate: Date,
- endDate: Date,
- variant: HeatmapVariant
-) => getColumnCount(startDate, endDate, variant) * getSquareSize() + GUTTERSIZE;
-
-export const getHeight = (variant: HeatmapVariant) => {
- if (variant === HeatmapVariant.DAYS)
- return DAYS_IN_WEEK * getSquareSize() + getMonthLabelSize();
- else return WEEKS_IN_MONTH * getSquareSize() + getMonthLabelSize();
-};
-
-// Coordinate
-
-export const getSquareCoordinates = (dayIndex: number) => [
- 0,
- dayIndex * getSquareSize(),
-];
-
-// Utils
-
-export const getEmpty = (date: Date, variant: HeatmapVariant) => {
- if (variant === HeatmapVariant.DAYS)
- return (date.getDay() + DAYS_IN_WEEK - 1) % DAYS_IN_WEEK;
- else return Math.floor((date.getDate() - 1) / DAYS_IN_WEEK);
-};
-
-export const getColumnCount = (
- startDate: Date,
- endDate: Date,
- variant: HeatmapVariant
-) => {
- if (variant === HeatmapVariant.DAYS) {
- return Math.ceil(
- (endDate.getTime() - startDate.getTime()) /
- (DAYS_IN_WEEK * MILLISECONDS_IN_ONE_DAY)
- );
- } else {
- return (
- (endDate.getFullYear() - startDate.getFullYear()) * 12 +
- (endDate.getMonth() - startDate.getMonth() + 1)
- );
- }
-};
-
-// Local functions
-
-const GUTTERSIZE = 5;
-const MONTH_LABEL_GUTTER_SIZE = 8;
-
-const getSquareSize = () => SQUARE_SIZE + GUTTERSIZE;
+export const DAYS_IN_WEEK = 7;
+export const WEEKS_IN_MONTH = 5;
+export const MILLISECONDS_IN_DAY = 1000 * 60 * 60 * 24;
diff --git a/vinvoor/src/overview/streak/Streak.tsx b/vinvoor/src/overview/streak/Streak.tsx
index 072f6b5..10f7ebd 100644
--- a/vinvoor/src/overview/streak/Streak.tsx
+++ b/vinvoor/src/overview/streak/Streak.tsx
@@ -45,9 +45,8 @@ const getStreak = (scans: readonly Scan[]): [boolean, number] => {
let streak = 0;
const isOnStreak =
- dates.length > 0 &&
- (isTheSameDay(dates[dates.length - 1], new Date()) ||
- isWeekendBetween(dates[dates.length - 1], new Date()));
+ isTheSameDay(dates[dates.length - 1], new Date()) ||
+ isWeekendBetween(dates[dates.length - 1], new Date());
if (isOnStreak) {
let i = dates.length;
@@ -71,12 +70,27 @@ const getStreak = (scans: readonly Scan[]): [boolean, number] => {
export const Streak = () => {
const { scans } = useContext(ScanContext);
+
let [isOnStreak, streak] = getStreak(scans);
const color = isOnStreak ? "primary" : "error";
const textEnd = isOnStreak ? "streak" : "absent";
- return (
+ return streak === 0 ? (
+ `1px solid ${theme.palette.primary.main}`}
+ borderBottom={(theme) => `1px solid ${theme.palette.primary.main}`}
+ >
+
+ Scan to retain streak
+
+
+ ) : (
= ({
+ children,
+}) => {
+ const theme = useTheme();
+
+ const StyledMaterialDesignContent = styled(MaterialDesignContent)(() => ({
+ "&.notistack-MuiContent-success": {
+ backgroundColor: theme.palette.success.main,
+ },
+ "&.notistack-MuiContent-error": {
+ backgroundColor: theme.palette.error.dark,
+ },
+ }));
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/vinvoor/src/theme/ThemeProvider.tsx b/vinvoor/src/providers/ThemeProvider.tsx
similarity index 62%
rename from vinvoor/src/theme/ThemeProvider.tsx
rename to vinvoor/src/providers/ThemeProvider.tsx
index 9410443..a524b49 100644
--- a/vinvoor/src/theme/ThemeProvider.tsx
+++ b/vinvoor/src/providers/ThemeProvider.tsx
@@ -1,9 +1,7 @@
import { ThemeProvider as MUIThemeProvider } from "@mui/material";
import Cookies from "js-cookie";
import { createContext, FC, ReactNode, useEffect, useState } from "react";
-import { darkTheme, lightTheme } from "./theme";
-
-type ThemeMode = "light" | "dark";
+import { ThemeMode, themeModes } from "../theme";
interface ThemeProviderProps {
children: ReactNode;
@@ -11,12 +9,12 @@ interface ThemeProviderProps {
interface ThemeContextProps {
themeMode: ThemeMode;
- toggleTheme: () => void;
+ setTheme: (theme: ThemeMode) => void;
}
export const ThemeContext = createContext({
themeMode: "light",
- toggleTheme: () => {},
+ setTheme: () => {},
});
export const ThemeProvider: FC = ({ children }) => {
@@ -24,15 +22,13 @@ export const ThemeProvider: FC = ({ children }) => {
(import.meta.env.VITE_DEFAULT_THEME_MODE as ThemeMode) || "light"
);
- const toggleTheme = () => {
- setThemeMode((prevMode) => (prevMode === "light" ? "dark" : "light"));
- Cookies.set("theme", themeMode === "light" ? "dark" : "light", {
+ const setTheme = (theme: ThemeMode) => {
+ setThemeMode(theme);
+ Cookies.set("theme", theme as string, {
sameSite: "Lax",
});
};
- const theme = themeMode === "light" ? lightTheme : darkTheme;
-
useEffect(() => {
const storedTheme = Cookies.get("theme");
@@ -42,8 +38,10 @@ export const ThemeProvider: FC = ({ children }) => {
}, []);
return (
-
- {children}
+
+
+ {children}
+
);
};
diff --git a/vinvoor/src/user/UserProvider.tsx b/vinvoor/src/providers/UserProvider.tsx
similarity index 100%
rename from vinvoor/src/user/UserProvider.tsx
rename to vinvoor/src/providers/UserProvider.tsx
index f145e97..eb778d3 100644
--- a/vinvoor/src/user/UserProvider.tsx
+++ b/vinvoor/src/providers/UserProvider.tsx
@@ -62,8 +62,8 @@ export const UserProvider: FC = ({ children }) => {
newUserState.error = error;
})
.finally(() => {
- newUserState.loading = false;
setUserState(newUserState);
+ newUserState.loading = false;
});
}, []);
diff --git a/vinvoor/src/scans/Scans.tsx b/vinvoor/src/scans/Scans.tsx
index ced950f..f4f95a5 100644
--- a/vinvoor/src/scans/Scans.tsx
+++ b/vinvoor/src/scans/Scans.tsx
@@ -4,7 +4,7 @@ import { LoadingSkeleton } from "../components/LoadingSkeleton";
import { useFetch } from "../hooks/useFetch";
import { Card, convertCardJSON } from "../types/cards";
import { convertScanJSON, Scan } from "../types/scans";
-import { ScansTableBody } from "./ScansBody";
+import { ScansTableBody } from "./ScansTableBody";
import { ScansTableHead } from "./ScansTableHead";
export const Scans = () => {
diff --git a/vinvoor/src/scans/ScansBody.tsx b/vinvoor/src/scans/ScansTableBody.tsx
similarity index 85%
rename from vinvoor/src/scans/ScansBody.tsx
rename to vinvoor/src/scans/ScansTableBody.tsx
index 588a07d..3f1b4c7 100644
--- a/vinvoor/src/scans/ScansBody.tsx
+++ b/vinvoor/src/scans/ScansTableBody.tsx
@@ -17,7 +17,11 @@ export const ScansTableBody: FC = ({ scans, cards }) => {
const [scanCards, setScanCards] = useState([]);
useEffect(() => {
- setScanCards(mergeScansCards(scans, cards));
+ const mergedScansCards = mergeScansCards(scans, cards);
+ mergedScansCards.sort(
+ (a, b) => b.scanTime.getTime() - a.scanTime.getTime()
+ );
+ setScanCards(mergedScansCards);
}, [scans, cards]);
return (
diff --git a/vinvoor/src/scans/ScansTableHead.tsx b/vinvoor/src/scans/ScansTableHead.tsx
index 1ca025b..1f69697 100644
--- a/vinvoor/src/scans/ScansTableHead.tsx
+++ b/vinvoor/src/scans/ScansTableHead.tsx
@@ -7,7 +7,7 @@ export const ScansTableHead = () => {
{scanCardHeadCells.map((headCell) => (
- {headCell.label}
+ {headCell.label}
))}
diff --git a/vinvoor/src/settings/Settings.tsx b/vinvoor/src/settings/Settings.tsx
deleted file mode 100644
index e69de29..0000000
diff --git a/vinvoor/src/settings/SettingsOverview.tsx b/vinvoor/src/settings/SettingsOverview.tsx
new file mode 100644
index 0000000..014a728
--- /dev/null
+++ b/vinvoor/src/settings/SettingsOverview.tsx
@@ -0,0 +1,174 @@
+import {
+ Box,
+ Button,
+ Checkbox,
+ FormControl,
+ FormControlLabel,
+ Grid,
+ Paper,
+ Stack,
+ Tooltip,
+ Typography,
+} from "@mui/material";
+import { useConfirm } from "material-ui-confirm";
+import { HelpCircleOutline } from "mdi-material-ui";
+import { useSnackbar } from "notistack";
+import { ChangeEvent, useState } from "react";
+import { LoadingSkeleton } from "../components/LoadingSkeleton";
+import { useFetch } from "../hooks/useFetch";
+import {
+ adjustableSettings,
+ converSettingsJSON,
+ Settings,
+} from "../types/settings";
+import { patchApi } from "../util/fetch";
+
+const defaultSettings: Settings = {
+ id: -1,
+ createdAt: new Date(),
+ scanInOut: false,
+ leaderboard: false,
+ public: false,
+};
+
+const saveSuccess = "Settings saved successfully";
+const saveFailure = "Unable to save settings";
+const handleDeleteContent = (
+
+
+ Are you sure you want to delete all your data?
+
+
+ This is irreversible!
+
+
+);
+
+export const SettingsOverview = () => {
+ const [settings, setSettings] = useState(defaultSettings);
+ const { loading } = useFetch(
+ "settings",
+ setSettings,
+ converSettingsJSON
+ );
+ const { enqueueSnackbar } = useSnackbar();
+ const confirm = useConfirm();
+
+ const handleChange = (event: ChangeEvent) => {
+ setSettings({
+ ...settings,
+ [event.target.name]: event.target.checked,
+ });
+ };
+
+ const handleSubmit = () => {
+ patchApi("settings", {
+ scanInOut: settings.scanInOut,
+ leaderboard: settings.leaderboard,
+ public: settings.public,
+ })
+ .then(() => enqueueSnackbar(saveSuccess, { variant: "success" }))
+ .catch((error) => enqueueSnackbar(error, { variant: "error" }));
+ };
+
+ const handleDelete = () => {
+ confirm({
+ title: "Delete data",
+ content: handleDeleteContent,
+ acknowledgement: "Delete all my data",
+ confirmationText: "Delete",
+ confirmationButtonProps: { color: "error" },
+ })
+ .then(() =>
+ enqueueSnackbar("This is not possible yet", {
+ variant: "error",
+ })
+ )
+ .catch(() => {});
+ };
+
+ return (
+
+
+
+
+
+ {adjustableSettings.map((setting) => (
+
+ }
+ label={
+
+
+ {setting.name}
+
+
+
+
+
+ }
+ key={setting.id}
+ />
+ ))}
+
+
+
+
+
+
+
+ More settings coming soon!
+
+ ...yay?
+
+
+
+
+
+ Save
+
+
+
+
+ Delete data
+
+
+
+
+ );
+};
diff --git a/vinvoor/src/settings/admin/Admin.tsx b/vinvoor/src/settings/admin/Admin.tsx
new file mode 100644
index 0000000..4fb06ba
--- /dev/null
+++ b/vinvoor/src/settings/admin/Admin.tsx
@@ -0,0 +1,31 @@
+import { Alert, Grid, Typography } from "@mui/material";
+import { FC } from "react";
+import { Days } from "./days/Days";
+
+export const Admin: FC = () => {
+ return (
+
+
+
+
+ This page doesn't ask for confirmation when modifying
+ data !
+
+
+
+
+
+
+
+ );
+};
diff --git a/vinvoor/src/settings/admin/days/Days.tsx b/vinvoor/src/settings/admin/days/Days.tsx
new file mode 100644
index 0000000..e88e586
--- /dev/null
+++ b/vinvoor/src/settings/admin/days/Days.tsx
@@ -0,0 +1,63 @@
+import { Grid } from "@mui/material";
+import { useSnackbar } from "notistack";
+import { createContext, Dispatch, SetStateAction, useState } from "react";
+import { LoadingSkeleton } from "../../../components/LoadingSkeleton";
+import { useFetch } from "../../../hooks/useFetch";
+import { convertDayJSON, Day } from "../../../types/days";
+import { getApi } from "../../../util/fetch";
+import { DaysAdd } from "./DaysAdd";
+import { DaysTable } from "./DaysTable";
+
+interface DayContextProps {
+ days: readonly Day[];
+ setDays: Dispatch>;
+ reloadDays: () => void;
+}
+
+export const DayContext = createContext({
+ days: [],
+ setDays: () => {},
+ reloadDays: () => null,
+});
+
+export const Days = () => {
+ const [days, setDays] = useState([]);
+ const { loading } = useFetch(
+ "admin/days",
+ setDays,
+ convertDayJSON
+ );
+
+ const { enqueueSnackbar } = useSnackbar();
+
+ const reloadDays = () => {
+ getApi("admin/days", convertDayJSON)
+ .then((data) => setDays(data))
+ // This is the admin page so just show the error
+ .catch((error) =>
+ enqueueSnackbar(`Error getting all days: ${error}`, {
+ variant: "error",
+ })
+ );
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/vinvoor/src/settings/admin/days/DaysAdd.tsx b/vinvoor/src/settings/admin/days/DaysAdd.tsx
new file mode 100644
index 0000000..e536998
--- /dev/null
+++ b/vinvoor/src/settings/admin/days/DaysAdd.tsx
@@ -0,0 +1,88 @@
+import { Box, Button, Paper, Stack } from "@mui/material";
+import { DatePicker, LocalizationProvider } from "@mui/x-date-pickers";
+import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
+import dayjs, { Dayjs } from "dayjs";
+import { useSnackbar } from "notistack";
+import { Dispatch, SetStateAction, useContext, useState } from "react";
+import { TypographyG } from "../../../components/TypographyG";
+import { postApi } from "../../../util/fetch";
+import { DayContext } from "./Days";
+export const DaysAdd = () => {
+ const { reloadDays } = useContext(DayContext);
+ const [startDate, setStartDate] = useState(dayjs());
+ const [endDate, setEndDate] = useState(dayjs());
+
+ const { enqueueSnackbar } = useSnackbar();
+
+ const handleDateChange = (
+ date: Dayjs | null,
+ setter: Dispatch>
+ ) => setter(date);
+
+ const handleOnClick = () => {
+ if (!startDate || !endDate) {
+ enqueueSnackbar("Please select a start and end date", {
+ variant: "error",
+ });
+ return;
+ }
+
+ postApi("admin/days", {
+ startDate: startDate.toISOString(),
+ endDate: endDate.toISOString(),
+ })
+ .then(() => {
+ enqueueSnackbar("successfully saved days", {
+ variant: "success",
+ });
+ reloadDays();
+ })
+ .catch((error) =>
+ // This is the admin page so just show the error
+ enqueueSnackbar(`Failed to save days: ${error}`, {
+ variant: "error",
+ })
+ );
+ };
+
+ return (
+
+
+ Add days
+
+
+
+ handleDateChange(newValue, setStartDate)
+ }
+ />
+
+ handleDateChange(newValue, setEndDate)
+ }
+ />
+
+
+
+
+ Add
+
+
+
+
+ );
+};
diff --git a/vinvoor/src/settings/admin/days/DaysTable.tsx b/vinvoor/src/settings/admin/days/DaysTable.tsx
new file mode 100644
index 0000000..7fc8dee
--- /dev/null
+++ b/vinvoor/src/settings/admin/days/DaysTable.tsx
@@ -0,0 +1,160 @@
+import { Paper, Stack, Table, TableContainer } from "@mui/material";
+import { useSnackbar } from "notistack";
+import { ChangeEvent, useContext, useEffect, useState } from "react";
+import { TypographyG } from "../../../components/TypographyG";
+import { Day } from "../../../types/days";
+import { deleteAPI } from "../../../util/fetch";
+import { randomInt } from "../../../util/util";
+import { DayContext } from "./Days";
+import { DaysTableBody } from "./DaysTableBody";
+import { DaysTableHead } from "./DaysTableHead";
+import { DaysTableToolbar } from "./DaysTableToolbar";
+
+export const DaysTable = () => {
+ const { days, reloadDays } = useContext(DayContext);
+ const [rows, setRows] = useState(days);
+ const [selected, setSelected] = useState([]);
+ const [deleting, setDeleting] = useState(false);
+
+ const [dateFilter, setDateFilter] = useState<
+ [Date | undefined, Date | undefined]
+ >([undefined, undefined]);
+ const [weekdaysFilter, setWeekdaysFilter] = useState(false);
+ const [weekendsFilter, setWeekendsFilter] = useState(false);
+
+ const { enqueueSnackbar, closeSnackbar } = useSnackbar();
+
+ const filterDays = (): readonly Day[] => {
+ let filteredDays = [...days];
+ if (dateFilter[0] !== undefined && dateFilter[1] !== undefined) {
+ filteredDays = filteredDays.filter(
+ (day) =>
+ day.date.getTime() >= dateFilter[0]!.getTime() &&
+ day.date.getTime() <= dateFilter[1]!.getTime()
+ );
+ }
+ if (weekdaysFilter) {
+ filteredDays = filteredDays.filter(
+ (day) => day.date.getDay() !== 0 && day.date.getDay() !== 6
+ );
+ }
+ if (weekendsFilter) {
+ filteredDays = filteredDays.filter(
+ (day) => day.date.getDay() === 0 || day.date.getDay() === 6
+ );
+ }
+
+ return filteredDays;
+ };
+
+ const handleDelete = async () => {
+ setDeleting(true);
+ const key = randomInt();
+ enqueueSnackbar("Deleting...", {
+ variant: "info",
+ key: key,
+ persist: true,
+ });
+
+ const promises = selected.map((id) =>
+ deleteAPI(`admin/days/${id}`).catch((error) =>
+ // This is the admin page so just show the error
+ enqueueSnackbar(`Failed to delete streakday ${id}: ${error}`, {
+ variant: "error",
+ })
+ )
+ );
+
+ await Promise.all(promises);
+
+ closeSnackbar(key);
+ enqueueSnackbar(
+ `Deleted ${selected.length} streakday${
+ selected.length > 1 ? "s" : ""
+ }`,
+ {
+ variant: "success",
+ }
+ );
+
+ setSelected([]);
+ setDeleting(false);
+ reloadDays();
+ };
+
+ const handleSelect = (id: number) => {
+ const selectedIndex = selected.indexOf(id);
+ let newSelected: readonly number[] = [];
+
+ switch (selectedIndex) {
+ case -1:
+ newSelected = newSelected.concat(selected, id);
+ break;
+ case 0:
+ newSelected = newSelected.concat(selected.slice(1));
+ break;
+ case selected.length - 1:
+ newSelected = newSelected.concat(selected.slice(0, -1));
+ break;
+ default:
+ newSelected = newSelected.concat(
+ selected.slice(0, selectedIndex),
+ selected.slice(selectedIndex + 1)
+ );
+ }
+
+ setSelected(newSelected);
+ };
+ const handleSelectAll = (event: ChangeEvent) => {
+ if (event.target.checked) setSelected(rows.map((day) => day.id));
+ else setSelected([]);
+ };
+ const isSelected = (id: number) => selected.indexOf(id) !== -1;
+
+ useEffect(
+ () => setRows(filterDays()),
+ [days, dateFilter, weekdaysFilter, weekendsFilter]
+ );
+
+ return (
+
+
+ Edit Days
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/vinvoor/src/settings/admin/days/DaysTableBody.tsx b/vinvoor/src/settings/admin/days/DaysTableBody.tsx
new file mode 100644
index 0000000..94f41ac
--- /dev/null
+++ b/vinvoor/src/settings/admin/days/DaysTableBody.tsx
@@ -0,0 +1,84 @@
+import DeleteIcon from "@mui/icons-material/Delete";
+import {
+ Checkbox,
+ IconButton,
+ TableBody,
+ TableCell,
+ TableRow,
+ Typography,
+} from "@mui/material";
+import { useSnackbar } from "notistack";
+import { FC, ReactNode, useContext } from "react";
+import { Day, daysHeadCells } from "../../../types/days";
+import { deleteAPI } from "../../../util/fetch";
+import { DayContext } from "./Days";
+
+interface DaysTableBodyProps {
+ rows: readonly Day[];
+ handleSelect: (id: number) => void;
+ isSelected: (id: number) => boolean;
+ deleting: boolean;
+}
+
+export const DaysTableBody: FC = ({
+ rows,
+ handleSelect,
+ isSelected,
+ deleting,
+}) => {
+ const { days, setDays } = useContext(DayContext);
+
+ const { enqueueSnackbar } = useSnackbar();
+
+ const handleClick = (id: number) => {
+ if (isSelected(id)) handleSelect(id); // This will remove it from the selected list
+
+ deleteAPI(`admin/days/${id}`)
+ .then(() => {
+ enqueueSnackbar("Deleted streakday", { variant: "success" });
+ setDays([...days].filter((day) => day.id !== id));
+ })
+ .catch((error) =>
+ // This is the admin page so just show the error
+ enqueueSnackbar(`Failed to delete streakday: ${error}`, {
+ variant: "error",
+ })
+ );
+ };
+
+ return (
+
+ {rows.map((day) => (
+
+ handleSelect(day.id)}
+ >
+
+
+ {daysHeadCells.map((headCell) => (
+
+
+ {headCell.convert
+ ? headCell.convert(day[headCell.id])
+ : (day[headCell.id] as ReactNode)}
+
+
+ ))}
+
+ handleClick(day.id)}
+ >
+
+
+
+
+ ))}
+
+ );
+};
diff --git a/vinvoor/src/settings/admin/days/DaysTableHead.tsx b/vinvoor/src/settings/admin/days/DaysTableHead.tsx
new file mode 100644
index 0000000..fbaaef0
--- /dev/null
+++ b/vinvoor/src/settings/admin/days/DaysTableHead.tsx
@@ -0,0 +1,63 @@
+import {
+ Box,
+ Button,
+ Checkbox,
+ TableCell,
+ TableHead,
+ TableRow,
+ Typography,
+} from "@mui/material";
+import { ChangeEvent, FC } from "react";
+import { daysHeadCells } from "../../../types/days";
+
+interface DaysTableHeadProps {
+ rowCount: number;
+ numSelected: number;
+ onSelectAll: (event: ChangeEvent) => void;
+ handleDelete: () => void;
+ deleting: boolean;
+}
+
+export const DaysTableHead: FC = ({
+ rowCount,
+ numSelected,
+ onSelectAll,
+ handleDelete,
+ deleting,
+}) => {
+ return (
+
+
+
+ 0 && numSelected < rowCount
+ }
+ checked={rowCount > 0 && numSelected === rowCount}
+ onChange={onSelectAll}
+ />
+
+ {daysHeadCells.map((headCell) => (
+
+ {headCell.label}
+
+ ))}
+
+
+ {`Delet${deleting ? "ing" : "e"} ${numSelected} ${
+ deleting ? "..." : ""
+ }`}
+
+
+
+
+ );
+};
diff --git a/vinvoor/src/settings/admin/days/DaysTableToolbar.tsx b/vinvoor/src/settings/admin/days/DaysTableToolbar.tsx
new file mode 100644
index 0000000..271bd19
--- /dev/null
+++ b/vinvoor/src/settings/admin/days/DaysTableToolbar.tsx
@@ -0,0 +1,129 @@
+import { Checkbox, Stack, Typography } from "@mui/material";
+import { DatePicker, LocalizationProvider } from "@mui/x-date-pickers";
+import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
+import dayjs, { Dayjs } from "dayjs";
+import {
+ ChangeEvent,
+ Dispatch,
+ FC,
+ SetStateAction,
+ useContext,
+ useState,
+} from "react";
+import { DayContext } from "./Days";
+
+interface DaysTableToolbarProps {
+ dateFilter: [Date | undefined, Date | undefined];
+ setDateFilter: Dispatch<
+ SetStateAction<[Date | undefined, Date | undefined]>
+ >;
+ weekdaysFilter: boolean;
+ setWeekdaysFilter: Dispatch>;
+ weekendsFilter: boolean;
+ setWeekendsFilter: Dispatch>;
+}
+
+export const DaysTableToolbar: FC = ({
+ dateFilter,
+ setDateFilter,
+ weekdaysFilter,
+ setWeekdaysFilter,
+ weekendsFilter,
+ setWeekendsFilter,
+}) => {
+ const { days } = useContext(DayContext);
+ const [startDate, setStartDate] = useState(
+ days.length ? dayjs(days[0].date) : dayjs()
+ );
+ const [endDate, setEndDate] = useState(
+ days.length ? dayjs(days[days.length - 1].date) : dayjs()
+ );
+
+ const handleDateChange = (
+ date: Dayjs | null,
+ setter: Dispatch>,
+ index: number
+ ) => {
+ setter(date);
+
+ if (dateFilter[0] !== undefined && dateFilter[1] !== undefined) {
+ const newDateFilter = [...dateFilter];
+ newDateFilter[index] = date?.toDate();
+ setDateFilter(
+ newDateFilter as [Date | undefined, Date | undefined]
+ );
+ }
+ };
+
+ const handleClickDate = (event: ChangeEvent) => {
+ if (event.target.checked)
+ setDateFilter([startDate?.toDate(), endDate?.toDate()]);
+ else setDateFilter([undefined, undefined]);
+ };
+
+ const handleClickBoolean = (
+ event: ChangeEvent,
+ setter: Dispatch>
+ ) => setter(event.target.checked);
+
+ return (
+
+
+
+ Filter date
+
+
+ handleDateChange(newValue, setStartDate, 0)
+ }
+ />
+
+ handleDateChange(newValue, setEndDate, 1)
+ }
+ />
+
+
+
+
+ handleClickBoolean(event, setWeekdaysFilter)
+ }
+ />
+ Only weekdays
+
+
+
+ handleClickBoolean(event, setWeekendsFilter)
+ }
+ />
+ Only weekends
+
+
+ );
+};
diff --git a/vinvoor/src/theme.ts b/vinvoor/src/theme.ts
new file mode 100644
index 0000000..457fc5e
--- /dev/null
+++ b/vinvoor/src/theme.ts
@@ -0,0 +1,228 @@
+import { createTheme, ThemeOptions } from "@mui/material";
+
+const baseTheme: ThemeOptions = {
+ palette: {
+ secondary: {
+ main: "#002379",
+ },
+ },
+ leaderboard: {
+ first: "#daa520",
+ second: "#c0c0c0",
+ third: "#934b01",
+ },
+ heatmap: {
+ color0: { fill: "#eeeeee", stroke: "#fcce9f" },
+ color1: { fill: "#fcce9f", stroke: "#fcbb79" },
+ color2: { fill: "#fcbb79", stroke: "#fa922a" },
+ color3: { fill: "#fa922a", stroke: "#ff7f00" },
+ color4: { fill: "#ff7f00", stroke: "#ba5f02" },
+ color5: { fill: "#ba5f02", stroke: "#934b01" },
+ colorActive: { fill: "#ff7f00", stroke: "#ba5f02" },
+ colorInActive: { fill: "#eeeeee", stroke: "#fcce9f" },
+ },
+ days: {
+ color0: "#fcbb79",
+ color1: "#fa922a",
+ color2: "#ff7f00",
+ color3: "#ba5f02",
+ color4: "#934b01",
+ },
+ components: {
+ MuiAppBar: {
+ styleOverrides: {
+ root: {
+ background:
+ "rgb(255,164,0) linear-gradient(45deg, rgba(255,164,0,1) 0%, rgba(255,127,0,1) 100%)",
+ },
+ },
+ },
+ },
+};
+
+export const lightTheme = createTheme({
+ ...baseTheme,
+ palette: {
+ ...baseTheme.palette,
+ mode: "light",
+ primary: {
+ main: "#ff7f00",
+ contrastText: "#121212",
+ },
+ },
+});
+
+export const darkTheme = createTheme({
+ ...baseTheme,
+ palette: {
+ ...baseTheme.palette,
+ mode: "dark",
+ primary: {
+ main: "#ff7f00",
+ contrastText: "#ffffff",
+ },
+ background: {
+ default: "#121212",
+ },
+ },
+});
+
+export const hiddenTheme = createTheme({
+ palette: {
+ mode: "light",
+ primary: {
+ main: "#6F4E37",
+ contrastText: "#28282B",
+ },
+ secondary: {
+ main: "#A67B5B",
+ contrastText: "#E9DCC9",
+ },
+ background: {
+ default: "#FED8B1",
+ paper: "#ECB176",
+ },
+ success: {
+ main: "#355E3B",
+ dark: "#454B1B",
+ light: "#009E60",
+ },
+ error: {
+ main: "#800020",
+ dark: "#800000",
+ light: "#A52A2A",
+ },
+ },
+ leaderboard: {
+ first: "#daa520",
+ second: "#c0c0c0",
+ third: "#934b01",
+ },
+ heatmap: {
+ color0: { fill: "#EADDCA", stroke: "#DAA06D" },
+ color1: { fill: "#DAA06D", stroke: "#d68c3c" },
+ color2: { fill: "#d68c3c", stroke: "#a6621b" },
+ color3: { fill: "#a6621b", stroke: "#8B4513" },
+ color4: { fill: "#8B4513", stroke: "#5c300f" },
+ color5: { fill: "#5c300f", stroke: "#381b06" },
+ colorActive: { fill: "#8B4513", stroke: "#5c300f" },
+ colorInActive: { fill: "#EADDCA", stroke: "#DAA06D" },
+ },
+ days: {
+ color0: "#d68c3c",
+ color1: "#a6621b",
+ color2: "#8B4513",
+ color3: "#5c300f",
+ color4: "#381b06",
+ },
+ components: {
+ MuiDivider: {
+ styleOverrides: {
+ root: {
+ backgroundColor: "#6F4E37",
+ },
+ },
+ },
+ MuiTableCell: {
+ styleOverrides: {
+ root: {
+ borderBottom: "1px solid #6F4E37",
+ },
+ },
+ },
+ MuiButton: {
+ styleOverrides: {
+ outlined: {
+ borderWidth: "2px",
+ "&:hover": {
+ borderWidth: "2px",
+ },
+ },
+ contained: {
+ color: "#FFF8DC",
+ },
+ },
+ },
+ MuiSnackbarContent: {
+ styleOverrides: {
+ root: {
+ succ: "#6F4E37",
+ },
+ },
+ },
+ MuiAlert: {
+ styleOverrides: {
+ outlinedError: {
+ borderColor: "#800020",
+ },
+ outlinedSuccess: {
+ borderColor: "#355E3B",
+ },
+ },
+ },
+ },
+});
+
+export interface HeatmapRectStyle {
+ fill: string;
+ stroke: string;
+}
+
+declare module "@mui/material/styles" {
+ interface Theme {
+ leaderboard: {
+ first: string;
+ second: string;
+ third: string;
+ };
+ heatmap: {
+ color0: HeatmapRectStyle;
+ color1: HeatmapRectStyle;
+ color2: HeatmapRectStyle;
+ color3: HeatmapRectStyle;
+ color4: HeatmapRectStyle;
+ color5: HeatmapRectStyle;
+ colorActive: HeatmapRectStyle;
+ colorInActive: HeatmapRectStyle;
+ };
+ days: {
+ color0: string;
+ color1: string;
+ color2: string;
+ color3: string;
+ color4: string;
+ };
+ }
+ interface ThemeOptions {
+ leaderboard?: {
+ first: string;
+ second: string;
+ third: string;
+ };
+ heatmap?: {
+ color0: HeatmapRectStyle;
+ color1: HeatmapRectStyle;
+ color2: HeatmapRectStyle;
+ color3: HeatmapRectStyle;
+ color4: HeatmapRectStyle;
+ color5: HeatmapRectStyle;
+ colorInActive: HeatmapRectStyle;
+ colorActive: HeatmapRectStyle;
+ };
+ days: {
+ color0: string;
+ color1: string;
+ color2: string;
+ color3: string;
+ color4: string;
+ };
+ }
+}
+
+export type ThemeMode = "light" | "dark" | "hidden";
+
+export const themeModes: Record = {
+ light: lightTheme,
+ dark: darkTheme,
+ hidden: hiddenTheme,
+};
diff --git a/vinvoor/src/theme/theme.ts b/vinvoor/src/theme/theme.ts
deleted file mode 100644
index fca57c3..0000000
--- a/vinvoor/src/theme/theme.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import { createTheme } from "@mui/material";
-
-export const lightTheme = createTheme({
- palette: {
- mode: "light",
- primary: {
- main: "#ff7f00",
- },
- secondary: {
- main: "#002379",
- },
- github: {
- main: "#FFF4F2",
- },
- },
-});
-
-export const darkTheme = createTheme({
- palette: {
- mode: "dark",
- primary: {
- main: "#ff7f00",
- },
- secondary: {
- main: "#002379",
- },
- github: {
- main: "#996860",
- },
- },
- components: {
- MuiAppBar: {
- styleOverrides: {
- root: {
- backgroundColor: "#ff7f00",
- },
- },
- },
- },
-});
-
-declare module "@mui/material/styles" {
- interface Palette {
- github: Palette["primary"];
- }
-
- interface PaletteOptions {
- github?: PaletteOptions["primary"];
- }
-}
diff --git a/vinvoor/src/types/cards.ts b/vinvoor/src/types/cards.ts
index e406160..088bde4 100644
--- a/vinvoor/src/types/cards.ts
+++ b/vinvoor/src/types/cards.ts
@@ -33,7 +33,7 @@ export const cardsHeadCells: readonly TableHeadCell[] = [
},
{
id: "amountUsed",
- label: "Amount of uses",
+ label: "Uses",
align: "right",
padding: "none",
},
diff --git a/vinvoor/src/types/days.ts b/vinvoor/src/types/days.ts
new file mode 100644
index 0000000..5027310
--- /dev/null
+++ b/vinvoor/src/types/days.ts
@@ -0,0 +1,28 @@
+import { Base, BaseJSON, TableHeadCell } from "./general";
+
+interface DayJSON extends BaseJSON {
+ date: string;
+}
+
+export interface Day extends Base {
+ date: Date;
+}
+
+export const convertDayJSON = (daysJSON: DayJSON[]): Day[] =>
+ daysJSON
+ .map((dayJSON) => ({
+ date: new Date(dayJSON.date),
+ id: dayJSON.id,
+ createdAt: new Date(dayJSON.createdAt),
+ }))
+ .sort((a, b) => a.date.getTime() - b.date.getTime());
+
+export const daysHeadCells: readonly TableHeadCell[] = [
+ {
+ id: "date",
+ label: "Date",
+ align: "left",
+ padding: "normal",
+ convert: (value: Date) => value.toDateString(),
+ },
+];
diff --git a/vinvoor/src/types/leaderboard.ts b/vinvoor/src/types/leaderboard.ts
index d1899c1..c71b552 100644
--- a/vinvoor/src/types/leaderboard.ts
+++ b/vinvoor/src/types/leaderboard.ts
@@ -12,7 +12,7 @@ export const leaderboardHeadCells: readonly TableHeadCell[] = [
{
id: "positionChange",
label: "Change",
- align: "left",
+ align: "right",
padding: "checkbox",
},
{
diff --git a/vinvoor/src/types/scans.ts b/vinvoor/src/types/scans.ts
index 285e8a8..c7fdc8e 100644
--- a/vinvoor/src/types/scans.ts
+++ b/vinvoor/src/types/scans.ts
@@ -27,7 +27,7 @@ export const convertScanJSON = (scansJSON: ScanJSON[]): Scan[] =>
export const mergeScansCards = (
scans: readonly Scan[],
cards: readonly Card[]
-): readonly ScanCard[] =>
+): ScanCard[] =>
scans.map((scan) => ({
scanTime: scan.scanTime,
card: cards.find((card) => card.serial === scan.cardSerial),
@@ -39,7 +39,7 @@ export const scanCardHeadCells: readonly TableHeadCell[] = [
label: "Scan time",
align: "left",
padding: "normal",
- convert: (value: Date) => value.toDateString(),
+ convert: (value: Date) => dateTimeFormat.format(value),
},
{
id: "card",
@@ -50,3 +50,11 @@ export const scanCardHeadCells: readonly TableHeadCell[] = [
value?.name || (value?.serial ?? "Unknown"),
},
];
+
+const dateTimeFormat = new Intl.DateTimeFormat("en-GB", {
+ year: "2-digit",
+ month: "short",
+ day: "numeric",
+ hour: "numeric",
+ minute: "numeric",
+});
diff --git a/vinvoor/src/types/settings.ts b/vinvoor/src/types/settings.ts
new file mode 100644
index 0000000..583d1c1
--- /dev/null
+++ b/vinvoor/src/types/settings.ts
@@ -0,0 +1,46 @@
+import { Base, BaseJSON } from "./general";
+
+interface SettingsJSON extends BaseJSON {
+ scanInOut: boolean;
+ leaderboard: boolean;
+ public: boolean;
+}
+
+export interface Settings extends Base {
+ scanInOut: boolean;
+ leaderboard: boolean;
+ public: boolean;
+}
+
+export const converSettingsJSON = (settingsJSON: SettingsJSON): Settings => ({
+ id: settingsJSON.id,
+ createdAt: new Date(settingsJSON.createdAt),
+ scanInOut: settingsJSON.scanInOut,
+ leaderboard: settingsJSON.leaderboard,
+ public: settingsJSON.public,
+});
+
+interface AdjustableSettings {
+ id: keyof Settings;
+ name: string;
+ description: string;
+}
+
+export const adjustableSettings: AdjustableSettings[] = [
+ {
+ id: "scanInOut",
+ name: "Scan in and out",
+ description:
+ "A second scan on the same day will be interpreted as a scan out",
+ },
+ {
+ id: "leaderboard",
+ name: "Leaderboard",
+ description: "Show yourself on the leaderboard",
+ },
+ {
+ id: "public",
+ name: "Public",
+ description: "Let others see you!",
+ },
+];
diff --git a/vinvoor/src/util/fetch.ts b/vinvoor/src/util/fetch.ts
index dbfe04e..74daf4c 100644
--- a/vinvoor/src/util/fetch.ts
+++ b/vinvoor/src/util/fetch.ts
@@ -1,33 +1,40 @@
-const URLS: { [key: string]: string } = {
+const URLS: Record = {
BASE: import.meta.env.VITE_BASE_URL,
API: import.meta.env.VITE_API_URL,
};
-export const getApi = (endpoint: string, convertData?: (data: any) => T) => {
- return _fetch(`${URLS.API}/${endpoint}`, {}, convertData);
-};
+export const getApi = (endpoint: string, convertData?: (data: any) => T) =>
+ _fetch(`${URLS.API}/${endpoint}`, {}, convertData);
export const postApi = (
endpoint: string,
- body: { [key: string]: string } = {}
-) => {
- return _fetch(`${URLS.API}/${endpoint}`, {
+ body: Record = {}
+) =>
+ _fetch(`${URLS.API}/${endpoint}`, {
method: "POST",
body: JSON.stringify(body),
headers: new Headers({ "content-type": "application/json" }),
});
-};
export const patchApi = (
endpoint: string,
- body: { [key: string]: string } = {}
-) => {
- return _fetch(`${URLS.API}/${endpoint}`, {
+ body: Record = {}
+) =>
+ _fetch(`${URLS.API}/${endpoint}`, {
method: "PATCH",
body: JSON.stringify(body),
headers: new Headers({ "content-type": "application/json" }),
});
-};
+
+export const deleteAPI = (
+ endpoint: string,
+ body: Record = {}
+) =>
+ _fetch(`${URLS.API}/${endpoint}`, {
+ method: "DELETE",
+ body: JSON.stringify(body),
+ headers: new Headers({ "content-type": "application/json" }),
+ });
interface ResponseNot200Error extends Error {
response: Response;
@@ -35,16 +42,15 @@ interface ResponseNot200Error extends Error {
export const isResponseNot200Error = (
error: any
-): error is ResponseNot200Error => {
- return (error as ResponseNot200Error).response !== undefined;
-};
+): error is ResponseNot200Error =>
+ (error as ResponseNot200Error).response !== undefined;
const _fetch = async (
url: string,
options: RequestInit = {},
convertData?: (data: any) => T
-): Promise => {
- return fetch(url, { credentials: "include", ...options })
+): Promise =>
+ fetch(url, { credentials: "include", ...options })
.then((response) => {
if (!response.ok) {
const error = new Error(
@@ -54,7 +60,10 @@ const _fetch = async (
throw error;
}
- return response.json();
+ const contentType = response.headers.get("content-type");
+
+ return contentType && contentType.includes("application/json")
+ ? response.json()
+ : response.text();
})
.then((data) => (convertData ? convertData(data) : data));
-};
diff --git a/vinvoor/yarn.lock b/vinvoor/yarn.lock
index 8a3865f..fc0db07 100644
--- a/vinvoor/yarn.lock
+++ b/vinvoor/yarn.lock
@@ -18,50 +18,50 @@
"@babel/highlight" "^7.24.7"
picocolors "^1.0.0"
-"@babel/compat-data@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.7.tgz#d23bbea508c3883ba8251fb4164982c36ea577ed"
- integrity sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==
+"@babel/compat-data@^7.24.8":
+ version "7.24.9"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.9.tgz#53eee4e68f1c1d0282aa0eb05ddb02d033fc43a0"
+ integrity sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==
"@babel/core@^7.21.3":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.7.tgz#b676450141e0b52a3d43bc91da86aa608f950ac4"
- integrity sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==
+ version "7.24.9"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.9.tgz#dc07c9d307162c97fa9484ea997ade65841c7c82"
+ integrity sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==
dependencies:
"@ampproject/remapping" "^2.2.0"
"@babel/code-frame" "^7.24.7"
- "@babel/generator" "^7.24.7"
- "@babel/helper-compilation-targets" "^7.24.7"
- "@babel/helper-module-transforms" "^7.24.7"
- "@babel/helpers" "^7.24.7"
- "@babel/parser" "^7.24.7"
+ "@babel/generator" "^7.24.9"
+ "@babel/helper-compilation-targets" "^7.24.8"
+ "@babel/helper-module-transforms" "^7.24.9"
+ "@babel/helpers" "^7.24.8"
+ "@babel/parser" "^7.24.8"
"@babel/template" "^7.24.7"
- "@babel/traverse" "^7.24.7"
- "@babel/types" "^7.24.7"
+ "@babel/traverse" "^7.24.8"
+ "@babel/types" "^7.24.9"
convert-source-map "^2.0.0"
debug "^4.1.0"
gensync "^1.0.0-beta.2"
json5 "^2.2.3"
semver "^6.3.1"
-"@babel/generator@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.7.tgz#1654d01de20ad66b4b4d99c135471bc654c55e6d"
- integrity sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==
+"@babel/generator@^7.24.8", "@babel/generator@^7.24.9":
+ version "7.24.10"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.10.tgz#a4ab681ec2a78bbb9ba22a3941195e28a81d8e76"
+ integrity sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==
dependencies:
- "@babel/types" "^7.24.7"
+ "@babel/types" "^7.24.9"
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.25"
jsesc "^2.5.1"
-"@babel/helper-compilation-targets@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz#4eb6c4a80d6ffeac25ab8cd9a21b5dfa48d503a9"
- integrity sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==
+"@babel/helper-compilation-targets@^7.24.8":
+ version "7.24.8"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz#b607c3161cd9d1744977d4f97139572fe778c271"
+ integrity sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==
dependencies:
- "@babel/compat-data" "^7.24.7"
- "@babel/helper-validator-option" "^7.24.7"
- browserslist "^4.22.2"
+ "@babel/compat-data" "^7.24.8"
+ "@babel/helper-validator-option" "^7.24.8"
+ browserslist "^4.23.1"
lru-cache "^5.1.1"
semver "^6.3.1"
@@ -95,10 +95,10 @@
"@babel/traverse" "^7.24.7"
"@babel/types" "^7.24.7"
-"@babel/helper-module-transforms@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz#31b6c9a2930679498db65b685b1698bfd6c7daf8"
- integrity sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==
+"@babel/helper-module-transforms@^7.24.9":
+ version "7.24.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz#e13d26306b89eea569180868e652e7f514de9d29"
+ integrity sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==
dependencies:
"@babel/helper-environment-visitor" "^7.24.7"
"@babel/helper-module-imports" "^7.24.7"
@@ -121,28 +121,28 @@
dependencies:
"@babel/types" "^7.24.7"
-"@babel/helper-string-parser@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz#4d2d0f14820ede3b9807ea5fc36dfc8cd7da07f2"
- integrity sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==
+"@babel/helper-string-parser@^7.24.8":
+ version "7.24.8"
+ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d"
+ integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==
"@babel/helper-validator-identifier@^7.24.7":
version "7.24.7"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db"
integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==
-"@babel/helper-validator-option@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz#24c3bb77c7a425d1742eec8fb433b5a1b38e62f6"
- integrity sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==
+"@babel/helper-validator-option@^7.24.8":
+ version "7.24.8"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d"
+ integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==
-"@babel/helpers@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.7.tgz#aa2ccda29f62185acb5d42fb4a3a1b1082107416"
- integrity sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==
+"@babel/helpers@^7.24.8":
+ version "7.24.8"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.8.tgz#2820d64d5d6686cca8789dd15b074cd862795873"
+ integrity sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==
dependencies:
"@babel/template" "^7.24.7"
- "@babel/types" "^7.24.7"
+ "@babel/types" "^7.24.8"
"@babel/highlight@^7.24.7":
version "7.24.7"
@@ -154,15 +154,15 @@
js-tokens "^4.0.0"
picocolors "^1.0.0"
-"@babel/parser@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.7.tgz#9a5226f92f0c5c8ead550b750f5608e766c8ce85"
- integrity sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==
+"@babel/parser@^7.24.7", "@babel/parser@^7.24.8":
+ version "7.24.8"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.8.tgz#58a4dbbcad7eb1d48930524a3fd93d93e9084c6f"
+ integrity sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==
-"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12"
- integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==
+"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.9", "@babel/runtime@^7.24.8", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
+ version "7.24.8"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.8.tgz#5d958c3827b13cc6d05e038c07fb2e5e3420d82e"
+ integrity sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==
dependencies:
regenerator-runtime "^0.14.0"
@@ -175,41 +175,41 @@
"@babel/parser" "^7.24.7"
"@babel/types" "^7.24.7"
-"@babel/traverse@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.7.tgz#de2b900163fa741721ba382163fe46a936c40cf5"
- integrity sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==
+"@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8":
+ version "7.24.8"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.8.tgz#6c14ed5232b7549df3371d820fbd9abfcd7dfab7"
+ integrity sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==
dependencies:
"@babel/code-frame" "^7.24.7"
- "@babel/generator" "^7.24.7"
+ "@babel/generator" "^7.24.8"
"@babel/helper-environment-visitor" "^7.24.7"
"@babel/helper-function-name" "^7.24.7"
"@babel/helper-hoist-variables" "^7.24.7"
"@babel/helper-split-export-declaration" "^7.24.7"
- "@babel/parser" "^7.24.7"
- "@babel/types" "^7.24.7"
+ "@babel/parser" "^7.24.8"
+ "@babel/types" "^7.24.8"
debug "^4.3.1"
globals "^11.1.0"
-"@babel/types@^7.21.3", "@babel/types@^7.24.7":
- version "7.24.7"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.7.tgz#6027fe12bc1aa724cd32ab113fb7f1988f1f66f2"
- integrity sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==
+"@babel/types@^7.21.3", "@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.24.9":
+ version "7.24.9"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.9.tgz#228ce953d7b0d16646e755acf204f4cf3d08cc73"
+ integrity sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==
dependencies:
- "@babel/helper-string-parser" "^7.24.7"
+ "@babel/helper-string-parser" "^7.24.8"
"@babel/helper-validator-identifier" "^7.24.7"
to-fast-properties "^2.0.0"
-"@emotion/babel-plugin@^11.11.0":
- version "11.11.0"
- resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c"
- integrity sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==
+"@emotion/babel-plugin@^11.12.0":
+ version "11.12.0"
+ resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz#7b43debb250c313101b3f885eba634f1d723fcc2"
+ integrity sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==
dependencies:
"@babel/helper-module-imports" "^7.16.7"
"@babel/runtime" "^7.18.3"
- "@emotion/hash" "^0.9.1"
- "@emotion/memoize" "^0.8.1"
- "@emotion/serialize" "^1.1.2"
+ "@emotion/hash" "^0.9.2"
+ "@emotion/memoize" "^0.9.0"
+ "@emotion/serialize" "^1.2.0"
babel-plugin-macros "^3.1.0"
convert-source-map "^1.5.0"
escape-string-regexp "^4.0.0"
@@ -217,95 +217,95 @@
source-map "^0.5.7"
stylis "4.2.0"
-"@emotion/cache@^11.11.0":
- version "11.11.0"
- resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff"
- integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==
+"@emotion/cache@^11.11.0", "@emotion/cache@^11.13.0":
+ version "11.13.0"
+ resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.13.0.tgz#8f51748b8116691dee0408b08ad758b8d246b097"
+ integrity sha512-hPV345J/tH0Cwk2wnU/3PBzORQ9HeX+kQSbwI+jslzpRCHE6fSGTohswksA/Ensr8znPzwfzKZCmAM9Lmlhp7g==
dependencies:
- "@emotion/memoize" "^0.8.1"
- "@emotion/sheet" "^1.2.2"
- "@emotion/utils" "^1.2.1"
- "@emotion/weak-memoize" "^0.3.1"
+ "@emotion/memoize" "^0.9.0"
+ "@emotion/sheet" "^1.4.0"
+ "@emotion/utils" "^1.4.0"
+ "@emotion/weak-memoize" "^0.4.0"
stylis "4.2.0"
-"@emotion/hash@^0.9.1":
- version "0.9.1"
- resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43"
- integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==
+"@emotion/hash@^0.9.2":
+ version "0.9.2"
+ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.2.tgz#ff9221b9f58b4dfe61e619a7788734bd63f6898b"
+ integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==
-"@emotion/is-prop-valid@^1.2.2":
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz#d4175076679c6a26faa92b03bb786f9e52612337"
- integrity sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==
+"@emotion/is-prop-valid@^1.3.0":
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz#bd84ba972195e8a2d42462387581560ef780e4e2"
+ integrity sha512-SHetuSLvJDzuNbOdtPVbq6yMMMlLoW5Q94uDqJZqy50gcmAjxFkVqmzqSGEFq9gT2iMuIeKV1PXVWmvUhuZLlQ==
dependencies:
- "@emotion/memoize" "^0.8.1"
+ "@emotion/memoize" "^0.9.0"
-"@emotion/memoize@^0.8.1":
- version "0.8.1"
- resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17"
- integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==
+"@emotion/memoize@^0.9.0":
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102"
+ integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
"@emotion/react@^11.11.4":
- version "11.11.4"
- resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.4.tgz#3a829cac25c1f00e126408fab7f891f00ecc3c1d"
- integrity sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==
+ version "11.13.0"
+ resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.13.0.tgz#a9ebf827b98220255e5760dac89fa2d38ca7b43d"
+ integrity sha512-WkL+bw1REC2VNV1goQyfxjx1GYJkcc23CRQkXX+vZNLINyfI7o+uUn/rTGPt/xJ3bJHd5GcljgnxHf4wRw5VWQ==
dependencies:
"@babel/runtime" "^7.18.3"
- "@emotion/babel-plugin" "^11.11.0"
- "@emotion/cache" "^11.11.0"
- "@emotion/serialize" "^1.1.3"
- "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1"
- "@emotion/utils" "^1.2.1"
- "@emotion/weak-memoize" "^0.3.1"
+ "@emotion/babel-plugin" "^11.12.0"
+ "@emotion/cache" "^11.13.0"
+ "@emotion/serialize" "^1.3.0"
+ "@emotion/use-insertion-effect-with-fallbacks" "^1.1.0"
+ "@emotion/utils" "^1.4.0"
+ "@emotion/weak-memoize" "^0.4.0"
hoist-non-react-statics "^3.3.1"
-"@emotion/serialize@^1.1.2", "@emotion/serialize@^1.1.3", "@emotion/serialize@^1.1.4":
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.4.tgz#fc8f6d80c492cfa08801d544a05331d1cc7cd451"
- integrity sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==
+"@emotion/serialize@^1.2.0", "@emotion/serialize@^1.3.0":
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.3.0.tgz#e07cadfc967a4e7816e0c3ffaff4c6ce05cb598d"
+ integrity sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA==
dependencies:
- "@emotion/hash" "^0.9.1"
- "@emotion/memoize" "^0.8.1"
- "@emotion/unitless" "^0.8.1"
- "@emotion/utils" "^1.2.1"
+ "@emotion/hash" "^0.9.2"
+ "@emotion/memoize" "^0.9.0"
+ "@emotion/unitless" "^0.9.0"
+ "@emotion/utils" "^1.4.0"
csstype "^3.0.2"
-"@emotion/sheet@^1.2.2":
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec"
- integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==
+"@emotion/sheet@^1.4.0":
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.4.0.tgz#c9299c34d248bc26e82563735f78953d2efca83c"
+ integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
"@emotion/styled@^11.11.5":
- version "11.11.5"
- resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.5.tgz#0c5c8febef9d86e8a926e663b2e5488705545dfb"
- integrity sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==
+ version "11.13.0"
+ resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.13.0.tgz#633fd700db701472c7a5dbef54d6f9834e9fb190"
+ integrity sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==
dependencies:
"@babel/runtime" "^7.18.3"
- "@emotion/babel-plugin" "^11.11.0"
- "@emotion/is-prop-valid" "^1.2.2"
- "@emotion/serialize" "^1.1.4"
- "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1"
- "@emotion/utils" "^1.2.1"
-
-"@emotion/unitless@^0.8.1":
- version "0.8.1"
- resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3"
- integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==
-
-"@emotion/use-insertion-effect-with-fallbacks@^1.0.1":
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz#08de79f54eb3406f9daaf77c76e35313da963963"
- integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==
+ "@emotion/babel-plugin" "^11.12.0"
+ "@emotion/is-prop-valid" "^1.3.0"
+ "@emotion/serialize" "^1.3.0"
+ "@emotion/use-insertion-effect-with-fallbacks" "^1.1.0"
+ "@emotion/utils" "^1.4.0"
+
+"@emotion/unitless@^0.9.0":
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.9.0.tgz#8e5548f072bd67b8271877e51c0f95c76a66cbe2"
+ integrity sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==
+
+"@emotion/use-insertion-effect-with-fallbacks@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz#1a818a0b2c481efba0cf34e5ab1e0cb2dcb9dfaf"
+ integrity sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==
-"@emotion/utils@^1.2.1":
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.1.tgz#bbab58465738d31ae4cb3dbb6fc00a5991f755e4"
- integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==
+"@emotion/utils@^1.4.0":
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.4.0.tgz#262f1d02aaedb2ec91c83a0955dd47822ad5fbdd"
+ integrity sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==
-"@emotion/weak-memoize@^0.3.1":
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6"
- integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==
+"@emotion/weak-memoize@^0.4.0":
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz#5e13fac887f08c44f76b0ccaf3370eb00fec9bb6"
+ integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==
"@esbuild/aix-ppc64@0.21.5":
version "0.21.5"
@@ -525,9 +525,9 @@
integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==
"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14":
- version "1.4.15"
- resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
- integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
+ integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25":
version "0.3.25"
@@ -537,7 +537,7 @@
"@jridgewell/resolve-uri" "^3.1.0"
"@jridgewell/sourcemap-codec" "^1.4.14"
-"@mui/base@5.0.0-beta.40":
+"@mui/base@^5.0.0-beta.40":
version "5.0.0-beta.40"
resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.40.tgz#1f8a782f1fbf3f84a961e954c8176b187de3dae2"
integrity sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==
@@ -550,83 +550,98 @@
clsx "^2.1.0"
prop-types "^15.8.1"
-"@mui/core-downloads-tracker@^5.16.0":
- version "5.16.0"
- resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.0.tgz#50153c698e321793c83a0283d8d7a9dc5d43858a"
- integrity sha512-8SLffXYPRVpcZx5QzxNE8fytTqzp+IuU3deZbQWg/vSaTlDpR5YVrQ4qQtXTi5cRdhOufV5INylmwlKK+//nPw==
+"@mui/core-downloads-tracker@^5.16.4":
+ version "5.16.4"
+ resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.4.tgz#a34de72acd7e81fdbcc7eeb07786205e90dda148"
+ integrity sha512-rNdHXhclwjEZnK+//3SR43YRx0VtjdHnUFhMSGYmAMJve+KiwEja/41EYh8V3pZKqF2geKyfcFUenTfDTYUR4w==
"@mui/icons-material@^5.15.19":
- version "5.16.0"
- resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.16.0.tgz#5269fda922fe5e6db3577ec497e8b987195606ef"
- integrity sha512-6ISoOhkp9w5gD0PEW9JklrcbyARDkFWNTBdwXZ1Oy5IGlyu9B0zG0hnUIe4H17IaF1Vgj6C8VI+v4tkSdK0veg==
+ version "5.16.4"
+ resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.16.4.tgz#8c7e228c1e178992d89fab47e057222c8209bd7b"
+ integrity sha512-j9/CWctv6TH6Dou2uR2EH7UOgu79CW/YcozxCYVLJ7l03pCsiOlJ5sBArnWJxJ+nGkFwyL/1d1k8JEPMDR125A==
dependencies:
"@babel/runtime" "^7.23.9"
"@mui/material@^5.15.19":
- version "5.16.0"
- resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.16.0.tgz#2ef4f52ae773574fc0a681f25705f376f5cd13f7"
- integrity sha512-DbR1NckTLpjt9Zut9EGQ70th86HfN0BYQgyYro6aXQrNfjzSwe3BJS1AyBQ5mJ7TdL6YVRqohfukxj9JlqZZUg==
+ version "5.16.4"
+ resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.16.4.tgz#992d630637d9d38620e4937fb11d0a97965fdabf"
+ integrity sha512-dBnh3/zRYgEVIS3OE4oTbujse3gifA0qLMmuUk13ywsDCbngJsdgwW5LuYeiT5pfA8PGPGSqM7mxNytYXgiMCw==
dependencies:
"@babel/runtime" "^7.23.9"
- "@mui/base" "5.0.0-beta.40"
- "@mui/core-downloads-tracker" "^5.16.0"
- "@mui/system" "^5.16.0"
- "@mui/types" "^7.2.14"
- "@mui/utils" "^5.16.0"
+ "@mui/core-downloads-tracker" "^5.16.4"
+ "@mui/system" "^5.16.4"
+ "@mui/types" "^7.2.15"
+ "@mui/utils" "^5.16.4"
+ "@popperjs/core" "^2.11.8"
"@types/react-transition-group" "^4.4.10"
clsx "^2.1.0"
csstype "^3.1.3"
prop-types "^15.8.1"
- react-is "^18.2.0"
+ react-is "^18.3.1"
react-transition-group "^4.4.5"
-"@mui/private-theming@^5.16.0":
- version "5.16.0"
- resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.16.0.tgz#c1abfd3e0d9c95459048240ef4209dc7f25dc949"
- integrity sha512-sYpubkO1MZOnxNyVOClrPNOTs0MfuRVVnAvCeMaOaXt6GimgQbnUcshYv2pSr6PFj+Mqzdff/FYOBceK8u5QgA==
+"@mui/private-theming@^5.16.4":
+ version "5.16.4"
+ resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.16.4.tgz#0118f137975b35dc4774c6d593b8fcf86594c3fc"
+ integrity sha512-ZsAm8cq31SJ37SVWLRlu02v9SRthxnfQofaiv14L5Bht51B0dz6yQEoVU/V8UduZDCCIrWkBHuReVfKhE/UuXA==
dependencies:
"@babel/runtime" "^7.23.9"
- "@mui/utils" "^5.16.0"
+ "@mui/utils" "^5.16.4"
prop-types "^15.8.1"
-"@mui/styled-engine@^5.15.14":
- version "5.15.14"
- resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.15.14.tgz#168b154c4327fa4ccc1933a498331d53f61c0de2"
- integrity sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==
+"@mui/styled-engine@^5.16.4":
+ version "5.16.4"
+ resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.16.4.tgz#a7a8c9079c307bab91ccd65ed5dd1496ddf2a3ab"
+ integrity sha512-0+mnkf+UiAmTVB8PZFqOhqf729Yh0Cxq29/5cA3VAyDVTRIUUQ8FXQhiAhUIbijFmM72rY80ahFPXIm4WDbzcA==
dependencies:
"@babel/runtime" "^7.23.9"
"@emotion/cache" "^11.11.0"
csstype "^3.1.3"
prop-types "^15.8.1"
-"@mui/system@^5.16.0":
- version "5.16.0"
- resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.16.0.tgz#e5b4cfbdfbc0ee9859f6b168e8b07d750303b7a0"
- integrity sha512-9YbkC2m3+pNumAvubYv+ijLtog6puJ0fJ6rYfzfLCM47pWrw3m+30nXNM8zMgDaKL6vpfWJcCXm+LPaWBpy7sw==
+"@mui/system@^5.16.2", "@mui/system@^5.16.4":
+ version "5.16.4"
+ resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.16.4.tgz#c03f971ed273f0ad06c69c949c05e866ad211407"
+ integrity sha512-ET1Ujl2/8hbsD611/mqUuNArMCGv/fIWO/f8B3ZqF5iyPHM2aS74vhTNyjytncc4i6dYwGxNk+tLa7GwjNS0/w==
dependencies:
"@babel/runtime" "^7.23.9"
- "@mui/private-theming" "^5.16.0"
- "@mui/styled-engine" "^5.15.14"
- "@mui/types" "^7.2.14"
- "@mui/utils" "^5.16.0"
+ "@mui/private-theming" "^5.16.4"
+ "@mui/styled-engine" "^5.16.4"
+ "@mui/types" "^7.2.15"
+ "@mui/utils" "^5.16.4"
clsx "^2.1.0"
csstype "^3.1.3"
prop-types "^15.8.1"
-"@mui/types@^7.2.14":
- version "7.2.14"
- resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.14.tgz#8a02ac129b70f3d82f2f9b76ded2c8d48e3fc8c9"
- integrity sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==
+"@mui/types@^7.2.14", "@mui/types@^7.2.15":
+ version "7.2.15"
+ resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.15.tgz#dadd232fe9a70be0d526630675dff3b110f30b53"
+ integrity sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==
-"@mui/utils@^5.15.14", "@mui/utils@^5.16.0":
- version "5.16.0"
- resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.16.0.tgz#3963127d9a619c251e5be1aef9adab0e89d3e7df"
- integrity sha512-kLLi5J1xY+mwtUlMb8Ubdxf4qFAA1+U7WPBvjM/qQ4CIwLCohNb0sHo1oYPufjSIH/Z9+dhVxD7dJlfGjd1AVA==
+"@mui/utils@^5.15.14", "@mui/utils@^5.16.2", "@mui/utils@^5.16.4":
+ version "5.16.4"
+ resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.16.4.tgz#8e50e27a630e3d8eeb3e9d3bc31cbb0e4956f5fd"
+ integrity sha512-nlppYwq10TBIFqp7qxY0SvbACOXeOjeVL3pOcDsK0FT8XjrEXh9/+lkg8AEIzD16z7YfiJDQjaJG2OLkE7BxNg==
dependencies:
"@babel/runtime" "^7.23.9"
- "@types/prop-types" "^15.7.11"
+ "@types/prop-types" "^15.7.12"
+ clsx "^2.1.1"
prop-types "^15.8.1"
- react-is "^18.2.0"
+ react-is "^18.3.1"
+
+"@mui/x-date-pickers@^7.11.0":
+ version "7.11.0"
+ resolved "https://registry.yarnpkg.com/@mui/x-date-pickers/-/x-date-pickers-7.11.0.tgz#ac98d9057b733ddec117bc0938f364316eb12b5a"
+ integrity sha512-+zPWs1dwe7J1nZ2iFhTgCae31BLMYMQ2VtQfHxx21Dh6gbBRy/U7YJZg1LdhfQyE093S3e4A5uMZ6PUWdne7iA==
+ dependencies:
+ "@babel/runtime" "^7.24.8"
+ "@mui/base" "^5.0.0-beta.40"
+ "@mui/system" "^5.16.2"
+ "@mui/utils" "^5.16.2"
+ "@types/react-transition-group" "^4.4.10"
+ clsx "^2.1.1"
+ prop-types "^15.8.1"
+ react-transition-group "^4.4.5"
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
@@ -654,10 +669,10 @@
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f"
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
-"@remix-run/router@1.17.1":
- version "1.17.1"
- resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.17.1.tgz#bf93997beb81863fde042ebd05013a2618471362"
- integrity sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==
+"@remix-run/router@1.18.0":
+ version "1.18.0"
+ resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.18.0.tgz#20b033d1f542a100c1d57cfd18ecf442d1784732"
+ integrity sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==
"@rollup/pluginutils@^5.0.5":
version "5.1.0"
@@ -668,85 +683,85 @@
estree-walker "^2.0.2"
picomatch "^2.3.1"
-"@rollup/rollup-android-arm-eabi@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz#bbd0e616b2078cd2d68afc9824d1fadb2f2ffd27"
- integrity sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==
-
-"@rollup/rollup-android-arm64@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz#97255ef6384c5f73f4800c0de91f5f6518e21203"
- integrity sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==
-
-"@rollup/rollup-darwin-arm64@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz#b6dd74e117510dfe94541646067b0545b42ff096"
- integrity sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==
-
-"@rollup/rollup-darwin-x64@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz#e07d76de1cec987673e7f3d48ccb8e106d42c05c"
- integrity sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==
-
-"@rollup/rollup-linux-arm-gnueabihf@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz#9f1a6d218b560c9d75185af4b8bb42f9f24736b8"
- integrity sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==
-
-"@rollup/rollup-linux-arm-musleabihf@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz#53618b92e6ffb642c7b620e6e528446511330549"
- integrity sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==
-
-"@rollup/rollup-linux-arm64-gnu@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz#99a7ba5e719d4f053761a698f7b52291cefba577"
- integrity sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==
-
-"@rollup/rollup-linux-arm64-musl@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz#f53db99a45d9bc00ce94db8a35efa7c3c144a58c"
- integrity sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==
-
-"@rollup/rollup-linux-powerpc64le-gnu@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz#cbb0837408fe081ce3435cf3730e090febafc9bf"
- integrity sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==
-
-"@rollup/rollup-linux-riscv64-gnu@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz#8ed09c1d1262ada4c38d791a28ae0fea28b80cc9"
- integrity sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==
-
-"@rollup/rollup-linux-s390x-gnu@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz#938138d3c8e0c96f022252a28441dcfb17afd7ec"
- integrity sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==
-
-"@rollup/rollup-linux-x64-gnu@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz#1a7481137a54740bee1ded4ae5752450f155d942"
- integrity sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==
-
-"@rollup/rollup-linux-x64-musl@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz#f1186afc601ac4f4fc25fac4ca15ecbee3a1874d"
- integrity sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==
-
-"@rollup/rollup-win32-arm64-msvc@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz#ed6603e93636a96203c6915be4117245c1bd2daf"
- integrity sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==
-
-"@rollup/rollup-win32-ia32-msvc@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz#14e0b404b1c25ebe6157a15edb9c46959ba74c54"
- integrity sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==
-
-"@rollup/rollup-win32-x64-msvc@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz#5d694d345ce36b6ecf657349e03eb87297e68da4"
- integrity sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==
+"@rollup/rollup-android-arm-eabi@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.0.tgz#3d9fd50164b94964f5de68c3c4ce61933b3a338d"
+ integrity sha512-JlPfZ/C7yn5S5p0yKk7uhHTTnFlvTgLetl2VxqE518QgyM7C9bSfFTYvB/Q/ftkq0RIPY4ySxTz+/wKJ/dXC0w==
+
+"@rollup/rollup-android-arm64@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.0.tgz#e1a6d4bca2eb08c84fd996a4bf896ce4b6f4014c"
+ integrity sha512-RDxUSY8D1tWYfn00DDi5myxKgOk6RvWPxhmWexcICt/MEC6yEMr4HNCu1sXXYLw8iAsg0D44NuU+qNq7zVWCrw==
+
+"@rollup/rollup-darwin-arm64@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.0.tgz#0a3fffea69489a24a96079af414b0be78df8abbc"
+ integrity sha512-emvKHL4B15x6nlNTBMtIaC9tLPRpeA5jMvRLXVbl/W9Ie7HhkrE7KQjvgS9uxgatL1HmHWDXk5TTS4IaNJxbAA==
+
+"@rollup/rollup-darwin-x64@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.0.tgz#13fbdb15f58f090871b0ffff047ece06ad6ad74c"
+ integrity sha512-fO28cWA1dC57qCd+D0rfLC4VPbh6EOJXrreBmFLWPGI9dpMlER2YwSPZzSGfq11XgcEpPukPTfEVFtw2q2nYJg==
+
+"@rollup/rollup-linux-arm-gnueabihf@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.0.tgz#e9d9219ddf6f6e946e2ee322198af12466d2c868"
+ integrity sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw==
+
+"@rollup/rollup-linux-arm-musleabihf@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.0.tgz#4ba804a00b5e793196a622f6977e05f23e01f59a"
+ integrity sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ==
+
+"@rollup/rollup-linux-arm64-gnu@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.0.tgz#d871e3f41de759a6db27fc99235b782ba47c15cc"
+ integrity sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug==
+
+"@rollup/rollup-linux-arm64-musl@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.0.tgz#6e63f7ad4cc51bd2c693a2826fd279de9eaa05b5"
+ integrity sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ==
+
+"@rollup/rollup-linux-powerpc64le-gnu@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.0.tgz#1540b284d91c440bc9fa7a1714cfb71a5597e94d"
+ integrity sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ==
+
+"@rollup/rollup-linux-riscv64-gnu@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.0.tgz#70ae58103b5bc7ba2e2235738b51d97022c8ef92"
+ integrity sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg==
+
+"@rollup/rollup-linux-s390x-gnu@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.0.tgz#579ca5f271421a961d3c73d221202c79e02ff03a"
+ integrity sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA==
+
+"@rollup/rollup-linux-x64-gnu@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.0.tgz#f0282d761b8b4e7b92b236813475248e37231849"
+ integrity sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA==
+
+"@rollup/rollup-linux-x64-musl@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.0.tgz#65da807ac66c505ad14b76f1e5976006cb67dd5f"
+ integrity sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A==
+
+"@rollup/rollup-win32-arm64-msvc@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.0.tgz#1eed24b91f421c2eea8bb7ca8889ba0c867e1780"
+ integrity sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg==
+
+"@rollup/rollup-win32-ia32-msvc@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.0.tgz#1ed93c9cdc84e185359797a686f4d1576afcea58"
+ integrity sha512-xItlIAZZaiG/u0wooGzRsx11rokP4qyc/79LkAOdznGRAbOFc+SfEdfUOszG1odsHNgwippUJavag/+W/Etc6Q==
+
+"@rollup/rollup-win32-x64-msvc@4.19.0":
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.0.tgz#baf9b65023ea2ecc5e6ec68f787a0fecfd8ee84c"
+ integrity sha512-xNo5fV5ycvCCKqiZcpB65VMR11NJB+StnxHz20jdqRAktfdfzhgjTiJ2doTDQE/7dqGaV5I7ZGqKpgph6lCIag==
"@svgr/babel-plugin-add-jsx-attribute@8.0.0":
version "8.0.0"
@@ -831,74 +846,74 @@
"@svgr/hast-util-to-babel-ast" "8.0.0"
svg-parser "^2.0.4"
-"@swc/core-darwin-arm64@1.6.7":
- version "1.6.7"
- resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.6.7.tgz#e98a0da9635297728a97faf7f4e11c46f8dfbb46"
- integrity sha512-sNb+ghP2OhZyUjS7E5Mf3PqSvoXJ5gY6GBaH2qp8WQxx9VL7ozC4HVo6vkeFJBN5cmYqUCLnhrM3HU4W+7yMSA==
-
-"@swc/core-darwin-x64@1.6.7":
- version "1.6.7"
- resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.6.7.tgz#fccd389046a8fe0d8b294f9657b3861046fcd3bb"
- integrity sha512-LQwYm/ATYN5fYSYVPMfComPiFo5i8jh75h1ASvNWhXtS+/+k1dq1zXTJWZRuojd5NXgW3bb6mJtJ2evwYIgYbA==
-
-"@swc/core-linux-arm-gnueabihf@1.6.7":
- version "1.6.7"
- resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.6.7.tgz#f384235e5f14870646157017eb06dfbaed0894c0"
- integrity sha512-kEDzVhNci38LX3kdY99t68P2CDf+2QFDk5LawVamXH0iN5DRAO/+wjOhxL8KOHa6wQVqKEt5WrhD+Rrvk/34Yw==
-
-"@swc/core-linux-arm64-gnu@1.6.7":
- version "1.6.7"
- resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.6.7.tgz#d2b8c0c6045eecb96bc3f3dfa7fb31b5ab708cdf"
- integrity sha512-SyOBUGfl31xLGpIJ/Jd6GKHtkfZyHBXSwFlK7FmPN//MBQLtTBm4ZaWTnWnGo4aRsJwQdXWDKPyqlMBtnIl1nQ==
-
-"@swc/core-linux-arm64-musl@1.6.7":
- version "1.6.7"
- resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.6.7.tgz#6ae2a160ba535b1f4747d35a124f410545092abe"
- integrity sha512-1fOAXkDFbRfItEdMZPxT3du1QWYhgToa4YsnqTujjE8EqJW8K27hIcHRIkVuzp7PNhq8nLBg0JpJM4g27EWD7g==
-
-"@swc/core-linux-x64-gnu@1.6.7":
- version "1.6.7"
- resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.6.7.tgz#6ebcf76fa868321c3b079e5c668c137b9b91df49"
- integrity sha512-Gp7uCwPsNO5ATxbyvfTyeNCHUGD9oA+xKMm43G1tWCy+l07gLqWMKp7DIr3L3qPD05TfAVo3OuiOn2abpzOFbw==
-
-"@swc/core-linux-x64-musl@1.6.7":
- version "1.6.7"
- resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.6.7.tgz#41531ef3e1c7123d87b7a7a1b984fa2689032621"
- integrity sha512-QeruGBZJ15tadqEMQ77ixT/CYGk20MtlS8wmvJiV+Wsb8gPW5LgCjtupzcLLnoQzDG54JGNCeeZ0l/T8NYsOvA==
-
-"@swc/core-win32-arm64-msvc@1.6.7":
- version "1.6.7"
- resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.6.7.tgz#af0b84a54d01bc3aad12acffa98ebb13fc03c3e6"
- integrity sha512-ouRqgSnT95lTCiU/6kJRNS5b1o+p8I/V9jxtL21WUj/JOVhsFmBErqQ0MZyCu514noWiR5BIqOrZXR8C1Knx6Q==
-
-"@swc/core-win32-ia32-msvc@1.6.7":
- version "1.6.7"
- resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.6.7.tgz#c454851c05c26f67d2edc399e1cde9d074744ce4"
- integrity sha512-eZAP/EmJ0IcfgAx6B4/SpSjq3aT8gr0ooktfMqw/w0/5lnNrbMl2v+2kvxcneNcF7bp8VNcYZnoHlsP+LvmVbA==
-
-"@swc/core-win32-x64-msvc@1.6.7":
- version "1.6.7"
- resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.6.7.tgz#6ee4a3caf3466971e6b5fb2fba4674924507a2de"
- integrity sha512-QOdE+7GQg1UQPS6p0KxzJOh/8GLbJ5zI1vqKArCCB0unFqUfKIjYb2TaH0geEBy3w9qtXxe3ZW6hzxtZSS9lDg==
+"@swc/core-darwin-arm64@1.7.0":
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.0.tgz#fdc694dd6e8543f3efea0619a6fba9ce82939205"
+ integrity sha512-2ylhM7f0HwUwLrFYZAe/dse8PCbPsYcJS3Dt7Q8NT3PUn7vy6QOMxNcOPPuDrnmaXqQQO3oxdmRapguTxaat9g==
+
+"@swc/core-darwin-x64@1.7.0":
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.7.0.tgz#a9a78ace5c7e43c8cb68d11c53d33a0bf966ca8e"
+ integrity sha512-SgVnN4gT1Rb9YfTkp4FCUITqSs7Yj0uB2SUciu5CV3HuGvS5YXCUzh+KrwpLFtx8NIgivISKcNnb41mJi98X8Q==
+
+"@swc/core-linux-arm-gnueabihf@1.7.0":
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.0.tgz#6861ac82fda01b68b44970d3b9aaa955d7311d98"
+ integrity sha512-+Z9Dayart1iKJQEJJ9N/KS4z5EdXJE3WPFikY0jonKTo4Dd8RuyVz5yLvqcIMeVdz/SwximATaL6iJXw7hZS9A==
+
+"@swc/core-linux-arm64-gnu@1.7.0":
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.0.tgz#aa0e3dac17807c73d501f52526115666d60ea7a6"
+ integrity sha512-UnLrCiZ1EI4shznJn0xP6DLgsXUSwtfsdgHhGYCrvbgVBBve3S9iFgVFEB3SPl7Q/TdowNbrN4zHU0oChfiNfw==
+
+"@swc/core-linux-arm64-musl@1.7.0":
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.0.tgz#4bb226a4e9eabac4e1a3b3ffd7ea5955629c84ed"
+ integrity sha512-H724UANA+ptsfwKRr9mnaDa9cb5fw0oFysiGKTgb3DMYcgk3Od0jMTnXVPFSVpo7FlmyxeC9K8ueUPBOoOK6XA==
+
+"@swc/core-linux-x64-gnu@1.7.0":
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.0.tgz#ee65d1362214e91de89414f41b3310ba5302c2c5"
+ integrity sha512-SY3HA0K0Dpqt1HIfMLGpwL4hd4UaL2xHP5oZXPlRQPhUDZrbb4PbI3ZJnh66c63eL4ZR8EJ+HRFI0Alx5p69Zw==
+
+"@swc/core-linux-x64-musl@1.7.0":
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.0.tgz#0868518771004753acb07d9871cf5b143b51dc30"
+ integrity sha512-cEJ2ebtV1v/5Ilb55E05J6F5SrHKQWzUttIhR5Mkayyo+yvPslcpByuFC3D+J7X1ebziTOBpWuMpUdjLfh3SMQ==
+
+"@swc/core-win32-arm64-msvc@1.7.0":
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.0.tgz#43048d67f871e798566c3883c991bed521ef3b9e"
+ integrity sha512-ecQOOmzEssz+m0pR4xDYCGuvn3E/l0nQ3tk5jp1NA1lsAy4bMV0YbYCHjptYvWL/UjhIerIp3IlCJ8x5DodSog==
+
+"@swc/core-win32-ia32-msvc@1.7.0":
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.0.tgz#6e98f413e6469cfd00dcc7c106cb69f2c709e581"
+ integrity sha512-gz81seZkRn3zMnVOc7L5k6F4vQC82gIxmHiL+GedK+A37XI/X26AASU3zxvORnqQbwQYXQ+AEVckxBmFlz3v2g==
+
+"@swc/core-win32-x64-msvc@1.7.0":
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.0.tgz#79dfce878552f0a066a40c9cef524f4a8f872674"
+ integrity sha512-b5Fd1xEOw9uqBpj2lqsaR4Iq9UhiL84hNDcEsi6DQA7Y1l85waQAslTbS0E4/pJ1PISAs0jW0zIGLco1eaWBOg==
"@swc/core@^1.5.7":
- version "1.6.7"
- resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.6.7.tgz#5d113df161fd8ec29ab8837f385240f41315735e"
- integrity sha512-BBzORL9qWz5hZqAZ83yn+WNaD54RH5eludjqIOboolFOK/Pw+2l00/H77H4CEBJnzCIBQszsyqtITmrn4evp0g==
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.7.0.tgz#81f4e7dadf03e1d7f9a5e48a87f5d857e8fc1468"
+ integrity sha512-d4vMzH6ICllDwlPuhset2h8gu/USHdbyfJim+2hQEdxC0UONtfpmu38XBgNqRjStrji1Q5M10jfeUZL3cu1i8g==
dependencies:
"@swc/counter" "^0.1.3"
"@swc/types" "^0.1.9"
optionalDependencies:
- "@swc/core-darwin-arm64" "1.6.7"
- "@swc/core-darwin-x64" "1.6.7"
- "@swc/core-linux-arm-gnueabihf" "1.6.7"
- "@swc/core-linux-arm64-gnu" "1.6.7"
- "@swc/core-linux-arm64-musl" "1.6.7"
- "@swc/core-linux-x64-gnu" "1.6.7"
- "@swc/core-linux-x64-musl" "1.6.7"
- "@swc/core-win32-arm64-msvc" "1.6.7"
- "@swc/core-win32-ia32-msvc" "1.6.7"
- "@swc/core-win32-x64-msvc" "1.6.7"
+ "@swc/core-darwin-arm64" "1.7.0"
+ "@swc/core-darwin-x64" "1.7.0"
+ "@swc/core-linux-arm-gnueabihf" "1.7.0"
+ "@swc/core-linux-arm64-gnu" "1.7.0"
+ "@swc/core-linux-arm64-musl" "1.7.0"
+ "@swc/core-linux-x64-gnu" "1.7.0"
+ "@swc/core-linux-x64-musl" "1.7.0"
+ "@swc/core-win32-arm64-msvc" "1.7.0"
+ "@swc/core-win32-ia32-msvc" "1.7.0"
+ "@swc/core-win32-x64-msvc" "1.7.0"
"@swc/counter@^0.1.3":
version "0.1.3"
@@ -906,9 +921,9 @@
integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==
"@swc/types@^0.1.9":
- version "0.1.9"
- resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.9.tgz#e67cdcc2e4dd74a3cef4474b465eb398e7ae83e2"
- integrity sha512-qKnCno++jzcJ4lM4NTfYifm1EFSCeIfKiAHAfkENZAV5Kl9PjJIyd2yeeVv6c/2CckuLyv2NmRC5pv6pm2WQBg==
+ version "0.1.12"
+ resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.12.tgz#7f632c06ab4092ce0ebd046ed77ff7557442282f"
+ integrity sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==
dependencies:
"@swc/counter" "^0.1.3"
@@ -932,7 +947,7 @@
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239"
integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==
-"@types/prop-types@*", "@types/prop-types@^15.7.11":
+"@types/prop-types@*", "@types/prop-types@^15.7.12":
version "15.7.12"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6"
integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==
@@ -986,61 +1001,61 @@
csstype "^3.0.2"
"@typescript-eslint/eslint-plugin@^7.2.0":
- version "7.15.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.15.0.tgz#8eaf396ac2992d2b8f874b68eb3fcd6b179cb7f3"
- integrity sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==
+ version "7.16.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.1.tgz#f5f5da52db674b1f2cdb9d5f3644e5b2ec750465"
+ integrity sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A==
dependencies:
"@eslint-community/regexpp" "^4.10.0"
- "@typescript-eslint/scope-manager" "7.15.0"
- "@typescript-eslint/type-utils" "7.15.0"
- "@typescript-eslint/utils" "7.15.0"
- "@typescript-eslint/visitor-keys" "7.15.0"
+ "@typescript-eslint/scope-manager" "7.16.1"
+ "@typescript-eslint/type-utils" "7.16.1"
+ "@typescript-eslint/utils" "7.16.1"
+ "@typescript-eslint/visitor-keys" "7.16.1"
graphemer "^1.4.0"
ignore "^5.3.1"
natural-compare "^1.4.0"
ts-api-utils "^1.3.0"
"@typescript-eslint/parser@^7.2.0":
- version "7.15.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.15.0.tgz#f4a536e5fc6a1c05c82c4d263a2bfad2da235c80"
- integrity sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A==
- dependencies:
- "@typescript-eslint/scope-manager" "7.15.0"
- "@typescript-eslint/types" "7.15.0"
- "@typescript-eslint/typescript-estree" "7.15.0"
- "@typescript-eslint/visitor-keys" "7.15.0"
+ version "7.16.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.16.1.tgz#84c581cf86c8b2becd48d33ddc41a6303d57b274"
+ integrity sha512-u+1Qx86jfGQ5i4JjK33/FnawZRpsLxRnKzGE6EABZ40KxVT/vWsiZFEBBHjFOljmmV3MBYOHEKi0Jm9hbAOClA==
+ dependencies:
+ "@typescript-eslint/scope-manager" "7.16.1"
+ "@typescript-eslint/types" "7.16.1"
+ "@typescript-eslint/typescript-estree" "7.16.1"
+ "@typescript-eslint/visitor-keys" "7.16.1"
debug "^4.3.4"
-"@typescript-eslint/scope-manager@7.15.0":
- version "7.15.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.15.0.tgz#201b34b0720be8b1447df17b963941bf044999b2"
- integrity sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==
+"@typescript-eslint/scope-manager@7.16.1":
+ version "7.16.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.16.1.tgz#2b43041caabf8ddd74512b8b550b9fc53ca3afa1"
+ integrity sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw==
dependencies:
- "@typescript-eslint/types" "7.15.0"
- "@typescript-eslint/visitor-keys" "7.15.0"
+ "@typescript-eslint/types" "7.16.1"
+ "@typescript-eslint/visitor-keys" "7.16.1"
-"@typescript-eslint/type-utils@7.15.0":
- version "7.15.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.15.0.tgz#5b83c904c6de91802fb399305a50a56d10472c39"
- integrity sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==
+"@typescript-eslint/type-utils@7.16.1":
+ version "7.16.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.16.1.tgz#4d7ae4f3d9e3c8cbdabae91609b1a431de6aa6ca"
+ integrity sha512-rbu/H2MWXN4SkjIIyWcmYBjlp55VT+1G3duFOIukTNFxr9PI35pLc2ydwAfejCEitCv4uztA07q0QWanOHC7dA==
dependencies:
- "@typescript-eslint/typescript-estree" "7.15.0"
- "@typescript-eslint/utils" "7.15.0"
+ "@typescript-eslint/typescript-estree" "7.16.1"
+ "@typescript-eslint/utils" "7.16.1"
debug "^4.3.4"
ts-api-utils "^1.3.0"
-"@typescript-eslint/types@7.15.0":
- version "7.15.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.15.0.tgz#fb894373a6e3882cbb37671ffddce44f934f62fc"
- integrity sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==
+"@typescript-eslint/types@7.16.1":
+ version "7.16.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.16.1.tgz#bbab066276d18e398bc64067b23f1ce84dfc6d8c"
+ integrity sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==
-"@typescript-eslint/typescript-estree@7.15.0":
- version "7.15.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.15.0.tgz#e323bfa3966e1485b638ce751f219fc1f31eba37"
- integrity sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==
+"@typescript-eslint/typescript-estree@7.16.1":
+ version "7.16.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.1.tgz#9b145ba4fd1dde1986697e1ce57dc501a1736dd3"
+ integrity sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ==
dependencies:
- "@typescript-eslint/types" "7.15.0"
- "@typescript-eslint/visitor-keys" "7.15.0"
+ "@typescript-eslint/types" "7.16.1"
+ "@typescript-eslint/visitor-keys" "7.16.1"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
@@ -1048,22 +1063,22 @@
semver "^7.6.0"
ts-api-utils "^1.3.0"
-"@typescript-eslint/utils@7.15.0":
- version "7.15.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.15.0.tgz#9e6253c4599b6e7da2fb64ba3f549c73eb8c1960"
- integrity sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==
+"@typescript-eslint/utils@7.16.1":
+ version "7.16.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.16.1.tgz#df42dc8ca5a4603016fd102db0346cdab415cdb7"
+ integrity sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA==
dependencies:
"@eslint-community/eslint-utils" "^4.4.0"
- "@typescript-eslint/scope-manager" "7.15.0"
- "@typescript-eslint/types" "7.15.0"
- "@typescript-eslint/typescript-estree" "7.15.0"
+ "@typescript-eslint/scope-manager" "7.16.1"
+ "@typescript-eslint/types" "7.16.1"
+ "@typescript-eslint/typescript-estree" "7.16.1"
-"@typescript-eslint/visitor-keys@7.15.0":
- version "7.15.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.15.0.tgz#1da0726201a859343fe6a05742a7c1792fff5b66"
- integrity sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==
+"@typescript-eslint/visitor-keys@7.16.1":
+ version "7.16.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.1.tgz#4287bcf44c34df811ff3bb4d269be6cfc7d8c74b"
+ integrity sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg==
dependencies:
- "@typescript-eslint/types" "7.15.0"
+ "@typescript-eslint/types" "7.16.1"
eslint-visitor-keys "^3.4.3"
"@ungap/structured-clone@^1.2.0":
@@ -1123,9 +1138,9 @@ ansi-styles@^4.1.0:
color-convert "^2.0.1"
apexcharts@^3.50.0:
- version "3.50.0"
- resolved "https://registry.yarnpkg.com/apexcharts/-/apexcharts-3.50.0.tgz#9030f206183978df0d762602b3d15b59ec6e783b"
- integrity sha512-LJT1PNAm+NoIU3aogL2P+ViC0y/Cjik54FdzzGV54UNnGQLBoLe5ok3fxsJDTgyez45BGYT8gqNpYKqhdfy5sg==
+ version "3.51.0"
+ resolved "https://registry.yarnpkg.com/apexcharts/-/apexcharts-3.51.0.tgz#f99d8a7f49045b61bab795522f35233faac5fe94"
+ integrity sha512-WpCdVdGiJjf9SAyEeg2rl3q5OqCcNqiEmH0+filMraUiH6Vqyn5GFeMMyH0pon44xjNr1G0xzIRERKRmsGEuRA==
dependencies:
"@yr/monotone-cubic-spline" "^1.0.3"
svg.draggable.js "^2.2.2"
@@ -1181,15 +1196,15 @@ braces@^3.0.3:
dependencies:
fill-range "^7.1.1"
-browserslist@^4.22.2:
- version "4.23.1"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.1.tgz#ce4af0534b3d37db5c1a4ca98b9080f985041e96"
- integrity sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==
+browserslist@^4.23.1:
+ version "4.23.2"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.2.tgz#244fe803641f1c19c28c48c4b6ec9736eb3d32ed"
+ integrity sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==
dependencies:
- caniuse-lite "^1.0.30001629"
- electron-to-chromium "^1.4.796"
+ caniuse-lite "^1.0.30001640"
+ electron-to-chromium "^1.4.820"
node-releases "^2.0.14"
- update-browserslist-db "^1.0.16"
+ update-browserslist-db "^1.1.0"
callsites@^3.0.0:
version "3.1.0"
@@ -1201,10 +1216,10 @@ camelcase@^6.2.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
-caniuse-lite@^1.0.30001629:
- version "1.0.30001640"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz#32c467d4bf1f1a0faa63fc793c2ba81169e7652f"
- integrity sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA==
+caniuse-lite@^1.0.30001640:
+ version "1.0.30001643"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz#9c004caef315de9452ab970c3da71085f8241dbd"
+ integrity sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==
chalk@^2.4.2:
version "2.4.2"
@@ -1233,7 +1248,7 @@ clsx@^1.1.0:
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
-clsx@^2.1.0:
+clsx@^2.1.0, clsx@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
@@ -1312,6 +1327,11 @@ csstype@^3.0.2, csstype@^3.1.3:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
+dayjs@^1.11.12:
+ version "1.11.12"
+ resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.12.tgz#5245226cc7f40a15bf52e0b99fd2a04669ccac1d"
+ integrity sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==
+
debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
version "4.3.5"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e"
@@ -1354,10 +1374,10 @@ dot-case@^3.0.4:
no-case "^3.0.4"
tslib "^2.0.3"
-electron-to-chromium@^1.4.796:
- version "1.4.818"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.818.tgz#7762c8bfd15a07c3833b7f5deed990e9e5a4c24f"
- integrity sha512-eGvIk2V0dGImV9gWLq8fDfTTsCAeMDwZqEPMr+jMInxZdnp9Us8UpovYpRCf9NQ7VOFgrN2doNSgvISbsbNpxA==
+electron-to-chromium@^1.4.820:
+ version "1.4.832"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.832.tgz#d25882ce0a9237577b039bffa124ecef1822003b"
+ integrity sha512-cTen3SB0H2SGU7x467NRe1eVcQgcuS6jckKfWJHia2eo0cHIGOqHoAxevIYZD4eRHcWjkvFzo93bi3vJ9W+1lA==
entities@^4.4.0:
version "4.5.0"
@@ -1421,9 +1441,9 @@ eslint-plugin-react-hooks@^4.6.0:
integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==
eslint-plugin-react-refresh@^0.4.6:
- version "0.4.7"
- resolved "https://registry.yarnpkg.com/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.7.tgz#1f597f9093b254f10ee0961c139a749acb19af7d"
- integrity sha512-yrj+KInFmwuQS2UQcg1SF83ha1tuHC1jMQbRNyuWtlEzzKRDgAl7L4Yp4NlDUZTZNlWvHEzOtJhMi40R7JxcSw==
+ version "0.4.9"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.9.tgz#bf870372b353b12e1e6fb7fc41b282d9cbc8d93d"
+ integrity sha512-QK49YrBAo5CLNLseZ7sZgvgTy21E6NEw22eZqc4teZfH8pxV3yXc9XXOYfUI6JNpw7mfHNkAeWtBxrTyykB6HA==
eslint-scope@^7.2.2:
version "7.2.2"
@@ -1492,9 +1512,9 @@ espree@^9.6.0, espree@^9.6.1:
eslint-visitor-keys "^3.4.1"
esquery@^1.4.2:
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b"
- integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7"
+ integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==
dependencies:
estraverse "^5.1.0"
@@ -1735,9 +1755,9 @@ is-arrayish@^0.2.1:
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
is-core-module@^2.13.0:
- version "2.14.0"
- resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1"
- integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==
+ version "2.15.0"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.0.tgz#71c72ec5442ace7e76b306e9d48db361f22699ea"
+ integrity sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==
dependencies:
hasown "^2.0.2"
@@ -1929,9 +1949,9 @@ no-case@^3.0.4:
tslib "^2.0.3"
node-releases@^2.0.14:
- version "2.0.14"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b"
- integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==
+ version "2.0.17"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.17.tgz#d74bc4fec38d839eec5db2a3c9c963d4f33cb366"
+ integrity sha512-Ww6ZlOiEQfPfXM45v17oabk77Z7mg5bOt7AjDyzy7RjK9OrLrLC8dyZQoAPEOtFX9SaNf1Tdvr5gRJWdTJj7GA==
notistack@^3.0.1:
version "3.0.1"
@@ -2071,13 +2091,6 @@ react-apexcharts@^1.4.1:
dependencies:
prop-types "^15.8.1"
-react-device-detect@^2.2.3:
- version "2.2.3"
- resolved "https://registry.yarnpkg.com/react-device-detect/-/react-device-detect-2.2.3.tgz#97a7ae767cdd004e7c3578260f48cf70c036e7ca"
- integrity sha512-buYY3qrCnQVlIFHrC5UcUoAj7iANs/+srdkwsnNjI7anr3Tt7UY6MqNxtMLlr0tMBied0O49UZVK8XKs3ZIiPw==
- dependencies:
- ua-parser-js "^1.0.33"
-
react-dom@^18.2.0:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4"
@@ -2091,18 +2104,18 @@ react-is@^16.13.1, react-is@^16.7.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
-react-is@^18.2.0:
+react-is@^18.3.1:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e"
integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
react-router-dom@^6.23.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.24.1.tgz#b1a22f7d6c5a1bfce30732bd370713f991ab4de4"
- integrity sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg==
+ version "6.25.1"
+ resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.25.1.tgz#b89f8d63fc8383ea4e89c44bf31c5843e1f7afa0"
+ integrity sha512-0tUDpbFvk35iv+N89dWNrJp+afLgd+y4VtorJZuOCXK0kkCWjEvb3vTJM++SYvMEpbVwXKf3FjeVveVEb6JpDQ==
dependencies:
- "@remix-run/router" "1.17.1"
- react-router "6.24.1"
+ "@remix-run/router" "1.18.0"
+ react-router "6.25.1"
react-router-hash-link@^2.4.3:
version "2.4.3"
@@ -2111,12 +2124,12 @@ react-router-hash-link@^2.4.3:
dependencies:
prop-types "^15.7.2"
-react-router@6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.24.1.tgz#5a3bbba0000afba68d42915456ca4c806f37a7de"
- integrity sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg==
+react-router@6.25.1:
+ version "6.25.1"
+ resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.25.1.tgz#70b4f1af79954cfcfd23f6ddf5c883e8c904203e"
+ integrity sha512-u8ELFr5Z6g02nUtpPAggP73Jigj1mRePSwhS/2nkTrlPU5yEkH1vYzWNyvSnSzeeE2DNqWdH+P8OhIh9wuXhTw==
dependencies:
- "@remix-run/router" "1.17.1"
+ "@remix-run/router" "1.18.0"
react-tooltip@^5.27.0:
version "5.27.1"
@@ -2175,28 +2188,28 @@ rimraf@^3.0.2:
glob "^7.1.3"
rollup@^4.13.0:
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.18.0.tgz#497f60f0c5308e4602cf41136339fbf87d5f5dda"
- integrity sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==
+ version "4.19.0"
+ resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.19.0.tgz#83b08cc0b2bc38c26c194cb7f2cdabd84a2a8c02"
+ integrity sha512-5r7EYSQIowHsK4eTZ0Y81qpZuJz+MUuYeqmmYmRMl1nwhdmbiYqt5jwzf6u7wyOzJgYqtCRMtVRKOtHANBz7rA==
dependencies:
"@types/estree" "1.0.5"
optionalDependencies:
- "@rollup/rollup-android-arm-eabi" "4.18.0"
- "@rollup/rollup-android-arm64" "4.18.0"
- "@rollup/rollup-darwin-arm64" "4.18.0"
- "@rollup/rollup-darwin-x64" "4.18.0"
- "@rollup/rollup-linux-arm-gnueabihf" "4.18.0"
- "@rollup/rollup-linux-arm-musleabihf" "4.18.0"
- "@rollup/rollup-linux-arm64-gnu" "4.18.0"
- "@rollup/rollup-linux-arm64-musl" "4.18.0"
- "@rollup/rollup-linux-powerpc64le-gnu" "4.18.0"
- "@rollup/rollup-linux-riscv64-gnu" "4.18.0"
- "@rollup/rollup-linux-s390x-gnu" "4.18.0"
- "@rollup/rollup-linux-x64-gnu" "4.18.0"
- "@rollup/rollup-linux-x64-musl" "4.18.0"
- "@rollup/rollup-win32-arm64-msvc" "4.18.0"
- "@rollup/rollup-win32-ia32-msvc" "4.18.0"
- "@rollup/rollup-win32-x64-msvc" "4.18.0"
+ "@rollup/rollup-android-arm-eabi" "4.19.0"
+ "@rollup/rollup-android-arm64" "4.19.0"
+ "@rollup/rollup-darwin-arm64" "4.19.0"
+ "@rollup/rollup-darwin-x64" "4.19.0"
+ "@rollup/rollup-linux-arm-gnueabihf" "4.19.0"
+ "@rollup/rollup-linux-arm-musleabihf" "4.19.0"
+ "@rollup/rollup-linux-arm64-gnu" "4.19.0"
+ "@rollup/rollup-linux-arm64-musl" "4.19.0"
+ "@rollup/rollup-linux-powerpc64le-gnu" "4.19.0"
+ "@rollup/rollup-linux-riscv64-gnu" "4.19.0"
+ "@rollup/rollup-linux-s390x-gnu" "4.19.0"
+ "@rollup/rollup-linux-x64-gnu" "4.19.0"
+ "@rollup/rollup-linux-x64-musl" "4.19.0"
+ "@rollup/rollup-win32-arm64-msvc" "4.19.0"
+ "@rollup/rollup-win32-ia32-msvc" "4.19.0"
+ "@rollup/rollup-win32-x64-msvc" "4.19.0"
fsevents "~2.3.2"
run-parallel@^1.1.9:
@@ -2219,9 +2232,9 @@ semver@^6.3.1:
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
semver@^7.6.0:
- version "7.6.2"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
- integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
+ version "7.6.3"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
+ integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
shebang-command@^2.0.0:
version "2.0.0"
@@ -2398,12 +2411,7 @@ typescript@^5.2.2:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.3.tgz#e1b0a3c394190838a0b168e771b0ad56a0af0faa"
integrity sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==
-ua-parser-js@^1.0.33:
- version "1.0.38"
- resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.38.tgz#66bb0c4c0e322fe48edfe6d446df6042e62f25e2"
- integrity sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==
-
-update-browserslist-db@^1.0.16:
+update-browserslist-db@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e"
integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==
@@ -2428,9 +2436,9 @@ vite-plugin-svgr@^4.2.0:
"@svgr/plugin-jsx" "^8.1.0"
vite@^5.2.0:
- version "5.3.3"
- resolved "https://registry.yarnpkg.com/vite/-/vite-5.3.3.tgz#5265b1f0a825b3b6564c2d07524777c83e3c04c2"
- integrity sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==
+ version "5.3.4"
+ resolved "https://registry.yarnpkg.com/vite/-/vite-5.3.4.tgz#b36ebd47c8a5e3a8727046375d5f10bf9fdf8715"
+ integrity sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA==
dependencies:
esbuild "^0.21.3"
postcss "^8.4.39"