feat: Add edit
pages with cache
This commit is contained in:
77
package-lock.json
generated
77
package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
"@hello-pangea/dnd": "^18.0.1",
|
"@hello-pangea/dnd": "^18.0.1",
|
||||||
|
"@mui/icons-material": "^7.1.1",
|
||||||
"@mui/material": "^7.1.0",
|
"@mui/material": "^7.1.0",
|
||||||
"@mui/x-data-grid": "^8.5.1",
|
"@mui/x-data-grid": "^8.5.1",
|
||||||
"@photo-sphere-viewer/core": "^5.13.2",
|
"@photo-sphere-viewer/core": "^5.13.2",
|
||||||
@ -838,26 +839,52 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/core-downloads-tracker": {
|
"node_modules/@mui/core-downloads-tracker": {
|
||||||
"version": "7.1.0",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.1.tgz",
|
||||||
"integrity": "sha512-E0OqhZv548Qdc0PwWhLVA2zmjJZSTvaL4ZhoswmI8NJEC1tpW2js6LLP827jrW9MEiXYdz3QS6+hask83w74yQ==",
|
"integrity": "sha512-yBckQs4aQ8mqukLnPC6ivIRv6guhaXi8snVl00VtyojBbm+l6VbVhyTSZ68Abcx7Ah8B+GZhrB7BOli+e+9LkQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/mui-org"
|
"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": {
|
"node_modules/@mui/material": {
|
||||||
"version": "7.1.0",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-7.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/material/-/material-7.1.1.tgz",
|
||||||
"integrity": "sha512-ahUJdrhEv+mCp4XHW+tHIEYzZMSRLg8z4AjUOsj44QpD1ZaMxQoVOG2xiHvLFdcsIPbgSRx1bg1eQSheHBgvtg==",
|
"integrity": "sha512-mTpdmdZCaHCGOH3SrYM41+XKvNL0iQfM9KlYgpSjgadXx/fEKhhvOktxm8++Xw6FFeOHoOiV+lzOI8X1rsv71A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.27.1",
|
"@babel/runtime": "^7.27.1",
|
||||||
"@mui/core-downloads-tracker": "^7.1.0",
|
"@mui/core-downloads-tracker": "^7.1.1",
|
||||||
"@mui/system": "^7.1.0",
|
"@mui/system": "^7.1.1",
|
||||||
"@mui/types": "^7.4.2",
|
"@mui/types": "^7.4.3",
|
||||||
"@mui/utils": "^7.1.0",
|
"@mui/utils": "^7.1.1",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"@types/react-transition-group": "^4.4.12",
|
"@types/react-transition-group": "^4.4.12",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
@ -876,7 +903,7 @@
|
|||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@emotion/react": "^11.5.0",
|
"@emotion/react": "^11.5.0",
|
||||||
"@emotion/styled": "^11.3.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",
|
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||||
"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"
|
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
@ -903,13 +930,13 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@mui/private-theming": {
|
"node_modules/@mui/private-theming": {
|
||||||
"version": "7.1.0",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.1.1.tgz",
|
||||||
"integrity": "sha512-4Kck4jxhqF6YxNwJdSae1WgDfXVg0lIH6JVJ7gtuFfuKcQCgomJxPvUEOySTFRPz1IZzwz5OAcToskRdffElDA==",
|
"integrity": "sha512-M8NbLUx+armk2ZuaxBkkMk11ultnWmrPlN0Xe3jUEaBChg/mcxa5HWIWS1EE4DF36WRACaAHVAvyekWlDQf0PQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.27.1",
|
"@babel/runtime": "^7.27.1",
|
||||||
"@mui/utils": "^7.1.0",
|
"@mui/utils": "^7.1.1",
|
||||||
"prop-types": "^15.8.1"
|
"prop-types": "^15.8.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -930,9 +957,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/styled-engine": {
|
"node_modules/@mui/styled-engine": {
|
||||||
"version": "7.1.0",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.1.1.tgz",
|
||||||
"integrity": "sha512-m0mJ0c6iRC+f9hMeRe0W7zZX1wme3oUX0+XTVHjPG7DJz6OdQ6K/ggEOq7ZdwilcpdsDUwwMfOmvO71qDkYd2w==",
|
"integrity": "sha512-R2wpzmSN127j26HrCPYVQ53vvMcT5DaKLoWkrfwUYq3cYytL6TQrCH8JBH3z79B6g4nMZZVoaXrxO757AlShaw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.27.1",
|
"@babel/runtime": "^7.27.1",
|
||||||
@ -964,16 +991,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mui/system": {
|
"node_modules/@mui/system": {
|
||||||
"version": "7.1.0",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-7.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/system/-/system-7.1.1.tgz",
|
||||||
"integrity": "sha512-iedAWgRJMCxeMHvkEhsDlbvkK+qKf9me6ofsf7twk/jfT4P1ImVf7Rwb5VubEA0sikrVL+1SkoZM41M4+LNAVA==",
|
"integrity": "sha512-Kj1uhiqnj4Zo7PDjAOghtXJtNABunWvhcRU0O7RQJ7WOxeynoH6wXPcilphV8QTFtkKaip8EiNJRiCD+B3eROA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.27.1",
|
"@babel/runtime": "^7.27.1",
|
||||||
"@mui/private-theming": "^7.1.0",
|
"@mui/private-theming": "^7.1.1",
|
||||||
"@mui/styled-engine": "^7.1.0",
|
"@mui/styled-engine": "^7.1.1",
|
||||||
"@mui/types": "^7.4.2",
|
"@mui/types": "^7.4.3",
|
||||||
"@mui/utils": "^7.1.0",
|
"@mui/utils": "^7.1.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"csstype": "^3.1.3",
|
"csstype": "^3.1.3",
|
||||||
"prop-types": "^15.8.1"
|
"prop-types": "^15.8.1"
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
"@hello-pangea/dnd": "^18.0.1",
|
"@hello-pangea/dnd": "^18.0.1",
|
||||||
|
"@mui/icons-material": "^7.1.1",
|
||||||
"@mui/material": "^7.1.0",
|
"@mui/material": "^7.1.0",
|
||||||
"@mui/x-data-grid": "^8.5.1",
|
"@mui/x-data-grid": "^8.5.1",
|
||||||
"@photo-sphere-viewer/core": "^5.13.2",
|
"@photo-sphere-viewer/core": "^5.13.2",
|
||||||
|
@ -25,8 +25,14 @@ import {
|
|||||||
SnapshotCreatePage,
|
SnapshotCreatePage,
|
||||||
CountryCreatePage,
|
CountryCreatePage,
|
||||||
CityCreatePage,
|
CityCreatePage,
|
||||||
// CarrierCreatePage,
|
CarrierCreatePage,
|
||||||
VehicleCreatePage,
|
VehicleCreatePage,
|
||||||
|
CountryEditPage,
|
||||||
|
CityEditPage,
|
||||||
|
UserCreatePage,
|
||||||
|
UserEditPage,
|
||||||
|
VehicleEditPage,
|
||||||
|
CarrierEditPage,
|
||||||
} from "@pages";
|
} from "@pages";
|
||||||
import { authStore, createSightStore, editSightStore } from "@shared";
|
import { authStore, createSightStore, editSightStore } from "@shared";
|
||||||
import { Layout } from "@widgets";
|
import { Layout } from "@widgets";
|
||||||
@ -121,25 +127,28 @@ const router = createBrowserRouter([
|
|||||||
{ path: "country", element: <CountryListPage /> },
|
{ path: "country", element: <CountryListPage /> },
|
||||||
{ path: "country/create", element: <CountryCreatePage /> },
|
{ path: "country/create", element: <CountryCreatePage /> },
|
||||||
{ path: "country/:id", element: <CountryPreviewPage /> },
|
{ path: "country/:id", element: <CountryPreviewPage /> },
|
||||||
|
{ path: "country/:id/edit", element: <CountryEditPage /> },
|
||||||
// City
|
// City
|
||||||
{ path: "city", element: <CityListPage /> },
|
{ path: "city", element: <CityListPage /> },
|
||||||
{ path: "city/create", element: <CityCreatePage /> },
|
{ path: "city/create", element: <CityCreatePage /> },
|
||||||
{ path: "city/:id", element: <CityPreviewPage /> },
|
{ path: "city/:id", element: <CityPreviewPage /> },
|
||||||
|
{ path: "city/:id/edit", element: <CityEditPage /> },
|
||||||
// Route
|
// Route
|
||||||
{ path: "route", element: <RouteListPage /> },
|
{ path: "route", element: <RouteListPage /> },
|
||||||
|
|
||||||
// User
|
// User
|
||||||
{ path: "user", element: <UserListPage /> },
|
{ path: "user", element: <UserListPage /> },
|
||||||
|
{ path: "user/create", element: <UserCreatePage /> },
|
||||||
|
{ path: "user/:id/edit", element: <UserEditPage /> },
|
||||||
// Snapshot
|
// Snapshot
|
||||||
{ path: "snapshot", element: <SnapshotListPage /> },
|
{ path: "snapshot", element: <SnapshotListPage /> },
|
||||||
{ path: "snapshot/create", element: <SnapshotCreatePage /> },
|
{ path: "snapshot/create", element: <SnapshotCreatePage /> },
|
||||||
|
|
||||||
// Carrier
|
// Carrier
|
||||||
{ path: "carrier", element: <CarrierListPage /> },
|
{ path: "carrier", element: <CarrierListPage /> },
|
||||||
// { path: "carrier/create", element: <CarrierCreatePage /> },
|
{ path: "carrier/create", element: <CarrierCreatePage /> },
|
||||||
{ path: "carrier/:id", element: <CarrierPreviewPage /> },
|
{ path: "carrier/:id", element: <CarrierPreviewPage /> },
|
||||||
|
{ path: "carrier/:id/edit", element: <CarrierEditPage /> },
|
||||||
// Station
|
// Station
|
||||||
{ path: "station", element: <StationListPage /> },
|
{ path: "station", element: <StationListPage /> },
|
||||||
|
|
||||||
@ -147,7 +156,7 @@ const router = createBrowserRouter([
|
|||||||
{ path: "vehicle", element: <VehicleListPage /> },
|
{ path: "vehicle", element: <VehicleListPage /> },
|
||||||
{ path: "vehicle/create", element: <VehicleCreatePage /> },
|
{ path: "vehicle/create", element: <VehicleCreatePage /> },
|
||||||
{ path: "vehicle/:id", element: <VehiclePreviewPage /> },
|
{ path: "vehicle/:id", element: <VehiclePreviewPage /> },
|
||||||
|
{ path: "vehicle/:id/edit", element: <VehicleEditPage /> },
|
||||||
// Article
|
// Article
|
||||||
{ path: "article", element: <ArticleListPage /> },
|
{ path: "article", element: <ArticleListPage /> },
|
||||||
|
|
||||||
|
@ -4,7 +4,9 @@ export interface NavigationItem {
|
|||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label: string;
|
||||||
icon: LucideIcon;
|
icon: LucideIcon;
|
||||||
path: string;
|
path?: string;
|
||||||
|
onClick?: () => void;
|
||||||
|
nestedItems?: NavigationItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type NavigationSection = "primary" | "secondary";
|
export type NavigationSection = "primary" | "secondary";
|
||||||
|
@ -3,6 +3,10 @@ import ListItem from "@mui/material/ListItem";
|
|||||||
import ListItemButton from "@mui/material/ListItemButton";
|
import ListItemButton from "@mui/material/ListItemButton";
|
||||||
import ListItemIcon from "@mui/material/ListItemIcon";
|
import ListItemIcon from "@mui/material/ListItemIcon";
|
||||||
import ListItemText from "@mui/material/ListItemText";
|
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 type { NavigationItem } from "../model";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
@ -10,73 +14,100 @@ interface NavigationItemProps {
|
|||||||
item: NavigationItem;
|
item: NavigationItem;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
|
isNested?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NavigationItemComponent: React.FC<NavigationItemProps> = ({
|
export const NavigationItemComponent: React.FC<NavigationItemProps> = ({
|
||||||
item,
|
item,
|
||||||
open,
|
open,
|
||||||
onClick,
|
onClick,
|
||||||
|
isNested = false,
|
||||||
}) => {
|
}) => {
|
||||||
const Icon = item.icon;
|
const Icon = item.icon;
|
||||||
const navigate = useNavigate();
|
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 (
|
return (
|
||||||
<ListItem
|
<>
|
||||||
onClick={() => {
|
<ListItem disablePadding sx={{ display: "block" }}>
|
||||||
if (onClick) {
|
<ListItemButton
|
||||||
onClick();
|
onClick={handleClick}
|
||||||
} else {
|
|
||||||
navigate(item.path);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
disablePadding
|
|
||||||
sx={{ display: "block" }}
|
|
||||||
>
|
|
||||||
<ListItemButton
|
|
||||||
sx={[
|
|
||||||
{
|
|
||||||
minHeight: 48,
|
|
||||||
px: 2.5,
|
|
||||||
},
|
|
||||||
open
|
|
||||||
? {
|
|
||||||
justifyContent: "initial",
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
justifyContent: "center",
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<ListItemIcon
|
|
||||||
sx={[
|
sx={[
|
||||||
{
|
{
|
||||||
minWidth: 0,
|
minHeight: 48,
|
||||||
justifyContent: "center",
|
px: 2.5,
|
||||||
},
|
},
|
||||||
open
|
open
|
||||||
? {
|
? {
|
||||||
mr: 3,
|
justifyContent: "initial",
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
mr: "auto",
|
justifyContent: "center",
|
||||||
},
|
},
|
||||||
|
isNested && {
|
||||||
|
pl: 4,
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Icon />
|
<ListItemIcon
|
||||||
</ListItemIcon>
|
sx={[
|
||||||
<ListItemText
|
{
|
||||||
primary={item.label}
|
minWidth: 0,
|
||||||
sx={[
|
justifyContent: "center",
|
||||||
open
|
},
|
||||||
? {
|
open
|
||||||
opacity: 1,
|
? {
|
||||||
}
|
mr: 3,
|
||||||
: {
|
}
|
||||||
opacity: 0,
|
: {
|
||||||
},
|
mr: "auto",
|
||||||
]}
|
},
|
||||||
/>
|
]}
|
||||||
</ListItemButton>
|
>
|
||||||
</ListItem>
|
<Icon />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText
|
||||||
|
primary={item.label}
|
||||||
|
sx={[
|
||||||
|
open
|
||||||
|
? {
|
||||||
|
opacity: 1,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
opacity: 0,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
{item.nestedItems &&
|
||||||
|
open &&
|
||||||
|
(isExpanded ? <ExpandLessIcon /> : <ExpandMoreIcon />)}
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
{item.nestedItems && (
|
||||||
|
<Collapse in={isExpanded && open} timeout="auto" unmountOnExit>
|
||||||
|
<List component="div" disablePadding>
|
||||||
|
{item.nestedItems.map((nestedItem) => (
|
||||||
|
<NavigationItemComponent
|
||||||
|
key={nestedItem.id}
|
||||||
|
item={nestedItem}
|
||||||
|
open={open}
|
||||||
|
onClick={nestedItem.onClick}
|
||||||
|
isNested={true}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</Collapse>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -23,15 +23,15 @@ export const CarrierCreatePage = observer(() => {
|
|||||||
const [fullName, setFullName] = useState("");
|
const [fullName, setFullName] = useState("");
|
||||||
const [shortName, setShortName] = useState("");
|
const [shortName, setShortName] = useState("");
|
||||||
const [cityId, setCityId] = useState<number | null>(null);
|
const [cityId, setCityId] = useState<number | null>(null);
|
||||||
const [primaryColor, setPrimaryColor] = useState("#000000");
|
const [main_color, setMainColor] = useState("#000000");
|
||||||
const [secondaryColor, setSecondaryColor] = useState("#ffffff");
|
const [left_color, setLeftColor] = useState("#ffffff");
|
||||||
const [accentColor, setAccentColor] = useState("#ff0000");
|
const [right_color, setRightColor] = useState("#ff0000");
|
||||||
const [slogan, setSlogan] = useState("");
|
const [slogan, setSlogan] = useState("");
|
||||||
const [selectedMediaId, setSelectedMediaId] = useState<string | null>(null);
|
const [selectedMediaId, setSelectedMediaId] = useState<string | null>(null);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
cityStore.getCities();
|
cityStore.getCities("ru");
|
||||||
mediaStore.getMedia();
|
mediaStore.getMedia();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -41,11 +41,11 @@ export const CarrierCreatePage = observer(() => {
|
|||||||
await carrierStore.createCarrier(
|
await carrierStore.createCarrier(
|
||||||
fullName,
|
fullName,
|
||||||
shortName,
|
shortName,
|
||||||
cityStore.cities.find((c) => c.id === cityId)?.name!,
|
cityStore.cities.ru.find((c) => c.id === cityId)?.name!,
|
||||||
cityId!,
|
cityId!,
|
||||||
primaryColor,
|
main_color,
|
||||||
secondaryColor,
|
left_color,
|
||||||
accentColor,
|
right_color,
|
||||||
slogan,
|
slogan,
|
||||||
selectedMediaId!
|
selectedMediaId!
|
||||||
);
|
);
|
||||||
@ -60,7 +60,6 @@ export const CarrierCreatePage = observer(() => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
||||||
<LanguageSwitcher />
|
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<button
|
<button
|
||||||
className="flex items-center gap-2"
|
className="flex items-center gap-2"
|
||||||
@ -80,7 +79,7 @@ export const CarrierCreatePage = observer(() => {
|
|||||||
required
|
required
|
||||||
onChange={(e) => setCityId(e.target.value as number)}
|
onChange={(e) => setCityId(e.target.value as number)}
|
||||||
>
|
>
|
||||||
{cityStore.cities.map((city) => (
|
{cityStore.cities.ru.map((city) => (
|
||||||
<MenuItem key={city.id} value={city.id}>
|
<MenuItem key={city.id} value={city.id}>
|
||||||
{city.name}
|
{city.name}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@ -104,51 +103,55 @@ export const CarrierCreatePage = observer(() => {
|
|||||||
onChange={(e) => setShortName(e.target.value)}
|
onChange={(e) => setShortName(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="w-full flex flex-col gap-4">
|
<div className="flex gap-4 w-full ">
|
||||||
<div className="flex items-center gap-4">
|
<TextField
|
||||||
<span className="w-32">Основной цвет:</span>
|
fullWidth
|
||||||
<Box
|
label="Основной цвет"
|
||||||
sx={{
|
value={main_color}
|
||||||
width: 40,
|
className="flex-1 w-full"
|
||||||
height: 40,
|
onChange={(e) => setMainColor(e.target.value)}
|
||||||
backgroundColor: primaryColor,
|
type="color"
|
||||||
border: "1px solid #ccc",
|
sx={{
|
||||||
|
"& input": {
|
||||||
|
height: "50px",
|
||||||
|
paddingBlock: "14px",
|
||||||
|
paddingInline: "14px",
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
}}
|
},
|
||||||
/>
|
}}
|
||||||
<HexColorPicker color={primaryColor} onChange={setPrimaryColor} />
|
/>
|
||||||
</div>
|
<TextField
|
||||||
|
fullWidth
|
||||||
<div className="flex items-center gap-4">
|
label="Цвет левого виджета"
|
||||||
<span className="w-32">Вторичный цвет:</span>
|
value={left_color}
|
||||||
<Box
|
className="flex-1 w-full"
|
||||||
sx={{
|
onChange={(e) => setLeftColor(e.target.value)}
|
||||||
width: 40,
|
type="color"
|
||||||
height: 40,
|
sx={{
|
||||||
backgroundColor: secondaryColor,
|
"& input": {
|
||||||
border: "1px solid #ccc",
|
height: "50px",
|
||||||
|
paddingBlock: "14px",
|
||||||
|
paddingInline: "14px",
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
}}
|
},
|
||||||
/>
|
}}
|
||||||
<HexColorPicker
|
/>
|
||||||
color={secondaryColor}
|
<TextField
|
||||||
onChange={setSecondaryColor}
|
fullWidth
|
||||||
/>
|
label="Цвет правого виджета"
|
||||||
</div>
|
value={right_color}
|
||||||
|
className="flex-1 w-full"
|
||||||
<div className="flex items-center gap-4">
|
onChange={(e) => setRightColor(e.target.value)}
|
||||||
<span className="w-32">Акцентный цвет:</span>
|
type="color"
|
||||||
<Box
|
sx={{
|
||||||
sx={{
|
"& input": {
|
||||||
width: 40,
|
height: "50px",
|
||||||
height: 40,
|
paddingBlock: "14px",
|
||||||
backgroundColor: accentColor,
|
paddingInline: "14px",
|
||||||
border: "1px solid #ccc",
|
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
}}
|
},
|
||||||
/>
|
}}
|
||||||
<HexColorPicker color={accentColor} onChange={setAccentColor} />
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
@ -167,11 +170,13 @@ export const CarrierCreatePage = observer(() => {
|
|||||||
required
|
required
|
||||||
onChange={(e) => setSelectedMediaId(e.target.value as string)}
|
onChange={(e) => setSelectedMediaId(e.target.value as string)}
|
||||||
>
|
>
|
||||||
{mediaStore.media.map((media) => (
|
{mediaStore.media
|
||||||
<MenuItem key={media.id} value={media.id}>
|
.filter((media) => media.media_type === 3)
|
||||||
{media.media_name || media.filename}
|
.map((media) => (
|
||||||
</MenuItem>
|
<MenuItem key={media.id} value={media.id}>
|
||||||
))}
|
{media.media_name || media.filename}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
{selectedMediaId && (
|
{selectedMediaId && (
|
||||||
|
307
src/pages/Carrier/CarrierEditPage/index.tsx
Normal file
307
src/pages/Carrier/CarrierEditPage/index.tsx
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Paper,
|
||||||
|
TextField,
|
||||||
|
Select,
|
||||||
|
MenuItem,
|
||||||
|
FormControl,
|
||||||
|
InputLabel,
|
||||||
|
} 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 { carrierStore, cityStore, mediaStore } from "@shared";
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { MediaViewer } from "@widgets";
|
||||||
|
|
||||||
|
export const CarrierEditPage = observer(() => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { id } = useParams();
|
||||||
|
const { carrier, getCarrier, setEditCarrierData, editCarrierData } =
|
||||||
|
carrierStore;
|
||||||
|
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
await getCarrier(Number(id));
|
||||||
|
setEditCarrierData(
|
||||||
|
carrier?.[Number(id)]?.full_name as string,
|
||||||
|
carrier?.[Number(id)]?.short_name as string,
|
||||||
|
carrier?.[Number(id)]?.city as string,
|
||||||
|
carrier?.[Number(id)]?.city_id as number,
|
||||||
|
carrier?.[Number(id)]?.main_color as string,
|
||||||
|
carrier?.[Number(id)]?.left_color as string,
|
||||||
|
carrier?.[Number(id)]?.right_color as string,
|
||||||
|
carrier?.[Number(id)]?.slogan as string,
|
||||||
|
carrier?.[Number(id)]?.logo as string
|
||||||
|
);
|
||||||
|
cityStore.getCities("ru");
|
||||||
|
mediaStore.getMedia();
|
||||||
|
})();
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
const handleEdit = async () => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
await carrierStore.editCarrier(Number(id));
|
||||||
|
toast.success("Перевозчик успешно обновлен");
|
||||||
|
navigate("/carrier");
|
||||||
|
} catch (error) {
|
||||||
|
toast.error("Ошибка при обновлении перевозчика");
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<button
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
onClick={() => navigate("/carrier")}
|
||||||
|
>
|
||||||
|
<ArrowLeft size={20} />
|
||||||
|
Назад
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-10 w-full items-end">
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<InputLabel>Город</InputLabel>
|
||||||
|
<Select
|
||||||
|
value={editCarrierData.city_id || ""}
|
||||||
|
label="Город"
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
setEditCarrierData(
|
||||||
|
editCarrierData.full_name,
|
||||||
|
editCarrierData.short_name,
|
||||||
|
editCarrierData.city,
|
||||||
|
Number(e.target.value),
|
||||||
|
editCarrierData.main_color,
|
||||||
|
editCarrierData.left_color,
|
||||||
|
editCarrierData.right_color,
|
||||||
|
editCarrierData.slogan,
|
||||||
|
editCarrierData.logo
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{cityStore.cities.ru.map((city) => (
|
||||||
|
<MenuItem key={city.id} value={city.id}>
|
||||||
|
{city.name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Полное название"
|
||||||
|
value={editCarrierData.full_name}
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Короткое название"
|
||||||
|
value={editCarrierData.short_name}
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="flex gap-4 w-full">
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Основной цвет"
|
||||||
|
value={editCarrierData.main_color}
|
||||||
|
className="flex-1 w-full"
|
||||||
|
onChange={(e) =>
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Цвет левого виджета"
|
||||||
|
value={editCarrierData.left_color}
|
||||||
|
className="flex-1 w-full"
|
||||||
|
onChange={(e) =>
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Цвет правого виджета"
|
||||||
|
value={editCarrierData.right_color}
|
||||||
|
className="flex-1 w-full"
|
||||||
|
onChange={(e) =>
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Слоган"
|
||||||
|
value={editCarrierData.slogan}
|
||||||
|
onChange={(e) =>
|
||||||
|
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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="w-full flex flex-col gap-4">
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<InputLabel>Логотип</InputLabel>
|
||||||
|
<Select
|
||||||
|
value={editCarrierData.logo || ""}
|
||||||
|
label="Логотип"
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
setEditCarrierData(
|
||||||
|
editCarrierData.full_name,
|
||||||
|
editCarrierData.short_name,
|
||||||
|
editCarrierData.city,
|
||||||
|
editCarrierData.city_id,
|
||||||
|
editCarrierData.main_color,
|
||||||
|
editCarrierData.left_color,
|
||||||
|
editCarrierData.right_color,
|
||||||
|
editCarrierData.slogan,
|
||||||
|
e.target.value as string
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{mediaStore.media
|
||||||
|
.filter((media) => media.media_type === 3)
|
||||||
|
.map((media) => (
|
||||||
|
<MenuItem key={media.id} value={media.id}>
|
||||||
|
{media.media_name || media.filename}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
{editCarrierData.logo && (
|
||||||
|
<div className="w-32 h-32">
|
||||||
|
<MediaViewer
|
||||||
|
media={{ id: editCarrierData.logo, media_type: 1 }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
className="w-min flex gap-2 items-center"
|
||||||
|
startIcon={<Save size={20} />}
|
||||||
|
onClick={handleEdit}
|
||||||
|
disabled={
|
||||||
|
isLoading ||
|
||||||
|
!editCarrierData.full_name ||
|
||||||
|
!editCarrierData.short_name ||
|
||||||
|
!editCarrierData.city_id ||
|
||||||
|
!editCarrierData.logo
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{isLoading ? (
|
||||||
|
<Loader2 size={20} className="animate-spin" />
|
||||||
|
) : (
|
||||||
|
"Обновить"
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
});
|
@ -1,21 +1,20 @@
|
|||||||
import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
|
import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
|
||||||
import { carrierStore, languageStore } from "@shared";
|
import { carrierStore } from "@shared";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
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 { useNavigate } from "react-router-dom";
|
||||||
import { DeleteModal, LanguageSwitcher } from "@widgets";
|
import { CreateButton, DeleteModal } from "@widgets";
|
||||||
|
|
||||||
export const CarrierListPage = observer(() => {
|
export const CarrierListPage = observer(() => {
|
||||||
const { carriers, getCarriers, deleteCarrier } = carrierStore;
|
const { carriers, getCarriers, deleteCarrier } = carrierStore;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||||
const [rowId, setRowId] = useState<number | null>(null); // Lifted state
|
const [rowId, setRowId] = useState<number | null>(null); // Lifted state
|
||||||
const { language } = languageStore;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getCarriers();
|
getCarriers();
|
||||||
}, [language]);
|
}, []);
|
||||||
|
|
||||||
const columns: GridColDef[] = [
|
const columns: GridColDef[] = [
|
||||||
{
|
{
|
||||||
@ -37,10 +36,15 @@ export const CarrierListPage = observer(() => {
|
|||||||
{
|
{
|
||||||
field: "actions",
|
field: "actions",
|
||||||
headerName: "Действия",
|
headerName: "Действия",
|
||||||
|
headerAlign: "center",
|
||||||
|
width: 200,
|
||||||
|
|
||||||
renderCell: (params: GridRenderCellParams) => {
|
renderCell: (params: GridRenderCellParams) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full gap-7 justify-center items-center">
|
<div className="flex h-full gap-7 justify-center items-center">
|
||||||
|
<button onClick={() => navigate(`/carrier/${params.row.id}/edit`)}>
|
||||||
|
<Pencil size={20} className="text-blue-500" />
|
||||||
|
</button>
|
||||||
<button onClick={() => navigate(`/carrier/${params.row.id}`)}>
|
<button onClick={() => navigate(`/carrier/${params.row.id}`)}>
|
||||||
<Eye size={20} className="text-green-500" />
|
<Eye size={20} className="text-green-500" />
|
||||||
</button>
|
</button>
|
||||||
@ -67,12 +71,10 @@ export const CarrierListPage = observer(() => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<LanguageSwitcher />
|
|
||||||
|
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex justify-between items-center mb-10">
|
<div className="flex justify-between items-center mb-10">
|
||||||
<h1 className="text-2xl">Перевозчики</h1>
|
<h1 className="text-2xl">Перевозчики</h1>
|
||||||
{/* <CreateButton label="Создать перевозчика" path="/carrier/create" /> */}
|
<CreateButton label="Создать перевозчика" path="/carrier/create" />
|
||||||
</div>
|
</div>
|
||||||
<DataGrid
|
<DataGrid
|
||||||
rows={rows}
|
rows={rows}
|
||||||
@ -86,7 +88,7 @@ export const CarrierListPage = observer(() => {
|
|||||||
open={isDeleteModalOpen}
|
open={isDeleteModalOpen}
|
||||||
onDelete={async () => {
|
onDelete={async () => {
|
||||||
if (rowId) {
|
if (rowId) {
|
||||||
deleteCarrier(rowId);
|
await deleteCarrier(rowId);
|
||||||
}
|
}
|
||||||
setIsDeleteModalOpen(false);
|
setIsDeleteModalOpen(false);
|
||||||
setRowId(null);
|
setRowId(null);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Paper } from "@mui/material";
|
import { Paper } from "@mui/material";
|
||||||
import { carrierStore, mediaStore } from "@shared";
|
import { carrierStore, languageStore, mediaStore } from "@shared";
|
||||||
import { MediaViewer } from "@widgets";
|
import { MediaViewer } from "@widgets";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { ArrowLeft } from "lucide-react";
|
import { ArrowLeft } from "lucide-react";
|
||||||
@ -8,13 +8,25 @@ import { useNavigate, useParams } from "react-router-dom";
|
|||||||
|
|
||||||
export const CarrierPreviewPage = observer(() => {
|
export const CarrierPreviewPage = observer(() => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const { getCarrier, carrier } = carrierStore;
|
const { getCarrier, carrier, setEditCarrierData } = carrierStore;
|
||||||
const { oneMedia, getOneMedia } = mediaStore;
|
const { oneMedia, getOneMedia } = mediaStore;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const carrierResponse = await getCarrier(Number(id));
|
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);
|
await getOneMedia(carrierResponse?.logo as string);
|
||||||
})();
|
})();
|
||||||
}, [id]);
|
}, [id]);
|
||||||
@ -31,48 +43,30 @@ export const CarrierPreviewPage = observer(() => {
|
|||||||
<ArrowLeft size={20} />
|
<ArrowLeft size={20} />
|
||||||
Назад
|
Назад
|
||||||
</button>
|
</button>
|
||||||
{/* <div className="flex gap-2">
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
|
||||||
onClick={() => navigate(`/carrier/${id}/edit`)}
|
|
||||||
startIcon={<Pencil size={20} />}
|
|
||||||
>
|
|
||||||
Редактировать
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
color="error"
|
|
||||||
onClick={() => navigate(`/carrier/${id}/delete`)}
|
|
||||||
startIcon={<Trash2 size={20} />}
|
|
||||||
>
|
|
||||||
Удалить
|
|
||||||
</Button>
|
|
||||||
</div> */}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-10 w-full">
|
<div className="flex flex-col gap-10 w-full">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<h1 className="text-lg font-bold">Полное имя</h1>
|
<h1 className="text-lg font-bold">Полное имя</h1>
|
||||||
<p>{carrier?.full_name}</p>
|
<p>{carrier[Number(id)]?.full_name}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<h1 className="text-lg font-bold">Полное имя</h1>
|
<h1 className="text-lg font-bold">Полное имя</h1>
|
||||||
<p>{carrier?.full_name}</p>
|
<p>{carrier[Number(id)]?.full_name}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<h1 className="text-lg font-bold">Город</h1>
|
<h1 className="text-lg font-bold">Город</h1>
|
||||||
<p>{carrier?.city}</p>
|
<p>{carrier[Number(id)]?.city}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-2 ">
|
<div className="flex flex-col gap-2 ">
|
||||||
<h1 className="text-lg font-bold">Основной цвет</h1>
|
<h1 className="text-lg font-bold">Основной цвет</h1>
|
||||||
<div
|
<div
|
||||||
className="w-min"
|
className="w-min"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: `${carrier?.main_color}90`,
|
backgroundColor: `${carrier[Number(id)]?.main_color}90`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{carrier?.main_color}
|
{carrier[Number(id)]?.main_color}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
@ -80,10 +74,10 @@ export const CarrierPreviewPage = observer(() => {
|
|||||||
<div
|
<div
|
||||||
className="w-min"
|
className="w-min"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: `${carrier?.left_color}90`,
|
backgroundColor: `${carrier[Number(id)]?.left_color}90`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{carrier?.left_color}
|
{carrier[Number(id)]?.left_color}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
@ -91,15 +85,15 @@ export const CarrierPreviewPage = observer(() => {
|
|||||||
<div
|
<div
|
||||||
className="w-min"
|
className="w-min"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: `${carrier?.right_color}90`,
|
backgroundColor: `${carrier[Number(id)]?.right_color}90`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{carrier?.right_color}
|
{carrier[Number(id)]?.right_color}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<h1 className="text-lg font-bold">Краткое имя</h1>
|
<h1 className="text-lg font-bold">Краткое имя</h1>
|
||||||
<p>{carrier?.short_name}</p>
|
<p>{carrier[Number(id)]?.short_name}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<h1 className="text-lg font-bold">Логотип</h1>
|
<h1 className="text-lg font-bold">Логотип</h1>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
export * from "./CarrierListPage";
|
export * from "./CarrierListPage";
|
||||||
export * from "./CarrierPreviewPage";
|
export * from "./CarrierPreviewPage";
|
||||||
export * from "./CarrierCreatePage";
|
export * from "./CarrierCreatePage";
|
||||||
|
export * from "./CarrierEditPage";
|
||||||
|
@ -13,33 +13,31 @@ import { ArrowLeft, Save, ImagePlus } from "lucide-react";
|
|||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import { cityStore, countryStore, mediaStore } from "@shared";
|
import { cityStore, countryStore, languageStore, mediaStore } from "@shared";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { LanguageSwitcher, MediaViewer } from "@widgets";
|
import { LanguageSwitcher, MediaViewer } from "@widgets";
|
||||||
import { SelectMediaDialog } from "@shared";
|
import { SelectMediaDialog } from "@shared";
|
||||||
|
|
||||||
export const CityCreatePage = observer(() => {
|
export const CityCreatePage = observer(() => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [name, setName] = useState("");
|
const { language } = languageStore;
|
||||||
const [countryCode, setCountryCode] = useState("");
|
const { createCityData, setCreateCityData } = cityStore;
|
||||||
const [selectedMediaId, setSelectedMediaId] = useState<string | null>(null);
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [isSelectMediaOpen, setIsSelectMediaOpen] = useState(false);
|
const [isSelectMediaOpen, setIsSelectMediaOpen] = useState(false);
|
||||||
|
const { getCountries } = countryStore;
|
||||||
|
const { getMedia } = mediaStore;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
countryStore.getCountries();
|
(async () => {
|
||||||
mediaStore.getMedia();
|
await getCountries(language);
|
||||||
}, []);
|
await getMedia();
|
||||||
|
})();
|
||||||
|
}, [language]);
|
||||||
|
|
||||||
const handleCreate = async () => {
|
const handleCreate = async () => {
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
await cityStore.createCity(
|
await cityStore.createCity();
|
||||||
name,
|
|
||||||
countryStore.countries.find((c) => c.code === countryCode)?.name!,
|
|
||||||
countryCode,
|
|
||||||
selectedMediaId!
|
|
||||||
);
|
|
||||||
toast.success("Город успешно создан");
|
toast.success("Город успешно создан");
|
||||||
navigate("/city");
|
navigate("/city");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -55,11 +53,17 @@ export const CityCreatePage = observer(() => {
|
|||||||
media_name?: string;
|
media_name?: string;
|
||||||
media_type: number;
|
media_type: number;
|
||||||
}) => {
|
}) => {
|
||||||
setSelectedMediaId(media.id);
|
setCreateCityData(
|
||||||
|
createCityData[language].name,
|
||||||
|
createCityData.country,
|
||||||
|
createCityData.country_code,
|
||||||
|
media.id,
|
||||||
|
language
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectedMedia = selectedMediaId
|
const selectedMedia = createCityData.arms
|
||||||
? mediaStore.media.find((m) => m.id === selectedMediaId)
|
? mediaStore.media.find((m) => m.id === createCityData.arms)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -79,20 +83,39 @@ export const CityCreatePage = observer(() => {
|
|||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
label="Название города"
|
label="Название города"
|
||||||
value={name}
|
value={createCityData[language]?.name || ""}
|
||||||
required
|
required
|
||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) =>
|
||||||
|
setCreateCityData(
|
||||||
|
e.target.value,
|
||||||
|
createCityData.country,
|
||||||
|
createCityData.country_code,
|
||||||
|
createCityData.arms,
|
||||||
|
language
|
||||||
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormControl fullWidth>
|
<FormControl fullWidth>
|
||||||
<InputLabel>Страна</InputLabel>
|
<InputLabel>Страна</InputLabel>
|
||||||
<Select
|
<Select
|
||||||
value={countryCode}
|
value={createCityData.country_code || ""}
|
||||||
label="Страна"
|
label="Страна"
|
||||||
required
|
required
|
||||||
onChange={(e) => setCountryCode(e.target.value)}
|
onChange={(e) => {
|
||||||
|
const selectedCountry = countryStore.countries[language]?.find(
|
||||||
|
(country) => country.code === e.target.value
|
||||||
|
);
|
||||||
|
setCreateCityData(
|
||||||
|
createCityData[language].name,
|
||||||
|
selectedCountry?.name || "",
|
||||||
|
e.target.value,
|
||||||
|
createCityData.arms,
|
||||||
|
language
|
||||||
|
);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{countryStore.countries.map((country) => (
|
{countryStore.countries[language].map((country) => (
|
||||||
<MenuItem key={country.code} value={country.code}>
|
<MenuItem key={country.code} value={country.code}>
|
||||||
{country.name}
|
{country.name}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@ -145,7 +168,7 @@ export const CityCreatePage = observer(() => {
|
|||||||
className="w-min flex gap-2 items-center"
|
className="w-min flex gap-2 items-center"
|
||||||
startIcon={<Save size={20} />}
|
startIcon={<Save size={20} />}
|
||||||
onClick={handleCreate}
|
onClick={handleCreate}
|
||||||
disabled={isLoading || !name || !countryCode}
|
disabled={isLoading || !createCityData[language]?.name}
|
||||||
>
|
>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Loader2 size={20} className="animate-spin" />
|
<Loader2 size={20} className="animate-spin" />
|
||||||
|
207
src/pages/City/CityEditPage/index.tsx
Normal file
207
src/pages/City/CityEditPage/index.tsx
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Paper,
|
||||||
|
TextField,
|
||||||
|
Select,
|
||||||
|
MenuItem,
|
||||||
|
FormControl,
|
||||||
|
InputLabel,
|
||||||
|
Box,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { ArrowLeft, Save, ImagePlus } from "lucide-react";
|
||||||
|
import { Loader2 } from "lucide-react";
|
||||||
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
import {
|
||||||
|
cityStore,
|
||||||
|
countryStore,
|
||||||
|
languageStore,
|
||||||
|
mediaStore,
|
||||||
|
CashedCities,
|
||||||
|
} from "@shared";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { LanguageSwitcher, MediaViewer } from "@widgets";
|
||||||
|
import { SelectMediaDialog } from "@shared";
|
||||||
|
|
||||||
|
export const CityEditPage = observer(() => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [isSelectMediaOpen, setIsSelectMediaOpen] = useState(false);
|
||||||
|
const { language } = languageStore;
|
||||||
|
const { id } = useParams();
|
||||||
|
const { editCityData, editCity, getCity, setEditCityData } = cityStore;
|
||||||
|
const { getCountries } = countryStore;
|
||||||
|
const { getMedia, getOneMedia, oneMedia } = mediaStore;
|
||||||
|
|
||||||
|
const handleEdit = async () => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
await editCity(id as string);
|
||||||
|
toast.success("Город успешно обновлен");
|
||||||
|
} catch (error) {
|
||||||
|
toast.error("Ошибка при обновлении города");
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
if (id) {
|
||||||
|
const data = await getCity(id as string, language);
|
||||||
|
setEditCityData(
|
||||||
|
data.name,
|
||||||
|
data.country,
|
||||||
|
data.country_code,
|
||||||
|
data.arms,
|
||||||
|
language
|
||||||
|
);
|
||||||
|
await getOneMedia(data.arms as string);
|
||||||
|
await getCountries(language);
|
||||||
|
await getMedia();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}, [id, language]);
|
||||||
|
|
||||||
|
const handleMediaSelect = (media: {
|
||||||
|
id: string;
|
||||||
|
filename: string;
|
||||||
|
media_name?: string;
|
||||||
|
media_type: number;
|
||||||
|
}) => {
|
||||||
|
setEditCityData(
|
||||||
|
editCityData[language].name,
|
||||||
|
editCityData.country,
|
||||||
|
editCityData.country_code,
|
||||||
|
media.id,
|
||||||
|
language
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectedMedia = editCityData.arms
|
||||||
|
? mediaStore.media.find((m) => m.id === editCityData.arms)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
||||||
|
<LanguageSwitcher />
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<button
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
onClick={() => navigate("/city")}
|
||||||
|
>
|
||||||
|
<ArrowLeft size={20} />
|
||||||
|
Назад
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-10 w-full items-end">
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Название"
|
||||||
|
value={editCityData[language].name}
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
setEditCityData(
|
||||||
|
e.target.value,
|
||||||
|
editCityData.country,
|
||||||
|
editCityData.country_code,
|
||||||
|
editCityData.arms,
|
||||||
|
language
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<InputLabel>Страна</InputLabel>
|
||||||
|
<Select
|
||||||
|
value={editCityData.country_code || ""}
|
||||||
|
label="Страна"
|
||||||
|
required
|
||||||
|
onChange={(e) => {
|
||||||
|
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) => (
|
||||||
|
<MenuItem key={country.code} value={country.code}>
|
||||||
|
{country.name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<div className="w-full flex flex-col gap-4">
|
||||||
|
<label className="text-sm text-gray-600">Герб города</label>
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => setIsSelectMediaOpen(true)}
|
||||||
|
startIcon={<ImagePlus size={20} />}
|
||||||
|
>
|
||||||
|
Выбрать герб
|
||||||
|
</Button>
|
||||||
|
{selectedMedia && (
|
||||||
|
<span className="text-sm text-gray-600">
|
||||||
|
{selectedMedia.media_name || selectedMedia.filename}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{selectedMedia && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "200px",
|
||||||
|
height: "200px",
|
||||||
|
border: "1px solid #e0e0e0",
|
||||||
|
borderRadius: "8px",
|
||||||
|
overflow: "hidden",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MediaViewer
|
||||||
|
media={{
|
||||||
|
id: selectedMedia.id,
|
||||||
|
media_type: selectedMedia.media_type,
|
||||||
|
filename: selectedMedia.filename,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
className="w-min flex gap-2 items-center"
|
||||||
|
startIcon={<Save size={20} />}
|
||||||
|
onClick={handleEdit}
|
||||||
|
disabled={
|
||||||
|
isLoading || !editCityData[language as keyof CashedCities]?.name
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{isLoading ? (
|
||||||
|
<Loader2 size={20} className="animate-spin" />
|
||||||
|
) : (
|
||||||
|
"Обновить"
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<SelectMediaDialog
|
||||||
|
open={isSelectMediaOpen}
|
||||||
|
onClose={() => setIsSelectMediaOpen(false)}
|
||||||
|
onSelectMedia={handleMediaSelect}
|
||||||
|
/>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
});
|
@ -1,8 +1,8 @@
|
|||||||
import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
|
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 { useEffect, useState } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
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 { useNavigate } from "react-router-dom";
|
||||||
import { CreateButton, DeleteModal, LanguageSwitcher } from "@widgets";
|
import { CreateButton, DeleteModal, LanguageSwitcher } from "@widgets";
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ export const CityListPage = observer(() => {
|
|||||||
const { language } = languageStore;
|
const { language } = languageStore;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getCities();
|
getCities(language);
|
||||||
}, [language]);
|
}, [language]);
|
||||||
|
|
||||||
const columns: GridColDef[] = [
|
const columns: GridColDef[] = [
|
||||||
@ -33,10 +33,14 @@ export const CityListPage = observer(() => {
|
|||||||
headerName: "Действия",
|
headerName: "Действия",
|
||||||
align: "center",
|
align: "center",
|
||||||
headerAlign: "center",
|
headerAlign: "center",
|
||||||
|
width: 200,
|
||||||
|
|
||||||
renderCell: (params: GridRenderCellParams) => {
|
renderCell: (params: GridRenderCellParams) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full gap-7 justify-center items-center">
|
<div className="flex h-full gap-7 justify-center items-center">
|
||||||
|
<button onClick={() => navigate(`/city/${params.row.id}/edit`)}>
|
||||||
|
<Pencil size={20} className="text-blue-500" />
|
||||||
|
</button>
|
||||||
<button onClick={() => navigate(`/city/${params.row.id}`)}>
|
<button onClick={() => navigate(`/city/${params.row.id}`)}>
|
||||||
<Eye size={20} className="text-green-500" />
|
<Eye size={20} className="text-green-500" />
|
||||||
</button>
|
</button>
|
||||||
@ -54,7 +58,7 @@ export const CityListPage = observer(() => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const rows = cities.map((city) => ({
|
const rows = cities[language].map((city) => ({
|
||||||
id: city.id,
|
id: city.id,
|
||||||
name: city.name,
|
name: city.name,
|
||||||
country: city.country,
|
country: city.country,
|
||||||
@ -81,7 +85,7 @@ export const CityListPage = observer(() => {
|
|||||||
open={isDeleteModalOpen}
|
open={isDeleteModalOpen}
|
||||||
onDelete={async () => {
|
onDelete={async () => {
|
||||||
if (rowId) {
|
if (rowId) {
|
||||||
deleteCity(rowId);
|
deleteCity(rowId.toString(), language as keyof CashedCities);
|
||||||
}
|
}
|
||||||
setIsDeleteModalOpen(false);
|
setIsDeleteModalOpen(false);
|
||||||
setRowId(null);
|
setRowId(null);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Paper } from "@mui/material";
|
import { Paper } from "@mui/material";
|
||||||
import { cityStore, mediaStore } from "@shared";
|
import { cityStore, languageStore, mediaStore } from "@shared";
|
||||||
import { MediaViewer } from "@widgets";
|
import { LanguageSwitcher, MediaViewer } from "@widgets";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { ArrowLeft } from "lucide-react";
|
import { ArrowLeft } from "lucide-react";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
@ -8,19 +8,30 @@ import { useNavigate, useParams } from "react-router-dom";
|
|||||||
|
|
||||||
export const CityPreviewPage = observer(() => {
|
export const CityPreviewPage = observer(() => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const { getCity, city } = cityStore;
|
const { getCity, city, setEditCityData } = cityStore;
|
||||||
const { oneMedia, getOneMedia } = mediaStore;
|
const { oneMedia, getOneMedia } = mediaStore;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { language } = languageStore;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const cityResponse = await getCity(id as string);
|
if (id) {
|
||||||
await getOneMedia(cityResponse.arms as string);
|
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 (
|
return (
|
||||||
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
||||||
|
<LanguageSwitcher />
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<button
|
<button
|
||||||
className="flex items-center gap-2"
|
className="flex items-center gap-2"
|
||||||
@ -29,36 +40,18 @@ export const CityPreviewPage = observer(() => {
|
|||||||
<ArrowLeft size={20} />
|
<ArrowLeft size={20} />
|
||||||
Назад
|
Назад
|
||||||
</button>
|
</button>
|
||||||
{/* <div className="flex gap-2">
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
|
||||||
onClick={() => navigate(`/city/${id}/edit`)}
|
|
||||||
startIcon={<Pencil size={20} />}
|
|
||||||
>
|
|
||||||
Редактировать
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
color="error"
|
|
||||||
onClick={() => navigate(`/city/${id}/edit`)}
|
|
||||||
startIcon={<Trash2 size={20} />}
|
|
||||||
>
|
|
||||||
Удалить
|
|
||||||
</Button>
|
|
||||||
</div> */}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-10 w-full">
|
<div className="flex flex-col gap-10 w-full">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<h1 className="text-lg font-bold">Название</h1>
|
<h1 className="text-lg font-bold">Название</h1>
|
||||||
<p>{city?.name}</p>
|
<p>{city[id!]?.[language]?.name}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<h1 className="text-lg font-bold">Страна</h1>
|
<h1 className="text-lg font-bold">Страна</h1>
|
||||||
<p>{city?.country}</p>
|
<p>{city[id!]?.[language]?.country}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2 pb-10">
|
||||||
<h1 className="text-lg font-bold">Герб</h1>
|
<h1 className="text-lg font-bold">Герб</h1>
|
||||||
<div className="w-[300px] h-[200px]">
|
<div className="w-[300px] h-[200px]">
|
||||||
<MediaViewer
|
<MediaViewer
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
export * from "./CityListPage";
|
export * from "./CityListPage";
|
||||||
export * from "./CityPreviewPage";
|
export * from "./CityPreviewPage";
|
||||||
export * from "./CityCreatePage";
|
export * from "./CityCreatePage";
|
||||||
|
export * from "./CityEditPage";
|
||||||
|
@ -4,20 +4,20 @@ import { ArrowLeft, Save } from "lucide-react";
|
|||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import { countryStore } from "@shared";
|
import { countryStore, languageStore } from "@shared";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { LanguageSwitcher } from "@widgets";
|
import { LanguageSwitcher } from "@widgets";
|
||||||
|
|
||||||
export const CountryCreatePage = observer(() => {
|
export const CountryCreatePage = observer(() => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [name, setName] = useState("");
|
|
||||||
const [code, setCode] = useState("");
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const { language } = languageStore;
|
||||||
|
const { createCountryData, setCountryData, createCountry } = countryStore;
|
||||||
|
|
||||||
const handleCreate = async () => {
|
const handleCreate = async () => {
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
await countryStore.createCountry(code, name);
|
await createCountry();
|
||||||
toast.success("Страна успешно создана");
|
toast.success("Страна успешно создана");
|
||||||
navigate("/country");
|
navigate("/country");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -44,16 +44,24 @@ export const CountryCreatePage = observer(() => {
|
|||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
label="Код страны"
|
label="Код страны"
|
||||||
value={code}
|
value={createCountryData.code}
|
||||||
required
|
required
|
||||||
onChange={(e) => setCode(e.target.value)}
|
onChange={(e) =>
|
||||||
|
setCountryData(
|
||||||
|
e.target.value,
|
||||||
|
createCountryData[language].name,
|
||||||
|
language
|
||||||
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
fullWidth
|
fullWidth
|
||||||
label="Название"
|
label="Название"
|
||||||
value={name}
|
value={createCountryData[language].name}
|
||||||
required
|
required
|
||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) =>
|
||||||
|
setCountryData(createCountryData.code, e.target.value, language)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@ -61,7 +69,7 @@ export const CountryCreatePage = observer(() => {
|
|||||||
className="w-min flex gap-2 items-center"
|
className="w-min flex gap-2 items-center"
|
||||||
startIcon={<Save size={20} />}
|
startIcon={<Save size={20} />}
|
||||||
onClick={handleCreate}
|
onClick={handleCreate}
|
||||||
disabled={isLoading || !name || !code}
|
disabled={isLoading || !createCountryData[language].name}
|
||||||
>
|
>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Loader2 size={20} className="animate-spin" />
|
<Loader2 size={20} className="animate-spin" />
|
||||||
|
87
src/pages/Country/CountryEditPage/index.tsx
Normal file
87
src/pages/Country/CountryEditPage/index.tsx
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import { Button, 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 { countryStore, languageStore } from "@shared";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { LanguageSwitcher } from "@widgets";
|
||||||
|
|
||||||
|
export const CountryEditPage = observer(() => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const { language } = languageStore;
|
||||||
|
const { id } = useParams();
|
||||||
|
const { editCountryData, editCountry, getCountry, setEditCountryData } =
|
||||||
|
countryStore;
|
||||||
|
|
||||||
|
const handleEdit = async () => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
await editCountry(id as string);
|
||||||
|
toast.success("Страна успешно обновлена");
|
||||||
|
} catch (error) {
|
||||||
|
toast.error("Ошибка при обновлении страны");
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
if (id) {
|
||||||
|
const data = await getCountry(id as string, language);
|
||||||
|
setEditCountryData(data.name, language);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}, [id, language]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
||||||
|
<LanguageSwitcher />
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<button
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
onClick={() => navigate("/country")}
|
||||||
|
>
|
||||||
|
<ArrowLeft size={20} />
|
||||||
|
Назад
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-10 w-full items-end">
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Код страны"
|
||||||
|
value={id as string}
|
||||||
|
required
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Название"
|
||||||
|
value={editCountryData[language].name}
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
countryStore.setEditCountryData(e.target.value, language)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
className="w-min flex gap-2 items-center"
|
||||||
|
startIcon={<Save size={20} />}
|
||||||
|
onClick={handleEdit}
|
||||||
|
disabled={isLoading || !editCountryData[language].name}
|
||||||
|
>
|
||||||
|
{isLoading ? (
|
||||||
|
<Loader2 size={20} className="animate-spin" />
|
||||||
|
) : (
|
||||||
|
"Обновить"
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
});
|
@ -2,7 +2,7 @@ import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
|
|||||||
import { countryStore, languageStore } from "@shared";
|
import { countryStore, languageStore } from "@shared";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
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 { useNavigate } from "react-router-dom";
|
||||||
import { CreateButton, DeleteModal, LanguageSwitcher } from "@widgets";
|
import { CreateButton, DeleteModal, LanguageSwitcher } from "@widgets";
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ export const CountryListPage = observer(() => {
|
|||||||
const { language } = languageStore;
|
const { language } = languageStore;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getCountries();
|
getCountries(language);
|
||||||
}, [language]);
|
}, [language]);
|
||||||
|
|
||||||
const columns: GridColDef[] = [
|
const columns: GridColDef[] = [
|
||||||
@ -28,10 +28,15 @@ export const CountryListPage = observer(() => {
|
|||||||
headerName: "Действия",
|
headerName: "Действия",
|
||||||
align: "center",
|
align: "center",
|
||||||
headerAlign: "center",
|
headerAlign: "center",
|
||||||
|
width: 200,
|
||||||
renderCell: (params: GridRenderCellParams) => {
|
renderCell: (params: GridRenderCellParams) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full gap-7 justify-center items-center">
|
<div className="flex h-full gap-7 justify-center items-center">
|
||||||
|
<button
|
||||||
|
onClick={() => navigate(`/country/${params.row.code}/edit`)}
|
||||||
|
>
|
||||||
|
<Pencil size={20} className="text-blue-500" />
|
||||||
|
</button>
|
||||||
<button onClick={() => navigate(`/country/${params.row.code}`)}>
|
<button onClick={() => navigate(`/country/${params.row.code}`)}>
|
||||||
<Eye size={20} className="text-green-500" />
|
<Eye size={20} className="text-green-500" />
|
||||||
</button>
|
</button>
|
||||||
@ -49,7 +54,7 @@ export const CountryListPage = observer(() => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const rows = countries.map((country) => ({
|
const rows = countries[language]?.map((country) => ({
|
||||||
id: country.code,
|
id: country.code,
|
||||||
code: country.code,
|
code: country.code,
|
||||||
name: country.name,
|
name: country.name,
|
||||||
@ -66,12 +71,14 @@ export const CountryListPage = observer(() => {
|
|||||||
</div>
|
</div>
|
||||||
<DataGrid rows={rows} columns={columns} hideFooter />
|
<DataGrid rows={rows} columns={columns} hideFooter />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<DeleteModal
|
<DeleteModal
|
||||||
open={isDeleteModalOpen}
|
open={isDeleteModalOpen}
|
||||||
onDelete={async () => {
|
onDelete={async () => {
|
||||||
if (rowId) {
|
if (rowId) {
|
||||||
await countryStore.deleteCountry(rowId);
|
await countryStore.deleteCountry(rowId, language);
|
||||||
getCountries(); // Refresh the list after deletion
|
getCountries(language); // Refresh the list after deletion
|
||||||
|
setIsDeleteModalOpen(false);
|
||||||
}
|
}
|
||||||
setIsDeleteModalOpen(false);
|
setIsDeleteModalOpen(false);
|
||||||
setRowId(null);
|
setRowId(null);
|
||||||
|
@ -1,23 +1,29 @@
|
|||||||
import { Paper } from "@mui/material";
|
import { Paper } from "@mui/material";
|
||||||
import { countryStore } from "@shared";
|
import { countryStore, languageStore } from "@shared";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { ArrowLeft } from "lucide-react";
|
import { ArrowLeft } from "lucide-react";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
import { LanguageSwitcher } from "@widgets";
|
||||||
|
|
||||||
export const CountryPreviewPage = observer(() => {
|
export const CountryPreviewPage = observer(() => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const { getCountry, country } = countryStore;
|
const { getCountry, country, setEditCountryData } = countryStore;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { language } = languageStore;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
await getCountry(id as string);
|
if (id) {
|
||||||
|
const data = await getCountry(id as string, language);
|
||||||
|
setEditCountryData(data.name, language);
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
}, [id]);
|
}, [id, language]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
||||||
|
<LanguageSwitcher />
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<button
|
<button
|
||||||
className="flex items-center gap-2"
|
className="flex items-center gap-2"
|
||||||
@ -45,11 +51,11 @@ export const CountryPreviewPage = observer(() => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div> */}
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
{country && (
|
{country[id!]?.[language] && (
|
||||||
<div className="flex flex-col gap-10 w-full">
|
<div className="flex flex-col gap-10 w-full">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<h1 className="text-lg font-bold">Название</h1>
|
<h1 className="text-lg font-bold">Название</h1>
|
||||||
<p>{country?.name}</p>
|
<p>{country[id!]?.[language]?.name}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
export * from "./CountryListPage";
|
export * from "./CountryListPage";
|
||||||
export * from "./CountryPreviewPage";
|
export * from "./CountryPreviewPage";
|
||||||
export * from "./CountryCreatePage";
|
export * from "./CountryCreatePage";
|
||||||
|
export * from "./CountryEditPage";
|
||||||
|
129
src/pages/User/UserCreatePage/index.tsx
Normal file
129
src/pages/User/UserCreatePage/index.tsx
Normal file
@ -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 (
|
||||||
|
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<button
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
onClick={() => navigate("/user")}
|
||||||
|
>
|
||||||
|
<ArrowLeft size={20} />
|
||||||
|
Назад
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-10 w-full items-end">
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Имя"
|
||||||
|
value={createUserData.name || ""}
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
setCreateUserData(
|
||||||
|
e.target.value,
|
||||||
|
createUserData.email || "",
|
||||||
|
createUserData.password || "",
|
||||||
|
createUserData.is_admin || false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Email"
|
||||||
|
value={createUserData.email || ""}
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
setCreateUserData(
|
||||||
|
createUserData.name || "",
|
||||||
|
e.target.value,
|
||||||
|
createUserData.password || "",
|
||||||
|
createUserData.is_admin || false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Пароль"
|
||||||
|
value={createUserData.password || ""}
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
setCreateUserData(
|
||||||
|
createUserData.name || "",
|
||||||
|
createUserData.email || "",
|
||||||
|
e.target.value,
|
||||||
|
createUserData.is_admin || false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="w-full flex flex-col items-start">
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={createUserData.is_admin || false}
|
||||||
|
onChange={(e) => {
|
||||||
|
setCreateUserData(
|
||||||
|
createUserData.name || "",
|
||||||
|
createUserData.email || "",
|
||||||
|
createUserData.password || "",
|
||||||
|
e.target.checked
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Администратор"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
className="w-min flex gap-2 items-center"
|
||||||
|
startIcon={<Save size={20} />}
|
||||||
|
onClick={handleCreate}
|
||||||
|
disabled={
|
||||||
|
isLoading || !createUserData.name || !createUserData.password
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{isLoading ? (
|
||||||
|
<Loader2 size={20} className="animate-spin" />
|
||||||
|
) : (
|
||||||
|
"Создать"
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
});
|
139
src/pages/User/UserEditPage/index.tsx
Normal file
139
src/pages/User/UserEditPage/index.tsx
Normal file
@ -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 (
|
||||||
|
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<button
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
onClick={() => navigate("/user")}
|
||||||
|
>
|
||||||
|
<ArrowLeft size={20} />
|
||||||
|
Назад
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-10 w-full items-start">
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Имя"
|
||||||
|
value={editUserData.name || ""}
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
setEditUserData(
|
||||||
|
e.target.value,
|
||||||
|
editUserData.email || "",
|
||||||
|
editUserData.password || "",
|
||||||
|
editUserData.is_admin || false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Email"
|
||||||
|
value={editUserData.email || ""}
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
setEditUserData(
|
||||||
|
editUserData.name || "",
|
||||||
|
e.target.value,
|
||||||
|
editUserData.password || "",
|
||||||
|
editUserData.is_admin || false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Пароль"
|
||||||
|
value={editUserData.password || ""}
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
setEditUserData(
|
||||||
|
editUserData.name || "",
|
||||||
|
editUserData.email || "",
|
||||||
|
e.target.value,
|
||||||
|
editUserData.is_admin || false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={editUserData.is_admin || false}
|
||||||
|
onChange={(e) =>
|
||||||
|
setEditUserData(
|
||||||
|
editUserData.name || "",
|
||||||
|
editUserData.email || "",
|
||||||
|
editUserData.password || "",
|
||||||
|
e.target.checked
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label="Администратор"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
className="w-min flex gap-2 items-center self-end"
|
||||||
|
startIcon={<Save size={20} />}
|
||||||
|
onClick={handleEdit}
|
||||||
|
disabled={isLoading || !editUserData.name || !editUserData.email}
|
||||||
|
>
|
||||||
|
{isLoading ? (
|
||||||
|
<Loader2 size={20} className="animate-spin" />
|
||||||
|
) : (
|
||||||
|
"Обновить"
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
});
|
@ -1,21 +1,21 @@
|
|||||||
import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
|
import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
|
||||||
import { languageStore, userStore } from "@shared";
|
import { userStore } from "@shared";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
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 { useNavigate } from "react-router-dom";
|
||||||
import { DeleteModal, LanguageSwitcher } from "@widgets";
|
|
||||||
|
import { CreateButton, DeleteModal } from "@widgets";
|
||||||
|
|
||||||
export const UserListPage = observer(() => {
|
export const UserListPage = observer(() => {
|
||||||
const { users, getUsers, deleteUser } = userStore;
|
const { users, getUsers, deleteUser } = userStore;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||||
const [rowId, setRowId] = useState<number | null>(null); // Lifted state
|
const [rowId, setRowId] = useState<number | null>(null); // Lifted state
|
||||||
const { language } = languageStore;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getUsers();
|
getUsers();
|
||||||
}, [language]);
|
}, []);
|
||||||
|
|
||||||
const columns: GridColDef[] = [
|
const columns: GridColDef[] = [
|
||||||
{
|
{
|
||||||
@ -56,6 +56,15 @@ export const UserListPage = observer(() => {
|
|||||||
renderCell: (params: GridRenderCellParams) => {
|
renderCell: (params: GridRenderCellParams) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full gap-7 justify-center items-center">
|
<div className="flex h-full gap-7 justify-center items-center">
|
||||||
|
<button>
|
||||||
|
<Pencil
|
||||||
|
size={20}
|
||||||
|
className="text-blue-500"
|
||||||
|
onClick={() => {
|
||||||
|
navigate(`/user/${params.row.id}/edit`);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsDeleteModalOpen(true);
|
setIsDeleteModalOpen(true);
|
||||||
@ -79,9 +88,11 @@ export const UserListPage = observer(() => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<LanguageSwitcher />
|
<div className="w-full">
|
||||||
|
<div className="flex justify-between items-center mb-10">
|
||||||
<div style={{ width: "100%" }}>
|
<h1 className="text-2xl">Пользователи</h1>
|
||||||
|
<CreateButton label="Создать пользователя" path="/user/create" />
|
||||||
|
</div>
|
||||||
<DataGrid
|
<DataGrid
|
||||||
rows={rows}
|
rows={rows}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
@ -96,6 +107,7 @@ export const UserListPage = observer(() => {
|
|||||||
if (rowId) {
|
if (rowId) {
|
||||||
await deleteUser(rowId);
|
await deleteUser(rowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsDeleteModalOpen(false);
|
setIsDeleteModalOpen(false);
|
||||||
setRowId(null);
|
setRowId(null);
|
||||||
}}
|
}}
|
||||||
|
@ -1 +1,3 @@
|
|||||||
export * from "./UserListPage";
|
export * from "./UserListPage";
|
||||||
|
export * from "./UserCreatePage";
|
||||||
|
export * from "./UserEditPage";
|
||||||
|
@ -14,7 +14,6 @@ import { Loader2 } from "lucide-react";
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import { LanguageSwitcher } from "@widgets";
|
|
||||||
|
|
||||||
export const VehicleCreatePage = observer(() => {
|
export const VehicleCreatePage = observer(() => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -46,7 +45,6 @@ export const VehicleCreatePage = observer(() => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
||||||
<LanguageSwitcher />
|
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<button
|
<button
|
||||||
className="flex items-center gap-2"
|
className="flex items-center gap-2"
|
||||||
|
140
src/pages/Vehicle/VehicleEditPage/index.tsx
Normal file
140
src/pages/Vehicle/VehicleEditPage/index.tsx
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
import {
|
||||||
|
Paper,
|
||||||
|
TextField,
|
||||||
|
Select,
|
||||||
|
MenuItem,
|
||||||
|
FormControl,
|
||||||
|
InputLabel,
|
||||||
|
Button,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { ArrowLeft, Loader2, Save } from "lucide-react";
|
||||||
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { carrierStore, VEHICLE_TYPES, vehicleStore } from "@shared";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
|
||||||
|
export const VehicleEditPage = observer(() => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { id } = useParams();
|
||||||
|
const {
|
||||||
|
getVehicle,
|
||||||
|
vehicle,
|
||||||
|
editVehicleData,
|
||||||
|
setEditVehicleData,
|
||||||
|
editVehicle,
|
||||||
|
} = vehicleStore;
|
||||||
|
const { getCarriers } = carrierStore;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
await getVehicle(Number(id));
|
||||||
|
await getCarriers();
|
||||||
|
setEditVehicleData({
|
||||||
|
tail_number: vehicle[Number(id)]?.vehicle.tail_number,
|
||||||
|
type: vehicle[Number(id)]?.vehicle.type,
|
||||||
|
carrier: vehicle[Number(id)]?.vehicle.carrier,
|
||||||
|
carrier_id: vehicle[Number(id)]?.vehicle.carrier_id,
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
}, [id]);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const handleEdit = async () => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
await editVehicle(Number(id), editVehicleData);
|
||||||
|
toast.success("Транспортное средство успешно обновлено");
|
||||||
|
navigate("/vehicle");
|
||||||
|
} catch (error) {
|
||||||
|
toast.error("Ошибка при обновлении транспортного средства");
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Paper className="w-full h-full p-3 flex flex-col gap-10">
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<button
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
onClick={() => navigate("/vehicle")}
|
||||||
|
>
|
||||||
|
<ArrowLeft size={20} />
|
||||||
|
Назад
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-10 w-full items-end">
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="Бортовой номер"
|
||||||
|
value={editVehicleData.tail_number}
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
setEditVehicleData({
|
||||||
|
...editVehicleData,
|
||||||
|
tail_number: Number(e.target.value),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<InputLabel>Тип</InputLabel>
|
||||||
|
<Select
|
||||||
|
value={editVehicleData.type}
|
||||||
|
label="Тип"
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
setEditVehicleData({ ...editVehicleData, type: e.target.value })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{VEHICLE_TYPES.map((type) => (
|
||||||
|
<MenuItem key={type.value} value={type.value}>
|
||||||
|
{type.label}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<InputLabel>Перевозчик</InputLabel>
|
||||||
|
<Select
|
||||||
|
value={editVehicleData.carrier_id}
|
||||||
|
label="Перевозчик"
|
||||||
|
required
|
||||||
|
onChange={(e) =>
|
||||||
|
setEditVehicleData({
|
||||||
|
...editVehicleData,
|
||||||
|
carrier_id: e.target.value as number,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{carrierStore.carriers.map((carrier) => (
|
||||||
|
<MenuItem key={carrier.id} value={carrier.id}>
|
||||||
|
{carrier.full_name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
className="w-min flex gap-2 items-center"
|
||||||
|
startIcon={<Save size={20} />}
|
||||||
|
onClick={handleEdit}
|
||||||
|
disabled={
|
||||||
|
isLoading ||
|
||||||
|
!editVehicleData.tail_number ||
|
||||||
|
!editVehicleData.type ||
|
||||||
|
!editVehicleData.carrier_id
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{isLoading ? (
|
||||||
|
<Loader2 size={20} className="animate-spin" />
|
||||||
|
) : (
|
||||||
|
"Сохранить"
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
});
|
@ -2,9 +2,9 @@ import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
|
|||||||
import { carrierStore, languageStore, vehicleStore } from "@shared";
|
import { carrierStore, languageStore, vehicleStore } from "@shared";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
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 { useNavigate } from "react-router-dom";
|
||||||
import { CreateButton, DeleteModal, LanguageSwitcher } from "@widgets";
|
import { CreateButton, DeleteModal } from "@widgets";
|
||||||
import { VEHICLE_TYPES } from "@shared";
|
import { VEHICLE_TYPES } from "@shared";
|
||||||
|
|
||||||
export const VehicleListPage = observer(() => {
|
export const VehicleListPage = observer(() => {
|
||||||
@ -68,6 +68,9 @@ export const VehicleListPage = observer(() => {
|
|||||||
renderCell: (params: GridRenderCellParams) => {
|
renderCell: (params: GridRenderCellParams) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full gap-7 justify-center items-center">
|
<div className="flex h-full gap-7 justify-center items-center">
|
||||||
|
<button onClick={() => navigate(`/vehicle/${params.row.id}/edit`)}>
|
||||||
|
<Pencil size={20} className="text-blue-500" />
|
||||||
|
</button>
|
||||||
<button onClick={() => navigate(`/vehicle/${params.row.id}`)}>
|
<button onClick={() => navigate(`/vehicle/${params.row.id}`)}>
|
||||||
<Eye size={20} className="text-green-500" />
|
<Eye size={20} className="text-green-500" />
|
||||||
</button>
|
</button>
|
||||||
@ -96,8 +99,6 @@ export const VehicleListPage = observer(() => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<LanguageSwitcher />
|
|
||||||
|
|
||||||
<div style={{ width: "100%" }}>
|
<div style={{ width: "100%" }}>
|
||||||
<div className="flex justify-between items-center mb-10">
|
<div className="flex justify-between items-center mb-10">
|
||||||
<h1 className="text-2xl">Транспортные средства</h1>
|
<h1 className="text-2xl">Транспортные средства</h1>
|
||||||
|
@ -45,23 +45,23 @@ export const VehiclePreviewPage = observer(() => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div> */}
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
{vehicle && (
|
{vehicle[id!] && (
|
||||||
<div className="flex flex-col gap-10 w-full">
|
<div className="flex flex-col gap-10 w-full">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<h1 className="text-lg font-bold">Системный номер</h1>
|
<h1 className="text-lg font-bold">Системный номер</h1>
|
||||||
<p>{vehicle?.vehicle.tail_number}</p>
|
<p>{vehicle[id!]?.vehicle.tail_number}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<h1 className="text-lg font-bold">Тип транспортного средства</h1>
|
<h1 className="text-lg font-bold">Тип транспортного средства</h1>
|
||||||
<p>
|
<p>
|
||||||
{VEHICLE_TYPES.find(
|
{VEHICLE_TYPES.find(
|
||||||
(type) => type.value === vehicle?.vehicle.type
|
(type) => type.value === vehicle[id!]?.vehicle.type
|
||||||
)?.label || vehicle?.vehicle.type}
|
)?.label || vehicle[id!]?.vehicle.type}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<h1 className="text-lg font-bold">Перевозчик</h1>
|
<h1 className="text-lg font-bold">Перевозчик</h1>
|
||||||
<p>{vehicle?.vehicle.carrier}</p>
|
<p>{vehicle[id!]?.vehicle.carrier}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
export * from "./VehicleListPage";
|
export * from "./VehicleListPage";
|
||||||
export * from "./VehiclePreviewPage";
|
export * from "./VehiclePreviewPage";
|
||||||
export * from "./VehicleCreatePage";
|
export * from "./VehicleCreatePage";
|
||||||
|
export * from "./VehicleEditPage";
|
||||||
|
@ -3,7 +3,6 @@ import {
|
|||||||
Power,
|
Power,
|
||||||
LucideIcon,
|
LucideIcon,
|
||||||
Building2,
|
Building2,
|
||||||
MonitorSmartphone,
|
|
||||||
Map,
|
Map,
|
||||||
Users,
|
Users,
|
||||||
Earth,
|
Earth,
|
||||||
@ -11,6 +10,14 @@ import {
|
|||||||
BusFront,
|
BusFront,
|
||||||
Bus,
|
Bus,
|
||||||
GitBranch,
|
GitBranch,
|
||||||
|
Car,
|
||||||
|
Train,
|
||||||
|
Ship,
|
||||||
|
Table,
|
||||||
|
Split,
|
||||||
|
Newspaper,
|
||||||
|
PersonStanding,
|
||||||
|
Cpu,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
export const DRAWER_WIDTH = 300;
|
export const DRAWER_WIDTH = 300;
|
||||||
|
|
||||||
@ -20,6 +27,7 @@ interface NavigationItem {
|
|||||||
icon: LucideIcon;
|
icon: LucideIcon;
|
||||||
path?: string;
|
path?: string;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
|
nestedItems?: NavigationItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const NAVIGATION_ITEMS: {
|
export const NAVIGATION_ITEMS: {
|
||||||
@ -45,30 +53,7 @@ export const NAVIGATION_ITEMS: {
|
|||||||
icon: BusFront,
|
icon: BusFront,
|
||||||
path: "/carrier",
|
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",
|
id: "snapshots",
|
||||||
label: "Снапшоты",
|
label: "Снапшоты",
|
||||||
@ -84,33 +69,59 @@ export const NAVIGATION_ITEMS: {
|
|||||||
{
|
{
|
||||||
id: "devices",
|
id: "devices",
|
||||||
label: "Устройства",
|
label: "Устройства",
|
||||||
icon: MonitorSmartphone,
|
icon: Cpu,
|
||||||
path: "/devices",
|
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",
|
id: "vehicles",
|
||||||
label: "Транспорт",
|
label: "Транспорт",
|
||||||
icon: Bus,
|
icon: Car,
|
||||||
path: "/vehicle",
|
path: "/vehicle",
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// id: "routes",
|
|
||||||
// label: "Маршруты",
|
|
||||||
// icon: Split,
|
|
||||||
// path: "/route",
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
id: "users",
|
id: "users",
|
||||||
label: "Пользователи",
|
label: "Пользователи",
|
||||||
icon: Users,
|
icon: Users,
|
||||||
path: "/user",
|
path: "/user",
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// id: "articles",
|
|
||||||
// label: "Статьи",
|
|
||||||
// icon: Newspaper,
|
|
||||||
// path: "/articles",
|
|
||||||
// },
|
|
||||||
],
|
],
|
||||||
secondary: [
|
secondary: [
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { authInstance } from "@shared";
|
import { authInstance, languageStore } from "@shared";
|
||||||
import { makeAutoObservable, runInAction } from "mobx";
|
import { makeAutoObservable, runInAction } from "mobx";
|
||||||
|
|
||||||
export type Carrier = {
|
export type Carrier = {
|
||||||
@ -14,14 +14,19 @@ export type Carrier = {
|
|||||||
right_color: string;
|
right_color: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Carriers = Carrier[];
|
||||||
|
|
||||||
|
type CashedCarrier = Record<number, Carrier>;
|
||||||
|
|
||||||
class CarrierStore {
|
class CarrierStore {
|
||||||
carriers: Carrier[] = [];
|
carriers: Carriers = [];
|
||||||
carrier: Carrier | null = null;
|
carrier: CashedCarrier = {};
|
||||||
constructor() {
|
constructor() {
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
getCarriers = async () => {
|
getCarriers = async () => {
|
||||||
|
if (this.carriers.length > 0) return;
|
||||||
const response = await authInstance.get("/carrier");
|
const response = await authInstance.get("/carrier");
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
@ -34,13 +39,30 @@ class CarrierStore {
|
|||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.carriers = this.carriers.filter((carrier) => carrier.id !== id);
|
this.carriers = this.carriers.filter((carrier) => carrier.id !== id);
|
||||||
|
delete this.carrier[id];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
getCarrier = async (id: number) => {
|
getCarrier = async (id: number) => {
|
||||||
|
if (this.carrier[id]) return this.carrier[id];
|
||||||
const response = await authInstance.get(`/carrier/${id}`);
|
const response = await authInstance.get(`/carrier/${id}`);
|
||||||
|
|
||||||
runInAction(() => {
|
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;
|
return response.data;
|
||||||
};
|
};
|
||||||
@ -50,9 +72,9 @@ class CarrierStore {
|
|||||||
shortName: string,
|
shortName: string,
|
||||||
city: string,
|
city: string,
|
||||||
cityId: number,
|
cityId: number,
|
||||||
primaryColor: string,
|
main_color: string,
|
||||||
secondaryColor: string,
|
left_color: string,
|
||||||
accentColor: string,
|
right_color: string,
|
||||||
slogan: string,
|
slogan: string,
|
||||||
logoId: string
|
logoId: string
|
||||||
) => {
|
) => {
|
||||||
@ -61,9 +83,9 @@ class CarrierStore {
|
|||||||
short_name: shortName,
|
short_name: shortName,
|
||||||
city,
|
city,
|
||||||
city_id: cityId,
|
city_id: cityId,
|
||||||
primary_color: primaryColor,
|
main_color,
|
||||||
secondary_color: secondaryColor,
|
left_color,
|
||||||
accent_color: accentColor,
|
right_color,
|
||||||
slogan,
|
slogan,
|
||||||
logo: logoId,
|
logo: logoId,
|
||||||
});
|
});
|
||||||
@ -71,6 +93,57 @@ class CarrierStore {
|
|||||||
this.carriers.push(response.data);
|
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();
|
export const carrierStore = new CarrierStore();
|
||||||
|
@ -70,4 +70,4 @@ class CityStore {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const cityStore = new CityStore();
|
// export const cityStore = new CityStore();
|
266
src/shared/store/CityStore/index.ts
Normal file
266
src/shared/store/CityStore/index.ts
Normal file
@ -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<string, CashedCity> = {};
|
||||||
|
|
||||||
|
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();
|
@ -1,4 +1,9 @@
|
|||||||
import { authInstance } from "@shared";
|
import {
|
||||||
|
authInstance,
|
||||||
|
languageInstance,
|
||||||
|
Language,
|
||||||
|
languageStore,
|
||||||
|
} from "@shared";
|
||||||
import { makeAutoObservable, runInAction } from "mobx";
|
import { makeAutoObservable, runInAction } from "mobx";
|
||||||
|
|
||||||
export type Country = {
|
export type Country = {
|
||||||
@ -6,43 +11,208 @@ export type Country = {
|
|||||||
name: string;
|
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 {
|
class CountryStore {
|
||||||
countries: Country[] = [];
|
countries: CashedCountries = {
|
||||||
country: Country | null = null;
|
ru: [],
|
||||||
|
en: [],
|
||||||
|
zh: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
country: Record<string, CashedCountry> = {};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
getCountries = async () => {
|
getCountries = async (language: keyof CashedCountries) => {
|
||||||
const response = await authInstance.get("/country");
|
if (this.countries[language] && this.countries[language].length > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await authInstance.get(`/country`);
|
||||||
|
|
||||||
runInAction(() => {
|
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}`);
|
const response = await authInstance.get(`/country/${code}`);
|
||||||
|
|
||||||
runInAction(() => {
|
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}`);
|
await authInstance.delete(`/country/${code}`);
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.countries = this.countries.filter(
|
this.countries[language] = this.countries[language].filter(
|
||||||
(country) => country.code !== code
|
(country) => country.code !== code
|
||||||
);
|
);
|
||||||
|
this.country[code][language] = null;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
createCountry = async (code: string, name: string) => {
|
createCountryData = {
|
||||||
await authInstance.post("/country", { code: code, name: name });
|
code: "",
|
||||||
await this.getCountries();
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,17 +6,20 @@ export type User = {
|
|||||||
email: string;
|
email: string;
|
||||||
is_admin: boolean;
|
is_admin: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
|
password?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
class UserStore {
|
class UserStore {
|
||||||
users: User[] = [];
|
users: User[] = [];
|
||||||
user: User | null = null;
|
user: Record<string, User> = {};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
getUsers = async () => {
|
getUsers = async () => {
|
||||||
|
if (this.users.length > 0) return;
|
||||||
|
|
||||||
const response = await authInstance.get("/user");
|
const response = await authInstance.get("/user");
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
@ -25,18 +28,77 @@ class UserStore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getUser = async (id: number) => {
|
getUser = async (id: number) => {
|
||||||
|
if (this.user[id]) return;
|
||||||
const response = await authInstance.get(`/user/${id}`);
|
const response = await authInstance.get(`/user/${id}`);
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.user = response.data as User;
|
this.user[id] = response.data as User;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
deleteUser = async (id: number) => {
|
deleteUser = async (id: number) => {
|
||||||
await authInstance.delete(`/users/${id}`);
|
await authInstance.delete(`/user/${id}`);
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.users = this.users.filter((user) => user.id !== id);
|
this.users = this.users.filter((user) => user.id !== id);
|
||||||
|
delete this.user[id];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
createUserData: Partial<User> = {
|
||||||
|
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<User> = {
|
||||||
|
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 };
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { authInstance } from "@shared";
|
import { authInstance, languageStore, languageInstance } from "@shared";
|
||||||
import { makeAutoObservable } from "mobx";
|
import { makeAutoObservable, runInAction } from "mobx";
|
||||||
|
|
||||||
export type Vehicle = {
|
export type Vehicle = {
|
||||||
vehicle: {
|
vehicle: {
|
||||||
@ -22,42 +22,121 @@ export type Vehicle = {
|
|||||||
|
|
||||||
class VehicleStore {
|
class VehicleStore {
|
||||||
vehicles: Vehicle[] = [];
|
vehicles: Vehicle[] = [];
|
||||||
vehicle: Vehicle | null = null;
|
vehicle: Record<string, Vehicle> = {};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
getVehicles = async () => {
|
getVehicles = async () => {
|
||||||
const response = await authInstance.get(`/vehicle`);
|
const response = await languageInstance("ru").get(`/vehicle`);
|
||||||
this.vehicles = response.data;
|
|
||||||
|
runInAction(() => {
|
||||||
|
this.vehicles = response.data;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
deleteVehicle = async (id: number) => {
|
deleteVehicle = async (id: number) => {
|
||||||
await authInstance.delete(`/vehicle/${id}`);
|
await languageInstance("ru").delete(`/vehicle/${id}`);
|
||||||
this.vehicles = this.vehicles.filter(
|
|
||||||
(vehicle) => vehicle.vehicle.id !== id
|
runInAction(() => {
|
||||||
);
|
this.vehicles = this.vehicles.filter(
|
||||||
|
(vehicle) => vehicle.vehicle.id !== id
|
||||||
|
);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
getVehicle = async (id: number) => {
|
getVehicle = async (id: number) => {
|
||||||
const response = await authInstance.get(`/vehicle/${id}`);
|
const response = await languageInstance("ru").get(`/vehicle/${id}`);
|
||||||
this.vehicle = response.data;
|
|
||||||
|
runInAction(() => {
|
||||||
|
this.vehicle[id] = response.data;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
createVehicle = async (
|
createVehicle = async (
|
||||||
tailNumber: number,
|
tailNumber: number,
|
||||||
type: string,
|
type: number,
|
||||||
carrier: string,
|
carrier: string,
|
||||||
carrierId: number
|
carrierId: number
|
||||||
) => {
|
) => {
|
||||||
await authInstance.post("/vehicle", {
|
const response = await languageInstance("ru").post("/vehicle", {
|
||||||
tail_number: tailNumber,
|
tail_number: tailNumber,
|
||||||
type,
|
type,
|
||||||
carrier,
|
carrier,
|
||||||
carrier_id: carrierId,
|
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
|
||||||
|
);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
500
yarn.lock
500
yarn.lock
@ -24,7 +24,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.3.tgz"
|
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.3.tgz"
|
||||||
integrity sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==
|
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"
|
version "7.27.3"
|
||||||
resolved "https://registry.npmjs.org/@babel/core/-/core-7.27.3.tgz"
|
resolved "https://registry.npmjs.org/@babel/core/-/core-7.27.3.tgz"
|
||||||
integrity sha512-hyrN8ivxfvJ4i0fIJuV4EOlV0WDMz5Ui4StRTgVaAvWeiRCilXgwVvxJKtFQ3TKtHgJscB2YiXKGNJuVwhQMtA==
|
integrity sha512-hyrN8ivxfvJ4i0fIJuV4EOlV0WDMz5Ui4StRTgVaAvWeiRCilXgwVvxJKtFQ3TKtHgJscB2YiXKGNJuVwhQMtA==
|
||||||
@ -173,28 +173,6 @@
|
|||||||
resolved "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz"
|
resolved "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz"
|
||||||
integrity sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==
|
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":
|
"@emotion/babel-plugin@^11.13.5":
|
||||||
version "11.13.5"
|
version "11.13.5"
|
||||||
resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz"
|
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"
|
resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz"
|
||||||
integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
|
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"
|
version "11.14.0"
|
||||||
resolved "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz"
|
resolved "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz"
|
||||||
integrity sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==
|
integrity sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==
|
||||||
@ -270,7 +248,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz"
|
resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz"
|
||||||
integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
|
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"
|
version "11.14.0"
|
||||||
resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz"
|
resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz"
|
||||||
integrity sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==
|
integrity sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==
|
||||||
@ -302,131 +280,11 @@
|
|||||||
resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz"
|
resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz"
|
||||||
integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==
|
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":
|
"@esbuild/darwin-arm64@0.25.5":
|
||||||
version "0.25.5"
|
version "0.25.5"
|
||||||
resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz"
|
resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz"
|
||||||
integrity sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==
|
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":
|
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.7.0":
|
||||||
version "4.7.0"
|
version "4.7.0"
|
||||||
resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz"
|
resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz"
|
||||||
@ -475,7 +333,7 @@
|
|||||||
minimatch "^3.1.2"
|
minimatch "^3.1.2"
|
||||||
strip-json-comments "^3.1.1"
|
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"
|
version "9.27.0"
|
||||||
resolved "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz"
|
resolved "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz"
|
||||||
integrity sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==
|
integrity sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==
|
||||||
@ -583,21 +441,28 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
promise-worker-transferable "^1.0.4"
|
promise-worker-transferable "^1.0.4"
|
||||||
|
|
||||||
"@mui/core-downloads-tracker@^7.1.0":
|
"@mui/core-downloads-tracker@^7.1.1":
|
||||||
version "7.1.0"
|
version "7.1.1"
|
||||||
resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.0.tgz"
|
resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.1.tgz"
|
||||||
integrity sha512-E0OqhZv548Qdc0PwWhLVA2zmjJZSTvaL4ZhoswmI8NJEC1tpW2js6LLP827jrW9MEiXYdz3QS6+hask83w74yQ==
|
integrity sha512-yBckQs4aQ8mqukLnPC6ivIRv6guhaXi8snVl00VtyojBbm+l6VbVhyTSZ68Abcx7Ah8B+GZhrB7BOli+e+9LkQ==
|
||||||
|
|
||||||
"@mui/material@^7.1.0":
|
"@mui/icons-material@^7.1.1":
|
||||||
version "7.1.0"
|
version "7.1.1"
|
||||||
resolved "https://registry.npmjs.org/@mui/material/-/material-7.1.0.tgz"
|
resolved "https://registry.npmjs.org/@mui/icons-material/-/icons-material-7.1.1.tgz"
|
||||||
integrity sha512-ahUJdrhEv+mCp4XHW+tHIEYzZMSRLg8z4AjUOsj44QpD1ZaMxQoVOG2xiHvLFdcsIPbgSRx1bg1eQSheHBgvtg==
|
integrity sha512-X37+Yc8QpEnl0sYmz+WcLFy2dWgNRzbswDzLPXG7QU1XDVlP5TPp1HXjdmCupOWLL/I9m1fyhcyZl8/HPpp/Cg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.27.1"
|
"@babel/runtime" "^7.27.1"
|
||||||
"@mui/core-downloads-tracker" "^7.1.0"
|
|
||||||
"@mui/system" "^7.1.0"
|
"@mui/material@^5.15.14 || ^6.0.0 || ^7.0.0", "@mui/material@^7.1.0", "@mui/material@^7.1.1":
|
||||||
"@mui/types" "^7.4.2"
|
version "7.1.1"
|
||||||
"@mui/utils" "^7.1.0"
|
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"
|
"@popperjs/core" "^2.11.8"
|
||||||
"@types/react-transition-group" "^4.4.12"
|
"@types/react-transition-group" "^4.4.12"
|
||||||
clsx "^2.1.1"
|
clsx "^2.1.1"
|
||||||
@ -606,19 +471,19 @@
|
|||||||
react-is "^19.1.0"
|
react-is "^19.1.0"
|
||||||
react-transition-group "^4.4.5"
|
react-transition-group "^4.4.5"
|
||||||
|
|
||||||
"@mui/private-theming@^7.1.0":
|
"@mui/private-theming@^7.1.1":
|
||||||
version "7.1.0"
|
version "7.1.1"
|
||||||
resolved "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.1.0.tgz"
|
resolved "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.1.1.tgz"
|
||||||
integrity sha512-4Kck4jxhqF6YxNwJdSae1WgDfXVg0lIH6JVJ7gtuFfuKcQCgomJxPvUEOySTFRPz1IZzwz5OAcToskRdffElDA==
|
integrity sha512-M8NbLUx+armk2ZuaxBkkMk11ultnWmrPlN0Xe3jUEaBChg/mcxa5HWIWS1EE4DF36WRACaAHVAvyekWlDQf0PQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.27.1"
|
"@babel/runtime" "^7.27.1"
|
||||||
"@mui/utils" "^7.1.0"
|
"@mui/utils" "^7.1.1"
|
||||||
prop-types "^15.8.1"
|
prop-types "^15.8.1"
|
||||||
|
|
||||||
"@mui/styled-engine@^7.1.0":
|
"@mui/styled-engine@^7.1.1":
|
||||||
version "7.1.0"
|
version "7.1.1"
|
||||||
resolved "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.1.0.tgz"
|
resolved "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.1.1.tgz"
|
||||||
integrity sha512-m0mJ0c6iRC+f9hMeRe0W7zZX1wme3oUX0+XTVHjPG7DJz6OdQ6K/ggEOq7ZdwilcpdsDUwwMfOmvO71qDkYd2w==
|
integrity sha512-R2wpzmSN127j26HrCPYVQ53vvMcT5DaKLoWkrfwUYq3cYytL6TQrCH8JBH3z79B6g4nMZZVoaXrxO757AlShaw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.27.1"
|
"@babel/runtime" "^7.27.1"
|
||||||
"@emotion/cache" "^11.13.5"
|
"@emotion/cache" "^11.13.5"
|
||||||
@ -627,28 +492,28 @@
|
|||||||
csstype "^3.1.3"
|
csstype "^3.1.3"
|
||||||
prop-types "^15.8.1"
|
prop-types "^15.8.1"
|
||||||
|
|
||||||
"@mui/system@^7.1.0":
|
"@mui/system@^5.15.14 || ^6.0.0 || ^7.0.0", "@mui/system@^7.1.1":
|
||||||
version "7.1.0"
|
version "7.1.1"
|
||||||
resolved "https://registry.npmjs.org/@mui/system/-/system-7.1.0.tgz"
|
resolved "https://registry.npmjs.org/@mui/system/-/system-7.1.1.tgz"
|
||||||
integrity sha512-iedAWgRJMCxeMHvkEhsDlbvkK+qKf9me6ofsf7twk/jfT4P1ImVf7Rwb5VubEA0sikrVL+1SkoZM41M4+LNAVA==
|
integrity sha512-Kj1uhiqnj4Zo7PDjAOghtXJtNABunWvhcRU0O7RQJ7WOxeynoH6wXPcilphV8QTFtkKaip8EiNJRiCD+B3eROA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.27.1"
|
"@babel/runtime" "^7.27.1"
|
||||||
"@mui/private-theming" "^7.1.0"
|
"@mui/private-theming" "^7.1.1"
|
||||||
"@mui/styled-engine" "^7.1.0"
|
"@mui/styled-engine" "^7.1.1"
|
||||||
"@mui/types" "^7.4.2"
|
"@mui/types" "^7.4.3"
|
||||||
"@mui/utils" "^7.1.0"
|
"@mui/utils" "^7.1.1"
|
||||||
clsx "^2.1.1"
|
clsx "^2.1.1"
|
||||||
csstype "^3.1.3"
|
csstype "^3.1.3"
|
||||||
prop-types "^15.8.1"
|
prop-types "^15.8.1"
|
||||||
|
|
||||||
"@mui/types@^7.4.2", "@mui/types@^7.4.3":
|
"@mui/types@^7.4.3":
|
||||||
version "7.4.3"
|
version "7.4.3"
|
||||||
resolved "https://registry.npmjs.org/@mui/types/-/types-7.4.3.tgz"
|
resolved "https://registry.npmjs.org/@mui/types/-/types-7.4.3.tgz"
|
||||||
integrity sha512-2UCEiK29vtiZTeLdS2d4GndBKacVyxGvReznGXGr+CzW/YhjIX+OHUdCIczZjzcRAgKBGmE9zCIgoV9FleuyRQ==
|
integrity sha512-2UCEiK29vtiZTeLdS2d4GndBKacVyxGvReznGXGr+CzW/YhjIX+OHUdCIczZjzcRAgKBGmE9zCIgoV9FleuyRQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.27.1"
|
"@babel/runtime" "^7.27.1"
|
||||||
|
|
||||||
"@mui/utils@^7.1.0", "@mui/utils@^7.1.1":
|
"@mui/utils@^7.1.1":
|
||||||
version "7.1.1"
|
version "7.1.1"
|
||||||
resolved "https://registry.npmjs.org/@mui/utils/-/utils-7.1.1.tgz"
|
resolved "https://registry.npmjs.org/@mui/utils/-/utils-7.1.1.tgz"
|
||||||
integrity sha512-BkOt2q7MBYl7pweY2JWwfrlahhp+uGLR8S+EhiyRaofeRYUWL2YKbSGQvN4hgSN1i8poN0PaUiii1kEMrchvzg==
|
integrity sha512-BkOt2q7MBYl7pweY2JWwfrlahhp+uGLR8S+EhiyRaofeRYUWL2YKbSGQvN4hgSN1i8poN0PaUiii1kEMrchvzg==
|
||||||
@ -681,15 +546,6 @@
|
|||||||
"@babel/runtime" "^7.27.4"
|
"@babel/runtime" "^7.27.4"
|
||||||
"@mui/utils" "^7.1.1"
|
"@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":
|
"@nodelib/fs.scandir@2.1.5":
|
||||||
version "2.1.5"
|
version "2.1.5"
|
||||||
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
|
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
|
||||||
@ -698,7 +554,7 @@
|
|||||||
"@nodelib/fs.stat" "2.0.5"
|
"@nodelib/fs.stat" "2.0.5"
|
||||||
run-parallel "^1.1.9"
|
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"
|
version "2.0.5"
|
||||||
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
|
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
|
||||||
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
|
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
|
||||||
@ -716,7 +572,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz"
|
resolved "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz"
|
||||||
integrity sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==
|
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"
|
version "5.13.2"
|
||||||
resolved "https://registry.npmjs.org/@photo-sphere-viewer/core/-/core-5.13.2.tgz"
|
resolved "https://registry.npmjs.org/@photo-sphere-viewer/core/-/core-5.13.2.tgz"
|
||||||
integrity sha512-rL4Ey39Prx4Iyxt1f2tAqlXvqu4/ovXfUvIpLt540OpZJiFjWccs6qLywof9vuhBJ7PXHudHWCjRPce0W8kx8w==
|
integrity sha512-rL4Ey39Prx4Iyxt1f2tAqlXvqu4/ovXfUvIpLt540OpZJiFjWccs6qLywof9vuhBJ7PXHudHWCjRPce0W8kx8w==
|
||||||
@ -755,7 +611,7 @@
|
|||||||
utility-types "^3.11.0"
|
utility-types "^3.11.0"
|
||||||
zustand "^5.0.1"
|
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"
|
version "9.1.2"
|
||||||
resolved "https://registry.npmjs.org/@react-three/fiber/-/fiber-9.1.2.tgz"
|
resolved "https://registry.npmjs.org/@react-three/fiber/-/fiber-9.1.2.tgz"
|
||||||
integrity sha512-k8FR9yVHV9kIF3iuOD0ds5hVymXYXfgdKklqziBVod9ZEJ8uk05Zjw29J/omU3IKeUfLNAIHfxneN3TUYM4I2w==
|
integrity sha512-k8FR9yVHV9kIF3iuOD0ds5hVymXYXfgdKklqziBVod9ZEJ8uk05Zjw29J/omU3IKeUfLNAIHfxneN3TUYM4I2w==
|
||||||
@ -778,106 +634,11 @@
|
|||||||
resolved "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.9.tgz"
|
resolved "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.9.tgz"
|
||||||
integrity sha512-e9MeMtVWo186sgvFFJOPGy7/d2j2mZhLJIdVW0C/xDluuOvymEATqz6zKsP0ZmXGzQtqlyjz5sC1sYQUoJG98w==
|
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":
|
"@rollup/rollup-darwin-arm64@4.41.1":
|
||||||
version "4.41.1"
|
version "4.41.1"
|
||||||
resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz"
|
resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz"
|
||||||
integrity sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==
|
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":
|
"@tailwindcss/node@4.1.8":
|
||||||
version "4.1.8"
|
version "4.1.8"
|
||||||
resolved "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.8.tgz"
|
resolved "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.8.tgz"
|
||||||
@ -891,73 +652,11 @@
|
|||||||
source-map-js "^1.2.1"
|
source-map-js "^1.2.1"
|
||||||
tailwindcss "4.1.8"
|
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":
|
"@tailwindcss/oxide-darwin-arm64@4.1.8":
|
||||||
version "4.1.8"
|
version "4.1.8"
|
||||||
resolved "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.8.tgz"
|
resolved "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.8.tgz"
|
||||||
integrity sha512-RdRvedGsT0vwVVDztvyXhKpsU2ark/BjgG0huo4+2BluxdXo8NDgzl77qh0T1nUxmM11eXwR8jA39ibvSTbi7A==
|
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":
|
"@tailwindcss/oxide@4.1.8":
|
||||||
version "4.1.8"
|
version "4.1.8"
|
||||||
resolved "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.8.tgz"
|
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"
|
resolved "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz"
|
||||||
integrity sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==
|
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":
|
"@types/babel__core@^7.20.5":
|
||||||
version "7.20.5"
|
version "7.20.5"
|
||||||
resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz"
|
resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz"
|
||||||
@ -1069,7 +761,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/estree" "*"
|
"@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"
|
version "1.0.7"
|
||||||
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz"
|
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz"
|
||||||
integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==
|
integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==
|
||||||
@ -1103,7 +795,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz"
|
resolved "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz"
|
||||||
integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==
|
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"
|
version "22.15.24"
|
||||||
resolved "https://registry.npmjs.org/@types/node/-/node-22.15.24.tgz"
|
resolved "https://registry.npmjs.org/@types/node/-/node-22.15.24.tgz"
|
||||||
integrity sha512-w9CZGm9RDjzTh/D+hFwlBJ3ziUaVw7oufKA3vOFSOZlzmW9AkZnfjPb+DLnrV6qtgL/LNmP0/2zBNCFHL3F0ng==
|
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"
|
resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz"
|
||||||
integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==
|
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"
|
version "19.1.6"
|
||||||
resolved "https://registry.npmjs.org/@types/react/-/react-19.1.6.tgz"
|
resolved "https://registry.npmjs.org/@types/react/-/react-19.1.6.tgz"
|
||||||
integrity sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==
|
integrity sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==
|
||||||
@ -1164,7 +856,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/estree" "*"
|
"@types/estree" "*"
|
||||||
|
|
||||||
"@types/three@*":
|
"@types/three@*", "@types/three@>=0.134.0":
|
||||||
version "0.177.0"
|
version "0.177.0"
|
||||||
resolved "https://registry.npmjs.org/@types/three/-/three-0.177.0.tgz"
|
resolved "https://registry.npmjs.org/@types/three/-/three-0.177.0.tgz"
|
||||||
integrity sha512-/ZAkn4OLUijKQySNci47lFO+4JLE1TihEjsGWPUT+4jWqxtwOPPEwJV1C3k5MEx0mcBPCdkFjzRzDOnHEI1R+A==
|
integrity sha512-/ZAkn4OLUijKQySNci47lFO+4JLE1TihEjsGWPUT+4jWqxtwOPPEwJV1C3k5MEx0mcBPCdkFjzRzDOnHEI1R+A==
|
||||||
@ -1212,7 +904,7 @@
|
|||||||
natural-compare "^1.4.0"
|
natural-compare "^1.4.0"
|
||||||
ts-api-utils "^2.1.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"
|
version "8.33.0"
|
||||||
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.0.tgz"
|
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.0.tgz"
|
||||||
integrity sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==
|
integrity sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==
|
||||||
@ -1240,7 +932,7 @@
|
|||||||
"@typescript-eslint/types" "8.33.0"
|
"@typescript-eslint/types" "8.33.0"
|
||||||
"@typescript-eslint/visitor-keys" "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"
|
version "8.33.0"
|
||||||
resolved "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz"
|
resolved "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz"
|
||||||
integrity sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==
|
integrity sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==
|
||||||
@ -1255,7 +947,7 @@
|
|||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
ts-api-utils "^2.1.0"
|
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"
|
version "8.33.0"
|
||||||
resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz"
|
resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz"
|
||||||
integrity sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==
|
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"
|
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
|
||||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
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"
|
version "8.14.1"
|
||||||
resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz"
|
resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz"
|
||||||
integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==
|
integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==
|
||||||
@ -1432,7 +1124,7 @@ braces@^3.0.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fill-range "^7.1.1"
|
fill-range "^7.1.1"
|
||||||
|
|
||||||
browserslist@^4.24.0:
|
browserslist@^4.24.0, "browserslist@>= 4.21.0":
|
||||||
version "4.24.5"
|
version "4.24.5"
|
||||||
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz"
|
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz"
|
||||||
integrity sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==
|
integrity sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==
|
||||||
@ -1691,7 +1383,7 @@ earcut@^3.0.0:
|
|||||||
resolved "https://registry.npmjs.org/earcut/-/earcut-3.0.1.tgz"
|
resolved "https://registry.npmjs.org/earcut/-/earcut-3.0.1.tgz"
|
||||||
integrity sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==
|
integrity sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==
|
||||||
|
|
||||||
easymde@^2.20.0:
|
easymde@^2.20.0, "easymde@>= 2.0.0 < 3.0.0":
|
||||||
version "2.20.0"
|
version "2.20.0"
|
||||||
resolved "https://registry.npmjs.org/easymde/-/easymde-2.20.0.tgz"
|
resolved "https://registry.npmjs.org/easymde/-/easymde-2.20.0.tgz"
|
||||||
integrity sha512-V1Z5f92TfR42Na852OWnIZMbM7zotWQYTddNaLYZFVKj7APBbyZ3FYJ27gBw2grMW3R6Qdv9J8n5Ij7XRSIgXQ==
|
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"
|
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz"
|
||||||
integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==
|
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"
|
version "9.27.0"
|
||||||
resolved "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz"
|
resolved "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz"
|
||||||
integrity sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==
|
integrity sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==
|
||||||
@ -2379,7 +2071,7 @@ its-fine@^2.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/react-reconciler" "^0.28.9"
|
"@types/react-reconciler" "^0.28.9"
|
||||||
|
|
||||||
jiti@^2.4.2:
|
jiti@*, jiti@^2.4.2, jiti@>=1.21.0:
|
||||||
version "2.4.2"
|
version "2.4.2"
|
||||||
resolved "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz"
|
resolved "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz"
|
||||||
integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==
|
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"
|
resolved "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz"
|
||||||
integrity sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==
|
integrity sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==
|
||||||
|
|
||||||
lightningcss-darwin-x64@1.30.1:
|
lightningcss@^1.21.0, lightningcss@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:
|
|
||||||
version "1.30.1"
|
version "1.30.1"
|
||||||
resolved "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz"
|
resolved "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz"
|
||||||
integrity sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==
|
integrity sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==
|
||||||
@ -2966,7 +2613,7 @@ mobx-react-lite@^4.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
use-sync-external-store "^1.4.0"
|
use-sync-external-store "^1.4.0"
|
||||||
|
|
||||||
mobx@^6.13.7:
|
mobx@^6.13.7, mobx@^6.9.0:
|
||||||
version "6.13.7"
|
version "6.13.7"
|
||||||
resolved "https://registry.npmjs.org/mobx/-/mobx-6.13.7.tgz"
|
resolved "https://registry.npmjs.org/mobx/-/mobx-6.13.7.tgz"
|
||||||
integrity sha512-aChaVU/DO5aRPmk1GX8L+whocagUUpBQqoPtJk+cm7UOXUk87J4PeWCh6nNmTTIfEhiR9DI/+FnA8dln/hTK7g==
|
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"
|
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
|
||||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||||
|
|
||||||
picomatch@^4.0.2:
|
"picomatch@^3 || ^4", picomatch@^4.0.2:
|
||||||
version "4.0.2"
|
version "4.0.2"
|
||||||
resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz"
|
resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz"
|
||||||
integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==
|
integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==
|
||||||
@ -3170,7 +2817,7 @@ promise-worker-transferable@^1.0.4:
|
|||||||
is-promise "^2.1.0"
|
is-promise "^2.1.0"
|
||||||
lie "^3.0.2"
|
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"
|
version "15.8.1"
|
||||||
resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
|
resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
|
||||||
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
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"
|
resolved "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz"
|
||||||
integrity sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==
|
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"
|
version "19.1.0"
|
||||||
resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz"
|
resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz"
|
||||||
integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==
|
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"
|
resolved "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.7.tgz"
|
||||||
integrity sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==
|
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"
|
version "19.1.0"
|
||||||
resolved "https://registry.npmjs.org/react/-/react-19.1.0.tgz"
|
resolved "https://registry.npmjs.org/react/-/react-19.1.0.tgz"
|
||||||
integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==
|
integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==
|
||||||
|
|
||||||
redux@^5.0.1:
|
redux@^5.0.0, redux@^5.0.1:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz"
|
resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz"
|
||||||
integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==
|
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"
|
resolved "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz"
|
||||||
integrity sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==
|
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"
|
version "4.1.8"
|
||||||
resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.8.tgz"
|
resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.8.tgz"
|
||||||
integrity sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==
|
integrity sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==
|
||||||
@ -3625,7 +3272,7 @@ three@^0.175.0:
|
|||||||
resolved "https://registry.npmjs.org/three/-/three-0.175.0.tgz"
|
resolved "https://registry.npmjs.org/three/-/three-0.175.0.tgz"
|
||||||
integrity sha512-nNE3pnTHxXN/Phw768u0Grr7W4+rumGg/H6PgeseNJojkJtmeHJfZWi41Gp2mpXl1pg1pf1zjwR4McM1jTqkpg==
|
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"
|
version "0.177.0"
|
||||||
resolved "https://registry.npmjs.org/three/-/three-0.177.0.tgz"
|
resolved "https://registry.npmjs.org/three/-/three-0.177.0.tgz"
|
||||||
integrity sha512-EiXv5/qWAaGI+Vz2A+JfavwYCMdGjxVsrn3oBwllUoqYeaBO75J63ZfyaQKoiLrqNHoTlUc6PFgMXnS0kI45zg==
|
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"
|
resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz"
|
||||||
integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==
|
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"
|
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==
|
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
|
||||||
|
|
||||||
tunnel-rat@^0.1.2:
|
tunnel-rat@^0.1.2:
|
||||||
@ -3713,7 +3360,7 @@ typescript-eslint@^8.30.1:
|
|||||||
"@typescript-eslint/parser" "8.33.0"
|
"@typescript-eslint/parser" "8.33.0"
|
||||||
"@typescript-eslint/utils" "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"
|
version "5.8.3"
|
||||||
resolved "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz"
|
resolved "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz"
|
||||||
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
|
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
|
||||||
@ -3794,7 +3441,7 @@ uri-js@^4.2.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.0"
|
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"
|
version "1.5.0"
|
||||||
resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz"
|
resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz"
|
||||||
integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==
|
integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==
|
||||||
@ -3840,7 +3487,7 @@ vfile@^6.0.0:
|
|||||||
"@types/unist" "^3.0.0"
|
"@types/unist" "^3.0.0"
|
||||||
vfile-message "^4.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"
|
version "6.3.5"
|
||||||
resolved "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz"
|
resolved "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz"
|
||||||
integrity sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==
|
integrity sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==
|
||||||
@ -3906,6 +3553,11 @@ yaml@^1.10.0:
|
|||||||
resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz"
|
resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz"
|
||||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
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:
|
yocto-queue@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"
|
resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"
|
||||||
|
Reference in New Issue
Block a user