From b09c1b3214a189201d6b7a21a70c3bfb2d001275 Mon Sep 17 00:00:00 2001 From: itoshi Date: Sun, 8 Jun 2025 08:33:43 +0300 Subject: [PATCH] feat: Add `edit` pages with `cache` --- package-lock.json | 77 ++- package.json | 1 + src/app/router/index.tsx | 19 +- src/entities/navigation/model/index.ts | 4 +- src/entities/navigation/ui/index.tsx | 125 +++-- src/pages/Carrier/CarrierCreatePage/index.tsx | 119 +++-- src/pages/Carrier/CarrierEditPage/index.tsx | 307 +++++++++++ src/pages/Carrier/CarrierListPage/index.tsx | 20 +- .../Carrier/CarrierPreviewPage/index.tsx | 54 +- src/pages/Carrier/index.ts | 1 + src/pages/City/CityCreatePage/index.tsx | 67 ++- src/pages/City/CityEditPage/index.tsx | 207 ++++++++ src/pages/City/CityListPage/index.tsx | 14 +- src/pages/City/CityPreviewPage/index.tsx | 47 +- src/pages/City/index.ts | 1 + src/pages/Country/CountryCreatePage/index.tsx | 26 +- src/pages/Country/CountryEditPage/index.tsx | 87 +++ src/pages/Country/CountryListPage/index.tsx | 19 +- .../Country/CountryPreviewPage/index.tsx | 18 +- src/pages/Country/index.ts | 1 + src/pages/User/UserCreatePage/index.tsx | 129 +++++ src/pages/User/UserEditPage/index.tsx | 139 +++++ src/pages/User/UserListPage/index.tsx | 28 +- src/pages/User/index.ts | 2 + src/pages/Vehicle/VehicleCreatePage/index.tsx | 2 - src/pages/Vehicle/VehicleEditPage/index.tsx | 140 +++++ src/pages/Vehicle/VehicleListPage/index.tsx | 9 +- .../Vehicle/VehiclePreviewPage/index.tsx | 10 +- src/pages/Vehicle/index.ts | 1 + src/shared/config/constants.tsx | 89 ++-- src/shared/store/CarrierStore/index.tsx | 93 +++- .../store/CityStore/{index.tsx => fd.tsx} | 2 +- src/shared/store/CityStore/index.ts | 266 ++++++++++ src/shared/store/CountryStore/index.ts | 196 ++++++- src/shared/store/UserStore/index.ts | 68 ++- src/shared/store/VehicleStore/index.ts | 107 +++- yarn.lock | 500 +++--------------- 37 files changed, 2223 insertions(+), 772 deletions(-) create mode 100644 src/pages/Carrier/CarrierEditPage/index.tsx create mode 100644 src/pages/City/CityEditPage/index.tsx create mode 100644 src/pages/Country/CountryEditPage/index.tsx create mode 100644 src/pages/User/UserCreatePage/index.tsx create mode 100644 src/pages/User/UserEditPage/index.tsx create mode 100644 src/pages/Vehicle/VehicleEditPage/index.tsx rename src/shared/store/CityStore/{index.tsx => fd.tsx} (96%) create mode 100644 src/shared/store/CityStore/index.ts diff --git a/package-lock.json b/package-lock.json index 61d62be..ce94f97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", "@hello-pangea/dnd": "^18.0.1", + "@mui/icons-material": "^7.1.1", "@mui/material": "^7.1.0", "@mui/x-data-grid": "^8.5.1", "@photo-sphere-viewer/core": "^5.13.2", @@ -838,26 +839,52 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.0.tgz", - "integrity": "sha512-E0OqhZv548Qdc0PwWhLVA2zmjJZSTvaL4ZhoswmI8NJEC1tpW2js6LLP827jrW9MEiXYdz3QS6+hask83w74yQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.1.tgz", + "integrity": "sha512-yBckQs4aQ8mqukLnPC6ivIRv6guhaXi8snVl00VtyojBbm+l6VbVhyTSZ68Abcx7Ah8B+GZhrB7BOli+e+9LkQ==", "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" } }, + "node_modules/@mui/icons-material": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-7.1.1.tgz", + "integrity": "sha512-X37+Yc8QpEnl0sYmz+WcLFy2dWgNRzbswDzLPXG7QU1XDVlP5TPp1HXjdmCupOWLL/I9m1fyhcyZl8/HPpp/Cg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^7.1.1", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@mui/material": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.1.0.tgz", - "integrity": "sha512-ahUJdrhEv+mCp4XHW+tHIEYzZMSRLg8z4AjUOsj44QpD1ZaMxQoVOG2xiHvLFdcsIPbgSRx1bg1eQSheHBgvtg==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.1.1.tgz", + "integrity": "sha512-mTpdmdZCaHCGOH3SrYM41+XKvNL0iQfM9KlYgpSjgadXx/fEKhhvOktxm8++Xw6FFeOHoOiV+lzOI8X1rsv71A==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.27.1", - "@mui/core-downloads-tracker": "^7.1.0", - "@mui/system": "^7.1.0", - "@mui/types": "^7.4.2", - "@mui/utils": "^7.1.0", + "@mui/core-downloads-tracker": "^7.1.1", + "@mui/system": "^7.1.1", + "@mui/types": "^7.4.3", + "@mui/utils": "^7.1.1", "@popperjs/core": "^2.11.8", "@types/react-transition-group": "^4.4.12", "clsx": "^2.1.1", @@ -876,7 +903,7 @@ "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@mui/material-pigment-css": "^7.1.0", + "@mui/material-pigment-css": "^7.1.1", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" @@ -903,13 +930,13 @@ "license": "MIT" }, "node_modules/@mui/private-theming": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.1.0.tgz", - "integrity": "sha512-4Kck4jxhqF6YxNwJdSae1WgDfXVg0lIH6JVJ7gtuFfuKcQCgomJxPvUEOySTFRPz1IZzwz5OAcToskRdffElDA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.1.1.tgz", + "integrity": "sha512-M8NbLUx+armk2ZuaxBkkMk11ultnWmrPlN0Xe3jUEaBChg/mcxa5HWIWS1EE4DF36WRACaAHVAvyekWlDQf0PQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.27.1", - "@mui/utils": "^7.1.0", + "@mui/utils": "^7.1.1", "prop-types": "^15.8.1" }, "engines": { @@ -930,9 +957,9 @@ } }, "node_modules/@mui/styled-engine": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.1.0.tgz", - "integrity": "sha512-m0mJ0c6iRC+f9hMeRe0W7zZX1wme3oUX0+XTVHjPG7DJz6OdQ6K/ggEOq7ZdwilcpdsDUwwMfOmvO71qDkYd2w==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.1.1.tgz", + "integrity": "sha512-R2wpzmSN127j26HrCPYVQ53vvMcT5DaKLoWkrfwUYq3cYytL6TQrCH8JBH3z79B6g4nMZZVoaXrxO757AlShaw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.27.1", @@ -964,16 +991,16 @@ } }, "node_modules/@mui/system": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.1.0.tgz", - "integrity": "sha512-iedAWgRJMCxeMHvkEhsDlbvkK+qKf9me6ofsf7twk/jfT4P1ImVf7Rwb5VubEA0sikrVL+1SkoZM41M4+LNAVA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.1.1.tgz", + "integrity": "sha512-Kj1uhiqnj4Zo7PDjAOghtXJtNABunWvhcRU0O7RQJ7WOxeynoH6wXPcilphV8QTFtkKaip8EiNJRiCD+B3eROA==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.27.1", - "@mui/private-theming": "^7.1.0", - "@mui/styled-engine": "^7.1.0", - "@mui/types": "^7.4.2", - "@mui/utils": "^7.1.0", + "@mui/private-theming": "^7.1.1", + "@mui/styled-engine": "^7.1.1", + "@mui/types": "^7.4.3", + "@mui/utils": "^7.1.1", "clsx": "^2.1.1", "csstype": "^3.1.3", "prop-types": "^15.8.1" diff --git a/package.json b/package.json index 475763a..bb35152 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", "@hello-pangea/dnd": "^18.0.1", + "@mui/icons-material": "^7.1.1", "@mui/material": "^7.1.0", "@mui/x-data-grid": "^8.5.1", "@photo-sphere-viewer/core": "^5.13.2", diff --git a/src/app/router/index.tsx b/src/app/router/index.tsx index 55b6e6f..089a9bb 100644 --- a/src/app/router/index.tsx +++ b/src/app/router/index.tsx @@ -25,8 +25,14 @@ import { SnapshotCreatePage, CountryCreatePage, CityCreatePage, - // CarrierCreatePage, + CarrierCreatePage, VehicleCreatePage, + CountryEditPage, + CityEditPage, + UserCreatePage, + UserEditPage, + VehicleEditPage, + CarrierEditPage, } from "@pages"; import { authStore, createSightStore, editSightStore } from "@shared"; import { Layout } from "@widgets"; @@ -121,25 +127,28 @@ const router = createBrowserRouter([ { path: "country", element: }, { path: "country/create", element: }, { path: "country/:id", element: }, + { path: "country/:id/edit", element: }, // City { path: "city", element: }, { path: "city/create", element: }, { path: "city/:id", element: }, + { path: "city/:id/edit", element: }, // Route { path: "route", element: }, // User { path: "user", element: }, - + { path: "user/create", element: }, + { path: "user/:id/edit", element: }, // Snapshot { path: "snapshot", element: }, { path: "snapshot/create", element: }, // Carrier { path: "carrier", element: }, - // { path: "carrier/create", element: }, + { path: "carrier/create", element: }, { path: "carrier/:id", element: }, - + { path: "carrier/:id/edit", element: }, // Station { path: "station", element: }, @@ -147,7 +156,7 @@ const router = createBrowserRouter([ { path: "vehicle", element: }, { path: "vehicle/create", element: }, { path: "vehicle/:id", element: }, - + { path: "vehicle/:id/edit", element: }, // Article { path: "article", element: }, diff --git a/src/entities/navigation/model/index.ts b/src/entities/navigation/model/index.ts index 6c0ed0a..99a9f01 100644 --- a/src/entities/navigation/model/index.ts +++ b/src/entities/navigation/model/index.ts @@ -4,7 +4,9 @@ export interface NavigationItem { id: string; label: string; icon: LucideIcon; - path: string; + path?: string; + onClick?: () => void; + nestedItems?: NavigationItem[]; } export type NavigationSection = "primary" | "secondary"; diff --git a/src/entities/navigation/ui/index.tsx b/src/entities/navigation/ui/index.tsx index 061caa3..77247ea 100644 --- a/src/entities/navigation/ui/index.tsx +++ b/src/entities/navigation/ui/index.tsx @@ -3,6 +3,10 @@ import ListItem from "@mui/material/ListItem"; import ListItemButton from "@mui/material/ListItemButton"; import ListItemIcon from "@mui/material/ListItemIcon"; import ListItemText from "@mui/material/ListItemText"; +import Collapse from "@mui/material/Collapse"; +import List from "@mui/material/List"; +import ExpandLessIcon from "@mui/icons-material/ExpandLess"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import type { NavigationItem } from "../model"; import { useNavigate } from "react-router-dom"; @@ -10,73 +14,100 @@ interface NavigationItemProps { item: NavigationItem; open: boolean; onClick?: () => void; + isNested?: boolean; } export const NavigationItemComponent: React.FC = ({ item, open, onClick, + isNested = false, }) => { const Icon = item.icon; const navigate = useNavigate(); + const [isExpanded, setIsExpanded] = React.useState(false); + + const handleClick = () => { + if (item.nestedItems) { + setIsExpanded(!isExpanded); + } else if (onClick) { + onClick(); + } else if (item.path) { + navigate(item.path); + } + }; return ( - { - if (onClick) { - onClick(); - } else { - navigate(item.path); - } - }} - disablePadding - sx={{ display: "block" }} - > - - + + - - - - - + + + + + {item.nestedItems && + open && + (isExpanded ? : )} + + + {item.nestedItems && ( + + + {item.nestedItems.map((nestedItem) => ( + + ))} + + + )} + ); }; diff --git a/src/pages/Carrier/CarrierCreatePage/index.tsx b/src/pages/Carrier/CarrierCreatePage/index.tsx index c9226e7..8f4acbc 100644 --- a/src/pages/Carrier/CarrierCreatePage/index.tsx +++ b/src/pages/Carrier/CarrierCreatePage/index.tsx @@ -23,15 +23,15 @@ export const CarrierCreatePage = observer(() => { const [fullName, setFullName] = useState(""); const [shortName, setShortName] = useState(""); const [cityId, setCityId] = useState(null); - const [primaryColor, setPrimaryColor] = useState("#000000"); - const [secondaryColor, setSecondaryColor] = useState("#ffffff"); - const [accentColor, setAccentColor] = useState("#ff0000"); + const [main_color, setMainColor] = useState("#000000"); + const [left_color, setLeftColor] = useState("#ffffff"); + const [right_color, setRightColor] = useState("#ff0000"); const [slogan, setSlogan] = useState(""); const [selectedMediaId, setSelectedMediaId] = useState(null); const [isLoading, setIsLoading] = useState(false); useEffect(() => { - cityStore.getCities(); + cityStore.getCities("ru"); mediaStore.getMedia(); }, []); @@ -41,11 +41,11 @@ export const CarrierCreatePage = observer(() => { await carrierStore.createCarrier( fullName, shortName, - cityStore.cities.find((c) => c.id === cityId)?.name!, + cityStore.cities.ru.find((c) => c.id === cityId)?.name!, cityId!, - primaryColor, - secondaryColor, - accentColor, + main_color, + left_color, + right_color, slogan, selectedMediaId! ); @@ -60,7 +60,6 @@ export const CarrierCreatePage = observer(() => { return ( -
+
+ +
+ + Город + + + + + setEditCarrierData( + e.target.value, + editCarrierData.short_name, + editCarrierData.city, + editCarrierData.city_id, + editCarrierData.main_color, + editCarrierData.left_color, + editCarrierData.right_color, + editCarrierData.slogan, + editCarrierData.logo + ) + } + /> + + + setEditCarrierData( + editCarrierData.full_name, + e.target.value, + editCarrierData.city, + editCarrierData.city_id, + editCarrierData.main_color, + editCarrierData.left_color, + editCarrierData.right_color, + editCarrierData.slogan, + editCarrierData.logo + ) + } + /> + +
+ + setEditCarrierData( + editCarrierData.full_name, + editCarrierData.short_name, + editCarrierData.city, + editCarrierData.city_id, + e.target.value, + editCarrierData.left_color, + editCarrierData.right_color, + editCarrierData.slogan, + editCarrierData.logo + ) + } + type="color" + sx={{ + "& input": { + height: "50px", + paddingBlock: "14px", + paddingInline: "14px", + cursor: "pointer", + }, + }} + /> + + setEditCarrierData( + editCarrierData.full_name, + editCarrierData.short_name, + editCarrierData.city, + editCarrierData.city_id, + editCarrierData.main_color, + e.target.value, + editCarrierData.right_color, + editCarrierData.slogan, + editCarrierData.logo + ) + } + type="color" + sx={{ + "& input": { + height: "50px", + paddingBlock: "14px", + paddingInline: "14px", + cursor: "pointer", + }, + }} + /> + + setEditCarrierData( + editCarrierData.full_name, + editCarrierData.short_name, + editCarrierData.city, + editCarrierData.city_id, + editCarrierData.main_color, + editCarrierData.left_color, + e.target.value, + editCarrierData.slogan, + editCarrierData.logo + ) + } + type="color" + sx={{ + "& input": { + height: "50px", + paddingBlock: "14px", + paddingInline: "14px", + cursor: "pointer", + }, + }} + /> +
+ + + setEditCarrierData( + editCarrierData.full_name, + editCarrierData.short_name, + editCarrierData.city, + editCarrierData.city_id, + editCarrierData.main_color, + editCarrierData.left_color, + editCarrierData.right_color, + e.target.value, + editCarrierData.logo + ) + } + /> + +
+ + Логотип + + + {editCarrierData.logo && ( +
+ +
+ )} +
+ + +
+
+ ); +}); diff --git a/src/pages/Carrier/CarrierListPage/index.tsx b/src/pages/Carrier/CarrierListPage/index.tsx index 0a42800..fbbd8b1 100644 --- a/src/pages/Carrier/CarrierListPage/index.tsx +++ b/src/pages/Carrier/CarrierListPage/index.tsx @@ -1,21 +1,20 @@ import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid"; -import { carrierStore, languageStore } from "@shared"; +import { carrierStore } from "@shared"; import { useEffect, useState } from "react"; import { observer } from "mobx-react-lite"; -import { Eye, Trash2 } from "lucide-react"; +import { Eye, Pencil, Trash2 } from "lucide-react"; import { useNavigate } from "react-router-dom"; -import { DeleteModal, LanguageSwitcher } from "@widgets"; +import { CreateButton, DeleteModal } from "@widgets"; export const CarrierListPage = observer(() => { const { carriers, getCarriers, deleteCarrier } = carrierStore; const navigate = useNavigate(); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [rowId, setRowId] = useState(null); // Lifted state - const { language } = languageStore; useEffect(() => { getCarriers(); - }, [language]); + }, []); const columns: GridColDef[] = [ { @@ -37,10 +36,15 @@ export const CarrierListPage = observer(() => { { field: "actions", headerName: "Действия", + headerAlign: "center", + width: 200, renderCell: (params: GridRenderCellParams) => { return (
+ @@ -67,12 +71,10 @@ export const CarrierListPage = observer(() => { return ( <> - -

Перевозчики

- {/* */} +
{ open={isDeleteModalOpen} onDelete={async () => { if (rowId) { - deleteCarrier(rowId); + await deleteCarrier(rowId); } setIsDeleteModalOpen(false); setRowId(null); diff --git a/src/pages/Carrier/CarrierPreviewPage/index.tsx b/src/pages/Carrier/CarrierPreviewPage/index.tsx index 60c3028..f3df3c9 100644 --- a/src/pages/Carrier/CarrierPreviewPage/index.tsx +++ b/src/pages/Carrier/CarrierPreviewPage/index.tsx @@ -1,5 +1,5 @@ import { Paper } from "@mui/material"; -import { carrierStore, mediaStore } from "@shared"; +import { carrierStore, languageStore, mediaStore } from "@shared"; import { MediaViewer } from "@widgets"; import { observer } from "mobx-react-lite"; import { ArrowLeft } from "lucide-react"; @@ -8,13 +8,25 @@ import { useNavigate, useParams } from "react-router-dom"; export const CarrierPreviewPage = observer(() => { const { id } = useParams(); - const { getCarrier, carrier } = carrierStore; + const { getCarrier, carrier, setEditCarrierData } = carrierStore; const { oneMedia, getOneMedia } = mediaStore; const navigate = useNavigate(); useEffect(() => { (async () => { const carrierResponse = await getCarrier(Number(id)); + setEditCarrierData( + carrierResponse?.full_name as string, + carrierResponse?.short_name as string, + carrierResponse?.city as string, + carrierResponse?.city_id as number, + carrierResponse?.main_color as string, + carrierResponse?.left_color as string, + carrierResponse?.right_color as string, + carrierResponse?.slogan as string, + carrierResponse?.logo as string + ); + console.log(carrierResponse); await getOneMedia(carrierResponse?.logo as string); })(); }, [id]); @@ -31,48 +43,30 @@ export const CarrierPreviewPage = observer(() => { Назад - {/*
- - -
*/}

Полное имя

-

{carrier?.full_name}

+

{carrier[Number(id)]?.full_name}

Полное имя

-

{carrier?.full_name}

+

{carrier[Number(id)]?.full_name}

Город

-

{carrier?.city}

+

{carrier[Number(id)]?.city}

Основной цвет

- {carrier?.main_color} + {carrier[Number(id)]?.main_color}
@@ -80,10 +74,10 @@ export const CarrierPreviewPage = observer(() => {
- {carrier?.left_color} + {carrier[Number(id)]?.left_color}
@@ -91,15 +85,15 @@ export const CarrierPreviewPage = observer(() => {
- {carrier?.right_color} + {carrier[Number(id)]?.right_color}

Краткое имя

-

{carrier?.short_name}

+

{carrier[Number(id)]?.short_name}

Логотип

diff --git a/src/pages/Carrier/index.ts b/src/pages/Carrier/index.ts index b660935..f5ffa27 100644 --- a/src/pages/Carrier/index.ts +++ b/src/pages/Carrier/index.ts @@ -1,3 +1,4 @@ export * from "./CarrierListPage"; export * from "./CarrierPreviewPage"; export * from "./CarrierCreatePage"; +export * from "./CarrierEditPage"; diff --git a/src/pages/City/CityCreatePage/index.tsx b/src/pages/City/CityCreatePage/index.tsx index 3da5d56..65bcf7d 100644 --- a/src/pages/City/CityCreatePage/index.tsx +++ b/src/pages/City/CityCreatePage/index.tsx @@ -13,33 +13,31 @@ import { ArrowLeft, Save, ImagePlus } from "lucide-react"; import { Loader2 } from "lucide-react"; import { useNavigate } from "react-router-dom"; import { toast } from "react-toastify"; -import { cityStore, countryStore, mediaStore } from "@shared"; +import { cityStore, countryStore, languageStore, mediaStore } from "@shared"; import { useState, useEffect } from "react"; import { LanguageSwitcher, MediaViewer } from "@widgets"; import { SelectMediaDialog } from "@shared"; export const CityCreatePage = observer(() => { const navigate = useNavigate(); - const [name, setName] = useState(""); - const [countryCode, setCountryCode] = useState(""); - const [selectedMediaId, setSelectedMediaId] = useState(null); + const { language } = languageStore; + const { createCityData, setCreateCityData } = cityStore; const [isLoading, setIsLoading] = useState(false); const [isSelectMediaOpen, setIsSelectMediaOpen] = useState(false); + const { getCountries } = countryStore; + const { getMedia } = mediaStore; useEffect(() => { - countryStore.getCountries(); - mediaStore.getMedia(); - }, []); + (async () => { + await getCountries(language); + await getMedia(); + })(); + }, [language]); const handleCreate = async () => { try { setIsLoading(true); - await cityStore.createCity( - name, - countryStore.countries.find((c) => c.code === countryCode)?.name!, - countryCode, - selectedMediaId! - ); + await cityStore.createCity(); toast.success("Город успешно создан"); navigate("/city"); } catch (error) { @@ -55,11 +53,17 @@ export const CityCreatePage = observer(() => { media_name?: string; media_type: number; }) => { - setSelectedMediaId(media.id); + setCreateCityData( + createCityData[language].name, + createCityData.country, + createCityData.country_code, + media.id, + language + ); }; - const selectedMedia = selectedMediaId - ? mediaStore.media.find((m) => m.id === selectedMediaId) + const selectedMedia = createCityData.arms + ? mediaStore.media.find((m) => m.id === createCityData.arms) : null; return ( @@ -79,20 +83,39 @@ export const CityCreatePage = observer(() => { setName(e.target.value)} + onChange={(e) => + setCreateCityData( + e.target.value, + createCityData.country, + createCityData.country_code, + createCityData.arms, + language + ) + } /> Страна { + const selectedCountry = countryStore.countries[language]?.find( + (country) => country.code === e.target.value + ); + setEditCityData( + editCityData[language as keyof CashedCities]?.name || "", + selectedCountry?.name || "", + e.target.value, + editCityData.arms, + language + ); + }} + > + {countryStore.countries[language].map((country) => ( + + {country.name} + + ))} + + + +
+ +
+ + {selectedMedia && ( + + {selectedMedia.media_name || selectedMedia.filename} + + )} +
+ {selectedMedia && ( + + + + )} +
+ + +
+ + setIsSelectMediaOpen(false)} + onSelectMedia={handleMediaSelect} + /> + + ); +}); diff --git a/src/pages/City/CityListPage/index.tsx b/src/pages/City/CityListPage/index.tsx index f321e19..3f60c4c 100644 --- a/src/pages/City/CityListPage/index.tsx +++ b/src/pages/City/CityListPage/index.tsx @@ -1,8 +1,8 @@ import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid"; -import { cityStore, languageStore } from "@shared"; +import { languageStore, cityStore, CashedCities } from "@shared"; import { useEffect, useState } from "react"; import { observer } from "mobx-react-lite"; -import { Eye, Trash2 } from "lucide-react"; +import { Eye, Pencil, Trash2 } from "lucide-react"; import { useNavigate } from "react-router-dom"; import { CreateButton, DeleteModal, LanguageSwitcher } from "@widgets"; @@ -14,7 +14,7 @@ export const CityListPage = observer(() => { const { language } = languageStore; useEffect(() => { - getCities(); + getCities(language); }, [language]); const columns: GridColDef[] = [ @@ -33,10 +33,14 @@ export const CityListPage = observer(() => { headerName: "Действия", align: "center", headerAlign: "center", + width: 200, renderCell: (params: GridRenderCellParams) => { return (
+ @@ -54,7 +58,7 @@ export const CityListPage = observer(() => { }, ]; - const rows = cities.map((city) => ({ + const rows = cities[language].map((city) => ({ id: city.id, name: city.name, country: city.country, @@ -81,7 +85,7 @@ export const CityListPage = observer(() => { open={isDeleteModalOpen} onDelete={async () => { if (rowId) { - deleteCity(rowId); + deleteCity(rowId.toString(), language as keyof CashedCities); } setIsDeleteModalOpen(false); setRowId(null); diff --git a/src/pages/City/CityPreviewPage/index.tsx b/src/pages/City/CityPreviewPage/index.tsx index 517de5c..7f49e6e 100644 --- a/src/pages/City/CityPreviewPage/index.tsx +++ b/src/pages/City/CityPreviewPage/index.tsx @@ -1,6 +1,6 @@ import { Paper } from "@mui/material"; -import { cityStore, mediaStore } from "@shared"; -import { MediaViewer } from "@widgets"; +import { cityStore, languageStore, mediaStore } from "@shared"; +import { LanguageSwitcher, MediaViewer } from "@widgets"; import { observer } from "mobx-react-lite"; import { ArrowLeft } from "lucide-react"; import { useEffect } from "react"; @@ -8,19 +8,30 @@ import { useNavigate, useParams } from "react-router-dom"; export const CityPreviewPage = observer(() => { const { id } = useParams(); - const { getCity, city } = cityStore; + const { getCity, city, setEditCityData } = cityStore; const { oneMedia, getOneMedia } = mediaStore; const navigate = useNavigate(); + const { language } = languageStore; useEffect(() => { (async () => { - const cityResponse = await getCity(id as string); - await getOneMedia(cityResponse.arms as string); + if (id) { + const cityResponse = await getCity(id as string, language); + setEditCityData( + cityResponse.name, + cityResponse.country, + cityResponse.country_code, + cityResponse.arms, + language + ); + await getOneMedia(cityResponse.arms as string); + } })(); - }, [id]); + }, [id, language]); return ( +
- {/*
- - -
*/}

Название

-

{city?.name}

+

{city[id!]?.[language]?.name}

Страна

-

{city?.country}

+

{city[id!]?.[language]?.country}

-
+

Герб

{ const navigate = useNavigate(); - const [name, setName] = useState(""); - const [code, setCode] = useState(""); const [isLoading, setIsLoading] = useState(false); + const { language } = languageStore; + const { createCountryData, setCountryData, createCountry } = countryStore; const handleCreate = async () => { try { setIsLoading(true); - await countryStore.createCountry(code, name); + await createCountry(); toast.success("Страна успешно создана"); navigate("/country"); } catch (error) { @@ -44,16 +44,24 @@ export const CountryCreatePage = observer(() => { setCode(e.target.value)} + onChange={(e) => + setCountryData( + e.target.value, + createCountryData[language].name, + language + ) + } /> setName(e.target.value)} + onChange={(e) => + setCountryData(createCountryData.code, e.target.value, language) + } /> +
+ +
+ + + countryStore.setEditCountryData(e.target.value, language) + } + /> + + +
+ + ); +}); diff --git a/src/pages/Country/CountryListPage/index.tsx b/src/pages/Country/CountryListPage/index.tsx index a25a718..fcc8fbf 100644 --- a/src/pages/Country/CountryListPage/index.tsx +++ b/src/pages/Country/CountryListPage/index.tsx @@ -2,7 +2,7 @@ import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid"; import { countryStore, languageStore } from "@shared"; import { useEffect, useState } from "react"; import { observer } from "mobx-react-lite"; -import { Eye, Trash2 } from "lucide-react"; +import { Eye, Pencil, Trash2 } from "lucide-react"; import { useNavigate } from "react-router-dom"; import { CreateButton, DeleteModal, LanguageSwitcher } from "@widgets"; @@ -14,7 +14,7 @@ export const CountryListPage = observer(() => { const { language } = languageStore; useEffect(() => { - getCountries(); + getCountries(language); }, [language]); const columns: GridColDef[] = [ @@ -28,10 +28,15 @@ export const CountryListPage = observer(() => { headerName: "Действия", align: "center", headerAlign: "center", - + width: 200, renderCell: (params: GridRenderCellParams) => { return (
+ @@ -49,7 +54,7 @@ export const CountryListPage = observer(() => { }, ]; - const rows = countries.map((country) => ({ + const rows = countries[language]?.map((country) => ({ id: country.code, code: country.code, name: country.name, @@ -66,12 +71,14 @@ export const CountryListPage = observer(() => {
+ { if (rowId) { - await countryStore.deleteCountry(rowId); - getCountries(); // Refresh the list after deletion + await countryStore.deleteCountry(rowId, language); + getCountries(language); // Refresh the list after deletion + setIsDeleteModalOpen(false); } setIsDeleteModalOpen(false); setRowId(null); diff --git a/src/pages/Country/CountryPreviewPage/index.tsx b/src/pages/Country/CountryPreviewPage/index.tsx index accea7f..d53894f 100644 --- a/src/pages/Country/CountryPreviewPage/index.tsx +++ b/src/pages/Country/CountryPreviewPage/index.tsx @@ -1,23 +1,29 @@ import { Paper } from "@mui/material"; -import { countryStore } from "@shared"; +import { countryStore, languageStore } from "@shared"; import { observer } from "mobx-react-lite"; import { ArrowLeft } from "lucide-react"; import { useEffect } from "react"; import { useNavigate, useParams } from "react-router-dom"; +import { LanguageSwitcher } from "@widgets"; export const CountryPreviewPage = observer(() => { const { id } = useParams(); - const { getCountry, country } = countryStore; + const { getCountry, country, setEditCountryData } = countryStore; const navigate = useNavigate(); + const { language } = languageStore; useEffect(() => { (async () => { - await getCountry(id as string); + if (id) { + const data = await getCountry(id as string, language); + setEditCountryData(data.name, language); + } })(); - }, [id]); + }, [id, language]); return ( +
*/}
- {country && ( + {country[id!]?.[language] && (

Название

-

{country?.name}

+

{country[id!]?.[language]?.name}

)} diff --git a/src/pages/Country/index.ts b/src/pages/Country/index.ts index 81a4c27..f80e3eb 100644 --- a/src/pages/Country/index.ts +++ b/src/pages/Country/index.ts @@ -1,3 +1,4 @@ export * from "./CountryListPage"; export * from "./CountryPreviewPage"; export * from "./CountryCreatePage"; +export * from "./CountryEditPage"; diff --git a/src/pages/User/UserCreatePage/index.tsx b/src/pages/User/UserCreatePage/index.tsx new file mode 100644 index 0000000..c641231 --- /dev/null +++ b/src/pages/User/UserCreatePage/index.tsx @@ -0,0 +1,129 @@ +import { + Button, + Paper, + TextField, + Checkbox, + FormControlLabel, +} from "@mui/material"; +import { observer } from "mobx-react-lite"; +import { ArrowLeft, Save } from "lucide-react"; +import { Loader2 } from "lucide-react"; +import { useNavigate } from "react-router-dom"; +import { toast } from "react-toastify"; +import { userStore } from "@shared"; +import { useState } from "react"; + +export const UserCreatePage = observer(() => { + const navigate = useNavigate(); + const { createUserData, setCreateUserData, createUser } = userStore; + const [isLoading, setIsLoading] = useState(false); + + const handleCreate = async () => { + try { + setIsLoading(true); + await createUser(); + toast.success("Пользователь успешно создан"); + navigate("/user"); + } catch (error) { + toast.error("Ошибка при создании пользователя"); + } finally { + setIsLoading(false); + } + }; + + return ( + +
+ +
+ +
+ + setCreateUserData( + e.target.value, + createUserData.email || "", + createUserData.password || "", + createUserData.is_admin || false + ) + } + /> + + + setCreateUserData( + createUserData.name || "", + e.target.value, + createUserData.password || "", + createUserData.is_admin || false + ) + } + /> + + + setCreateUserData( + createUserData.name || "", + createUserData.email || "", + e.target.value, + createUserData.is_admin || false + ) + } + /> + +
+ { + setCreateUserData( + createUserData.name || "", + createUserData.email || "", + createUserData.password || "", + e.target.checked + ); + }} + /> + } + label="Администратор" + /> +
+ + +
+
+ ); +}); diff --git a/src/pages/User/UserEditPage/index.tsx b/src/pages/User/UserEditPage/index.tsx new file mode 100644 index 0000000..26cc233 --- /dev/null +++ b/src/pages/User/UserEditPage/index.tsx @@ -0,0 +1,139 @@ +import { + Button, + FormControlLabel, + Checkbox, + Paper, + TextField, +} from "@mui/material"; +import { observer } from "mobx-react-lite"; +import { ArrowLeft, Save } from "lucide-react"; +import { Loader2 } from "lucide-react"; +import { useNavigate, useParams } from "react-router-dom"; +import { toast } from "react-toastify"; +import { userStore } from "@shared"; +import { useEffect, useState } from "react"; + +export const UserEditPage = observer(() => { + const navigate = useNavigate(); + const [isLoading, setIsLoading] = useState(false); + const { id } = useParams(); + const { editUserData, editUser, getUser, setEditUserData, user } = userStore; + + const handleEdit = async () => { + try { + setIsLoading(true); + await editUser(Number(id)); + toast.success("Пользователь успешно обновлен"); + navigate("/user"); + } catch (error) { + toast.error("Ошибка при обновлении пользователя"); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + (async () => { + if (id) { + const data = await getUser(Number(id)); + + setEditUserData( + data?.name || "", + data?.email || "", + data?.password || "", + data?.is_admin || false + ); + } + })(); + }, [id]); + + return ( + +
+ +
+ +
+ + setEditUserData( + e.target.value, + editUserData.email || "", + editUserData.password || "", + editUserData.is_admin || false + ) + } + /> + + setEditUserData( + editUserData.name || "", + e.target.value, + editUserData.password || "", + editUserData.is_admin || false + ) + } + /> + + + setEditUserData( + editUserData.name || "", + editUserData.email || "", + e.target.value, + editUserData.is_admin || false + ) + } + /> + + setEditUserData( + editUserData.name || "", + editUserData.email || "", + editUserData.password || "", + e.target.checked + ) + } + /> + } + label="Администратор" + /> + + +
+
+ ); +}); diff --git a/src/pages/User/UserListPage/index.tsx b/src/pages/User/UserListPage/index.tsx index d476cf6..d328e55 100644 --- a/src/pages/User/UserListPage/index.tsx +++ b/src/pages/User/UserListPage/index.tsx @@ -1,21 +1,21 @@ import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid"; -import { languageStore, userStore } from "@shared"; +import { userStore } from "@shared"; import { useEffect, useState } from "react"; import { observer } from "mobx-react-lite"; -import { Eye, Trash2 } from "lucide-react"; +import { Pencil, Trash2 } from "lucide-react"; import { useNavigate } from "react-router-dom"; -import { DeleteModal, LanguageSwitcher } from "@widgets"; + +import { CreateButton, DeleteModal } from "@widgets"; export const UserListPage = observer(() => { const { users, getUsers, deleteUser } = userStore; const navigate = useNavigate(); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [rowId, setRowId] = useState(null); // Lifted state - const { language } = languageStore; useEffect(() => { getUsers(); - }, [language]); + }, []); const columns: GridColDef[] = [ { @@ -56,6 +56,15 @@ export const UserListPage = observer(() => { renderCell: (params: GridRenderCellParams) => { return (
+ +
+ +
+ + setEditVehicleData({ + ...editVehicleData, + tail_number: Number(e.target.value), + }) + } + /> + + + Тип + + + + + Перевозчик + + + + +
+ + ); +}); diff --git a/src/pages/Vehicle/VehicleListPage/index.tsx b/src/pages/Vehicle/VehicleListPage/index.tsx index 8d41771..13d7154 100644 --- a/src/pages/Vehicle/VehicleListPage/index.tsx +++ b/src/pages/Vehicle/VehicleListPage/index.tsx @@ -2,9 +2,9 @@ import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid"; import { carrierStore, languageStore, vehicleStore } from "@shared"; import { useEffect, useState } from "react"; import { observer } from "mobx-react-lite"; -import { Eye, Trash2 } from "lucide-react"; +import { Eye, Pencil, Trash2 } from "lucide-react"; import { useNavigate } from "react-router-dom"; -import { CreateButton, DeleteModal, LanguageSwitcher } from "@widgets"; +import { CreateButton, DeleteModal } from "@widgets"; import { VEHICLE_TYPES } from "@shared"; export const VehicleListPage = observer(() => { @@ -68,6 +68,9 @@ export const VehicleListPage = observer(() => { renderCell: (params: GridRenderCellParams) => { return (
+ @@ -96,8 +99,6 @@ export const VehicleListPage = observer(() => { return ( <> - -

Транспортные средства

diff --git a/src/pages/Vehicle/VehiclePreviewPage/index.tsx b/src/pages/Vehicle/VehiclePreviewPage/index.tsx index 207f048..57de0f9 100644 --- a/src/pages/Vehicle/VehiclePreviewPage/index.tsx +++ b/src/pages/Vehicle/VehiclePreviewPage/index.tsx @@ -45,23 +45,23 @@ export const VehiclePreviewPage = observer(() => {
*/}
- {vehicle && ( + {vehicle[id!] && (

Системный номер

-

{vehicle?.vehicle.tail_number}

+

{vehicle[id!]?.vehicle.tail_number}

Тип транспортного средства

{VEHICLE_TYPES.find( - (type) => type.value === vehicle?.vehicle.type - )?.label || vehicle?.vehicle.type} + (type) => type.value === vehicle[id!]?.vehicle.type + )?.label || vehicle[id!]?.vehicle.type}

Перевозчик

-

{vehicle?.vehicle.carrier}

+

{vehicle[id!]?.vehicle.carrier}

)} diff --git a/src/pages/Vehicle/index.ts b/src/pages/Vehicle/index.ts index e1ccf6e..9ad8d9d 100644 --- a/src/pages/Vehicle/index.ts +++ b/src/pages/Vehicle/index.ts @@ -1,3 +1,4 @@ export * from "./VehicleListPage"; export * from "./VehiclePreviewPage"; export * from "./VehicleCreatePage"; +export * from "./VehicleEditPage"; diff --git a/src/shared/config/constants.tsx b/src/shared/config/constants.tsx index 584d681..9a7f2d4 100644 --- a/src/shared/config/constants.tsx +++ b/src/shared/config/constants.tsx @@ -3,7 +3,6 @@ import { Power, LucideIcon, Building2, - MonitorSmartphone, Map, Users, Earth, @@ -11,6 +10,14 @@ import { BusFront, Bus, GitBranch, + Car, + Train, + Ship, + Table, + Split, + Newspaper, + PersonStanding, + Cpu, } from "lucide-react"; export const DRAWER_WIDTH = 300; @@ -20,6 +27,7 @@ interface NavigationItem { icon: LucideIcon; path?: string; onClick?: () => void; + nestedItems?: NavigationItem[]; } export const NAVIGATION_ITEMS: { @@ -45,30 +53,7 @@ export const NAVIGATION_ITEMS: { icon: BusFront, path: "/carrier", }, - // { - // id: "media", - // label: "Медиа", - // icon: BookImage, - // path: "/media", - // }, - // { - // id: "articles", - // label: "Статьи", - // icon: Newspaper, - // path: "/article", - // }, - { - id: "attractions", - label: "Достопримечательности", - icon: Landmark, - path: "/sight", - }, - // { - // id: "stations", - // label: "Остановки", - // icon: PersonStanding, - // path: "/station", - // }, + { id: "snapshots", label: "Снапшоты", @@ -84,33 +69,59 @@ export const NAVIGATION_ITEMS: { { id: "devices", label: "Устройства", - icon: MonitorSmartphone, + icon: Cpu, path: "/devices", }, + { + id: "all", + label: "Все сущности", + icon: Table, + nestedItems: [ + // { + // id: "media", + // label: "Медиа", + // icon: BookImage, + // path: "/media", + // }, + // { + // id: "articles", + // label: "Статьи", + // icon: Newspaper, + // path: "/article", + // }, + { + id: "attractions", + label: "Достопримечательности", + icon: Landmark, + path: "/sight", + }, + { + id: "stations", + label: "Остановки", + icon: PersonStanding, + path: "/station", + }, + { + id: "routes", + label: "Маршруты", + icon: Split, + path: "/route", + }, + ], + }, + { id: "vehicles", label: "Транспорт", - icon: Bus, + icon: Car, path: "/vehicle", }, - // { - // id: "routes", - // label: "Маршруты", - // icon: Split, - // path: "/route", - // }, { id: "users", label: "Пользователи", icon: Users, path: "/user", }, - // { - // id: "articles", - // label: "Статьи", - // icon: Newspaper, - // path: "/articles", - // }, ], secondary: [ { diff --git a/src/shared/store/CarrierStore/index.tsx b/src/shared/store/CarrierStore/index.tsx index 28a5533..2c0a3b6 100644 --- a/src/shared/store/CarrierStore/index.tsx +++ b/src/shared/store/CarrierStore/index.tsx @@ -1,4 +1,4 @@ -import { authInstance } from "@shared"; +import { authInstance, languageStore } from "@shared"; import { makeAutoObservable, runInAction } from "mobx"; export type Carrier = { @@ -14,14 +14,19 @@ export type Carrier = { right_color: string; }; +type Carriers = Carrier[]; + +type CashedCarrier = Record; + class CarrierStore { - carriers: Carrier[] = []; - carrier: Carrier | null = null; + carriers: Carriers = []; + carrier: CashedCarrier = {}; constructor() { makeAutoObservable(this); } getCarriers = async () => { + if (this.carriers.length > 0) return; const response = await authInstance.get("/carrier"); runInAction(() => { @@ -34,13 +39,30 @@ class CarrierStore { runInAction(() => { this.carriers = this.carriers.filter((carrier) => carrier.id !== id); + delete this.carrier[id]; }); }; getCarrier = async (id: number) => { + if (this.carrier[id]) return this.carrier[id]; const response = await authInstance.get(`/carrier/${id}`); + runInAction(() => { - this.carrier = response.data; + if (!this.carrier[id]) { + this.carrier[id] = { + id: 0, + short_name: "", + full_name: "", + slogan: "", + city: "", + city_id: 0, + logo: "", + main_color: "", + left_color: "", + right_color: "", + }; + } + this.carrier[id] = response.data; }); return response.data; }; @@ -50,9 +72,9 @@ class CarrierStore { shortName: string, city: string, cityId: number, - primaryColor: string, - secondaryColor: string, - accentColor: string, + main_color: string, + left_color: string, + right_color: string, slogan: string, logoId: string ) => { @@ -61,9 +83,9 @@ class CarrierStore { short_name: shortName, city, city_id: cityId, - primary_color: primaryColor, - secondary_color: secondaryColor, - accent_color: accentColor, + main_color, + left_color, + right_color, slogan, logo: logoId, }); @@ -71,6 +93,57 @@ class CarrierStore { this.carriers.push(response.data); }); }; + + editCarrierData = { + full_name: "", + short_name: "", + city: "", + city_id: 0, + main_color: "", + left_color: "", + right_color: "", + slogan: "", + logo: "", + }; + + setEditCarrierData = ( + fullName: string, + shortName: string, + city: string, + cityId: number, + main_color: string, + left_color: string, + right_color: string, + slogan: string, + logoId: string + ) => { + this.editCarrierData = { + full_name: fullName, + short_name: shortName, + city, + city_id: cityId, + main_color: main_color, + left_color: left_color, + right_color: right_color, + slogan: slogan, + logo: logoId, + }; + }; + + editCarrier = async (id: number) => { + const response = await authInstance.patch( + `/carrier/${id}`, + this.editCarrierData + ); + + runInAction(() => { + this.carriers = this.carriers.map((carrier) => + carrier.id === id ? { ...carrier, ...response.data } : carrier + ); + + this.carrier[id] = response.data; + }); + }; } export const carrierStore = new CarrierStore(); diff --git a/src/shared/store/CityStore/index.tsx b/src/shared/store/CityStore/fd.tsx similarity index 96% rename from src/shared/store/CityStore/index.tsx rename to src/shared/store/CityStore/fd.tsx index 81f169f..17cf51f 100644 --- a/src/shared/store/CityStore/index.tsx +++ b/src/shared/store/CityStore/fd.tsx @@ -70,4 +70,4 @@ class CityStore { }; } -export const cityStore = new CityStore(); +// export const cityStore = new CityStore(); diff --git a/src/shared/store/CityStore/index.ts b/src/shared/store/CityStore/index.ts new file mode 100644 index 0000000..8e57b6f --- /dev/null +++ b/src/shared/store/CityStore/index.ts @@ -0,0 +1,266 @@ +import { + authInstance, + languageInstance, + Language, + languageStore, + countryStore, +} from "@shared"; +import { makeAutoObservable, runInAction } from "mobx"; + +export type City = { + id?: number; + name: string; + country: string; + country_code: string; + arms: string; +}; + +export type CashedCities = { + ru: City[]; + en: City[]; + zh: City[]; +}; + +export type CashedCity = { + ru: City | null; + en: City | null; + zh: City | null; +}; + +class CityStore { + cities: CashedCities = { + ru: [], + en: [], + zh: [], + }; + + city: Record = {}; + + constructor() { + makeAutoObservable(this); + } + + getCities = async (language: keyof CashedCities) => { + if (this.cities[language] && this.cities[language].length > 0) { + return; + } + + const response = await authInstance.get(`/city`); + + runInAction(() => { + this.cities[language] = response.data; + }); + }; + + getCity = async (code: string, language: keyof CashedCities) => { + if (this.city[code]?.[language] && this.city[code][language] !== null) { + return; + } + + const response = await authInstance.get(`/city/${code}`); + + runInAction(() => { + if (!this.city[code]) { + this.city[code] = { + ru: null, + en: null, + zh: null, + }; + } + this.city[code][language] = response.data; + }); + + return response.data; + }; + + deleteCity = async (code: string, language: keyof CashedCities) => { + await authInstance.delete(`/city/${code}`); + + runInAction(() => { + this.cities[language] = this.cities[language].filter( + (city) => city.country_code !== code + ); + this.city[code][language] = null; + }); + }; + + createCityData = { + country: "", + country_code: "", + arms: "", + ru: { + name: "", + }, + en: { + name: "", + }, + zh: { + name: "", + }, + }; + + setCreateCityData = ( + name: string, + country: string, + country_code: string, + arms: string, + language: keyof CashedCities + ) => { + this.createCityData = { + ...this.createCityData, + country: country, + country_code: country_code, + arms: arms, + [language]: { + name: name, + }, + }; + }; + + createCity = async () => { + const { language } = languageStore; + const { country, country_code, arms } = this.createCityData; + const { name } = this.createCityData[language as keyof CashedCities]; + + if (name && country && country_code && arms) { + const cityResponse = await languageInstance(language as Language).post( + "/city", + { + name: name, + country: country, + country_code: country_code, + arms: arms, + } + ); + + runInAction(() => { + this.cities[language as keyof CashedCities] = [ + ...this.cities[language as keyof CashedCities], + cityResponse.data, + ]; + }); + + for (const secondaryLanguage of ["ru", "en", "zh"].filter( + (l) => l !== language + )) { + const { name } = + this.createCityData[secondaryLanguage as keyof CashedCities]; + + const patchResponse = await languageInstance( + secondaryLanguage as Language + ).patch(`/city/${cityResponse.data.id}`, { + name: name, + country: country, + country_code: country_code, + arms: arms, + }); + + runInAction(() => { + this.cities[secondaryLanguage as keyof CashedCities] = [ + ...this.cities[secondaryLanguage as keyof CashedCities], + patchResponse.data, + ]; + }); + } + } + + runInAction(() => { + this.createCityData = { + country: "", + country_code: "", + arms: "", + ru: { + name: "", + }, + en: { + name: "", + }, + zh: { + name: "", + }, + }; + }); + }; + + editCityData = { + country: "", + country_code: "", + arms: "", + ru: { + name: "", + }, + en: { + name: "", + }, + zh: { + name: "", + }, + }; + + setEditCityData = ( + name: string, + country: string, + country_code: string, + arms: string, + language: keyof CashedCities + ) => { + this.editCityData = { + ...this.editCityData, + country: country, + country_code: country_code, + arms: arms, + + [language]: { + name: name, + }, + }; + }; + + editCity = async (code: string) => { + for (const language of ["ru", "en", "zh"]) { + const { country_code, arms } = this.editCityData; + const { name } = this.editCityData[language as keyof CashedCities]; + const { countries } = countryStore; + + const country = countries[language as keyof CashedCities].find( + (country) => country.code === country_code + ); + + await languageInstance(language as Language).patch(`/city/${code}`, { + name, + country: country?.name || "", + country_code: country_code, + arms, + }); + + runInAction(() => { + if (this.city[code]) { + this.city[code][language as keyof CashedCities] = { + name, + country: country?.name || "", + country_code: country_code, + arms, + }; + } + + if (this.cities[language as keyof CashedCities]) { + this.cities[language as keyof CashedCities] = this.cities[ + language as keyof CashedCities + ].map((city) => + city.id === Number(code) + ? { + id: city.id, + name, + country: country?.name || "", + country_code: country_code, + arms, + } + : city + ); + } + }); + } + }; +} + +export const cityStore = new CityStore(); diff --git a/src/shared/store/CountryStore/index.ts b/src/shared/store/CountryStore/index.ts index 5e48b67..bf7fa01 100644 --- a/src/shared/store/CountryStore/index.ts +++ b/src/shared/store/CountryStore/index.ts @@ -1,4 +1,9 @@ -import { authInstance } from "@shared"; +import { + authInstance, + languageInstance, + Language, + languageStore, +} from "@shared"; import { makeAutoObservable, runInAction } from "mobx"; export type Country = { @@ -6,43 +11,208 @@ export type Country = { name: string; }; +export type CashedCountries = { + ru: Country[]; + en: Country[]; + zh: Country[]; +}; + +export type CashedCountry = { + ru: Country | null; + en: Country | null; + zh: Country | null; +}; + class CountryStore { - countries: Country[] = []; - country: Country | null = null; + countries: CashedCountries = { + ru: [], + en: [], + zh: [], + }; + + country: Record = {}; constructor() { makeAutoObservable(this); } - getCountries = async () => { - const response = await authInstance.get("/country"); + getCountries = async (language: keyof CashedCountries) => { + if (this.countries[language] && this.countries[language].length > 0) { + return; + } + + const response = await authInstance.get(`/country`); runInAction(() => { - this.countries = response.data; + this.countries[language] = response.data; }); }; - getCountry = async (code: string) => { + getCountry = async (code: string, language: keyof CashedCountries) => { + if ( + this.country[code]?.[language] && + this.country[code][language] !== null + ) { + return; + } + const response = await authInstance.get(`/country/${code}`); runInAction(() => { - this.country = response.data; + if (!this.country[code]) { + this.country[code] = { + ru: null, + en: null, + zh: null, + }; + } + this.country[code][language] = response.data; }); + + return response.data; }; - deleteCountry = async (code: string) => { + deleteCountry = async (code: string, language: keyof CashedCountries) => { await authInstance.delete(`/country/${code}`); runInAction(() => { - this.countries = this.countries.filter( + this.countries[language] = this.countries[language].filter( (country) => country.code !== code ); + this.country[code][language] = null; }); }; - createCountry = async (code: string, name: string) => { - await authInstance.post("/country", { code: code, name: name }); - await this.getCountries(); + createCountryData = { + code: "", + ru: { + name: "", + }, + en: { + name: "", + }, + zh: { + name: "", + }, + }; + setCountryData = ( + code: string, + name: string, + language: keyof CashedCountries + ) => { + this.createCountryData = { + ...this.createCountryData, + code: code, + [language]: { + name: name, + }, + }; + }; + + createCountry = async () => { + const { code } = this.createCountryData; + const { language } = languageStore; + const { name } = this.createCountryData[language as keyof CashedCountries]; + + if (code && this.createCountryData[language].name) { + await languageInstance(language as Language).post("/country", { + code: code, + name: name, + }); + + runInAction(() => { + this.countries[language as keyof CashedCountries] = [ + ...this.countries[language as keyof CashedCountries], + { code: code, name: name }, + ]; + }); + + for (const secondaryLanguage of ["ru", "en", "zh"].filter( + (l) => l !== language + )) { + const { name } = + this.createCountryData[secondaryLanguage as keyof CashedCountries]; + + if (name) { + await languageInstance(secondaryLanguage as Language).patch( + `/country/${code}`, + { + name: name, + } + ); + } + runInAction(() => { + this.countries[secondaryLanguage as keyof CashedCountries] = [ + ...this.countries[secondaryLanguage as keyof CashedCountries], + { code: code, name: name }, + ]; + }); + } + } + + runInAction(() => { + this.createCountryData = { + code: "", + ru: { + name: "", + }, + en: { + name: "", + }, + zh: { + name: "", + }, + }; + }); + }; + + editCountryData = { + ru: { + name: "", + }, + en: { + name: "", + }, + zh: { + name: "", + }, + }; + + setEditCountryData = (name: string, language: keyof CashedCountries) => { + this.editCountryData = { + ...this.editCountryData, + [language]: { + name: name, + }, + }; + }; + + editCountry = async (code: string) => { + for (const language of ["ru", "en", "zh"]) { + const { name } = this.editCountryData[language as keyof CashedCountries]; + + if (name) { + await languageInstance(language as Language).patch(`/country/${code}`, { + name: name, + }); + + runInAction(() => { + if (this.country[code]) { + this.country[code][language as keyof CashedCountries] = { + code, + name, + }; + } + if (this.countries[language as keyof CashedCountries]) { + this.countries[language as keyof CashedCountries] = this.countries[ + language as keyof CashedCountries + ].map((country) => + country.code === code ? { code, name } : country + ); + } + }); + } + } }; } diff --git a/src/shared/store/UserStore/index.ts b/src/shared/store/UserStore/index.ts index 9ea9cb0..2be3029 100644 --- a/src/shared/store/UserStore/index.ts +++ b/src/shared/store/UserStore/index.ts @@ -6,17 +6,20 @@ export type User = { email: string; is_admin: boolean; name: string; + password?: string; }; class UserStore { users: User[] = []; - user: User | null = null; + user: Record = {}; constructor() { makeAutoObservable(this); } getUsers = async () => { + if (this.users.length > 0) return; + const response = await authInstance.get("/user"); runInAction(() => { @@ -25,18 +28,77 @@ class UserStore { }; getUser = async (id: number) => { + if (this.user[id]) return; const response = await authInstance.get(`/user/${id}`); runInAction(() => { - this.user = response.data as User; + this.user[id] = response.data as User; }); + + return response.data; }; deleteUser = async (id: number) => { - await authInstance.delete(`/users/${id}`); + await authInstance.delete(`/user/${id}`); runInAction(() => { this.users = this.users.filter((user) => user.id !== id); + delete this.user[id]; + }); + }; + + createUserData: Partial = { + name: "", + email: "", + password: "", + is_admin: false, + }; + + setCreateUserData = ( + name: string, + email: string, + password: string, + is_admin: boolean + ) => { + this.createUserData = { name, email, password, is_admin }; + }; + + createUser = async () => { + const id = this.users[this.users.length - 1].id + 1; + const response = await authInstance.post("/user", this.createUserData); + + runInAction(() => { + this.users.push({ + id, + ...response.data, + }); + }); + }; + + editUserData: Partial = { + name: "", + email: "", + password: "", + is_admin: false, + }; + + setEditUserData = ( + name: string, + email: string, + password: string, + is_admin: boolean + ) => { + this.editUserData = { name, email, password, is_admin }; + }; + + editUser = async (id: number) => { + const response = await authInstance.patch(`/user/${id}`, this.editUserData); + + runInAction(() => { + this.users = this.users.map((user) => + user.id === id ? { ...user, ...response.data } : user + ); + this.user[id] = { ...this.user[id], ...response.data }; }); }; } diff --git a/src/shared/store/VehicleStore/index.ts b/src/shared/store/VehicleStore/index.ts index 1ead75d..c8807c6 100644 --- a/src/shared/store/VehicleStore/index.ts +++ b/src/shared/store/VehicleStore/index.ts @@ -1,5 +1,5 @@ -import { authInstance } from "@shared"; -import { makeAutoObservable } from "mobx"; +import { authInstance, languageStore, languageInstance } from "@shared"; +import { makeAutoObservable, runInAction } from "mobx"; export type Vehicle = { vehicle: { @@ -22,42 +22,121 @@ export type Vehicle = { class VehicleStore { vehicles: Vehicle[] = []; - vehicle: Vehicle | null = null; + vehicle: Record = {}; constructor() { makeAutoObservable(this); } getVehicles = async () => { - const response = await authInstance.get(`/vehicle`); - this.vehicles = response.data; + const response = await languageInstance("ru").get(`/vehicle`); + + runInAction(() => { + this.vehicles = response.data; + }); }; deleteVehicle = async (id: number) => { - await authInstance.delete(`/vehicle/${id}`); - this.vehicles = this.vehicles.filter( - (vehicle) => vehicle.vehicle.id !== id - ); + await languageInstance("ru").delete(`/vehicle/${id}`); + + runInAction(() => { + this.vehicles = this.vehicles.filter( + (vehicle) => vehicle.vehicle.id !== id + ); + }); }; getVehicle = async (id: number) => { - const response = await authInstance.get(`/vehicle/${id}`); - this.vehicle = response.data; + const response = await languageInstance("ru").get(`/vehicle/${id}`); + + runInAction(() => { + this.vehicle[id] = response.data; + }); }; createVehicle = async ( tailNumber: number, - type: string, + type: number, carrier: string, carrierId: number ) => { - await authInstance.post("/vehicle", { + const response = await languageInstance("ru").post("/vehicle", { tail_number: tailNumber, type, carrier, carrier_id: carrierId, }); - await this.getVehicles(); + + runInAction(() => { + this.vehicles.push({ + vehicle: { + id: response.data.id, + tail_number: response.data.tail_number, + type: response.data.type, + carrier_id: response.data.carrier_id, + carrier: response.data.carrier, + uuid: response.data.uuid, + }, + }); + }); + }; + + editVehicleData: { + tail_number: number; + type: number; + carrier: string; + carrier_id: number; + } = { + tail_number: 0, + type: 0, + carrier: "", + carrier_id: 0, + }; + + setEditVehicleData = (data: { + tail_number: number; + type: number; + carrier: string; + carrier_id: number; + }) => { + this.editVehicleData = { + ...this.editVehicleData, + ...data, + }; + }; + + editVehicle = async ( + id: number, + data: { + tail_number: number; + type: number; + carrier: string; + carrier_id: number; + } + ) => { + const response = await languageInstance("ru").patch(`/vehicle/${id}`, { + tail_number: data.tail_number, + type: data.type, + carrier: data.carrier, + carrier_id: data.carrier_id, + }); + + runInAction(() => { + this.vehicle[id] = { + vehicle: { + ...this.vehicle[id].vehicle, + ...response.data, + }, + }; + this.vehicles = this.vehicles.map((vehicle) => + vehicle.vehicle.id === id + ? { + ...vehicle, + ...response.data, + } + : vehicle + ); + }); }; } diff --git a/yarn.lock b/yarn.lock index b1576b9..3f35a87 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24,7 +24,7 @@ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.3.tgz" integrity sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw== -"@babel/core@^7.26.10": +"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.26.10": version "7.27.3" resolved "https://registry.npmjs.org/@babel/core/-/core-7.27.3.tgz" integrity sha512-hyrN8ivxfvJ4i0fIJuV4EOlV0WDMz5Ui4StRTgVaAvWeiRCilXgwVvxJKtFQ3TKtHgJscB2YiXKGNJuVwhQMtA== @@ -173,28 +173,6 @@ resolved "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz" integrity sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow== -"@emnapi/core@^1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.4.3.tgz#9ac52d2d5aea958f67e52c40a065f51de59b77d6" - integrity sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g== - dependencies: - "@emnapi/wasi-threads" "1.0.2" - tslib "^2.4.0" - -"@emnapi/runtime@^1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.4.3.tgz#c0564665c80dc81c448adac23f9dfbed6c838f7d" - integrity sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ== - dependencies: - tslib "^2.4.0" - -"@emnapi/wasi-threads@1.0.2", "@emnapi/wasi-threads@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz#977f44f844eac7d6c138a415a123818c655f874c" - integrity sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA== - dependencies: - tslib "^2.4.0" - "@emotion/babel-plugin@^11.13.5": version "11.13.5" resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz" @@ -240,7 +218,7 @@ resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz" integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ== -"@emotion/react@^11.14.0": +"@emotion/react@^11.0.0-rc.0", "@emotion/react@^11.14.0", "@emotion/react@^11.4.1", "@emotion/react@^11.5.0", "@emotion/react@^11.9.0": version "11.14.0" resolved "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz" integrity sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA== @@ -270,7 +248,7 @@ resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz" integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg== -"@emotion/styled@^11.14.0": +"@emotion/styled@^11.14.0", "@emotion/styled@^11.3.0", "@emotion/styled@^11.8.1": version "11.14.0" resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz" integrity sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA== @@ -302,131 +280,11 @@ resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz" integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg== -"@esbuild/aix-ppc64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz#4e0f91776c2b340e75558f60552195f6fad09f18" - integrity sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA== - -"@esbuild/android-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz#bc766407f1718923f6b8079c8c61bf86ac3a6a4f" - integrity sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg== - -"@esbuild/android-arm@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.5.tgz#4290d6d3407bae3883ad2cded1081a234473ce26" - integrity sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA== - -"@esbuild/android-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.5.tgz#40c11d9cbca4f2406548c8a9895d321bc3b35eff" - integrity sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw== - "@esbuild/darwin-arm64@0.25.5": version "0.25.5" resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz" integrity sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ== -"@esbuild/darwin-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz#e27a5d92a14886ef1d492fd50fc61a2d4d87e418" - integrity sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ== - -"@esbuild/freebsd-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz#97cede59d638840ca104e605cdb9f1b118ba0b1c" - integrity sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw== - -"@esbuild/freebsd-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz#71c77812042a1a8190c3d581e140d15b876b9c6f" - integrity sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw== - -"@esbuild/linux-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz#f7b7c8f97eff8ffd2e47f6c67eb5c9765f2181b8" - integrity sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg== - -"@esbuild/linux-arm@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz#2a0be71b6cd8201fa559aea45598dffabc05d911" - integrity sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw== - -"@esbuild/linux-ia32@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz#763414463cd9ea6fa1f96555d2762f9f84c61783" - integrity sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA== - -"@esbuild/linux-loong64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz#428cf2213ff786a502a52c96cf29d1fcf1eb8506" - integrity sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg== - -"@esbuild/linux-mips64el@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz#5cbcc7fd841b4cd53358afd33527cd394e325d96" - integrity sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg== - -"@esbuild/linux-ppc64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz#0d954ab39ce4f5e50f00c4f8c4fd38f976c13ad9" - integrity sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ== - -"@esbuild/linux-riscv64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz#0e7dd30730505abd8088321e8497e94b547bfb1e" - integrity sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA== - -"@esbuild/linux-s390x@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz#5669af81327a398a336d7e40e320b5bbd6e6e72d" - integrity sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ== - -"@esbuild/linux-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz#b2357dd153aa49038967ddc1ffd90c68a9d2a0d4" - integrity sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw== - -"@esbuild/netbsd-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz#53b4dfb8fe1cee93777c9e366893bd3daa6ba63d" - integrity sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw== - -"@esbuild/netbsd-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz#a0206f6314ce7dc8713b7732703d0f58de1d1e79" - integrity sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ== - -"@esbuild/openbsd-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz#2a796c87c44e8de78001d808c77d948a21ec22fd" - integrity sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw== - -"@esbuild/openbsd-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz#28d0cd8909b7fa3953af998f2b2ed34f576728f0" - integrity sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg== - -"@esbuild/sunos-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz#a28164f5b997e8247d407e36c90d3fd5ddbe0dc5" - integrity sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA== - -"@esbuild/win32-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz#6eadbead38e8bd12f633a5190e45eff80e24007e" - integrity sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw== - -"@esbuild/win32-ia32@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz#bab6288005482f9ed2adb9ded7e88eba9a62cc0d" - integrity sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ== - -"@esbuild/win32-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz#7fc114af5f6563f19f73324b5d5ff36ece0803d1" - integrity sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g== - "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.7.0": version "4.7.0" resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz" @@ -475,7 +333,7 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.27.0", "@eslint/js@^9.25.0": +"@eslint/js@^9.25.0", "@eslint/js@9.27.0": version "9.27.0" resolved "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz" integrity sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA== @@ -583,21 +441,28 @@ dependencies: promise-worker-transferable "^1.0.4" -"@mui/core-downloads-tracker@^7.1.0": - version "7.1.0" - resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.0.tgz" - integrity sha512-E0OqhZv548Qdc0PwWhLVA2zmjJZSTvaL4ZhoswmI8NJEC1tpW2js6LLP827jrW9MEiXYdz3QS6+hask83w74yQ== +"@mui/core-downloads-tracker@^7.1.1": + version "7.1.1" + resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.1.tgz" + integrity sha512-yBckQs4aQ8mqukLnPC6ivIRv6guhaXi8snVl00VtyojBbm+l6VbVhyTSZ68Abcx7Ah8B+GZhrB7BOli+e+9LkQ== -"@mui/material@^7.1.0": - version "7.1.0" - resolved "https://registry.npmjs.org/@mui/material/-/material-7.1.0.tgz" - integrity sha512-ahUJdrhEv+mCp4XHW+tHIEYzZMSRLg8z4AjUOsj44QpD1ZaMxQoVOG2xiHvLFdcsIPbgSRx1bg1eQSheHBgvtg== +"@mui/icons-material@^7.1.1": + version "7.1.1" + resolved "https://registry.npmjs.org/@mui/icons-material/-/icons-material-7.1.1.tgz" + integrity sha512-X37+Yc8QpEnl0sYmz+WcLFy2dWgNRzbswDzLPXG7QU1XDVlP5TPp1HXjdmCupOWLL/I9m1fyhcyZl8/HPpp/Cg== dependencies: "@babel/runtime" "^7.27.1" - "@mui/core-downloads-tracker" "^7.1.0" - "@mui/system" "^7.1.0" - "@mui/types" "^7.4.2" - "@mui/utils" "^7.1.0" + +"@mui/material@^5.15.14 || ^6.0.0 || ^7.0.0", "@mui/material@^7.1.0", "@mui/material@^7.1.1": + version "7.1.1" + resolved "https://registry.npmjs.org/@mui/material/-/material-7.1.1.tgz" + integrity sha512-mTpdmdZCaHCGOH3SrYM41+XKvNL0iQfM9KlYgpSjgadXx/fEKhhvOktxm8++Xw6FFeOHoOiV+lzOI8X1rsv71A== + dependencies: + "@babel/runtime" "^7.27.1" + "@mui/core-downloads-tracker" "^7.1.1" + "@mui/system" "^7.1.1" + "@mui/types" "^7.4.3" + "@mui/utils" "^7.1.1" "@popperjs/core" "^2.11.8" "@types/react-transition-group" "^4.4.12" clsx "^2.1.1" @@ -606,19 +471,19 @@ react-is "^19.1.0" react-transition-group "^4.4.5" -"@mui/private-theming@^7.1.0": - version "7.1.0" - resolved "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.1.0.tgz" - integrity sha512-4Kck4jxhqF6YxNwJdSae1WgDfXVg0lIH6JVJ7gtuFfuKcQCgomJxPvUEOySTFRPz1IZzwz5OAcToskRdffElDA== +"@mui/private-theming@^7.1.1": + version "7.1.1" + resolved "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.1.1.tgz" + integrity sha512-M8NbLUx+armk2ZuaxBkkMk11ultnWmrPlN0Xe3jUEaBChg/mcxa5HWIWS1EE4DF36WRACaAHVAvyekWlDQf0PQ== dependencies: "@babel/runtime" "^7.27.1" - "@mui/utils" "^7.1.0" + "@mui/utils" "^7.1.1" prop-types "^15.8.1" -"@mui/styled-engine@^7.1.0": - version "7.1.0" - resolved "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.1.0.tgz" - integrity sha512-m0mJ0c6iRC+f9hMeRe0W7zZX1wme3oUX0+XTVHjPG7DJz6OdQ6K/ggEOq7ZdwilcpdsDUwwMfOmvO71qDkYd2w== +"@mui/styled-engine@^7.1.1": + version "7.1.1" + resolved "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.1.1.tgz" + integrity sha512-R2wpzmSN127j26HrCPYVQ53vvMcT5DaKLoWkrfwUYq3cYytL6TQrCH8JBH3z79B6g4nMZZVoaXrxO757AlShaw== dependencies: "@babel/runtime" "^7.27.1" "@emotion/cache" "^11.13.5" @@ -627,28 +492,28 @@ csstype "^3.1.3" prop-types "^15.8.1" -"@mui/system@^7.1.0": - version "7.1.0" - resolved "https://registry.npmjs.org/@mui/system/-/system-7.1.0.tgz" - integrity sha512-iedAWgRJMCxeMHvkEhsDlbvkK+qKf9me6ofsf7twk/jfT4P1ImVf7Rwb5VubEA0sikrVL+1SkoZM41M4+LNAVA== +"@mui/system@^5.15.14 || ^6.0.0 || ^7.0.0", "@mui/system@^7.1.1": + version "7.1.1" + resolved "https://registry.npmjs.org/@mui/system/-/system-7.1.1.tgz" + integrity sha512-Kj1uhiqnj4Zo7PDjAOghtXJtNABunWvhcRU0O7RQJ7WOxeynoH6wXPcilphV8QTFtkKaip8EiNJRiCD+B3eROA== dependencies: "@babel/runtime" "^7.27.1" - "@mui/private-theming" "^7.1.0" - "@mui/styled-engine" "^7.1.0" - "@mui/types" "^7.4.2" - "@mui/utils" "^7.1.0" + "@mui/private-theming" "^7.1.1" + "@mui/styled-engine" "^7.1.1" + "@mui/types" "^7.4.3" + "@mui/utils" "^7.1.1" clsx "^2.1.1" csstype "^3.1.3" prop-types "^15.8.1" -"@mui/types@^7.4.2", "@mui/types@^7.4.3": +"@mui/types@^7.4.3": version "7.4.3" resolved "https://registry.npmjs.org/@mui/types/-/types-7.4.3.tgz" integrity sha512-2UCEiK29vtiZTeLdS2d4GndBKacVyxGvReznGXGr+CzW/YhjIX+OHUdCIczZjzcRAgKBGmE9zCIgoV9FleuyRQ== dependencies: "@babel/runtime" "^7.27.1" -"@mui/utils@^7.1.0", "@mui/utils@^7.1.1": +"@mui/utils@^7.1.1": version "7.1.1" resolved "https://registry.npmjs.org/@mui/utils/-/utils-7.1.1.tgz" integrity sha512-BkOt2q7MBYl7pweY2JWwfrlahhp+uGLR8S+EhiyRaofeRYUWL2YKbSGQvN4hgSN1i8poN0PaUiii1kEMrchvzg== @@ -681,15 +546,6 @@ "@babel/runtime" "^7.27.4" "@mui/utils" "^7.1.1" -"@napi-rs/wasm-runtime@^0.2.10": - version "0.2.10" - resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.10.tgz#f3b7109419c6670000b2401e0c778b98afc25f84" - integrity sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ== - dependencies: - "@emnapi/core" "^1.4.3" - "@emnapi/runtime" "^1.4.3" - "@tybys/wasm-util" "^0.9.0" - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" @@ -698,7 +554,7 @@ "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": version "2.0.5" resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== @@ -716,7 +572,7 @@ resolved "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz" integrity sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog== -"@photo-sphere-viewer/core@^5.13.2": +"@photo-sphere-viewer/core@^5.13.2", "@photo-sphere-viewer/core@>=5.13.1": version "5.13.2" resolved "https://registry.npmjs.org/@photo-sphere-viewer/core/-/core-5.13.2.tgz" integrity sha512-rL4Ey39Prx4Iyxt1f2tAqlXvqu4/ovXfUvIpLt540OpZJiFjWccs6qLywof9vuhBJ7PXHudHWCjRPce0W8kx8w== @@ -755,7 +611,7 @@ utility-types "^3.11.0" zustand "^5.0.1" -"@react-three/fiber@^9.1.2": +"@react-three/fiber@^9.0.0", "@react-three/fiber@^9.1.2": version "9.1.2" resolved "https://registry.npmjs.org/@react-three/fiber/-/fiber-9.1.2.tgz" integrity sha512-k8FR9yVHV9kIF3iuOD0ds5hVymXYXfgdKklqziBVod9ZEJ8uk05Zjw29J/omU3IKeUfLNAIHfxneN3TUYM4I2w== @@ -778,106 +634,11 @@ resolved "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.9.tgz" integrity sha512-e9MeMtVWo186sgvFFJOPGy7/d2j2mZhLJIdVW0C/xDluuOvymEATqz6zKsP0ZmXGzQtqlyjz5sC1sYQUoJG98w== -"@rollup/rollup-android-arm-eabi@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz#f39f09f60d4a562de727c960d7b202a2cf797424" - integrity sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw== - -"@rollup/rollup-android-arm64@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz#d19af7e23760717f1d879d4ca3d2cd247742dff2" - integrity sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA== - "@rollup/rollup-darwin-arm64@4.41.1": version "4.41.1" resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz" integrity sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w== -"@rollup/rollup-darwin-x64@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz#aa66d2ba1a25e609500e13bef06dc0e71cc0c0d4" - integrity sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg== - -"@rollup/rollup-freebsd-arm64@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz#df10a7b6316a0ef1028c6ca71a081124c537e30d" - integrity sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg== - -"@rollup/rollup-freebsd-x64@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz#a3fdce8a05e95b068cbcb46e4df5185e407d0c35" - integrity sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA== - -"@rollup/rollup-linux-arm-gnueabihf@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz#49f766c55383bd0498014a9d76924348c2f3890c" - integrity sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg== - -"@rollup/rollup-linux-arm-musleabihf@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz#1d4d7d32fc557e17d52e1857817381ea365e2959" - integrity sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA== - -"@rollup/rollup-linux-arm64-gnu@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz#f4fc317268441e9589edad3be8f62b6c03009bc1" - integrity sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA== - -"@rollup/rollup-linux-arm64-musl@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz#63a1f1b0671cb17822dabae827fef0e443aebeb7" - integrity sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg== - -"@rollup/rollup-linux-loongarch64-gnu@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz#c659b01cc6c0730b547571fc3973e1e955369f98" - integrity sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw== - -"@rollup/rollup-linux-powerpc64le-gnu@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz#612e746f9ad7e58480f964d65e0d6c3f4aae69a8" - integrity sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A== - -"@rollup/rollup-linux-riscv64-gnu@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz#4610dbd1dcfbbae32fbc10c20ae7387acb31110c" - integrity sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw== - -"@rollup/rollup-linux-riscv64-musl@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz#054911fab40dc83fafc21e470193c058108f19d8" - integrity sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw== - -"@rollup/rollup-linux-s390x-gnu@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz#98896eca8012547c7f04bd07eaa6896825f9e1a5" - integrity sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g== - -"@rollup/rollup-linux-x64-gnu@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz#01cf56844a1e636ee80dfb364e72c2b7142ad896" - integrity sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A== - -"@rollup/rollup-linux-x64-musl@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz#e67c7531df6dff0b4c241101d4096617fbca87c3" - integrity sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ== - -"@rollup/rollup-win32-arm64-msvc@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz#7eeada98444e580674de6989284e4baacd48ea65" - integrity sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ== - -"@rollup/rollup-win32-ia32-msvc@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz#516c4b54f80587b4a390aaf4940b40870271d35d" - integrity sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg== - -"@rollup/rollup-win32-x64-msvc@4.41.1": - version "4.41.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz#848f99b0d9936d92221bb6070baeff4db6947a30" - integrity sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw== - "@tailwindcss/node@4.1.8": version "4.1.8" resolved "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.8.tgz" @@ -891,73 +652,11 @@ source-map-js "^1.2.1" tailwindcss "4.1.8" -"@tailwindcss/oxide-android-arm64@4.1.8": - version "4.1.8" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.8.tgz#4cb4b464636fc7e3154a1bb7df38a828291b3e9a" - integrity sha512-Fbz7qni62uKYceWYvUjRqhGfZKwhZDQhlrJKGtnZfuNtHFqa8wmr+Wn74CTWERiW2hn3mN5gTpOoxWKk0jRxjg== - "@tailwindcss/oxide-darwin-arm64@4.1.8": version "4.1.8" resolved "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.8.tgz" integrity sha512-RdRvedGsT0vwVVDztvyXhKpsU2ark/BjgG0huo4+2BluxdXo8NDgzl77qh0T1nUxmM11eXwR8jA39ibvSTbi7A== -"@tailwindcss/oxide-darwin-x64@4.1.8": - version "4.1.8" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.8.tgz#d0f3fa4c3bde21a772e29e31c9739d91db79de12" - integrity sha512-t6PgxjEMLp5Ovf7uMb2OFmb3kqzVTPPakWpBIFzppk4JE4ix0yEtbtSjPbU8+PZETpaYMtXvss2Sdkx8Vs4XRw== - -"@tailwindcss/oxide-freebsd-x64@4.1.8": - version "4.1.8" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.8.tgz#545c94c941007ed1aa2e449465501b70d59cb3da" - integrity sha512-g8C8eGEyhHTqwPStSwZNSrOlyx0bhK/V/+zX0Y+n7DoRUzyS8eMbVshVOLJTDDC+Qn9IJnilYbIKzpB9n4aBsg== - -"@tailwindcss/oxide-linux-arm-gnueabihf@4.1.8": - version "4.1.8" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.8.tgz#e1bdbf63a179081669b8cd1c9523889774760eb9" - integrity sha512-Jmzr3FA4S2tHhaC6yCjac3rGf7hG9R6Gf2z9i9JFcuyy0u79HfQsh/thifbYTF2ic82KJovKKkIB6Z9TdNhCXQ== - -"@tailwindcss/oxide-linux-arm64-gnu@4.1.8": - version "4.1.8" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.8.tgz#8d28093bbd43bdae771a2dcca720e926baa57093" - integrity sha512-qq7jXtO1+UEtCmCeBBIRDrPFIVI4ilEQ97qgBGdwXAARrUqSn/L9fUrkb1XP/mvVtoVeR2bt/0L77xx53bPZ/Q== - -"@tailwindcss/oxide-linux-arm64-musl@4.1.8": - version "4.1.8" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.8.tgz#cc6cece814d813885ead9cd8b9d55aeb3db56c97" - integrity sha512-O6b8QesPbJCRshsNApsOIpzKt3ztG35gfX9tEf4arD7mwNinsoCKxkj8TgEE0YRjmjtO3r9FlJnT/ENd9EVefQ== - -"@tailwindcss/oxide-linux-x64-gnu@4.1.8": - version "4.1.8" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.8.tgz#4cac14fa71382574773fb7986d9f0681ad89e3de" - integrity sha512-32iEXX/pXwikshNOGnERAFwFSfiltmijMIAbUhnNyjFr3tmWmMJWQKU2vNcFX0DACSXJ3ZWcSkzNbaKTdngH6g== - -"@tailwindcss/oxide-linux-x64-musl@4.1.8": - version "4.1.8" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.8.tgz#e085f1ccbc8f97625773a6a3afc2a6f88edf59da" - integrity sha512-s+VSSD+TfZeMEsCaFaHTaY5YNj3Dri8rST09gMvYQKwPphacRG7wbuQ5ZJMIJXN/puxPcg/nU+ucvWguPpvBDg== - -"@tailwindcss/oxide-wasm32-wasi@4.1.8": - version "4.1.8" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.8.tgz#c5e19fffe67f25cabf12a357bba4e87128151ea0" - integrity sha512-CXBPVFkpDjM67sS1psWohZ6g/2/cd+cq56vPxK4JeawelxwK4YECgl9Y9TjkE2qfF+9/s1tHHJqrC4SS6cVvSg== - dependencies: - "@emnapi/core" "^1.4.3" - "@emnapi/runtime" "^1.4.3" - "@emnapi/wasi-threads" "^1.0.2" - "@napi-rs/wasm-runtime" "^0.2.10" - "@tybys/wasm-util" "^0.9.0" - tslib "^2.8.0" - -"@tailwindcss/oxide-win32-arm64-msvc@4.1.8": - version "4.1.8" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.8.tgz#77521f23f91604c587736927fd2cb526667b7344" - integrity sha512-7GmYk1n28teDHUjPlIx4Z6Z4hHEgvP5ZW2QS9ygnDAdI/myh3HTHjDqtSqgu1BpRoI4OiLx+fThAyA1JePoENA== - -"@tailwindcss/oxide-win32-x64-msvc@4.1.8": - version "4.1.8" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.8.tgz#55c876ab35f8779d1dceec61483cd9834d7365ac" - integrity sha512-fou+U20j+Jl0EHwK92spoWISON2OBnCazIc038Xj2TdweYV33ZRkS9nwqiUi2d/Wba5xg5UoHfvynnb/UB49cQ== - "@tailwindcss/oxide@4.1.8": version "4.1.8" resolved "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.8.tgz" @@ -1003,13 +702,6 @@ resolved "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz" integrity sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA== -"@tybys/wasm-util@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.9.0.tgz#3e75eb00604c8d6db470bf18c37b7d984a0e3355" - integrity sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw== - dependencies: - tslib "^2.4.0" - "@types/babel__core@^7.20.5": version "7.20.5" resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz" @@ -1069,7 +761,7 @@ dependencies: "@types/estree" "*" -"@types/estree@*", "@types/estree@1.0.7", "@types/estree@^1.0.0", "@types/estree@^1.0.6": +"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.6", "@types/estree@1.0.7": version "1.0.7" resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz" integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== @@ -1103,7 +795,7 @@ resolved "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz" integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== -"@types/node@^22.15.24": +"@types/node@^18.0.0 || ^20.0.0 || >=22.0.0", "@types/node@^22.15.24": version "22.15.24" resolved "https://registry.npmjs.org/@types/node/-/node-22.15.24.tgz" integrity sha512-w9CZGm9RDjzTh/D+hFwlBJ3ziUaVw7oufKA3vOFSOZlzmW9AkZnfjPb+DLnrV6qtgL/LNmP0/2zBNCFHL3F0ng== @@ -1145,7 +837,7 @@ resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz" integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w== -"@types/react@^19.1.2": +"@types/react@*", "@types/react@^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react@^18.2.25 || ^19", "@types/react@^19.0.0", "@types/react@^19.1.2", "@types/react@>=16.8", "@types/react@>=18", "@types/react@>=18.0.0": version "19.1.6" resolved "https://registry.npmjs.org/@types/react/-/react-19.1.6.tgz" integrity sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q== @@ -1164,7 +856,7 @@ dependencies: "@types/estree" "*" -"@types/three@*": +"@types/three@*", "@types/three@>=0.134.0": version "0.177.0" resolved "https://registry.npmjs.org/@types/three/-/three-0.177.0.tgz" integrity sha512-/ZAkn4OLUijKQySNci47lFO+4JLE1TihEjsGWPUT+4jWqxtwOPPEwJV1C3k5MEx0mcBPCdkFjzRzDOnHEI1R+A== @@ -1212,7 +904,7 @@ natural-compare "^1.4.0" ts-api-utils "^2.1.0" -"@typescript-eslint/parser@8.33.0": +"@typescript-eslint/parser@^8.33.0", "@typescript-eslint/parser@8.33.0": version "8.33.0" resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.0.tgz" integrity sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ== @@ -1240,7 +932,7 @@ "@typescript-eslint/types" "8.33.0" "@typescript-eslint/visitor-keys" "8.33.0" -"@typescript-eslint/tsconfig-utils@8.33.0", "@typescript-eslint/tsconfig-utils@^8.33.0": +"@typescript-eslint/tsconfig-utils@^8.33.0", "@typescript-eslint/tsconfig-utils@8.33.0": version "8.33.0" resolved "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz" integrity sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug== @@ -1255,7 +947,7 @@ debug "^4.3.4" ts-api-utils "^2.1.0" -"@typescript-eslint/types@8.33.0", "@typescript-eslint/types@^8.33.0": +"@typescript-eslint/types@^8.33.0", "@typescript-eslint/types@8.33.0": version "8.33.0" resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz" integrity sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg== @@ -1333,7 +1025,7 @@ acorn-jsx@^5.3.2: resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.14.0: +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.14.0: version "8.14.1" resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz" integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== @@ -1432,7 +1124,7 @@ braces@^3.0.3: dependencies: fill-range "^7.1.1" -browserslist@^4.24.0: +browserslist@^4.24.0, "browserslist@>= 4.21.0": version "4.24.5" resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz" integrity sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw== @@ -1691,7 +1383,7 @@ earcut@^3.0.0: resolved "https://registry.npmjs.org/earcut/-/earcut-3.0.1.tgz" integrity sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw== -easymde@^2.20.0: +easymde@^2.20.0, "easymde@>= 2.0.0 < 3.0.0": version "2.20.0" resolved "https://registry.npmjs.org/easymde/-/easymde-2.20.0.tgz" integrity sha512-V1Z5f92TfR42Na852OWnIZMbM7zotWQYTddNaLYZFVKj7APBbyZ3FYJ27gBw2grMW3R6Qdv9J8n5Ij7XRSIgXQ== @@ -1823,7 +1515,7 @@ eslint-visitor-keys@^4.2.0: resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz" integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== -eslint@^9.25.0: +"eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^8.57.0 || ^9.0.0", eslint@^9.25.0, eslint@>=8.40: version "9.27.0" resolved "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz" integrity sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q== @@ -2379,7 +2071,7 @@ its-fine@^2.0.0: dependencies: "@types/react-reconciler" "^0.28.9" -jiti@^2.4.2: +jiti@*, jiti@^2.4.2, jiti@>=1.21.0: version "2.4.2" resolved "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz" integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A== @@ -2458,52 +2150,7 @@ lightningcss-darwin-arm64@1.30.1: resolved "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz" integrity sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ== -lightningcss-darwin-x64@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz#e81105d3fd6330860c15fe860f64d39cff5fbd22" - integrity sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA== - -lightningcss-freebsd-x64@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz#a0e732031083ff9d625c5db021d09eb085af8be4" - integrity sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig== - -lightningcss-linux-arm-gnueabihf@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz#1f5ecca6095528ddb649f9304ba2560c72474908" - integrity sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q== - -lightningcss-linux-arm64-gnu@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz#eee7799726103bffff1e88993df726f6911ec009" - integrity sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw== - -lightningcss-linux-arm64-musl@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz#f2e4b53f42892feeef8f620cbb889f7c064a7dfe" - integrity sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ== - -lightningcss-linux-x64-gnu@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz#2fc7096224bc000ebb97eea94aea248c5b0eb157" - integrity sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw== - -lightningcss-linux-x64-musl@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz#66dca2b159fd819ea832c44895d07e5b31d75f26" - integrity sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ== - -lightningcss-win32-arm64-msvc@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz#7d8110a19d7c2d22bfdf2f2bb8be68e7d1b69039" - integrity sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA== - -lightningcss-win32-x64-msvc@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz#fd7dd008ea98494b85d24b4bea016793f2e0e352" - integrity sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg== - -lightningcss@1.30.1: +lightningcss@^1.21.0, lightningcss@1.30.1: version "1.30.1" resolved "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz" integrity sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg== @@ -2966,7 +2613,7 @@ mobx-react-lite@^4.1.0: dependencies: use-sync-external-store "^1.4.0" -mobx@^6.13.7: +mobx@^6.13.7, mobx@^6.9.0: version "6.13.7" resolved "https://registry.npmjs.org/mobx/-/mobx-6.13.7.tgz" integrity sha512-aChaVU/DO5aRPmk1GX8L+whocagUUpBQqoPtJk+cm7UOXUk87J4PeWCh6nNmTTIfEhiR9DI/+FnA8dln/hTK7g== @@ -3125,7 +2772,7 @@ picomatch@^2.3.1: resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -picomatch@^4.0.2: +"picomatch@^3 || ^4", picomatch@^4.0.2: version "4.0.2" resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz" integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== @@ -3170,7 +2817,7 @@ promise-worker-transferable@^1.0.4: is-promise "^2.1.0" lie "^3.0.2" -prop-types@^15.6.2, prop-types@^15.8.1: +prop-types@^15.5.4, prop-types@^15.6.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -3236,7 +2883,7 @@ react-colorful@^5.6.1: resolved "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz" integrity sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw== -react-dom@^19.1.0: +"react-dom@^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^18 || ^19", "react-dom@^18.0.0 || ^19.0.0", react-dom@^19, react-dom@^19.0.0, react-dom@^19.1.0, react-dom@>=16.0.0, react-dom@>=16.13, react-dom@>=16.6.0, react-dom@>=16.8.0, react-dom@>=16.8.2, react-dom@>=18: version "19.1.0" resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz" integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g== @@ -3350,12 +2997,12 @@ react-use-measure@^2.1.7: resolved "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.7.tgz" integrity sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg== -react@^19.1.0: +"react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^17.0.0 || ^18.0.0 || ^19.0.0", "react@^18 || ^19", "react@^18.0 || ^19", "react@^18.0.0 || ^19.0.0", react@^19, react@^19.0.0, react@^19.1.0, "react@>= 16.8 || 18.0.0", "react@>= 16.8.0", react@>=16.0.0, react@>=16.13, react@>=16.6.0, react@>=16.8, react@>=16.8.0, react@>=16.8.2, react@>=17.0, react@>=18, react@>=18.0.0: version "19.1.0" resolved "https://registry.npmjs.org/react/-/react-19.1.0.tgz" integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg== -redux@^5.0.1: +redux@^5.0.0, redux@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz" integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w== @@ -3576,7 +3223,7 @@ suspend-react@^0.1.3: resolved "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz" integrity sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ== -tailwindcss@4.1.8, tailwindcss@^4.1.8: +tailwindcss@^4.1.8, "tailwindcss@>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1", tailwindcss@4.1.8: version "4.1.8" resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.8.tgz" integrity sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og== @@ -3625,7 +3272,7 @@ three@^0.175.0: resolved "https://registry.npmjs.org/three/-/three-0.175.0.tgz" integrity sha512-nNE3pnTHxXN/Phw768u0Grr7W4+rumGg/H6PgeseNJojkJtmeHJfZWi41Gp2mpXl1pg1pf1zjwR4McM1jTqkpg== -three@^0.177.0: +three@^0.177.0, "three@>= 0.159.0", three@>=0.125.0, three@>=0.126.1, three@>=0.128.0, three@>=0.134.0, three@>=0.137, three@>=0.156, three@>=0.159: version "0.177.0" resolved "https://registry.npmjs.org/three/-/three-0.177.0.tgz" integrity sha512-EiXv5/qWAaGI+Vz2A+JfavwYCMdGjxVsrn3oBwllUoqYeaBO75J63ZfyaQKoiLrqNHoTlUc6PFgMXnS0kI45zg== @@ -3685,9 +3332,9 @@ ts-api-utils@^2.1.0: resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz" integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ== -tslib@^2.4.0, tslib@^2.7.0, tslib@^2.8.0: +tslib@^2.7.0: version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== tunnel-rat@^0.1.2: @@ -3713,7 +3360,7 @@ typescript-eslint@^8.30.1: "@typescript-eslint/parser" "8.33.0" "@typescript-eslint/utils" "8.33.0" -typescript@~5.8.3: +typescript@>=4.8.4, "typescript@>=4.8.4 <5.9.0", typescript@~5.8.3: version "5.8.3" resolved "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz" integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== @@ -3794,7 +3441,7 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -use-sync-external-store@^1.2.2, use-sync-external-store@^1.4.0, use-sync-external-store@^1.5.0: +use-sync-external-store@^1.2.2, use-sync-external-store@^1.4.0, use-sync-external-store@^1.5.0, use-sync-external-store@>=1.2.0: version "1.5.0" resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz" integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A== @@ -3840,7 +3487,7 @@ vfile@^6.0.0: "@types/unist" "^3.0.0" vfile-message "^4.0.0" -vite@^6.3.5: +"vite@^4.2.0 || ^5.0.0 || ^6.0.0", "vite@^5.2.0 || ^6", vite@^6.3.5: version "6.3.5" resolved "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz" integrity sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ== @@ -3906,6 +3553,11 @@ yaml@^1.10.0: resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== +yaml@^2.4.2: + version "2.8.0" + resolved "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz" + integrity sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"