Price estimate
- {summary.length ? (
- `${currency} ${formatMoney(summary.reduce(
- (prev, next) => {
- return prev + next.price;
- }, 0
- ) + mode.price)}`
- ) : (
- `${currency} ${formatMoney(mode.price)}`
- )}
-
+ ${currency} ${formatMoney(total_price)}
diff --git a/static/js/shop/Shop.jsx b/static/js/shop/Shop.jsx
index 4dd5ed3..68614ee 100644
--- a/static/js/shop/Shop.jsx
+++ b/static/js/shop/Shop.jsx
@@ -50,6 +50,7 @@ export class Shop extends PureComponent {
this.handleCardsUpdated = this.handleCardsUpdated.bind(this);
this.onAddCrate = this.onAddCrate.bind(this);
this.onDeleteCrate = this.onDeleteCrate.bind(this);
+ this.onCrateModeChange = this.onCrateModeChange.bind(this);
this.timer = null;
this.timer_remove = null;
@@ -68,10 +69,10 @@ export class Shop extends PureComponent {
index: 0,
};
- /*this.handleOnDragEnd({
+ this.handleOnDragEnd({
source,
destination
- });*/
+ });
}
componentDidUpdate(prevProps, prevState) {
@@ -524,6 +525,22 @@ export class Shop extends PureComponent {
this.setState(new_state);
}
+ onCrateModeChange(crate_id, new_mode) {
+ let new_state = {
+ ...this.state,
+ columns: {
+ ...this.state.columns,
+ crates: {
+ ...this.state.columns.crates,
+ [crate_id]: {
+ ...this.state.columns.crates[crate_id],
+ crate_type: new_mode
+ }
+ }
+ }};
+ this.setState(new_state);
+ }
+
render() {
const {
@@ -586,14 +603,13 @@ export class Shop extends PureComponent {
isMobile={isMobile}
onAddCrate={this.onAddCrate}
onDeleteCrate={this.onDeleteCrate}
+ onModeChange={this.onCrateModeChange}
/>
}
summaryPrice={
{
+ sum += shared_data.crateModes[crate.crate_type].price;
+ crate.items.forEach((item, _) => {
+ sum += item.price;
+ });
+ });
+ return sum;
}
\ No newline at end of file
--
2.42.0
From 9bdaca2ca9bf7e62ffe95900c4360d02114b41ea Mon Sep 17 00:00:00 2001
From: Egor Savkin
Date: Fri, 8 Dec 2023 17:36:12 +0800
Subject: [PATCH 10/42] Start adding the warnings
Signed-off-by: Egor Savkin
---
static/js/shop/CrateList.jsx | 8 +++---
static/js/shop/Shop.jsx | 56 ++++++++++++++++++++----------------
static/js/shop/warnings.js | 33 ++++++++++++++++++++-
static/js/shop_data.js | 3 +-
4 files changed, 69 insertions(+), 31 deletions(-)
diff --git a/static/js/shop/CrateList.jsx b/static/js/shop/CrateList.jsx
index f559519..369dae7 100644
--- a/static/js/shop/CrateList.jsx
+++ b/static/js/shop/CrateList.jsx
@@ -2,16 +2,16 @@ import React from 'react'
import {Accordion} from "react-bootstrap";
import {Crate} from "./Crate.jsx";
-export function CrateList({crates, isMobile, isTouch, onAddCrate, onDeleteCrate, onModeChange}) {
+export function CrateList({crates, active_crate, isMobile, isTouch, onAddCrate, onDeleteCrate, onModeChange, onCrateSelect}) {
const onClickAdd = (_) => {
onAddCrate("crate" + Object.entries(crates).length);
}
return (
-
+
{Object.entries(crates).map(([crate_id, crate], index) =>
-
- Crate #{`${index}`}
+
+ onCrateSelect(crate_id)}>Crate #{`${index}`}
{
if (!(idx in itemsCloned)) itemsCloned[idx] = elem;
@@ -473,27 +477,20 @@ export class Shop extends PureComponent {
itemsCloned = FillResources(itemsCloned);
itemsCloned = TriggerWarnings(itemsCloned);
- // check number of slot in crate
- const nbrOccupied = nbrOccupiedSlotsInCrate(newItems);
- if (nbrOccupied > crateModeSlots[currentMode]) {
- rules[crateRules.maxSlot.type] = {...crateRules.maxSlot};
- } else if (crateModeSlots[currentMode] === 21 && nbrOccupied <= 10) {
- rules[crateRules.compactSlot.type] = {...crateRules.compactSlot};
- }
-
// update state with rules
this.setState({
...this.state,
columns: {
...this.state.columns,
- cart: {
- ...this.state.columns.cart,
- itemsData: itemsCloned,
+ crates: {
+ ...this.state.columns.crates,
+ [crate_id]: {
+ ...this.state.columns.crates[crate_id],
+ items: itemsCloned,
+ warnings: crate_warnings
+ },
}
- },
- rules: {
- ...rules,
- },
+ }
});
}
@@ -525,6 +522,13 @@ export class Shop extends PureComponent {
this.setState(new_state);
}
+ onCrateSelected(id) {
+ console.log(id)
+ this.setState({
+ active_crate: id
+ })
+ }
+
onCrateModeChange(crate_id, new_mode) {
let new_state = {
...this.state,
@@ -604,6 +608,8 @@ export class Shop extends PureComponent {
onAddCrate={this.onAddCrate}
onDeleteCrate={this.onDeleteCrate}
onModeChange={this.onCrateModeChange}
+ onCrateSelect={this.onCrateSelected}
+ active_crate={this.state.active_crate}
/>
}
summaryPrice={
diff --git a/static/js/shop/warnings.js b/static/js/shop/warnings.js
index 9a86157..0f21c82 100644
--- a/static/js/shop/warnings.js
+++ b/static/js/shop/warnings.js
@@ -5,7 +5,8 @@
* Second - resources indicator should be separate component
*/
-import {item_occupied_counters} from "./count_resources";
+import {crate_type_to_hp, item_occupied_counters, resource_counters} from "./count_resources";
+import {data as shared_data} from "./utils";
const Levels = {
"reminder": {priority: 1, icon: '/images/shop/icon-reminder.svg'},
@@ -120,4 +121,34 @@ export function MaxLevel(warnings) {
if (Levels[warning.level].priority > mx.priority) mx = Levels[warning.level];
}
return mx;
+}
+
+
+
+const crate_warnings = {
+ "overfit": {
+ message: "You have reached the maximum number of slots allowed for this crate. Consider removing cards.",
+ level: "warning",
+ trigger: (crate, occupied) => {
+ const nbrHP = crate_type_to_hp(crate.crate_type);
+ return occupied > nbrHP;
+ }
+ },
+ "underfit_rack": {
+ message: "The selected cards fit in a 42hp desktop crate, consider switching to it for a more compact system",
+ level: "reminder",
+ trigger: (crate, occupied) => {
+ const nbrHPDesktop = shared_data.crateModes.desktop.hp;
+ return crate.crate_type === shared_data.crateModes.rack.id && occupied < nbrHPDesktop;
+ }
+ }
+}
+
+export function TriggerCrateWarnings(crate) {
+ const nbrOccupied = resource_counters.hp(crate.items, -1);
+ let warnings = [];
+ Object.entries(crate_warnings).forEach(([id, warning], _) => {
+ if (warning.trigger(crate, nbrOccupied)) warnings.push({...warning, id: id, trigger: undefined});
+ })
+ return warnings;
}
\ No newline at end of file
diff --git a/static/js/shop_data.js b/static/js/shop_data.js
index da6c7a4..1be11d0 100644
--- a/static/js/shop_data.js
+++ b/static/js/shop_data.js
@@ -1188,7 +1188,8 @@ const shop_data = {
"crates": {
"crate0": {
crate_type: "rack",
- items: []
+ items: [],
+ warnings: []
}
}
--
2.42.0
From 9edf410e4dfe9098aa17de0b6d62fa7fa96109e0 Mon Sep 17 00:00:00 2001
From: Egor Savkin
Date: Mon, 11 Dec 2023 17:05:35 +0800
Subject: [PATCH 11/42] Start refactor to state manager zustand
Signed-off-by: Egor Savkin
---
package-lock.json | 31 +++-
package.json | 3 +-
static/js/shop/Backlog.jsx | 190 ++++++++++-----------
static/js/shop/Cart.jsx | 49 +++---
static/js/shop/Crate.jsx | 39 ++---
static/js/shop/CrateList.jsx | 34 ++--
static/js/shop/CrateMode.jsx | 20 ++-
static/js/shop/CrateWarnings.jsx | 11 +-
static/js/shop/Layout.jsx | 53 +++---
static/js/shop/OrderPanel.jsx | 90 ++++------
static/js/shop/ProductCartItem.jsx | 258 +++++++++++------------------
static/js/shop/Shop.jsx | 175 +++++++------------
static/js/shop/count_resources.js | 2 +-
static/js/shop/shop_store.js | 192 +++++++++++++++++++++
static/js/shop/warnings.js | 14 ++
static/js/shop_data.js | 9 +-
16 files changed, 634 insertions(+), 536 deletions(-)
create mode 100644 static/js/shop/shop_store.js
diff --git a/package-lock.json b/package-lock.json
index 4c8b015..b1e5e38 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -24,7 +24,8 @@
"react-dom": "^18.2.0",
"uuid": "^9.0.1",
"webpack": "^5.89.0",
- "webpack-cli": "^5.1.4"
+ "webpack-cli": "^5.1.4",
+ "zustand": "^4.4.7"
}
},
"node_modules/@ampproject/remapping": {
@@ -4915,6 +4916,34 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/zustand": {
+ "version": "4.4.7",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.7.tgz",
+ "integrity": "sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==",
+ "dev": true,
+ "dependencies": {
+ "use-sync-external-store": "1.2.0"
+ },
+ "engines": {
+ "node": ">=12.7.0"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.8",
+ "immer": ">=9.0",
+ "react": ">=16.8"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "immer": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ }
+ }
}
}
}
diff --git a/package.json b/package.json
index cdf0984..3aa2866 100644
--- a/package.json
+++ b/package.json
@@ -29,7 +29,8 @@
"uuid": "^9.0.1",
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4",
- "json-logic-js": "^2.0.2"
+ "json-logic-js": "^2.0.2",
+ "zustand": "^4.4.7"
},
"babel": {
"presets": [
diff --git a/static/js/shop/Backlog.jsx b/static/js/shop/Backlog.jsx
index dc0985a..c207e6a 100644
--- a/static/js/shop/Backlog.jsx
+++ b/static/js/shop/Backlog.jsx
@@ -1,118 +1,106 @@
-import React, {PureComponent} from 'react';
-import PropTypes from "prop-types";
+import React from 'react';
import {v4 as uuidv4} from "uuid";
import {Droppable} from "@hello-pangea/dnd";
import {ProductItem} from "./ProductItem.jsx";
+import {useShopStore} from "./shop_store";
/**
* Component that renders the backlog in the aside
*/
-export class Backlog extends PureComponent {
-
- static get propTypes() {
- return {
- currency: PropTypes.string,
- data: PropTypes.object.isRequired,
- items: PropTypes.object,
- isMobile: PropTypes.bool,
- onClickAddItem: PropTypes.func,
- onClickToggleMobileSideMenu: PropTypes.func,
- };
- }
-
- static get defaultProps() {
- return {
- items: {},
- };
- }
-
- render() {
- const {
- currency,
- data,
- items,
- onClickAddItem,
- onClickToggleMobileSideMenu,
- isMobile,
- } = this.props;
+export function Backlog() {
+ const {
+ currency,
+ data,
+ items,
+ onClickAddItem,
+ onClickToggleMobileSideMenu,
+ isMobile,
+ } = useShopStore(state=> ({
+ currency: state.currency,
+ data: state.groups,
+ items: state.cards,
+ onClickAddItem: state.addCardFromBacklog,
+ onClickToggleMobileSideMenu: state.switchSideMenu,
+ isMobile: state.isMobile
+ }));
- const ordered_groups = data.categories.map(groupItem => ({
- name: groupItem.name,
- items: groupItem.itemIds.map(itemId => items[itemId])
- }));
- let item_index = -1;
- const groups = ordered_groups.map((group, g_index) => {
- return (
-
-
-
- {group.name}
+ const ordered_groups = data.categories.map(groupItem => ({
+ name: groupItem.name,
+ items: groupItem.itemIds.map(itemId => items[itemId])
+ }));
+ let item_index = -1;
+ const groups = ordered_groups.map((group, g_index) => {
+ return (
+
+
+
+ {group.name}
+
+
+
+
+ {group.items.map(item => {
+ item_index++;
+ return (
+
+ )
+ })}
+
+
+
+ );
+ }
+ );
+
+ return (
+
+
+ {(provided) => (
+
+
+ {isMobile ? (
+
+
+
-
-
-
- {group.items.map(item => {
- item_index++;
- return (
-
- )
- })}
-
+ ) : null}
+
+
+ {groups}
- );
- }
- );
- return (
-
-
- {(provided) => (
-
-
- {isMobile ? (
-
-
-
-
-
- ) : null}
-
-
- {groups}
+ {provided.placeholder && (
+
+ {provided.placeholder}
+ )}
+
+ )}
- {provided.placeholder && (
-
- {provided.placeholder}
-
- )}
-
- )}
+
+ );
-
- );
- }
}
\ No newline at end of file
diff --git a/static/js/shop/Cart.jsx b/static/js/shop/Cart.jsx
index 7e20658..2b180aa 100644
--- a/static/js/shop/Cart.jsx
+++ b/static/js/shop/Cart.jsx
@@ -4,45 +4,42 @@ import {cartStyle} from "./utils";
import {ProductCartItem} from "./ProductCartItem.jsx";
import {FakePlaceholder} from "./FakePlaceholder.jsx";
import {FillExtData} from "./options/utils";
-import {crate_type_to_hp, hp_to_slots, resource_counters} from "./count_resources";
+import {CountResources, crate_type_to_hp, hp_to_slots, resource_counters} from "./count_resources";
+import {useShopStore} from "./shop_store";
+import {TriggerCardWarnings} from "./warnings";
/**
* Component that displays a list of
*/
-export function Cart({isMobile, isTouch, data, onToggleOverlayRemove, onClickRemoveItem, onCardUpdate, onClickItem}) {
- const nbrOccupied = hp_to_slots(resource_counters.hp(data.items, -1));
- const nbrSlots = hp_to_slots(crate_type_to_hp(data.crate_type));
+export function Cart({crate_index}) {
+ // isMobile, isTouch, crate, onToggleOverlayRemove, onClickRemoveItem, onCardUpdate, onClickItem
+ const {crate} = useShopStore(state => ({
+ crate: state.crates[crate_index]
+ }));
+
+ const nbrOccupied = hp_to_slots(resource_counters.hp(crate.items, -1));
+ const nbrSlots = hp_to_slots(crate_type_to_hp(crate.crate_mode));
console.log(nbrOccupied, nbrSlots);
- const products = data.items.map((item, index) => {
- let itemData;
- let ext_data = FillExtData(data.items, index);
- if (data.items && index in data.items) {
- itemData = data.items[index];
- }
+ const products = crate.items.map((item, index) => {
+ const ext_data = FillExtData(crate.items, index);
+ const resources = CountResources(crate.items, index);
+ const warnings = TriggerCardWarnings(crate.items, index, resources);
return (
= nbrSlots}
- data={itemData}
+ card_index={index}
+ crate_index={crate_index}
ext_data={ext_data}
- onToggleOverlayRemove={onToggleOverlayRemove}
- onClickRemoveItem={onClickRemoveItem}
- onCardUpdate={onCardUpdate}
- onClickItem={onClickItem}
- model={item}>
-
+ first={index === 0}
+ last={index === crate.items.length - 1 && nbrOccupied >= nbrSlots}
+ resources={resources}
+ warnings={warnings}
+ key={item.id}/>
);
});
return (
-
+
{(provided, snapshot) => (
and rules
*/
-export function Crate({
- data,
- handleToggleOverlayRemove,
- handleDeleteItem,
- handleShowOverlayRemove,
- handleCardsUpdated,
- isMobile,
- isTouch,
- onDelete,
- onModeChange
- }) {
+export function Crate({crate_index}) {
+ const {
+ onDeleteCrate,
+ crate
+ } = useShopStore(state => ({
+ onDeleteCrate: state.delCrate,
+ crate: state.crates[crate_index]
+ }))
+
return (
-
+
Delete crate
-
onDelete(data.id)}>
+ onDeleteCrate(crate.id)}>
-
-
+
{1 || (rules && rules.length > 0) && (
-
+
)}
-
);
diff --git a/static/js/shop/CrateList.jsx b/static/js/shop/CrateList.jsx
index 369dae7..5b61788 100644
--- a/static/js/shop/CrateList.jsx
+++ b/static/js/shop/CrateList.jsx
@@ -1,32 +1,34 @@
import React from 'react'
import {Accordion} from "react-bootstrap";
import {Crate} from "./Crate.jsx";
+import {useShopStore} from "./shop_store";
-export function CrateList({crates, active_crate, isMobile, isTouch, onAddCrate, onDeleteCrate, onModeChange, onCrateSelect}) {
- const onClickAdd = (_) => {
- onAddCrate("crate" + Object.entries(crates).length);
- }
-
+export function CrateList() {
+ const {
+ crates,
+ active_crate,
+ onAddCrate,
+ setActiveCrate,
+ } = useShopStore(state=> ({
+ crates: state.crates,
+ active_crate: state.active_crate,
+ onAddCrate: state.newCrate,
+ setActiveCrate: state.setActiveCrate,
+ }));
return (
- {Object.entries(crates).map(([crate_id, crate], index) =>
-
- onCrateSelect(crate_id)}>Crate #{`${index}`}
+ {crates.map((crate, index) =>
+
+ setActiveCrate(crate.id)}>Crate #{`${index}`}
- onModeChange(crate_id, new_mode)}
- />
+
)}
Add new crate
-
+
diff --git a/static/js/shop/CrateMode.jsx b/static/js/shop/CrateMode.jsx
index 8e2aa20..c8bcd91 100644
--- a/static/js/shop/CrateMode.jsx
+++ b/static/js/shop/CrateMode.jsx
@@ -1,19 +1,25 @@
import React from 'react';
-import {data as shared_data} from "./utils";
+import {useShopStore} from "./shop_store";
/**
* Component that displays crate modes
*/
-export function CrateMode({current, onChange}) {
+export function CrateMode({crate_index}) {
+ const {modes_order, crate_modes, crate, setMode} = useShopStore(state => ({
+ modes_order: state.modes_order,
+ crate_modes: state.crate_modes,
+ crate: state.crates[crate_index].crate_mode,
+ setMode: state.setCrateMode
+ }))
return (
);
diff --git a/static/js/shop/CrateWarnings.jsx b/static/js/shop/CrateWarnings.jsx
index e9887c5..4f80d3a 100644
--- a/static/js/shop/CrateWarnings.jsx
+++ b/static/js/shop/CrateWarnings.jsx
@@ -1,10 +1,15 @@
import React from "react";
+import {TriggerCrateWarnings} from "./warnings";
+import {useShopStore} from "./shop_store";
-export function CrateWarnings() {
+export function CrateWarnings({crate_index}) {
+ const crate = useShopStore(state => (state.crates[crate_index]))
+ const crate_warnings = TriggerCrateWarnings(crate);
+ // TODO UI/colors
return (
- {rules.map((rule, index) => (
-
+ {crate_warnings.map((rule, index) => (
+
{rule.name}: {rule.message}
))}
diff --git a/static/js/shop/Layout.jsx b/static/js/shop/Layout.jsx
index 2c39917..a0e62db 100644
--- a/static/js/shop/Layout.jsx
+++ b/static/js/shop/Layout.jsx
@@ -1,27 +1,12 @@
-import React, {PureComponent} from 'react';
-import PropTypes from "prop-types";
+import React from 'react';
+import {useShopStore} from "./shop_store";
/**
* Component that provides a base layout (aside/main) for the page.
*/
-export class Layout extends PureComponent {
-
- static get propTypes() {
- return {
- aside: PropTypes.any,
- main: PropTypes.any,
- mobileSideMenuShouldOpen: PropTypes.bool,
- isMobile: PropTypes.bool,
- newCardJustAdded: PropTypes.bool,
- onClickToggleMobileSideMenu: PropTypes.func,
- onClickCloseRFQFeedback: PropTypes.func,
- RFQBodyType: PropTypes.string,
- RFQBodyOrder: PropTypes.string,
- onClickLoadCustomConf: PropTypes.func,
- items: PropTypes.object,
- };
- }
+/*
+export function Layout({aside, main}) {
static get defaultProps() {
return {
mobileSideMenuShouldOpen: false,
@@ -270,4 +255,32 @@ export class Layout extends PureComponent {
);
}
-}
\ No newline at end of file
+}
+*/
+
+
+export function Layout({aside, main}) {
+ const mobileSideMenuShouldOpen = useShopStore((state) => state.sideMenuOpen);
+ const onClickToggleMobileSideMenu = useShopStore((state) => state.switchSideMenu);
+ const newCardJustAdded = useShopStore((state) => state.newCardJustAdded);
+ const isMobile = useShopStore((state) => state.isMobile);
+
+ return (
+
+
+
+
+ {mobileSideMenuShouldOpen ? (
+
+ ) : (
+
+ )}
+
+ {isMobile && newCardJustAdded ? (
+
+ ✓ added
+
+ ) : null}
+
+ );
+}
diff --git a/static/js/shop/OrderPanel.jsx b/static/js/shop/OrderPanel.jsx
index fff6f41..bb77050 100644
--- a/static/js/shop/OrderPanel.jsx
+++ b/static/js/shop/OrderPanel.jsx
@@ -1,71 +1,49 @@
-import React, {PureComponent} from 'react'
-import PropTypes from "prop-types";
+import React from 'react'
+import {OrderSummary} from "./OrderSummary";
+import {OrderForm} from "./OrderForm";
+import {CrateList} from "./CrateList";
+import {useShopStore} from "./shop_store";
/**
* Component that renders all things for order.
* It acts like-a layout, this component do nothing more.
*/
-export class OrderPanel extends PureComponent {
+export function OrderPanel({title, description}) {
+ const isMobile = useShopStore((state) => state.isMobile);
+ const onClickToggleMobileSideMenu = useShopStore((state) => state.switchSideMenu);
+ const onClickOpenImport = useShopStore((state) => state.openImport);
- static get propTypes() {
- return {
- title: PropTypes.string,
- description: PropTypes.element,
- cratesList: PropTypes.element,
- summaryPrice: PropTypes.element,
- form: PropTypes.element,
- isMobile: PropTypes.bool,
- onClickToggleMobileSideMenu: PropTypes.func,
- onClickOpenImport: PropTypes.func,
- };
- }
+ return (
- render() {
- const {
- title,
- description,
- cratesList,
- summaryPrice,
- form,
- isMobile,
- onClickToggleMobileSideMenu,
- onClickOpenImport,
- } = this.props;
+ {title}
- return (
-
+
+ {description}
+
- {title}
+
+ Import JSON
+
+
-
- {description}
-
+ {isMobile ? (
+
+
+
+
+
+ ) : null}
-
- Import JSON
-
-
+
- {isMobile ? (
-
-
-
-
-
- ) : null}
+
-
- {summaryPrice}
-
- {form}
-
-
-
- );
- }
+ );
}
\ No newline at end of file
diff --git a/static/js/shop/ProductCartItem.jsx b/static/js/shop/ProductCartItem.jsx
index 8be6500..0e5a928 100644
--- a/static/js/shop/ProductCartItem.jsx
+++ b/static/js/shop/ProductCartItem.jsx
@@ -1,186 +1,122 @@
-import React, {PureComponent} from 'react'
-import PropTypes from "prop-types";
+import React from 'react'
import {Draggable} from "@hello-pangea/dnd";
import {DialogPopup} from "./options/DialogPopup.jsx";
import {productStyle} from "./utils";
import {Resources} from "./Resources.jsx";
import {CardWarnings} from "./CardWarnings.jsx";
+import {useShopStore} from "./shop_store";
/**
* Component that renders a product.
* Used in the crate
*/
-export class ProductCartItem extends PureComponent {
+export function ProductCartItem({card_index, crate_index, ext_data, first, last, resources, warnings}) {
+ const {card, crate, highlighted, setHighlight, removeHighlight, onCardUpdate, onCardRemove} = useShopStore(state => ({
+ card: state.crates[crate_index].items[card_index],
+ highlighted: state.crates[crate_index].id === state.highlighted.crate && card_index === state.highlighted.card,
+ crate: state.crates[crate_index],
+ setHighlight: state.highlightCard,
+ removeHighlight: state.highlightReset,
+ onCardUpdate: state.updateOptions,
+ onCardRemove: state.deleteCard
+ }))
- static get propTypes() {
- return {
- isMobile: PropTypes.bool,
- isTouch: PropTypes.bool,
- hovered: PropTypes.bool,
- first: PropTypes.bool,
- last: PropTypes.bool,
- index: PropTypes.number.isRequired,
- model: PropTypes.object.isRequired,
- data: PropTypes.object,
- ext_data: PropTypes.object,
- resources: PropTypes.object,
- onToggleOverlayRemove: PropTypes.func,
- onClickRemoveItem: PropTypes.func,
- onClickItem: PropTypes.func,
- onCardUpdate: PropTypes.func,
- };
+ let options, options_data;
+ //const warnings = data && data.show_warnings;
+
+ if (data && data.options) {
+ options = data.options;
+ if (!data.options_data) crate.options_data = {};
+ options_data = crate.options_data;
+ options_data.ext_data = ext_data;
}
- static get defaultProps() {
- return {
- hovered: false,
- };
- }
+ return (
+
- constructor(props) {
- super(props);
- this.handleOnMouseEnterRemoveItem = this.handleOnMouseEnterRemoveItem.bind(this);
- this.handleOnMouseLeaveRemoveItem = this.handleOnMouseLeaveRemoveItem.bind(this);
- this.handleOnClickRemoveItem = this.handleOnClickRemoveItem.bind(this);
- this.handleOnClickItem = this.handleOnClickItem.bind(this);
- }
+ {(provided, snapshot) => (
+ setHighlight(crate.id, card_index)}
+ onMouseLeave={removeHighlight}
+ >
- handleOnMouseEnterRemoveItem(index, e) {
- if (this.props.onToggleOverlayRemove && !this.props.isMobile) {
- this.props.onToggleOverlayRemove(index, true);
- }
- e.preventDefault();
- }
+ {/* warning container */}
- handleOnMouseLeaveRemoveItem(index, e) {
- if (this.props.onToggleOverlayRemove && !this.props.isMobile) {
- this.props.onToggleOverlayRemove(index, false);
- }
- e.preventDefault();
- }
+
+ {warnings && warnings.length > 0 &&
+ ()
+ }
- handleOnClickItem(index, e) {
- if (this.props.onClickItem && this.props.isTouch) {
- this.props.onClickItem(index);
- }
- e.preventDefault();
- }
+ {options && (
+ {
+ // console.log("construct", outvar, value, options_data);
+ options_data[outvar] = value;
+ }),
+ update: ((outvar, value) => {
+ // console.log("update", outvar, value, options_data);
+ if (outvar in options_data) options_data[outvar] = value;
+ onCardUpdate(crate.id, card_index, {[outvar]: value});
+ })
+ }}
+ />
+ )}
+
- handleOnClickRemoveItem(index, e) {
- if (this.props.onClickRemoveItem) {
- this.props.onClickRemoveItem(index);
- }
- }
+
{card.name_number}
- render() {
- const {
- hovered,
- model,
- data,
- index,
- first,
- last,
- ext_data,
- onCardUpdate,
- } = this.props;
-
- let options, options_data;
- const warnings = data && data.show_warnings;
- const resources = data && data.counted_resources;
-
- if (data && data.options) {
- options = data.options;
- if (!data.options_data) data.options_data = {};
- options_data = data.options_data;
- options_data.ext_data = ext_data;
- }
-
-
- return (
-
-
- {(provided, snapshot) => (
setHighlight(crate.id, card_index)}
+ onClick={() => setHighlight(crate.id, card_index)}
>
- {/* warning container */}
-
-
- {warnings && warnings.length > 0 &&
- ( )
- }
-
- {options && (
- {
- // console.log("construct", outvar, value, options_data);
- options_data[outvar] = value;
- }),
- update: ((outvar, value) => {
- // console.log("update", outvar, value, options_data);
- if (outvar in options_data) options_data[outvar] = value;
- onCardUpdate();
- })
- }}
- />
- )}
-
-
-
{model.name_number}
-
-
-
-
-
-
- {/* remove container */}
-
-
-
-
-
Remove
-
-
- {/* progression container */}
- {resources && (
-
- )}
-
-
+
- )}
-
- );
- }
+ {/* remove container */}
+
onCardRemove(crate.id, card_index)}>
+
+
+
+
Remove
+
+
+ {/* progression container */}
+ {resources && (
+
+ )}
+
+
+
+ )}
+
+
+ );
}
diff --git a/static/js/shop/Shop.jsx b/static/js/shop/Shop.jsx
index c6ca37f..ef8d1e1 100644
--- a/static/js/shop/Shop.jsx
+++ b/static/js/shop/Shop.jsx
@@ -19,7 +19,7 @@ import {CrateList} from "./CrateList.jsx";
* Component that render the entire shop
*/
-export class Shop extends PureComponent {
+export function Shop() {
static get propTypes() {
return {
@@ -37,7 +37,7 @@ export class Shop extends PureComponent {
this.handleMouseEnterItem = this.handleMouseEnterItem.bind(this);
this.handleMouseLeaveItem = this.handleMouseLeaveItem.bind(this);
this.handleClickAddItem = this.handleClickAddItem.bind(this);
- this.checkAlerts = this.checkAlerts.bind(this);
+ this.checkAlertsInNewState = this.checkAlertsInNewState.bind(this);
this.handleClickSelectItem = this.handleClickSelectItem.bind(this);
this.handleClickSubmit = this.handleClickSubmit.bind(this);
this.handleToggleOverlayRemove = this.handleToggleOverlayRemove.bind(this);
@@ -47,11 +47,11 @@ export class Shop extends PureComponent {
this.handleClickShowOrder = this.handleClickShowOrder.bind(this);
this.handleClickOpenImport = this.handleClickOpenImport.bind(this);
this.handleLoadCustomConf = this.handleLoadCustomConf.bind(this);
- this.handleCardsUpdated = this.handleCardsUpdated.bind(this);
this.onAddCrate = this.onAddCrate.bind(this);
this.onDeleteCrate = this.onDeleteCrate.bind(this);
this.onCrateModeChange = this.onCrateModeChange.bind(this);
this.onCrateSelected = this.onCrateSelected.bind(this);
+ this.onCrateChanged = this.onCrateChanged.bind(this);
this.timer = null;
this.timer_remove = null;
@@ -111,14 +111,10 @@ export class Shop extends PureComponent {
onCrateChanged(crate_id) {
// kinda silly that hover over cards triggers checkAlerts
- this.checkAlerts(crate_id)
+ this.checkAlertsInNewState(crate_id, this.state);
}
- handleCardsUpdated() {
- this.checkAlerts(this.state.columns.cart.items);
- }
-
handleCrateModeChange(mode) {
this.setState({
currentMode: mode,
@@ -398,7 +394,22 @@ export class Shop extends PureComponent {
switch (source.droppableId) {
// TODO add delete functionality
case destination.droppableId:
- this.setState({
+ /*this.setState({
+ ...this.state,
+ columns: {
+ ...this.state.columns,
+ crates: {
+ ...this.state.columns.crates,
+ [destination.droppableId]: {
+ ...this.state.columns.crates[destination.droppableId],
+ items: reorder(
+ this.state.columns.crates[source.droppableId].items,
+ source.index,
+ destination.index
+ )}}
+ }
+ });*/
+ this.checkAlertsInNewState(destination.droppableId, {
...this.state,
columns: {
...this.state.columns,
@@ -413,10 +424,9 @@ export class Shop extends PureComponent {
)}}
}
});
- this.onCrateChanged(destination.droppableId);
break;
case 'backlog':
- this.setState({
+ /*this.setState({
...this.state,
columns: {
...this.state.columns,
@@ -431,8 +441,23 @@ export class Shop extends PureComponent {
destination
)}}
}
+ });*/
+ this.checkAlertsInNewState(destination.droppableId, {
+ ...this.state,
+ columns: {
+ ...this.state.columns,
+ crates: {
+ ...this.state.columns.crates,
+ [destination.droppableId]: {
+ ...this.state.columns.crates[destination.droppableId],
+ items: copyFromBacklog(
+ this.state.items,
+ this.state.columns.crates[destination.droppableId],
+ source,
+ destination
+ )}}
+ }
});
- this.onCrateChanged(destination.droppableId);
break;
default:
this.setState({
@@ -460,17 +485,16 @@ export class Shop extends PureComponent {
});
}
- checkAlerts(crate_id) {
+ checkAlertsInNewState(crate_id, new_state) {
console.log('--- START CHECKING CRATE WARNING ---');
- let itemsCloned = Array.from(this.state.columns.crates[crate_id].items);
+ let itemsCloned = Array.from(new_state.columns.crates[crate_id].items);
- const crate_warnings = TriggerCrateWarnings(this.state.columns.crates[crate_id]);
+ const crate_warnings = TriggerCrateWarnings(new_state.columns.crates[crate_id]);
- itemsCloned.forEach((elem, idx) => {
- if (!(idx in itemsCloned)) itemsCloned[idx] = elem;
- if (idx in this.state.columns.cart.itemsData && this.state.columns.cart.itemsData[idx].options_data) {
- itemsCloned[idx].options_data = this.state.columns.cart.itemsData[idx].options_data;
+ itemsCloned.forEach((elem, _idx) => {
+ if (!elem.options_data && !!elem.options) {
+ elem.options_data = {}
}
});
@@ -481,11 +505,11 @@ export class Shop extends PureComponent {
this.setState({
...this.state,
columns: {
- ...this.state.columns,
+ ...new_state.columns,
crates: {
- ...this.state.columns.crates,
+ ...new_state.columns.crates,
[crate_id]: {
- ...this.state.columns.crates[crate_id],
+ ...new_state.columns.crates[crate_id],
items: itemsCloned,
warnings: crate_warnings
},
@@ -545,98 +569,21 @@ export class Shop extends PureComponent {
this.setState(new_state);
}
- render() {
- const {
- currency,
- currentItemHovered,
- currentMode,
- crateModeSlots,
- crateModeItems,
- items,
- columns,
- rules,
- mobileSideMenuShouldOpen,
- newCardJustAdded,
- isProcessing,
- shouldShowRFQFeedback,
- RFQBodyType,
- RFQBodyOrder,
- isProcessingComplete,
- } = this.state;
+ return (
+
+
+ }
+ main={(
+ Drag and drop the cards you want into the crate below to see how the combination would look like. Setup card's configuration by tapping at the top of the card, most of the options can be modified after shipment. If you have any issues with this ordering system, or if you need other configurations, email us directly anytime at sales@m-labs.hk . The price is estimated and must be confirmed by a quote.)}
+ />
+ )}>
+
+
+ );
- const isMobile = window.deviceIsMobile();
- const isTouch = window.isTouchEnabled();
-
- return (
-
-
-
-
- }
- main={(
- Drag and drop the cards you want into the crate below to see how the combination would look like. Setup card's configuration by tapping at the top of the card, most of the options can be modified after shipment. If you have any issues with this ordering system, or if you need other configurations, email us directly anytime at sales@m-labs.hk . The price is estimated and must be confirmed by a quote.)}
- cratesList={
-
- }
- summaryPrice={
-
-
- }
- form={
-
-
- }>
-
- )}>
-
-
-
- );
- }
}
\ No newline at end of file
diff --git a/static/js/shop/count_resources.js b/static/js/shop/count_resources.js
index 419d28a..d9fd374 100644
--- a/static/js/shop/count_resources.js
+++ b/static/js/shop/count_resources.js
@@ -53,7 +53,7 @@ export const resource_counters = {
"hp": CounterFactory("hp"),
}
-function CountResources(data, index) {
+export function CountResources(data, index) {
if (!data[index].resources) return null;
let result = [];
data[index].resources.forEach((item, _) => {
diff --git a/static/js/shop/shop_store.js b/static/js/shop/shop_store.js
new file mode 100644
index 0000000..124ff57
--- /dev/null
+++ b/static/js/shop/shop_store.js
@@ -0,0 +1,192 @@
+'use strict';
+
+import {create} from "zustand";
+import {data, itemsUnfoldedList} from "./utils";
+import {true_type_of} from "./options/utils";
+import {v4 as uuidv4} from "uuid";
+import {FillResources} from "./count_resources";
+import {TriggerCrateWarnings, TriggerWarnings} from "./warnings";
+
+
+const useBacklog = ((set, get) => ({
+ cards: data.items,
+ groups: data.columns.backlog,
+ cards_list: itemsUnfoldedList,
+ currency: data.currency
+}));
+
+const useCrateModes = ((set, get) => ({
+ crate_modes: data.crateModes,
+ modes_order: data.crateModeOrder
+}));
+
+const useLayout = ((set, get) => ({
+ isTouch: window.isTouchEnabled(),
+ isMobile: window.deviceIsMobile(),
+ sideMenuIsOpen: false,
+ newCardJustAdded: false,
+ importIsOpen: false,
+
+ switchSideMenu: () => set(state => ({
+ sideMenuIsOpen: !state.sideMenuIsOpen
+ })),
+ openImport: () => set(state => ({
+ importIsOpen: true
+ })),
+ closeImport: () => set(state => ({
+ importIsOpen: false
+ })),
+}))
+
+
+const useSubmitForm = ((set, get) => ({
+ // TODO think about it
+ isProcessing: false,
+ shouldShowRFQFeedback: true,
+ RFQBodyType: 'email',
+ isProcessingComplete: true,
+}));
+
+const useCart = ((set, get) => ({
+ crates: data.columns.crates,
+ active_crate: "crate0",
+ highlighted: {
+ crate: "",
+ card: 0
+ },
+
+
+ newCrate: () => set((state) => ({crates: state.crates.concat({
+ id: "crate"+state.crates.length,
+ crate_mode: "rack",
+ items: [],
+ warnings: []
+ })})),
+ delCrate: (id) => set(state => ({
+ crates: state.crates.filter((crate => crate.id !== id))
+ })),
+ setCrateMode: (id, mode) => set(state => ({
+ crates: state.crates.map((crate, _i) => {
+ if (crate.id === id) {
+ return {
+ ...crate,
+ crate_mode: mode
+ }
+ } else return crate;
+ })
+ })),
+ setActiveCrate: (id) => set(state => ({active_crate: id})),
+ addCardFromBacklog: (crate_to, index_from, index_to) => set(state => {
+ const take_from = (true_type_of(index_from) === "array" ? index_from : [index_from]).map((item, _i) => (state.cards_list[item]));
+ const dest = crate_to || state.active_crate;
+ return {
+ crates: state.crates.map((crate, _i) => {
+ if (dest === crate.id) {
+ return {
+ ...crate,
+ items: crate.items.toSpliced(index_to, 0, ...take_from.map((card_name, _) => {
+ return {...state.cards[card_name], id: uuidv4()}
+ }))
+ }
+ } else return crate;
+ })
+ }
+ }),
+ moveCard: (crate_from, index_from, crate_to, index_to) => set(state => {
+ const the_card = state.crates.find((crate, _) => crate_from === crate.id )[index_from];
+ const del_card = crate_from === crate_to ? 1 : 0;
+ return {
+ crates: state.crates.map((crate, _i) => {
+ if (crate_to === crate.id) {
+ return {
+ ...crate,
+ items: crate.items.toSpliced(index_to, del_card, the_card)
+ }
+ } else if (crate_from === crate.id) {
+ return {
+ ...crate,
+ items: crate.items.toSpliced(index_to, 1)
+ }
+ }
+ else return crate;
+ })
+ }
+ }),
+ deleteCard: (crate, index) => set(state => ({
+ crates: state.crates.map((crate, _i) => {
+ if (crate === crate.id) {
+ return {
+ ...crate,
+ items: crate.items.splice(index, 1)
+ }
+ }
+ else return crate;
+ })
+ })),
+ clearCrate: (id) => set(state => ({
+ crates: state.crates.map((crate, _i) => {
+ if (id === crate.id) {
+ return {
+ ...crate,
+ items: []
+ }
+ }
+ else return crate;
+ })
+ })),
+ updateOptions: (crate, index, new_options) => set(state => ({
+ crates: state.crates.map((crate, _i) => {
+ if (crate === crate.id) {
+ let itemsCopy = Array.from(crate.items);
+ itemsCopy[index].options_data = {...itemsCopy[index].options_data, ...new_options};
+ return {
+ ...crate,
+ items: itemsCopy
+ }
+ }
+ else return crate;
+ })
+ })),
+ highlightCard: (crate, index) => set(state => ({
+ highlighted: {
+ crate: crate,
+ card: index
+ }
+ })),
+ highlightReset: () => set(state => ({
+ highlighted: {
+ crate: "",
+ card: 0
+ }
+ })),
+
+ fillWarnings: (crate) => set(state => ({
+ // actually seems to be just render-time action, no need to put data in it,
+ // though needs to be optimized to be done only on real crate updates
+ crates: state.crates.map((crate, _i) => {
+ if (crate === crate.id) {
+ let itemsCopy = Array.from(crate.items);
+ itemsCopy = FillResources(itemsCopy);
+ itemsCopy = TriggerWarnings(itemsCopy);
+ const crate_warnings = TriggerCrateWarnings(crate);
+ return {
+ ...crate,
+ items: itemsCopy,
+ warnings: crate_warnings
+ }
+ }
+ else return crate;
+ })
+ }))
+
+ // TODO load and save jsons?
+}))
+
+
+export const useShopStore = create((...params) => ({
+ ...useBacklog(...params),
+ ...useCrateModes(...params),
+ ...useCart(...params),
+ ...useSubmitForm(...params),
+ ...useLayout(...params)
+}))
\ No newline at end of file
diff --git a/static/js/shop/warnings.js b/static/js/shop/warnings.js
index 0f21c82..beaca90 100644
--- a/static/js/shop/warnings.js
+++ b/static/js/shop/warnings.js
@@ -98,6 +98,20 @@ const Types = {
}
+export function TriggerCardWarnings(data, index, precounted) {
+ const element = data[index];
+ return element.warnings
+ .map((warning, _) => {
+ if (!!Types[warning])
+ return Types[warning].trigger(data, index, precounted) ? {trigger: undefined, name: warning, ...Types[warning]} : null;
+ else
+ return Types.default;
+ })
+ .filter((warning, _) => {
+ return !!warning
+ });
+}
+
export function TriggerWarnings(data) {
return data.map((element, index) => {
if (!element.warnings) return element;
diff --git a/static/js/shop_data.js b/static/js/shop_data.js
index 1be11d0..ca685f9 100644
--- a/static/js/shop_data.js
+++ b/static/js/shop_data.js
@@ -1185,13 +1185,12 @@ const shop_data = {
],
},
- "crates": {
- "crate0": {
- crate_type: "rack",
+ "crates": [{
+ id: "crate0",
+ crate_mode: "rack",
items: [],
warnings: []
- }
- }
+ }]
},
--
2.42.0
From ec2c0a3b80748ad6d5bf80810ee4761d69994acd Mon Sep 17 00:00:00 2001
From: Egor Savkin
Date: Mon, 11 Dec 2023 17:47:16 +0800
Subject: [PATCH 12/42] Somewhat minimal working example
Signed-off-by: Egor Savkin
---
static/js/shop/Cart.jsx | 2 +
static/js/shop/OrderPanel.jsx | 8 +-
static/js/shop/ProductCartItem.jsx | 8 +-
static/js/shop/Shop.jsx | 590 ++---------------------------
static/js/shop/shop_store.js | 15 +-
static/js/shop/warnings.js | 4 +-
6 files changed, 54 insertions(+), 573 deletions(-)
diff --git a/static/js/shop/Cart.jsx b/static/js/shop/Cart.jsx
index 2b180aa..965b9ce 100644
--- a/static/js/shop/Cart.jsx
+++ b/static/js/shop/Cart.jsx
@@ -17,6 +17,8 @@ export function Cart({crate_index}) {
crate: state.crates[crate_index]
}));
+ console.log(resource_counters, crate)
+
const nbrOccupied = hp_to_slots(resource_counters.hp(crate.items, -1));
const nbrSlots = hp_to_slots(crate_type_to_hp(crate.crate_mode));
console.log(nbrOccupied, nbrSlots);
diff --git a/static/js/shop/OrderPanel.jsx b/static/js/shop/OrderPanel.jsx
index bb77050..ada7a91 100644
--- a/static/js/shop/OrderPanel.jsx
+++ b/static/js/shop/OrderPanel.jsx
@@ -1,7 +1,7 @@
import React from 'react'
-import {OrderSummary} from "./OrderSummary";
-import {OrderForm} from "./OrderForm";
-import {CrateList} from "./CrateList";
+import {OrderSummary} from "./OrderSummary.jsx";
+import {OrderForm} from "./OrderForm.jsx";
+import {CrateList} from "./CrateList.jsx";
import {useShopStore} from "./shop_store";
/**
@@ -40,7 +40,7 @@ export function OrderPanel({title, description}) {
diff --git a/static/js/shop/ProductCartItem.jsx b/static/js/shop/ProductCartItem.jsx
index 0e5a928..429e9ca 100644
--- a/static/js/shop/ProductCartItem.jsx
+++ b/static/js/shop/ProductCartItem.jsx
@@ -24,10 +24,10 @@ export function ProductCartItem({card_index, crate_index, ext_data, first, last,
let options, options_data;
//const warnings = data && data.show_warnings;
- if (data && data.options) {
- options = data.options;
- if (!data.options_data) crate.options_data = {};
- options_data = crate.options_data;
+ if (card && card.options) {
+ options = card.options;
+ if (!card.options_data) card.options_data = {};
+ options_data = card.options_data;
options_data.ext_data = ext_data;
}
diff --git a/static/js/shop/Shop.jsx b/static/js/shop/Shop.jsx
index ef8d1e1..d3c12f4 100644
--- a/static/js/shop/Shop.jsx
+++ b/static/js/shop/Shop.jsx
@@ -1,577 +1,49 @@
-import React, {PureComponent} from 'react';
-import PropTypes from "prop-types";
-import {FilterOptions} from "./options/utils";
-import {v4 as uuidv4} from "uuid";
+import React from 'react';
import {DragDropContext} from "@hello-pangea/dnd";
-import {copyFromBacklog, itemsUnfoldedList, nbrOccupiedSlotsInCrate, remove, reorder} from "./utils";
import {Layout} from "./Layout.jsx";
import {Backlog} from "./Backlog.jsx";
import {OrderPanel} from "./OrderPanel.jsx";
-import {OrderSummary} from "./OrderSummary.jsx";
-import {OrderForm} from "./OrderForm.jsx";
-import {TriggerCrateWarnings, TriggerWarnings} from "./warnings";
-import {FillResources} from "./count_resources";
-import {CrateList} from "./CrateList.jsx";
+import {useShopStore} from "./shop_store";
/**
* Component that render the entire shop
*/
export function Shop() {
-
- static get propTypes() {
- return {
- data: PropTypes.object.isRequired,
- };
+ const {addCardFromBacklog, moveCard, deleteCard} = useShopStore(state => ({
+ addCardFromBacklog: state.addCardFromBacklog,
+ moveCard: state.moveCard,
+ deleteCard: state.deleteCard
+ }));
+ const handleOnDragEnd = (drop_result, provided) => {
+ console.log(drop_result, provided)
+ //{
+ // "draggableId": "42dc17e9-9e75-45ee-ad27-2233b6f07a5e",
+ // "type": "DEFAULT",
+ // "source": {
+ // "index": 17,
+ // "droppableId": "backlog"
+ // },
+ // "reason": "DROP",
+ // "mode": "FLUID",
+ // "destination": {
+ // "droppableId": "crate0",
+ // "index": 0
+ // },
+ // "combine": null
+ // }
+ if (drop_result.source.droppableId === "backlog")
+ addCardFromBacklog(drop_result.destination.droppableId, drop_result.source.index, drop_result.destination.index);
+ else if(drop_result.destination.droppableId === "backlog")
+ deleteCard(drop_result.destination.droppableId, drop_result.destination.index);
+ else
+ moveCard(drop_result.source.droppableId, drop_result.source.index, drop_result.destination.droppableId, drop_result.destination.index)
}
- constructor(props) {
- super(props);
- this.state = this.props.data;
- this.handleCrateModeChange = this.handleCrateModeChange.bind(this);
- this.handleOnDragEnd = this.handleOnDragEnd.bind(this);
- this.handleDeleteItem = this.handleDeleteItem.bind(this);
- this.handleDeleteAllItems = this.handleDeleteAllItems.bind(this);
- this.handleMouseEnterItem = this.handleMouseEnterItem.bind(this);
- this.handleMouseLeaveItem = this.handleMouseLeaveItem.bind(this);
- this.handleClickAddItem = this.handleClickAddItem.bind(this);
- this.checkAlertsInNewState = this.checkAlertsInNewState.bind(this);
- this.handleClickSelectItem = this.handleClickSelectItem.bind(this);
- this.handleClickSubmit = this.handleClickSubmit.bind(this);
- this.handleToggleOverlayRemove = this.handleToggleOverlayRemove.bind(this);
- this.handleShowOverlayRemove = this.handleShowOverlayRemove.bind(this);
- this.handleClickToggleMobileSideMenu = this.handleClickToggleMobileSideMenu.bind(this);
- this.handleClickCloseRFQFeedback = this.handleClickCloseRFQFeedback.bind(this);
- this.handleClickShowOrder = this.handleClickShowOrder.bind(this);
- this.handleClickOpenImport = this.handleClickOpenImport.bind(this);
- this.handleLoadCustomConf = this.handleLoadCustomConf.bind(this);
- this.onAddCrate = this.onAddCrate.bind(this);
- this.onDeleteCrate = this.onDeleteCrate.bind(this);
- this.onCrateModeChange = this.onCrateModeChange.bind(this);
- this.onCrateSelected = this.onCrateSelected.bind(this);
- this.onCrateChanged = this.onCrateChanged.bind(this);
-
- this.timer = null;
- this.timer_remove = null;
- }
-
- componentDidMount() {
- const source = {
- droppableId: 'backlog',
- indexes: [
- itemsUnfoldedList.findIndex(element => element === "eem_pwr_mod"),
- itemsUnfoldedList.findIndex(element => element === "kasli")
- ],
- };
- const destination = {
- droppableId: 'crate0',
- index: 0,
- };
-
- this.handleOnDragEnd({
- source,
- destination
- });
- }
-
- componentDidUpdate(prevProps, prevState) {
- /**
- * We check alerts (reminder + warning) only when items inside crate or
- * crate mode change.
- *
- * In the function checkAlerts, we DO NOT want to change items as we will
- * trigger again this function (componentDidUpdate) and thus,
- * making an infinite loop.
- */
- console.log("componentDidUpdate")
- return;
- if (
- (prevState.columns.crates !== this.state.columns.crates.items) ||
- (prevState.currentMode !== this.state.currentMode)
- ) {
- this.checkAlerts(this.state.columns.cart.items);
- }
-
-
- if (this.state.newCardJustAdded) {
- this.timer = setTimeout(() => {
- this.setState({
- newCardJustAdded: false,
- });
- }, 2000);
- }
- }
-
- componentWillUnmount() {
- clearTimeout(this.timer);
- }
-
- onCrateChanged(crate_id) {
- // kinda silly that hover over cards triggers checkAlerts
-
- this.checkAlertsInNewState(crate_id, this.state);
-
- }
-
- handleCrateModeChange(mode) {
- this.setState({
- currentMode: mode,
- });
- }
-
- handleDeleteItem(index) {
- let cloned = Array.from(this.state.columns.cart.items);
- let cloned_data = Array.from(this.state.columns.cart.itemsData);
- cloned.splice(index, 1);
- cloned_data.splice(index, 1);
-
- this.setState({
- ...this.state,
- columns: {
- ...this.state.columns,
- cart: {
- ...this.state.columns.cart,
- items: cloned,
- itemsData: cloned_data,
- },
- },
- });
- }
-
- handleDeleteAllItems() {
- this.setState({
- ...this.state,
- columns: {
- ...this.state.columns,
- cart: {
- ...this.state.columns.cart,
- items: [],
- itemsData: []
- },
- },
- });
- }
-
- handleMouseEnterItem(id) {
- this.setState({
- ...this.state,
- currentItemHovered: id,
- });
- }
-
- handleMouseLeaveItem() {
- this.setState({
- ...this.state,
- currentItemHovered: null,
- });
- }
-
- handleClickAddItem(index, tap) {
- const source = {
- droppableId: 'backlog',
- index: index,
- };
- const destination = {
- droppableId: 'cart',
- index: this.state.columns.cart.items.length,
- };
-
- this.handleOnDragEnd({
- source,
- destination
- }, tap);
- }
-
- handleClickSelectItem(index) {
- const itemsCloned = Array.from(this.state.columns.cart.items);
-
- this.setState({
- ...this.state,
- columns: {
- ...this.state.columns,
- cart: {
- ...this.state.columns.cart,
- items: itemsCloned.map((item, id) => {
- return {...item, selected: id === index ? true : false};
- }),
- }
- },
- });
- }
-
- handleToggleOverlayRemove(index, show) {
- const itemsCloned = Array.from(this.state.columns.cart.items);
-
- this.setState({
- ...this.state,
- columns: {
- ...this.state.columns,
- cart: {
- ...this.state.columns.cart,
- items: itemsCloned.map((item, id) => {
- return {
- ...item,
- showOverlayRemove: id === index ? show : false
- };
- }),
- }
- },
- });
- }
-
- handleShowOverlayRemove(index) {
- if (this.timer_remove)
- clearTimeout(this.timer_remove);
-
- this.handleToggleOverlayRemove(index, true);
-
- this.timer_remove = setTimeout(() => {
- this.handleToggleOverlayRemove(index, false);
- }, 2000);
- }
-
- handleClickShowOrder() {
- const crate = {
- items: [],
- type: this.state.currentMode,
- };
- const clonedCart = Array.from(this.state.columns.cart.items);
- const clonedCartData = Array.from(this.state.columns.cart.itemsData);
- for (const i in clonedCart) {
- const item = clonedCart[i];
- const item_data = clonedCartData[i];
- crate.items.push({
- 'pn': item.name_number,
- 'options': (item_data.options_data && item_data.options) ? FilterOptions(item_data.options, item_data.options_data) : null,
- });
- }
-
- this.setState({
- isProcessing: false,
- shouldShowRFQFeedback: true,
- RFQBodyType: 'show',
- RFQBodyOrder: JSON.stringify(crate, null, 2),
- });
- }
-
- handleClickOpenImport() {
- this.setState({
- isProcessing: false,
- shouldShowRFQFeedback: true,
- RFQBodyType: 'import',
- });
- }
-
- handleLoadCustomConf(customconf) {
- if (!customconf) {return; }
-
- const items = this.props.data.items;
-
- let new_items = [];
- let new_items_data = [];
-
-
- this.setState({
- ...this.state,
- columns: {
- ...this.state.columns,
- cart: {
- ...this.state.columns.cart,
- items: [],
- },
- },
- }, function () {
-
- customconf.items.map(function (item) {
- Object.keys(items).map(key => {
- if (item.pn && item.pn === items[key].name_number) {
- new_items.push(Object.assign({
- ...items[key],
- }, {
- id: uuidv4(),
- options_data: item.options ? item.options : null,
- }));
- new_items_data.push({options_data: item.options ? item.options : null});
- }
- });
-
- return item;
- });
-
- this.setState({
- ...this.state,
- columns: {
- ...this.state.columns,
- cart: {
- ...this.state.columns.cart,
- items: new_items,
- itemsData: new_items_data,
- },
- },
- currentMode: customconf.type,
- });
- });
- }
-
- handleClickSubmit(note, email) {
- const crate = {
- items: [],
- type: this.state.currentMode,
- };
- const clonedCart = Array.from(this.state.columns.cart.items);
- const clonedCartData = Array.from(this.state.columns.cart.itemsData);
- for (const i in clonedCart) {
- const item = clonedCart[i];
- const item_data = clonedCartData[i];
- crate.items.push({
- 'pn': item.name_number,
- 'options': (item_data.options_data && item_data.options) ? FilterOptions(item_data.options, item_data.options_data) : null,
- });
- }
-
- const {data} = this.props;
-
- this.setState({isProcessing: true});
-
- fetch(data.API_RFQ, {
- method: "POST",
- headers: {'Content-Type': 'application/json'},
- body: JSON.stringify({
- email,
- note,
- configuration: JSON.stringify(crate)
- })
- }).then(response => {
- if (response.status !== 200) {
- throw Error("Response status is not OK: " + response.status + ".\n" + response);
- }
- this.setState({
- isProcessing: false,
- shouldShowRFQFeedback: true,
- RFQBodyType: 'email',
- isProcessingComplete: true,
- });
- }).catch(err => {
- console.error("Request failed, reason:", err)
- this.setState({isProcessing: false}, () => {
- alert("We cannot receive your request. Try using the export by coping the configuration and send it to us at sales@m-labs.hk");
- });
- })
- }
-
- handleOnDragEnd(result) {
- /**
- * 4 cases:
- * - from backlog to one of the crate - add to the correct crate in correct order
- * - from one crate to another - delete from one crate and put to another in correct order
- * - within one crate - reorder
- * - from crate to backlog - delete
- * */
-
- const {
- source,
- destination,
- } = result;
- /* better move to another function
- let dragged_items = [];
- if (source.indexes) {
- source.indexes.forEach((card_index, _) => {
- dragged_items.push(itemsUnfoldedList[card_index]);
- })
- } else if (source.index >= 0) {
- dragged_items.push(itemsUnfoldedList[source.index]);
- }*/
-
- console.log('==> result', result);
-
- // dropped outside the list
- if (!destination) {
- return;
- }
-
- switch (source.droppableId) {
- // TODO add delete functionality
- case destination.droppableId:
- /*this.setState({
- ...this.state,
- columns: {
- ...this.state.columns,
- crates: {
- ...this.state.columns.crates,
- [destination.droppableId]: {
- ...this.state.columns.crates[destination.droppableId],
- items: reorder(
- this.state.columns.crates[source.droppableId].items,
- source.index,
- destination.index
- )}}
- }
- });*/
- this.checkAlertsInNewState(destination.droppableId, {
- ...this.state,
- columns: {
- ...this.state.columns,
- crates: {
- ...this.state.columns.crates,
- [destination.droppableId]: {
- ...this.state.columns.crates[destination.droppableId],
- items: reorder(
- this.state.columns.crates[source.droppableId].items,
- source.index,
- destination.index
- )}}
- }
- });
- break;
- case 'backlog':
- /*this.setState({
- ...this.state,
- columns: {
- ...this.state.columns,
- crates: {
- ...this.state.columns.crates,
- [destination.droppableId]: {
- ...this.state.columns.crates[destination.droppableId],
- items: copyFromBacklog(
- this.state.items,
- this.state.columns.crates[destination.droppableId],
- source,
- destination
- )}}
- }
- });*/
- this.checkAlertsInNewState(destination.droppableId, {
- ...this.state,
- columns: {
- ...this.state.columns,
- crates: {
- ...this.state.columns.crates,
- [destination.droppableId]: {
- ...this.state.columns.crates[destination.droppableId],
- items: copyFromBacklog(
- this.state.items,
- this.state.columns.crates[destination.droppableId],
- source,
- destination
- )}}
- }
- });
- break;
- default:
- this.setState({
- columns: move(
- this.state.columns[source.droppableId],
- this.state.columns[destination.droppableId],
- source,
- destination
- )
- });
- break;
- }
- }
-
- handleClickToggleMobileSideMenu() {
- this.setState({
- ...this.state,
- mobileSideMenuShouldOpen: !this.state.mobileSideMenuShouldOpen,
- });
- }
-
- handleClickCloseRFQFeedback() {
- this.setState({
- shouldShowRFQFeedback: false,
- });
- }
-
- checkAlertsInNewState(crate_id, new_state) {
- console.log('--- START CHECKING CRATE WARNING ---');
-
- let itemsCloned = Array.from(new_state.columns.crates[crate_id].items);
-
- const crate_warnings = TriggerCrateWarnings(new_state.columns.crates[crate_id]);
-
- itemsCloned.forEach((elem, _idx) => {
- if (!elem.options_data && !!elem.options) {
- elem.options_data = {}
- }
- });
-
- itemsCloned = FillResources(itemsCloned);
- itemsCloned = TriggerWarnings(itemsCloned);
-
- // update state with rules
- this.setState({
- ...this.state,
- columns: {
- ...new_state.columns,
- crates: {
- ...new_state.columns.crates,
- [crate_id]: {
- ...new_state.columns.crates[crate_id],
- items: itemsCloned,
- warnings: crate_warnings
- },
- }
- }
- });
- }
-
- onAddCrate(id) {
- this.setState({
- ...this.state,
- columns: {
- ...this.state.columns,
- crates: {
- ...this.state.columns.crates,
- [id]: {
- crate_type: "rack",
- items: []
- }}
- }
- });
- }
- onDeleteCrate(id) {
- let new_state = {
- ...this.state,
- columns: {
- ...this.state.columns,
- crates: {
- ...this.state.columns.crates,
- [id]: undefined
- }
- }};
- delete new_state.columns.crates[id];
- this.setState(new_state);
- }
-
- onCrateSelected(id) {
- console.log(id)
- this.setState({
- active_crate: id
- })
- }
-
- onCrateModeChange(crate_id, new_mode) {
- let new_state = {
- ...this.state,
- columns: {
- ...this.state.columns,
- crates: {
- ...this.state.columns.crates,
- [crate_id]: {
- ...this.state.columns.crates[crate_id],
- crate_type: new_mode
- }
- }
- }};
- this.setState(new_state);
- }
-
-
return (
-
+
diff --git a/static/js/shop/shop_store.js b/static/js/shop/shop_store.js
index 124ff57..96061d5 100644
--- a/static/js/shop/shop_store.js
+++ b/static/js/shop/shop_store.js
@@ -93,14 +93,21 @@ const useCart = ((set, get) => ({
}
}),
moveCard: (crate_from, index_from, crate_to, index_to) => set(state => {
- const the_card = state.crates.find((crate, _) => crate_from === crate.id )[index_from];
- const del_card = crate_from === crate_to ? 1 : 0;
+ const the_card = state.crates.find((crate, _) => crate_from === crate.id ).items[index_from];
return {
crates: state.crates.map((crate, _i) => {
- if (crate_to === crate.id) {
+ if (crate_to === crate_from && crate_to === crate.id) {
+ //const the_card = {...crate[index_from]};
+ let items_copy = Array.from(crate.items);
+ delete items_copy[index_from];
return {
...crate,
- items: crate.items.toSpliced(index_to, del_card, the_card)
+ items: items_copy.toSpliced(index_to, 0, the_card).filter((item, _) => !!item)
+ }
+ } else if (crate_to === crate.id) {
+ return {
+ ...crate,
+ items: crate.items.toSpliced(index_to, 0, the_card)
}
} else if (crate_from === crate.id) {
return {
diff --git a/static/js/shop/warnings.js b/static/js/shop/warnings.js
index beaca90..fc325ce 100644
--- a/static/js/shop/warnings.js
+++ b/static/js/shop/warnings.js
@@ -100,7 +100,7 @@ const Types = {
export function TriggerCardWarnings(data, index, precounted) {
const element = data[index];
- return element.warnings
+ return (element.warnings && element.warnings
.map((warning, _) => {
if (!!Types[warning])
return Types[warning].trigger(data, index, precounted) ? {trigger: undefined, name: warning, ...Types[warning]} : null;
@@ -109,7 +109,7 @@ export function TriggerCardWarnings(data, index, precounted) {
})
.filter((warning, _) => {
return !!warning
- });
+ }));
}
export function TriggerWarnings(data) {
--
2.42.0
From 6b92bf91456910a877d1a97a641b93ecccf2d322 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=81=AB=E7=84=9A=20=E5=AF=8C=E8=89=AF?=
Date: Tue, 12 Dec 2023 16:09:29 +0800
Subject: [PATCH 13/42] Make cards behavior working somewhat properly
---
static/js/shop/Backlog.jsx | 19 +-
static/js/shop/Cart.jsx | 20 +-
static/js/shop/Crate.jsx | 4 +-
static/js/shop/CrateMode.jsx | 2 +-
static/js/shop/CrateWarnings.jsx | 8 +-
static/js/shop/OrderPanel.jsx | 2 +-
static/js/shop/OrderSummary.jsx | 287 +++++++++++++----------------
static/js/shop/ProductCartItem.jsx | 7 +-
static/js/shop/ProductItem.jsx | 162 +++++++---------
static/js/shop/Shop.jsx | 27 +--
static/js/shop/shop_store.js | 146 ++++++++++-----
static/js/shop/warnings.js | 35 ++--
static/js/shop_data.js | 55 +++---
13 files changed, 356 insertions(+), 418 deletions(-)
diff --git a/static/js/shop/Backlog.jsx b/static/js/shop/Backlog.jsx
index c207e6a..39afc9d 100644
--- a/static/js/shop/Backlog.jsx
+++ b/static/js/shop/Backlog.jsx
@@ -9,17 +9,13 @@ import {useShopStore} from "./shop_store";
*/
export function Backlog() {
const {
- currency,
data,
items,
- onClickAddItem,
onClickToggleMobileSideMenu,
isMobile,
} = useShopStore(state=> ({
- currency: state.currency,
data: state.groups,
items: state.cards,
- onClickAddItem: state.addCardFromBacklog,
onClickToggleMobileSideMenu: state.switchSideMenu,
isMobile: state.isMobile
}));
@@ -46,20 +42,7 @@ export function Backlog() {
{group.items.map(item => {
item_index++;
return (
-
+
)
})}
diff --git a/static/js/shop/Cart.jsx b/static/js/shop/Cart.jsx
index 965b9ce..ecf1641 100644
--- a/static/js/shop/Cart.jsx
+++ b/static/js/shop/Cart.jsx
@@ -4,29 +4,23 @@ import {cartStyle} from "./utils";
import {ProductCartItem} from "./ProductCartItem.jsx";
import {FakePlaceholder} from "./FakePlaceholder.jsx";
import {FillExtData} from "./options/utils";
-import {CountResources, crate_type_to_hp, hp_to_slots, resource_counters} from "./count_resources";
+import {hp_to_slots, resource_counters} from "./count_resources";
import {useShopStore} from "./shop_store";
-import {TriggerCardWarnings} from "./warnings";
/**
* Component that displays a list of
*/
export function Cart({crate_index}) {
- // isMobile, isTouch, crate, onToggleOverlayRemove, onClickRemoveItem, onCardUpdate, onClickItem
- const {crate} = useShopStore(state => ({
- crate: state.crates[crate_index]
+ const {crate, crateParams} = useShopStore(state => ({
+ crate: state.crates[crate_index],
+ crateParams: state.crateParams
}));
- console.log(resource_counters, crate)
-
- const nbrOccupied = hp_to_slots(resource_counters.hp(crate.items, -1));
- const nbrSlots = hp_to_slots(crate_type_to_hp(crate.crate_mode));
- console.log(nbrOccupied, nbrSlots);
+ const nbrOccupied = hp_to_slots(crate.occupiedHP);
+ const nbrSlots = hp_to_slots(crateParams(crate.crate_mode).hp);
const products = crate.items.map((item, index) => {
const ext_data = FillExtData(crate.items, index);
- const resources = CountResources(crate.items, index);
- const warnings = TriggerCardWarnings(crate.items, index, resources);
return (
= nbrSlots}
- resources={resources}
- warnings={warnings}
key={item.id}/>
);
});
diff --git a/static/js/shop/Crate.jsx b/static/js/shop/Crate.jsx
index 1115cce..9f23ca4 100644
--- a/static/js/shop/Crate.jsx
+++ b/static/js/shop/Crate.jsx
@@ -34,9 +34,7 @@ export function Crate({crate_index}) {
- {1 || (rules && rules.length > 0) && (
-
- )}
+
);
diff --git a/static/js/shop/CrateMode.jsx b/static/js/shop/CrateMode.jsx
index c8bcd91..ac207ee 100644
--- a/static/js/shop/CrateMode.jsx
+++ b/static/js/shop/CrateMode.jsx
@@ -8,7 +8,7 @@ export function CrateMode({crate_index}) {
const {modes_order, crate_modes, crate, setMode} = useShopStore(state => ({
modes_order: state.modes_order,
crate_modes: state.crate_modes,
- crate: state.crates[crate_index].crate_mode,
+ crate: state.crates[crate_index],
setMode: state.setCrateMode
}))
return (
diff --git a/static/js/shop/CrateWarnings.jsx b/static/js/shop/CrateWarnings.jsx
index 4f80d3a..8c26631 100644
--- a/static/js/shop/CrateWarnings.jsx
+++ b/static/js/shop/CrateWarnings.jsx
@@ -1,16 +1,16 @@
import React from "react";
-import {TriggerCrateWarnings} from "./warnings";
+import {LevelUI} from "./warnings";
import {useShopStore} from "./shop_store";
export function CrateWarnings({crate_index}) {
const crate = useShopStore(state => (state.crates[crate_index]))
- const crate_warnings = TriggerCrateWarnings(crate);
+ const crate_warnings = crate.warnings;
// TODO UI/colors
return (
{crate_warnings.map((rule, index) => (
-
- {rule.name}: {rule.message}
+
+ {rule.message}
))}
diff --git a/static/js/shop/OrderPanel.jsx b/static/js/shop/OrderPanel.jsx
index ada7a91..ea95b4c 100644
--- a/static/js/shop/OrderPanel.jsx
+++ b/static/js/shop/OrderPanel.jsx
@@ -40,7 +40,7 @@ export function OrderPanel({title, description}) {
diff --git a/static/js/shop/OrderSummary.jsx b/static/js/shop/OrderSummary.jsx
index aed8ccc..846d20e 100644
--- a/static/js/shop/OrderSummary.jsx
+++ b/static/js/shop/OrderSummary.jsx
@@ -1,190 +1,149 @@
-import React, {PureComponent} from 'react';
-import PropTypes from "prop-types";
+import React from 'react';
import {SummaryPopup} from "./options/SummaryPopup.jsx";
import {formatMoney} from "./utils";
import {WarningIndicator} from "./CardWarnings.jsx";
-import {total_order_price} from "./count_resources";
-import {data as shared_data} from "./utils";
+import {useShopStore} from "./shop_store";
/**
* Components that displays the list of card that are used in the crate.
* It is a summary of purchase
*/
-export class OrderSummary extends PureComponent {
+export function OrderSummary() {
- static get propTypes() {
- return {
- currency: PropTypes.string,
- crates: PropTypes.object,
- onDeleteItem: PropTypes.func,
- onDeleteAllItems: PropTypes.func,
- onMouseEnterItem: PropTypes.func,
- onMouseLeaveItem: PropTypes.func,
- onClickSelectItem: PropTypes.func,
- };
- }
+ const {
+ currency,
+ crates,
+ total_price,
+ crateParams,
+ deleteCard,
+ setHighlight,
+ resetHighlight,
+ highlighted,
+ clearCrate,
+ clearAll
+ } = useShopStore(state =>({
+ currency: state.currency,
+ crates: state.crates,
+ total_price: state.totalOrderPrice(),
+ crateParams: state.crateParams,
+ deleteCard: state.deleteCard,
+ setHighlight: state.highlightCard,
+ resetHighlight: state.highlightReset,
+ highlighted: state.highlighted,
+ clearAll: state.clearAll,
+ clearCrate: state.clearCrate
+ }));
- constructor(props) {
- super(props);
- this.handleOnDeleteItem = this.handleOnDeleteItem.bind(this);
- this.handleOnDeleteAllItems = this.handleOnDeleteAllItems.bind(this);
- this.handleOnMouseEnterItem = this.handleOnMouseEnterItem.bind(this);
- this.handleOnMouseLeaveItem = this.handleOnMouseLeaveItem.bind(this);
- this.handleOnClickSelectItem = this.handleOnClickSelectItem.bind(this);
- }
+ return (
+
- handleOnDeleteItem(index, e) {
- if (this.props.onDeleteItem) {
- this.props.onDeleteItem(index);
- }
- e.preventDefault();
- }
+
- handleOnDeleteAllItems(e) {
- if (this.props.onDeleteAllItems) {
- this.props.onDeleteAllItems();
- }
- e.preventDefault();
- }
+
+
+
+ Remove all cards
- handleOnMouseEnterItem(id, e) {
- if (this.props.onMouseEnterItem) {
- this.props.onMouseEnterItem(id);
- }
- e.preventDefault();
- }
+
+
+
+
+
+
- handleOnMouseLeaveItem(e) {
- if (this.props.onMouseLeaveItem) {
- this.props.onMouseLeaveItem();
- }
- e.preventDefault();
- }
+ {crates.map((crate, _i) => {
+ let crate_type = crateParams(crate.crate_mode);
+ return (
+
+
+ {crate_type.name}
+
+
+ {`${currency} ${formatMoney(crate_type.price)}`}
- handleOnClickSelectItem(index, e) {
- if (e.target.tagName !== 'IMG') {
- if (this.props.onClickSelectItem) {
- this.props.onClickSelectItem(index);
- }
- }
- return e.preventDefault();
- }
+
+
+
+
- render() {
- const {
- currency,
- crates
- } = this.props;
+
+
+
+ {crate.items.map((item, index) => {
+ const options = item && item.options;
+ const options_data = item && item.options_data;
+ const warnings = item && item.show_warnings;
+ const selected = crate.id === highlighted.crate && index === highlighted.card;
- const total_price = total_order_price(crates);
-
- return (
-
-
-
-
-
-
-
- Remove all cards
-
-
-
-
-
-
-
-
- {Object.entries(crates).map(([crate_id, crate], _i) => {
- let crate_type = shared_data.crateModes[crate.crate_type];
- return (
-
-
- {crate_type.name}
-
-
- {`${currency} ${formatMoney(crate_type.price)}`}
-
-
-
-
-
-
-
+ return ( setHighlight(crate.id, index)}
+ onMouseEnter={() => setHighlight(crate.id, index)}
+ onMouseLeave={() => resetHighlight()}>
+
+ {`${item.name_number} ${item.name} ${item.name_codename}`}
-
- {crate.items.map((item, index) => {
- let options = item && item.options;
- let options_data = item && item.options_data;
- const warnings = item && item.show_warnings;
- return (
-
- {`${item.name_number} ${item.name} ${item.name_codename}`}
-
+
+
+ {`${currency} ${formatMoney(item.price)}`}
-
-
- {`${currency} ${formatMoney(item.price)}`}
+
deleteCard(crate.id, index)}>
+
+
-
-
-
+
+ {(warnings && warnings.length > 0 ? (
+
+ ) : (
+
+ ))}
+ {((options && options_data) ? (
+
+ ) : (
+
+ ))}
+
+
+
+
);
+ })}
+
+ )
+ })}
-
- {(warnings && warnings.length > 0 ? (
-
- ) : (
-
- ))}
- {((options && options_data) ? (
-
- ) : (
-
- ))}
-
-
-
- );
- })}
-
- )})}
+
+
+ Price estimate
+
+
+ {currency} {formatMoney(total_price)}
+
+
+
+
-
-
- Price estimate
-
-
- ${currency} ${formatMoney(total_price)}
-
-
-
-
+
+
+
+
-
-
-
-
+
-
-
-
- );
- }
+
+ );
}
\ No newline at end of file
diff --git a/static/js/shop/ProductCartItem.jsx b/static/js/shop/ProductCartItem.jsx
index 429e9ca..f817aff 100644
--- a/static/js/shop/ProductCartItem.jsx
+++ b/static/js/shop/ProductCartItem.jsx
@@ -10,7 +10,7 @@ import {useShopStore} from "./shop_store";
* Component that renders a product.
* Used in the crate
*/
-export function ProductCartItem({card_index, crate_index, ext_data, first, last, resources, warnings}) {
+export function ProductCartItem({card_index, crate_index, ext_data, first, last}) {
const {card, crate, highlighted, setHighlight, removeHighlight, onCardUpdate, onCardRemove} = useShopStore(state => ({
card: state.crates[crate_index].items[card_index],
highlighted: state.crates[crate_index].id === state.highlighted.crate && card_index === state.highlighted.card,
@@ -22,7 +22,8 @@ export function ProductCartItem({card_index, crate_index, ext_data, first, last,
}))
let options, options_data;
- //const warnings = data && data.show_warnings;
+ const warnings = card && card.show_warnings;
+ const resources = card && card.counted_resources;
if (card && card.options) {
options = card.options;
@@ -94,7 +95,7 @@ export function ProductCartItem({card_index, crate_index, ext_data, first, last,
+ src={card.image}/>
{/* remove container */}
diff --git a/static/js/shop/ProductItem.jsx b/static/js/shop/ProductItem.jsx
index 532ce36..bbf7164 100644
--- a/static/js/shop/ProductItem.jsx
+++ b/static/js/shop/ProductItem.jsx
@@ -1,120 +1,84 @@
-import React, {PureComponent} from 'react';
-import PropTypes from "prop-types";
+import React from 'react';
import {Draggable} from "@hello-pangea/dnd";
import {formatMoney, productStyle} from "./utils";
+import {useShopStore} from "./shop_store";
/**
* Component that renders a product.
* Used in the aside (e.g backlog of product)
*/
-export class ProductItem extends PureComponent {
+export function ProductItem({card_index}) {
+ const {card, currency, onAddCard} = useShopStore(state => ({
+ card: state.getCardDescription(card_index),
+ currency: state.currency,
+ onAddCard: state.addCardFromBacklog
+ }));
- static get propTypes() {
- return {
- id: PropTypes.string.isRequired,
- index: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- name_codename: PropTypes.string,
- price: PropTypes.number.isRequired,
- currency: PropTypes.string.isRequired,
- image: PropTypes.string.isRequired,
- specs: PropTypes.array,
- datasheet_file: PropTypes.string,
- datasheet_name: PropTypes.string,
- onClickAddItem: PropTypes.func,
- };
- }
- constructor(props) {
- super(props);
- this.handleOnClickAddItem = this.handleOnClickAddItem.bind(this);
- }
+ const render_specs = (card.specs && card.specs.length > 0 && (
+
+ {card.specs.map((spec, index) =>
+ {spec}
+ )}
+
+ ));
- handleOnClickAddItem(id, tap, e) {
- if (this.props.onClickAddItem) {
- this.props.onClickAddItem(id, tap);
- }
- e.preventDefault();
- }
+ const render_datasheet_link = (card.datasheet_file && card.datasheet_name && (
+
+ ));
- render() {
- const {
- id,
- index,
- name,
- name_codename,
- price,
- currency,
- image,
- specs,
- datasheet_file,
- datasheet_name,
- } = this.props;
+ return (
+
- const render_specs = (specs && specs.length > 0 && (
-
- {specs.map((spec, index) =>
- {spec}
- )}
-
- ));
+
+
{card.name}
+ {card.name_codename ? (
+
{card.name_codename}
+ ) : null}
- const render_datasheet_link = (datasheet_file && datasheet_name && (
-
-
-
- {datasheet_name}
-
+
{`${currency} ${formatMoney(card.price)}`}
+
+ {render_specs}
+
+ {render_datasheet_link}
- ));
- return (
-
+
-
-
{name}
- {name_codename ? (
-
{name_codename}
- ) : null }
+
onAddCard(null, card_index, null)}>
+
+
-
{`${currency} ${formatMoney(price)}`}
-
- {render_specs}
-
- {render_datasheet_link}
-
-
-
+ {/* Allows to simulate a clone */}
+ {snapshot.isDragging && (
+
+ )}
+
+ )}
+
+
+
+
+
+ );
-
- );
- }
}
\ No newline at end of file
diff --git a/static/js/shop/Shop.jsx b/static/js/shop/Shop.jsx
index d3c12f4..10e02f2 100644
--- a/static/js/shop/Shop.jsx
+++ b/static/js/shop/Shop.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, {useEffect} from 'react';
import {DragDropContext} from "@hello-pangea/dnd";
@@ -12,28 +12,13 @@ import {useShopStore} from "./shop_store";
*/
export function Shop() {
- const {addCardFromBacklog, moveCard, deleteCard} = useShopStore(state => ({
+ const {addCardFromBacklog, moveCard, deleteCard, cardIndexById} = useShopStore(state => ({
addCardFromBacklog: state.addCardFromBacklog,
moveCard: state.moveCard,
- deleteCard: state.deleteCard
+ deleteCard: state.deleteCard,
+ cardIndexById: state.cardIndexById
}));
const handleOnDragEnd = (drop_result, provided) => {
- console.log(drop_result, provided)
- //{
- // "draggableId": "42dc17e9-9e75-45ee-ad27-2233b6f07a5e",
- // "type": "DEFAULT",
- // "source": {
- // "index": 17,
- // "droppableId": "backlog"
- // },
- // "reason": "DROP",
- // "mode": "FLUID",
- // "destination": {
- // "droppableId": "crate0",
- // "index": 0
- // },
- // "combine": null
- // }
if (drop_result.source.droppableId === "backlog")
addCardFromBacklog(drop_result.destination.droppableId, drop_result.source.index, drop_result.destination.index);
else if(drop_result.destination.droppableId === "backlog")
@@ -42,6 +27,10 @@ export function Shop() {
moveCard(drop_result.source.droppableId, drop_result.source.index, drop_result.destination.droppableId, drop_result.destination.index)
}
+ useEffect(() => {
+ addCardFromBacklog(null, [cardIndexById("kasli"), cardIndexById("eem_pwr_mod")], -1);
+ }, []);
+
return (
({
- cards: data.items,
- groups: data.columns.backlog,
+ cards: shared_data.items,
+ groups: shared_data.columns.backlog,
cards_list: itemsUnfoldedList,
- currency: data.currency
+ currency: shared_data.currency,
+ getCardDescription: index => get().cards[get().cards_list[index]],
+ cardIndexById: card_id => get().cards_list.findIndex((element) => (card_id === element))
}));
const useCrateModes = ((set, get) => ({
- crate_modes: data.crateModes,
- modes_order: data.crateModeOrder
+ crate_modes: shared_data.crateModes,
+ modes_order: shared_data.crateModeOrder,
+ crateParams: mode => get().crate_modes[mode],
}));
const useLayout = ((set, get) => ({
@@ -47,25 +50,41 @@ const useSubmitForm = ((set, get) => ({
isProcessingComplete: true,
}));
-const useCart = ((set, get) => ({
- crates: data.columns.crates,
- active_crate: "crate0",
+const useHighlighted = ((set, get) => ({
highlighted: {
crate: "",
card: 0
},
+ highlightCard: (crate_id, index) => set(state => ({
+ highlighted: {
+ crate: crate_id,
+ card: index
+ }
+ })),
+ highlightReset: () => set(state => ({
+ highlighted: {
+ crate: "",
+ card: 0
+ }
+ })),
+}));
- newCrate: () => set((state) => ({crates: state.crates.concat({
- id: "crate"+state.crates.length,
+const useCart = ((set, get) => ({
+ crates: shared_data.columns.crates,
+ active_crate: "crate0",
+
+ _newCrate: (crate_id) => set((state) => ({crates: state.crates.concat({
+ id: crate_id || "crate" + state.crates.length,
crate_mode: "rack",
items: [],
- warnings: []
+ warnings: [],
+ occupiedHP: 0
})})),
delCrate: (id) => set(state => ({
crates: state.crates.filter((crate => crate.id !== id))
})),
- setCrateMode: (id, mode) => set(state => ({
+ _setCrateMode: (id, mode) => set(state => ({
crates: state.crates.map((crate, _i) => {
if (crate.id === id) {
return {
@@ -76,12 +95,13 @@ const useCart = ((set, get) => ({
})
})),
setActiveCrate: (id) => set(state => ({active_crate: id})),
- addCardFromBacklog: (crate_to, index_from, index_to) => set(state => {
+ _addCardFromBacklog: (crate_to, index_from, index_to) => set(state => {
const take_from = (true_type_of(index_from) === "array" ? index_from : [index_from]).map((item, _i) => (state.cards_list[item]));
const dest = crate_to || state.active_crate;
return {
crates: state.crates.map((crate, _i) => {
if (dest === crate.id) {
+ index_to = index_to != null ? index_to : crate.items.length;
return {
...crate,
items: crate.items.toSpliced(index_to, 0, ...take_from.map((card_name, _) => {
@@ -92,7 +112,8 @@ const useCart = ((set, get) => ({
})
}
}),
- moveCard: (crate_from, index_from, crate_to, index_to) => set(state => {
+ _moveCard: (crate_from, index_from, crate_to, index_to) => set(state => {
+ console.log(crate_from, index_from, crate_to, index_to)
const the_card = state.crates.find((crate, _) => crate_from === crate.id ).items[index_from];
return {
crates: state.crates.map((crate, _i) => {
@@ -102,7 +123,7 @@ const useCart = ((set, get) => ({
delete items_copy[index_from];
return {
...crate,
- items: items_copy.toSpliced(index_to, 0, the_card).filter((item, _) => !!item)
+ items: items_copy.toSpliced(index_to+1, 0, the_card).filter((item, _) => !!item)
}
} else if (crate_to === crate.id) {
return {
@@ -119,18 +140,18 @@ const useCart = ((set, get) => ({
})
}
}),
- deleteCard: (crate, index) => set(state => ({
+ _deleteCard: (crate_id, index) => set(state => ({
crates: state.crates.map((crate, _i) => {
- if (crate === crate.id) {
+ if (crate_id === crate.id) {
return {
...crate,
- items: crate.items.splice(index, 1)
+ items: crate.items.toSpliced(index, 1)
}
}
else return crate;
})
})),
- clearCrate: (id) => set(state => ({
+ _clearCrate: (id) => set(state => ({
crates: state.crates.map((crate, _i) => {
if (id === crate.id) {
return {
@@ -141,9 +162,12 @@ const useCart = ((set, get) => ({
else return crate;
})
})),
- updateOptions: (crate, index, new_options) => set(state => ({
+ clearAll: () => set(state => ({
+ crates: []
+ })),
+ _updateOptions: (crate_id, index, new_options) => set(state => ({
crates: state.crates.map((crate, _i) => {
- if (crate === crate.id) {
+ if (crate_id === crate.id) {
let itemsCopy = Array.from(crate.items);
itemsCopy[index].options_data = {...itemsCopy[index].options_data, ...new_options};
return {
@@ -154,37 +178,74 @@ const useCart = ((set, get) => ({
else return crate;
})
})),
- highlightCard: (crate, index) => set(state => ({
- highlighted: {
- crate: crate,
- card: index
- }
- })),
- highlightReset: () => set(state => ({
- highlighted: {
- crate: "",
- card: 0
- }
- })),
- fillWarnings: (crate) => set(state => ({
- // actually seems to be just render-time action, no need to put data in it,
- // though needs to be optimized to be done only on real crate updates
+ fillWarnings: (crate_id) => set(state => ({
crates: state.crates.map((crate, _i) => {
- if (crate === crate.id) {
+ if (crate_id === crate.id) {
let itemsCopy = Array.from(crate.items);
itemsCopy = FillResources(itemsCopy);
itemsCopy = TriggerWarnings(itemsCopy);
- const crate_warnings = TriggerCrateWarnings(crate);
+ const [crate_warnings, occupied] = TriggerCrateWarnings(crate);
return {
...crate,
items: itemsCopy,
- warnings: crate_warnings
+ warnings: crate_warnings,
+ occupiedHP: occupied
}
}
else return crate;
})
- }))
+ })),
+
+ totalOrderPrice: () => {
+ let sum = 0;
+ get().crates.forEach( (crate, _i) => {
+ sum += get().crate_modes[crate.crate_mode].price;
+ crate.items.forEach((item, _) => {
+ sum += item.price;
+ });
+ });
+ return sum;
+ },
+
+ // Composite actions that require warnings recalculation:
+
+ newCrate: () => {
+ const crate_id = "crate" + get().crates.length;
+ get()._newCrate(crate_id)
+ get().fillWarnings(crate_id);
+ },
+
+ setCrateMode: (id, mode) => {
+ console.log("setCrateMode", id, mode)
+ get()._setCrateMode(id, mode)
+ get().fillWarnings(id);
+ },
+
+ addCardFromBacklog: (crate_to, index_from, index_to) => {
+ const dest = crate_to || get().active_crate;
+ get()._addCardFromBacklog(dest, index_from, index_to)
+ get().fillWarnings(dest);
+ },
+
+ moveCard: (crate_from, index_from, crate_to, index_to) => {
+ get()._moveCard(crate_from, index_from, crate_to, index_to);
+ get().fillWarnings(crate_to);
+ if (crate_from !== crate_to) get().fillWarnings(crate_from);
+ },
+ deleteCard: (crate_id, index) => {
+ get()._deleteCard(crate_id, index);
+ get().fillWarnings(crate_id);
+ },
+ clearCrate: (id) => {
+ get()._clearCrate(id);
+ get().fillWarnings(id);
+ },
+
+ updateOptions: (crate_id, index, new_options) => {
+ get()._updateOptions(crate_id, index, new_options);
+ get().fillWarnings(crate_id);
+ }
// TODO load and save jsons?
}))
@@ -195,5 +256,6 @@ export const useShopStore = create((...params) => ({
...useCrateModes(...params),
...useCart(...params),
...useSubmitForm(...params),
- ...useLayout(...params)
+ ...useLayout(...params),
+ ...useHighlighted(...params),
}))
\ No newline at end of file
diff --git a/static/js/shop/warnings.js b/static/js/shop/warnings.js
index fc325ce..224c135 100644
--- a/static/js/shop/warnings.js
+++ b/static/js/shop/warnings.js
@@ -7,10 +7,11 @@
import {crate_type_to_hp, item_occupied_counters, resource_counters} from "./count_resources";
import {data as shared_data} from "./utils";
+import {useShopStore} from "./shop_store";
const Levels = {
- "reminder": {priority: 1, icon: '/images/shop/icon-reminder.svg'},
- "warning": {priority: 2, icon: '/images/shop/icon-warning.svg'},
+ "reminder": {priority: 1, icon: '/images/shop/icon-reminder.svg', color: "black"},
+ "warning": {priority: 2, icon: '/images/shop/icon-warning.svg', color: "#c75e5e"},
}
const find_in_counters = (counters, name) => {
@@ -97,21 +98,6 @@ const Types = {
}
}
-
-export function TriggerCardWarnings(data, index, precounted) {
- const element = data[index];
- return (element.warnings && element.warnings
- .map((warning, _) => {
- if (!!Types[warning])
- return Types[warning].trigger(data, index, precounted) ? {trigger: undefined, name: warning, ...Types[warning]} : null;
- else
- return Types.default;
- })
- .filter((warning, _) => {
- return !!warning
- }));
-}
-
export function TriggerWarnings(data) {
return data.map((element, index) => {
if (!element.warnings) return element;
@@ -137,23 +123,26 @@ export function MaxLevel(warnings) {
return mx;
}
-
+export function LevelUI(warning_level) {
+ const warning_t = Levels[warning_level];
+ return {icon: warning_t.icon, color: warning_t.color};
+}
const crate_warnings = {
"overfit": {
message: "You have reached the maximum number of slots allowed for this crate. Consider removing cards.",
level: "warning",
trigger: (crate, occupied) => {
- const nbrHP = crate_type_to_hp(crate.crate_type);
- return occupied > nbrHP;
+ const nbrHP = useShopStore.getState().crateParams(crate.crate_mode).hp;
+ return occupied > nbrHP && nbrHP > 0;
}
},
"underfit_rack": {
message: "The selected cards fit in a 42hp desktop crate, consider switching to it for a more compact system",
level: "reminder",
trigger: (crate, occupied) => {
- const nbrHPDesktop = shared_data.crateModes.desktop.hp;
- return crate.crate_type === shared_data.crateModes.rack.id && occupied < nbrHPDesktop;
+ const nbrHPDesktop = useShopStore.getState().crate_modes.desktop.hp;
+ return crate.crate_mode === useShopStore.getState().crate_modes.rack.id && occupied < nbrHPDesktop;
}
}
}
@@ -164,5 +153,5 @@ export function TriggerCrateWarnings(crate) {
Object.entries(crate_warnings).forEach(([id, warning], _) => {
if (warning.trigger(crate, nbrOccupied)) warnings.push({...warning, id: id, trigger: undefined});
})
- return warnings;
+ return [warnings, nbrOccupied];
}
\ No newline at end of file
diff --git a/static/js/shop_data.js b/static/js/shop_data.js
index ca685f9..39b0513 100644
--- a/static/js/shop_data.js
+++ b/static/js/shop_data.js
@@ -70,7 +70,7 @@ const shop_data = {
name_number: '1124',
name_codename: 'Kasli 2.0',
price: 3600,
- image: '/shop/graphic-03_kasli.svg',
+ image: '/images/shop/graphic-03_kasli.svg',
specs: [
'FPGA core device, runs ARTIQ kernels, controls the EEMs.',
'4 SFP 6Gb/s slots for Ethernet or DRTIO.',
@@ -126,7 +126,7 @@ const shop_data = {
name_number: '1125',
name_codename: 'Kasli-SoC',
price: 5100,
- image: '/shop/graphic-03_kaslisoc.svg',
+ image: '/images/shop/graphic-03_kaslisoc.svg',
specs: [
'Core device based on Zynq-7000 CPU+FPGA system-on-chip.',
'Runs ARTIQ kernels on 1GHz Cortex-A9 CPU with hardware FPU.',
@@ -194,7 +194,7 @@ const shop_data = {
name_number: '1008',
name_codename: '',
price: 400,
- image: '/shop/graphic-03_VHDCI_carrier.svg',
+ image: '/images/shop/graphic-03_VHDCI_carrier.svg',
specs: [
'Passive adapter between VHDCI and EEMs.',
'VHDCI (SCSI-3) cables can carry EEM signals over short distances between crates.',
@@ -221,7 +221,7 @@ const shop_data = {
name_number: '2118',
name_codename: '',
price: 450,
- image: '/shop/graphic-03_BNC-TTL.svg',
+ image: '/images/shop/graphic-03_BNC-TTL.svg',
specs: [
'Two banks of four digital channels each, with BNC connectors.',
'Each bank with individual ground isolation.',
@@ -293,7 +293,7 @@ const shop_data = {
name_number: '2128',
name_codename: '',
price: 400,
- image: '/shop/graphic-03_SMA-TTL.svg',
+ image: '/images/shop/graphic-03_SMA-TTL.svg',
specs: [
'Same as above, but with SMA connectors.'
],
@@ -359,7 +359,7 @@ const shop_data = {
name_number: '2238',
name_codename: '',
price: 600,
- image: '/shop/graphic-03_MCX-TTL.svg',
+ image: '/images/shop/graphic-03_MCX-TTL.svg',
specs: [
'16 single-ended digital signals on MCX connectors.',
'Direction selectable in banks of four signals.',
@@ -451,7 +451,7 @@ const shop_data = {
name_number: '2245',
name_codename: '',
price: 390,
- image: '/shop/graphic-03_LVDS.svg',
+ image: '/images/shop/graphic-03_LVDS.svg',
specs: [
'Supplies 16 LVDS pairs via 4 front-panel RJ45 connectors.',
'Each RJ45 supplies 4 LVDS DIOs.',
@@ -538,7 +538,7 @@ const shop_data = {
name_number: '4410',
name_codename: 'Urukul',
price: 2350,
- image: '/shop/graphic-03_Urukul.svg',
+ image: '/images/shop/graphic-03_Urukul.svg',
specs: [
'4 channel 1GS/s DDS.',
'Output frequency (-3 dB): <1 to >400 MHz.',
@@ -599,7 +599,7 @@ const shop_data = {
name_number: '4412',
name_codename: 'Urukul',
price: 2350,
- image: '/shop/graphic-03_Urukul-4412.svg',
+ image: '/images/shop/graphic-03_Urukul-4412.svg',
specs: [
'4 channel 1GS/s DDS.',
'Higher frequency resolution ~8 µHz (47 bit)',
@@ -635,7 +635,7 @@ const shop_data = {
name_number: '4624',
name_codename: 'Phaser',
price: 4260,
- image: '/shop/graphic-03_Phaser.svg',
+ image: '/images/shop/graphic-03_Phaser.svg',
specs: [
'2x 1.25 GS/s IQ upconverters.',
'dual IQ mixer + 0.3 GHz to 4.8 GHz VCO + PLL.',
@@ -667,7 +667,7 @@ const shop_data = {
name_number: '5432',
name_codename: 'Zotino',
price: 1600,
- image: '/shop/graphic-03_Zotino.svg',
+ image: '/images/shop/graphic-03_Zotino.svg',
specs: [
'32-channel DAC.',
'16-bit resolution.',
@@ -702,7 +702,7 @@ const shop_data = {
name_number: '5632',
name_codename: 'Fastino',
price: 3390,
- image: '/shop/graphic-03_Fastino.svg',
+ image: '/images/shop/graphic-03_Fastino.svg',
specs: [
'32-channel DAC.',
'16-bit resolution.',
@@ -731,7 +731,7 @@ const shop_data = {
name_number: '5518',
name_codename: '',
price: 160,
- image: '/shop/graphic-03_IDC-BNC-adapter.svg',
+ image: '/images/shop/graphic-03_IDC-BNC-adapter.svg',
specs: [
'Breaks out analog signals from Zotino or HD68-IDC to BNC connectors.',
'Each card provides 8 channels.',
@@ -753,7 +753,7 @@ const shop_data = {
name_number: '5528',
name_codename: '',
price: 160,
- image: '/shop/graphic-03_SMA-IDC.svg',
+ image: '/images/shop/graphic-03_SMA-IDC.svg',
specs: [
'Breaks out analog signals from Zotino or HD68-IDC to SMA connectors.',
'Each card provides 8 channels.',
@@ -775,7 +775,7 @@ const shop_data = {
name_number: '5538',
name_codename: '',
price: 160,
- image: '/shop/graphic-03_MCX-IDC.svg',
+ image: '/images/shop/graphic-03_MCX-IDC.svg',
specs: [
'Breaks out analog signals from Zotino or HD68-IDC to MCX connectors.',
'Each card provides 8 channels.',
@@ -797,7 +797,7 @@ const shop_data = {
name_number: '5568',
name_codename: '',
price: 150,
- image: '/shop/graphic-03_HD68.svg',
+ image: '/images/shop/graphic-03_HD68.svg',
specs: [
'Connects an external HD68 cable to IDC-BNC, IDC-SMA or IDC-MCX cards.',
],
@@ -823,7 +823,7 @@ const shop_data = {
name_number: '5108',
name_codename: '',
price: 1600,
- image: '/shop/graphic-03_Sampler.svg',
+ image: '/images/shop/graphic-03_Sampler.svg',
specs: [
'8-channel ADC.',
'16-bit resolution.',
@@ -874,7 +874,7 @@ const shop_data = {
name_number: '6302',
name_codename: '',
price: 550,
- image: '/shop/graphic-03_Grabber.svg',
+ image: '/images/shop/graphic-03_Grabber.svg',
specs: [
'Camera input interface card.',
'Supports some EMCCD cameras.',
@@ -901,7 +901,7 @@ const shop_data = {
name_number: '7210',
name_codename: '',
price: 525,
- image: '/shop/graphic-03_Clocker.svg',
+ image: '/images/shop/graphic-03_Clocker.svg',
specs: [
'Distribute a low jitter clock signal among cards.',
'2 inputs.',
@@ -936,7 +936,7 @@ const shop_data = {
name_number: '8452',
name_codename: 'Stabilizer',
price: 2000,
- image: '/shop/graphic-03_Stabilizer.svg',
+ image: '/images/shop/graphic-03_Stabilizer.svg',
specs: [
'CPU-based dual-channel fast servo.',
'400MHz STM32H743ZIT6.',
@@ -968,7 +968,7 @@ const shop_data = {
name_number: '4456',
name_codename: 'Mirny',
price: 2660,
- image: '/shop/graphic-03_Mirny.svg',
+ image: '/images/shop/graphic-03_Mirny.svg',
specs: [
'4-channel Wide-band PLL/VCO-based microwave frequency synthesiser.',
'53 MHz to >4 GHz.',
@@ -998,7 +998,7 @@ const shop_data = {
name_number: '4457',
name_codename: 'Mirny + Almazny',
price: 3660,
- image: '/shop/graphic-03_Almazny.svg',
+ image: '/images/shop/graphic-03_Almazny.svg',
specs: [
'Mirny with high frequency mezzanine.',
'Additional 4 channels up to 12 GHz.',
@@ -1025,7 +1025,7 @@ const shop_data = {
name_number: '8453',
name_codename: '',
price: 2600,
- image: '/shop/graphic-03_Thermostat-EEM.svg',
+ image: '/images/shop/graphic-03_Thermostat-EEM.svg',
specs: [
'4 TEC channels.',
'Sensor channel count: 8 differential, 16 single-ended.',
@@ -1053,7 +1053,7 @@ const shop_data = {
name_number: '5716',
name_codename: 'Shuttler',
price: 8500,
- image: '/shop/graphic-03_Shuttler.svg',
+ image: '/images/shop/graphic-03_Shuttler.svg',
specs: [
'16-ch, 125 MSPS DAC EEM with remote analog front end board.',
'High DC resolution (up to ~18 bits with sigma-delta modulation) for trap electrode bias.',
@@ -1080,7 +1080,7 @@ const shop_data = {
name_number: '4459',
name_codename: 'Stabilizer + Pounder',
price: 4460,
- image: '/shop/graphic-03_Pounder.svg',
+ image: '/images/shop/graphic-03_Pounder.svg',
specs: [
'Stabilizer with Pounder daughter card.',
'2-channel Pound Drever Hall (PDH) lock generator.',
@@ -1111,7 +1111,7 @@ const shop_data = {
name_number: '1106',
name_codename: '',
price: 750,
- image: '/shop/graphic-03_eem_pwr_mod.svg',
+ image: '/images/shop/graphic-03_eem_pwr_mod.svg',
specs: [
"EEM AC power module.",
"400W with forced cooling (25CFM), 200W with free air convection.",
@@ -1189,7 +1189,8 @@ const shop_data = {
id: "crate0",
crate_mode: "rack",
items: [],
- warnings: []
+ warnings: [],
+ occupiedHP: 0,
}]
},
--
2.42.0
From 59f726e805acb434d88448a129a30a1c7247f048 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=81=AB=E7=84=9A=20=E5=AF=8C=E8=89=AF?=
Date: Tue, 12 Dec 2023 18:21:09 +0800
Subject: [PATCH 14/42] Start refactor of order form
---
static/js/shop/Backlog.jsx | 2 +-
static/js/shop/Cart.jsx | 4 +-
static/js/shop/Crate.jsx | 6 +-
static/js/shop/CrateList.jsx | 2 +-
static/js/shop/ImportJSON.jsx | 2 +-
static/js/shop/OrderForm.jsx | 274 +++++-------------
static/js/shop/OrderPanel.jsx | 6 +-
static/js/shop/OrderSummary.jsx | 4 +-
static/js/shop/ProductCartItem.jsx | 6 +-
static/js/shop/Shop.jsx | 6 +-
static/js/shop/ShowJSON.jsx | 5 +
static/js/shop/json_porter.js | 47 +++
static/js/shop/options/DialogPopup.jsx | 2 +-
static/js/shop/options/components/Line.jsx | 2 +-
static/js/shop/options/components/Radio.jsx | 2 +-
static/js/shop/options/components/Switch.jsx | 2 +-
.../js/shop/options/components/SwitchLine.jsx | 2 +-
.../js/shop/options/components/components.js | 10 +-
static/js/shop/shop_store.js | 46 +++
static/js/shop/validate.js | 34 +++
webpack.config.js | 11 +-
21 files changed, 234 insertions(+), 241 deletions(-)
create mode 100644 static/js/shop/ShowJSON.jsx
create mode 100644 static/js/shop/json_porter.js
create mode 100644 static/js/shop/validate.js
diff --git a/static/js/shop/Backlog.jsx b/static/js/shop/Backlog.jsx
index 39afc9d..b96e59c 100644
--- a/static/js/shop/Backlog.jsx
+++ b/static/js/shop/Backlog.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import {v4 as uuidv4} from "uuid";
import {Droppable} from "@hello-pangea/dnd";
-import {ProductItem} from "./ProductItem.jsx";
+import {ProductItem} from "./ProductItem";
import {useShopStore} from "./shop_store";
/**
diff --git a/static/js/shop/Cart.jsx b/static/js/shop/Cart.jsx
index ecf1641..77c78c3 100644
--- a/static/js/shop/Cart.jsx
+++ b/static/js/shop/Cart.jsx
@@ -1,8 +1,8 @@
import React from 'react'
import {Droppable} from "@hello-pangea/dnd";
import {cartStyle} from "./utils";
-import {ProductCartItem} from "./ProductCartItem.jsx";
-import {FakePlaceholder} from "./FakePlaceholder.jsx";
+import {ProductCartItem} from "./ProductCartItem";
+import {FakePlaceholder} from "./FakePlaceholder";
import {FillExtData} from "./options/utils";
import {hp_to_slots, resource_counters} from "./count_resources";
import {useShopStore} from "./shop_store";
diff --git a/static/js/shop/Crate.jsx b/static/js/shop/Crate.jsx
index 9f23ca4..4c74d92 100644
--- a/static/js/shop/Crate.jsx
+++ b/static/js/shop/Crate.jsx
@@ -1,7 +1,7 @@
import React from 'react';
-import {Cart} from "./Cart.jsx";
-import {CrateMode} from "./CrateMode.jsx";
-import {CrateWarnings} from "./CrateWarnings.jsx";
+import {Cart} from "./Cart";
+import {CrateMode} from "./CrateMode";
+import {CrateWarnings} from "./CrateWarnings";
import {useShopStore} from "./shop_store";
import {TriggerCrateWarnings} from "./warnings";
diff --git a/static/js/shop/CrateList.jsx b/static/js/shop/CrateList.jsx
index 5b61788..c4f9a21 100644
--- a/static/js/shop/CrateList.jsx
+++ b/static/js/shop/CrateList.jsx
@@ -1,6 +1,6 @@
import React from 'react'
import {Accordion} from "react-bootstrap";
-import {Crate} from "./Crate.jsx";
+import {Crate} from "./Crate";
import {useShopStore} from "./shop_store";
export function CrateList() {
diff --git a/static/js/shop/ImportJSON.jsx b/static/js/shop/ImportJSON.jsx
index bad145d..19a01c7 100644
--- a/static/js/shop/ImportJSON.jsx
+++ b/static/js/shop/ImportJSON.jsx
@@ -1,5 +1,5 @@
export function ImportJSON() {
return (
- Import JSON BAOBAO
+ Import JSON PLACEHOLDER
)
}
\ No newline at end of file
diff --git a/static/js/shop/OrderForm.jsx b/static/js/shop/OrderForm.jsx
index 7927619..b101026 100644
--- a/static/js/shop/OrderForm.jsx
+++ b/static/js/shop/OrderForm.jsx
@@ -1,220 +1,78 @@
-import React, {PureComponent} from 'react'
-import PropTypes from "prop-types";
+import React from 'react'
+import {validateEmail, Validation} from "./validate.js";
+import {useShopStore} from "./shop_store";
/**
* Components that renders the form to request quote.
*/
-export class OrderForm extends PureComponent {
+export function OrderForm() {
+ const {
+ email,
+ note,
+ isProcessing,
+ isProcessingComplete,
+ showDescription,
+ updateEmail,
+ updateNote,
+ submitForm,
+ } = useShopStore(state => ({
+ email: state.email,
+ note: state.note,
+ isProcessing: state.isProcessing,
+ isProcessingComplete: state.isProcessingComplete,
+ showDescription: state.showDescription,
+ updateEmail: state.updateEmail,
+ updateNote: state.updateNote,
+ submitForm: state.submitForm,
+ }));
- static get propTypes() {
- return {
- isProcessing: PropTypes.bool,
- isProcessingComplete: PropTypes.bool,
- onClickSubmit: PropTypes.func,
- };
- }
- constructor(props) {
- super(props);
- this.state = {
- note: '',
- email: '',
- error: {
- note: null,
- email: null,
- },
- empty: {
- note: null,
- email: null,
- },
- };
+ return (
+
- this.handleEmail = this.handleEmail.bind(this);
- this.handleNote = this.handleNote.bind(this);
- this.handleSubmit = this.handleSubmit.bind(this);
- this.resetEmptyError = this.resetEmptyError.bind(this);
- this.checkValidation = this.checkValidation.bind(this);
- }
+
);
-}
+}
\ No newline at end of file
diff --git a/static/js/shop/ImportJSON.jsx b/static/js/shop/ImportJSON.jsx
index 19a01c7..2dc0d9c 100644
--- a/static/js/shop/ImportJSON.jsx
+++ b/static/js/shop/ImportJSON.jsx
@@ -1,5 +1,71 @@
+import {useShopStore} from "./shop_store";
+import {useClickAway} from "./options/useClickAway";
+import {Modal} from "react-bootstrap";
+import React from "react";
+import {Validation} from "./validate";
+
+const JSONExample = JSON.stringify({
+ "items": [{"pn": "1124"}, {"pn": "2118"}, {"pn": "2118"}, {"pn": "2128"}],
+ "type": "desktop"
+});
+
export function ImportJSON() {
- return (
- Import JSON PLACEHOLDER
- )
+ const {shouldShow, data, loadDescription, updateImportDescription, closeImport, showImport} = useShopStore(state => ({
+ shouldShow: state.importShouldOpen,
+ data: state.importValue,
+ loadDescription: state.loadDescription,
+ updateImportDescription: state.updateImportDescription,
+ closeImport: state.closeImport,
+ showImport: state.openImport,
+ }));
+
+ const ref = useClickAway((e) => {
+ if (e.type === "mousedown") // ignore touchstart
+ closeImport()
+ }
+ );
+
+ return (<>
+ Import JSON
+
+
+
+
+
+ Input the JSON description below. Should be something like:
+
+ {JSONExample}
+
+
+
+
+ {
+ console.log(event)
+ updateImportDescription(event.target.value)
+ }}
+ value={data.value}
+ className="form-control w-100"
+ rows="5"
+ placeholder="Input JSON description here."/>
+
+ {data.error !== Validation.OK ? (
+
+
{data.error === Validation.Empty ? "Empty input" : "Invalid JSON"}
+
+ ) : null}
+
+
+
+
+ >)
}
\ No newline at end of file
diff --git a/static/js/shop/OrderForm.jsx b/static/js/shop/OrderForm.jsx
index b101026..038cdb4 100644
--- a/static/js/shop/OrderForm.jsx
+++ b/static/js/shop/OrderForm.jsx
@@ -1,6 +1,7 @@
import React from 'react'
import {validateEmail, Validation} from "./validate.js";
import {useShopStore} from "./shop_store";
+import {ShowJSON} from "./ShowJSON";
/**
* Components that renders the form to request quote.
@@ -10,20 +11,18 @@ export function OrderForm() {
email,
note,
isProcessing,
- isProcessingComplete,
- showDescription,
updateEmail,
updateNote,
submitForm,
+ submitDisabled,
} = useShopStore(state => ({
email: state.email,
note: state.note,
isProcessing: state.isProcessing,
- isProcessingComplete: state.isProcessingComplete,
- showDescription: state.showDescription,
updateEmail: state.updateEmail,
updateNote: state.updateNote,
submitForm: state.submitForm,
+ submitDisabled: state.submitDisabled
}));
@@ -59,14 +58,10 @@ export function OrderForm() {
placeholder="Additional notes"/>
-
+
{/*This will open an email window. Send the email to make your request.*/}
diff --git a/static/js/shop/OrderPanel.jsx b/static/js/shop/OrderPanel.jsx
index bb77050..65bc747 100644
--- a/static/js/shop/OrderPanel.jsx
+++ b/static/js/shop/OrderPanel.jsx
@@ -3,6 +3,8 @@ import {OrderSummary} from "./OrderSummary";
import {OrderForm} from "./OrderForm";
import {CrateList} from "./CrateList";
import {useShopStore} from "./shop_store";
+import {ImportJSON} from "./ImportJSON";
+import {RFQFeedback} from "./RFQFeedback";
/**
* Component that renders all things for order.
@@ -22,13 +24,11 @@ export function OrderPanel({title, description}) {
- Import JSON
-
+
+
+
{isMobile ? (
diff --git a/static/js/shop/RFQFeedback.jsx b/static/js/shop/RFQFeedback.jsx
new file mode 100644
index 0000000..477c8cb
--- /dev/null
+++ b/static/js/shop/RFQFeedback.jsx
@@ -0,0 +1,36 @@
+import {useShopStore} from "./shop_store";
+import {useClickAway} from "./options/useClickAway";
+import {Modal} from "react-bootstrap";
+import {Validation} from "./validate";
+import React from "react";
+
+export function RFQFeedback() {
+ const {closeRFQ, shouldShow, status} = useShopStore(state => ({
+ closeRFQ: state.closeRFQFeedback,
+ shouldShow: state.shouldShowRFQFeedback,
+ status: state.processingResult
+ }))
+
+ const ref = useClickAway((e) => {
+ if (e.type === "mousedown") // ignore touchstart
+ closeRFQ()
+ });
+
+ return (
+
+
+
+
+ {status.status === Validation.OK ?
+
+ :
+ }
+
+
+ {status.message}
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/static/js/shop/Shop.jsx b/static/js/shop/Shop.jsx
index abe6915..2f25c4a 100644
--- a/static/js/shop/Shop.jsx
+++ b/static/js/shop/Shop.jsx
@@ -8,7 +8,7 @@ import {OrderPanel} from "./OrderPanel";
import {useShopStore} from "./shop_store";
/**
- * Component that render the entire shop
+ * Component that renders the entire shop
*/
export function Shop() {
@@ -18,7 +18,7 @@ export function Shop() {
deleteCard: state.deleteCard,
cardIndexById: state.cardIndexById
}));
- const handleOnDragEnd = (drop_result, provided) => {
+ const handleOnDragEnd = (drop_result, _provided) => {
if (drop_result.source.droppableId === "backlog")
addCardFromBacklog(drop_result.destination.droppableId, drop_result.source.index, drop_result.destination.index);
else if(drop_result.destination.droppableId === "backlog")
@@ -28,7 +28,7 @@ export function Shop() {
}
useEffect(() => {
- addCardFromBacklog(null, [cardIndexById("kasli"), cardIndexById("eem_pwr_mod")], -1);
+ addCardFromBacklog(null, [cardIndexById("eem_pwr_mod"), cardIndexById("kasli")], -1);
}, []);
return (
diff --git a/static/js/shop/ShowJSON.jsx b/static/js/shop/ShowJSON.jsx
index c8f3e93..a793e15 100644
--- a/static/js/shop/ShowJSON.jsx
+++ b/static/js/shop/ShowJSON.jsx
@@ -1,5 +1,43 @@
+import React from "react";
+import {Modal} from "react-bootstrap";
+import {useShopStore} from "./shop_store";
+import {useClickAway} from "./options/useClickAway";
+
export function ShowJSON() {
- return (
- SHOW JSON PLACEHOLDER
- )
+ const {shouldShow, description, showDescription, closeDescription} = useShopStore(state => ({
+ shouldShow: state.shouldShowDescription,
+ description: state.description,
+ closeDescription: state.closeDescription,
+ showDescription: state.showDescription,
+ }));
+
+ const ref = useClickAway((e) => {
+ if (e.type === "mousedown") // ignore touchstart
+ closeDescription()
+ }
+ );
+
+ return (<>
+
+
+
+
+
+
+
+
+ >)
}
\ No newline at end of file
diff --git a/static/js/shop/json_porter.js b/static/js/shop/json_porter.js
index 809e490..d5afd60 100644
--- a/static/js/shop/json_porter.js
+++ b/static/js/shop/json_porter.js
@@ -1,4 +1,6 @@
import {useShopStore} from "./shop_store";
+import {FilterOptions} from "./options/utils";
+import {v4 as uuidv4} from "uuid";
export function validateJSON(description) {
@@ -11,11 +13,15 @@ export function validateJSON(description) {
const crate_modes = useShopStore.getState().crate_modes;
const pn_to_card = useShopStore.getState().pn_to_cards;
- for (const crate of crates_raw) {
- if (!crate.type || !crate.items || !(crate.type in crate_modes)) return false;
- for (const card of crate.items) {
- if (!(card.pn in pn_to_card)) return false;
+ try {
+ for (const crate of crates_raw) {
+ if (!crate.type || !crate.items || !(crate.type in crate_modes)) return false;
+ for (const card of crate.items) {
+ if (!(card.pn in pn_to_card)) return false;
+ }
}
+ } catch (e) {
+ return false;
}
return true;
@@ -29,6 +35,7 @@ export function JSONToCrates(description) {
crate_mode: crate.type,
items: Array.from(crate.items.map((card, i) => ({
...pn_to_card(card.pn),
+ id: uuidv4(),
options_data: card.options
}))),
warnings: [],
diff --git a/static/js/shop/shop_store.js b/static/js/shop/shop_store.js
index 57bd0f1..a45ece8 100644
--- a/static/js/shop/shop_store.js
+++ b/static/js/shop/shop_store.js
@@ -6,8 +6,8 @@ import {true_type_of} from "./options/utils";
import {v4 as uuidv4} from "uuid";
import {FillResources} from "./count_resources";
import {TriggerCrateWarnings, TriggerWarnings} from "./warnings";
-import {Validation, validateEmail, validateNote} from "./validate";
-import {CratesToJSON} from "./json_porter";
+import {Validation, validateEmail, validateNote, validateJSONInput} from "./validate";
+import {CratesToJSON, JSONToCrates} from "./json_porter";
const cards_to_pn_map = (cards) => {
@@ -38,26 +38,46 @@ const useLayout = ((set, get) => ({
isMobile: window.deviceIsMobile(),
sideMenuIsOpen: false,
newCardJustAdded: false,
- importIsOpen: false,
switchSideMenu: () => set(state => ({
sideMenuIsOpen: !state.sideMenuIsOpen
})),
+}));
+
+const useImportJSON = ((set, get) => ({
+ importShouldOpen: false,
+ importValue: {
+ value: "",
+ error: Validation.OK
+ },
openImport: () => set(state => ({
- importIsOpen: true
+ importShouldOpen: true
})),
closeImport: () => set(state => ({
- importIsOpen: false
+ importShouldOpen: false
})),
-}))
+ loadDescription: () => set(state => ({
+ importShouldOpen: false,
+ crates: JSONToCrates(state.importValue.value)
+ })),
+ updateImportDescription: (new_description) => set(state => ({
+ importValue: {
+ value: new_description,
+ error: validateJSONInput(new_description)
+ }
+ }))
+}));
const useSubmitForm = ((set, get) => ({
// TODO think about it
isProcessing: false,
- shouldShowRFQFeedback: true,
- RFQBodyType: 'email',
- isProcessingComplete: true,
+ shouldShowRFQFeedback: false,
+ processingResult: {
+ status: Validation.OK,
+ message: ""
+ },
+ API_RFQ: shared_data.API_RFQ,
email: {
value: "",
error: null
@@ -83,6 +103,17 @@ const useSubmitForm = ((set, get) => ({
}
})),
+ _revalidateForm: () => set(state => ({
+ email: {
+ value: state.email.value,
+ error: validateEmail(state.email.value)
+ },
+ note: {
+ value: state.note.value,
+ error: validateEmail(state.note.value)
+ },
+ })),
+
updateDescription: () => set(state => ({
description: CratesToJSON(state.crates)
})),
@@ -93,7 +124,41 @@ const useSubmitForm = ((set, get) => ({
closeDescription: () => set(state => ({
shouldShowDescription: false
})),
- submitForm: () => set(state => ({})) // TODO
+ _submitForm: () => set(state => ({isProcessing: true})),
+ finishSubmitForm: (result) => set(state => ({
+ isProcessing: false,
+ shouldShowRFQFeedback: true,
+ processingResult: result})),
+
+ submitDisabled: () => (get().email.error !== Validation.OK),
+
+ submitForm: () => {
+ get().updateDescription();
+ get()._revalidateForm();
+ get()._submitForm();
+ if (get().submitDisabled()) return;
+ fetch(get().API_RFQ, {
+ method: "POST",
+ headers: {'Content-Type': 'application/json'},
+ body: JSON.stringify({
+ email: get().email.value,
+ note: get().note.value,
+ configuration: get().description
+ })
+ }).then(response => {
+ if (response.status !== 200) {
+ throw Error("Response status is not OK: " + response.status + ".\n" + response);
+ }
+ get().finishSubmitForm({status: Validation.OK, message: "We've received your request and will be in contact soon."})
+ }).catch(err => {
+ console.error("Request failed, reason:", err)
+ get().finishSubmitForm({
+ status: Validation.Invalid,
+ message: "We cannot receive your request. Try using the export by coping the configuration and send it to us at sales@m-labs.hk"
+ })
+ })
+ },
+ closeRFQFeedback: () => set(state => ({shouldShowRFQFeedback: false}))
}));
const useHighlighted = ((set, get) => ({
@@ -263,7 +328,6 @@ const useCart = ((set, get) => ({
},
setCrateMode: (id, mode) => {
- console.log("setCrateMode", id, mode)
get()._setCrateMode(id, mode)
get().fillWarnings(id);
},
@@ -292,8 +356,6 @@ const useCart = ((set, get) => ({
get()._updateOptions(crate_id, index, new_options);
get().fillWarnings(crate_id);
}
-
- // TODO load and save jsons?
}))
@@ -304,4 +366,5 @@ export const useShopStore = create((...params) => ({
...useSubmitForm(...params),
...useLayout(...params),
...useHighlighted(...params),
+ ...useImportJSON(...params),
}))
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
index 7c8fae7..bc1ffb3 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -20,8 +20,8 @@ module.exports = {
resolve: {
extensions: ['.tsx', '.ts', '.js', '.jsx'],
},
- devtool: "inline-source-map",
- mode: "development"
- //devtool: false,
- //mode: "production"
+ //devtool: "inline-source-map",
+ //mode: "development"
+ devtool: false,
+ mode: "production"
};
--
2.42.0
From 3b1d9fcb561776b8a7a51c1101e81c7d219c3258 Mon Sep 17 00:00:00 2001
From: Egor Savkin
Date: Wed, 13 Dec 2023 15:17:14 +0800
Subject: [PATCH 16/42] Minor fixes
Signed-off-by: Egor Savkin
---
static/js/shop/Backlog.jsx | 3 +-
static/js/shop/Cart.jsx | 2 +-
static/js/shop/Crate.jsx | 1 -
static/js/shop/CrateList.jsx | 6 +-
static/js/shop/ImportJSON.jsx | 1 -
static/js/shop/Layout.jsx | 265 +-----------------------
static/js/shop/OrderForm.jsx | 7 +-
static/js/shop/OrderPanel.jsx | 1 -
static/js/shop/OrderSummary.jsx | 2 +-
static/js/shop/Shop.jsx | 6 +-
static/js/shop/count_resources.js | 17 --
static/js/shop/json_porter.js | 2 +-
static/js/shop/options/DialogPopup.jsx | 2 +-
static/js/shop/options/SummaryPopup.jsx | 2 +-
static/js/shop/shop_store.js | 49 ++++-
static/js/shop/utils.js | 67 +-----
static/js/shop/warnings.js | 3 +-
static/js/shop_data.js | 38 ----
18 files changed, 67 insertions(+), 407 deletions(-)
diff --git a/static/js/shop/Backlog.jsx b/static/js/shop/Backlog.jsx
index b96e59c..7bc440f 100644
--- a/static/js/shop/Backlog.jsx
+++ b/static/js/shop/Backlog.jsx
@@ -1,5 +1,4 @@
import React from 'react';
-import {v4 as uuidv4} from "uuid";
import {Droppable} from "@hello-pangea/dnd";
import {ProductItem} from "./ProductItem";
import {useShopStore} from "./shop_store";
@@ -42,7 +41,7 @@ export function Backlog() {
{group.items.map(item => {
item_index++;
return (
-
+
)
})}
diff --git a/static/js/shop/Cart.jsx b/static/js/shop/Cart.jsx
index 77c78c3..2baae64 100644
--- a/static/js/shop/Cart.jsx
+++ b/static/js/shop/Cart.jsx
@@ -4,7 +4,7 @@ import {cartStyle} from "./utils";
import {ProductCartItem} from "./ProductCartItem";
import {FakePlaceholder} from "./FakePlaceholder";
import {FillExtData} from "./options/utils";
-import {hp_to_slots, resource_counters} from "./count_resources";
+import {hp_to_slots} from "./count_resources";
import {useShopStore} from "./shop_store";
/**
diff --git a/static/js/shop/Crate.jsx b/static/js/shop/Crate.jsx
index 4c74d92..e5f8a37 100644
--- a/static/js/shop/Crate.jsx
+++ b/static/js/shop/Crate.jsx
@@ -3,7 +3,6 @@ import {Cart} from "./Cart";
import {CrateMode} from "./CrateMode";
import {CrateWarnings} from "./CrateWarnings";
import {useShopStore} from "./shop_store";
-import {TriggerCrateWarnings} from "./warnings";
/**
* Component that displays the main crate with reminder rules.
diff --git a/static/js/shop/CrateList.jsx b/static/js/shop/CrateList.jsx
index c4f9a21..04e49b6 100644
--- a/static/js/shop/CrateList.jsx
+++ b/static/js/shop/CrateList.jsx
@@ -26,11 +26,9 @@ export function CrateList() {
)}
-
+
Add new crate
-
-
-
+
)
diff --git a/static/js/shop/ImportJSON.jsx b/static/js/shop/ImportJSON.jsx
index 2dc0d9c..3592f74 100644
--- a/static/js/shop/ImportJSON.jsx
+++ b/static/js/shop/ImportJSON.jsx
@@ -44,7 +44,6 @@ export function ImportJSON() {
{
- console.log(event)
updateImportDescription(event.target.value)
}}
value={data.value}
diff --git a/static/js/shop/Layout.jsx b/static/js/shop/Layout.jsx
index a0e62db..517a4e1 100644
--- a/static/js/shop/Layout.jsx
+++ b/static/js/shop/Layout.jsx
@@ -5,265 +5,14 @@ import {useShopStore} from "./shop_store";
* Component that provides a base layout (aside/main) for the page.
*/
-/*
-export function Layout({aside, main}) {
- static get defaultProps() {
- return {
- mobileSideMenuShouldOpen: false,
- };
- }
-
- constructor(props) {
- super(props);
-
- this.state = {
- customconf: '',
- error: null,
- };
-
- this.handleCustomConfig = this.handleCustomConfig.bind(this);
- this.handleClickLoad = this.handleClickLoad.bind(this);
- this.checkValidation = this.checkValidation.bind(this);
-
- // retrieve list of available pn
- const items_keys = Object.keys(props.items);
- this.list_pn = items_keys.map(function (key) {
- return props.items[key].name_number;
- });
- }
-
- handleCustomConfig(e) {
- const value = e.target.value;
-
- this.checkValidation(value);
- }
-
- checkValidation(conf) {
- let conf_obj;
-
- try {
- conf_obj = JSON.parse(conf);
- } catch (e) {
- return this.setState({
- ...this.state,
- customconf: conf,
- customconf_ready: null,
- error: 'invalid format',
- });
- }
-
- if (!conf_obj) {
- return this.setState({
- ...this.state,
- customconf: conf,
- customconf_ready: null,
- error: 'invalid format',
- });
- }
-
- if ((!conf_obj.items || !conf_obj.type) &&
- (Object.prototype.toString.call(conf_obj.items) !== '[object Array]' ||
- Object.prototype.toString.call(conf_obj.type) !== '[object String]')) {
- return this.setState({
- ...this.state,
- customconf: conf,
- customconf_ready: null,
- error: 'invalid format',
- });
- }
-
- if (conf_obj.type !== "desktop" && conf_obj.type !== "rack") {
- return this.setState({
- ...this.state,
- customconf: conf,
- customconf_ready: null,
- error: 'invalid format',
- });
- }
-
- conf_obj.items.map(function (item) {
- try {
- return JSON.parse(item);
- } catch (e) {
- return null;
- }
- });
-
- conf_obj.items = conf_obj.items.filter(function (item) {
- return item;
- });
-
- if (conf_obj.items.filter(function (item) {
- return Object.prototype.toString.call(item) !== '[object Object]' || !item.pn || Object.prototype.toString.call(item.pn) !== '[object String]';
- }).length > 0) {
- return this.setState({
- ...this.state,
- customconf: conf,
- customconf_ready: null,
- error: 'invalid format',
- });
- }
-
- conf_obj.items = conf_obj.items.map(function (item) {
- return {
- pn: item.pn,
- options: item.options ? item.options : null,
- };
- });
-
- const self = this;
- const unknow_pn = conf_obj.items.filter(function (item_pn) {
- return self.list_pn.includes(item_pn.pn) === false;
- }).map(function (item_pn) {
- return item_pn.pn;
- });
-
- if (unknow_pn.length > 0) {
- return this.setState({
- ...this.state,
- customconf: conf,
- customconf_ready: null,
- error: `${unknow_pn.join(', ')} unknown${unknow_pn.length > 1 ? 's':''} pn number`,
- });
- }
-
- this.setState({
- ...this.state,
- customconf: conf,
- error: null,
- customconf_ready: conf_obj,
- });
- }
-
- handleClickLoad() {
- this.checkValidation(this.state.customconf);
-
- if (this.props.onClickLoadCustomConf) {
- this.props.onClickLoadCustomConf(this.state.customconf_ready);
- }
- }
-
- render() {
- const {
- aside,
- main,
- mobileSideMenuShouldOpen,
- isMobile,
- newCardJustAdded,
- onClickToggleMobileSideMenu,
- onClickCloseRFQFeedback,
- showRFQFeedback,
- RFQBodyType,
- RFQBodyOrder,
- } = this.props;
-
- return (
-
-
-
-
- {mobileSideMenuShouldOpen ? (
-
- ) : (
-
- )}
-
- {isMobile && newCardJustAdded ? (
-
- ✓ added
-
- ) : null}
-
-
-
-
-
-
-
-
-
- {RFQBodyType === 'email' ? (
-
-
-
-
-
-
-
- We've received your request and will be in contact soon.
-
-
-
- ) : null }
-
- {RFQBodyType === 'show' ? (
-
- {RFQBodyOrder}
-
- ) : null}
-
- {RFQBodyType === 'import' ? (
-
-
-
-
-
- Input the JSON description below. Should be something like:
-
- {JSON.stringify({"items":[{"pn":"1124"},{"pn":"2118"},{"pn":"2118"},{"pn":"2128"}],"type":"desktop"})}
-
-
-
-
-
-
- {this.state.error ? (
-
- ) : null}
-
-
-
-
- ) : null}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-}
-*/
-
export function Layout({aside, main}) {
- const mobileSideMenuShouldOpen = useShopStore((state) => state.sideMenuOpen);
- const onClickToggleMobileSideMenu = useShopStore((state) => state.switchSideMenu);
- const newCardJustAdded = useShopStore((state) => state.newCardJustAdded);
- const isMobile = useShopStore((state) => state.isMobile);
+ const {mobileSideMenuShouldOpen, onClickToggleMobileSideMenu, showCardAddedFeedback} = useShopStore((state) => ({
+ mobileSideMenuShouldOpen: state.sideMenuIsOpen,
+ onClickToggleMobileSideMenu: state.switchSideMenu,
+ showCardAddedFeedback: state.showCardAddedFeedback,
+ isMobile: state.isMobile,
+ }));
return (
@@ -276,7 +25,7 @@ export function Layout({aside, main}) {
)}
- {isMobile && newCardJustAdded ? (
+ {showCardAddedFeedback ? (
✓ added
diff --git a/static/js/shop/OrderForm.jsx b/static/js/shop/OrderForm.jsx
index 038cdb4..a5f8363 100644
--- a/static/js/shop/OrderForm.jsx
+++ b/static/js/shop/OrderForm.jsx
@@ -1,5 +1,5 @@
import React from 'react'
-import {validateEmail, Validation} from "./validate.js";
+import {Validation} from "./validate.js";
import {useShopStore} from "./shop_store";
import {ShowJSON} from "./ShowJSON";
@@ -13,6 +13,7 @@ export function OrderForm() {
isProcessing,
updateEmail,
updateNote,
+ resetEmailValidation,
submitForm,
submitDisabled,
} = useShopStore(state => ({
@@ -22,7 +23,8 @@ export function OrderForm() {
updateEmail: state.updateEmail,
updateNote: state.updateNote,
submitForm: state.submitForm,
- submitDisabled: state.submitDisabled
+ submitDisabled: state.submitDisabled,
+ resetEmailValidation: state.resetEmailValidation
}));
@@ -35,6 +37,7 @@ export function OrderForm() {
className={`${email.error > 0 ? 'errorField' : ''}`}
type="email"
placeholder="Email"
+ onFocus={resetEmailValidation}
onChange={(event) => updateEmail(event.target.value)}
onBlur={(event) => updateEmail(event.target.value)}
value={email.value}/>
diff --git a/static/js/shop/OrderPanel.jsx b/static/js/shop/OrderPanel.jsx
index 65bc747..55b5e50 100644
--- a/static/js/shop/OrderPanel.jsx
+++ b/static/js/shop/OrderPanel.jsx
@@ -13,7 +13,6 @@ import {RFQFeedback} from "./RFQFeedback";
export function OrderPanel({title, description}) {
const isMobile = useShopStore((state) => state.isMobile);
const onClickToggleMobileSideMenu = useShopStore((state) => state.switchSideMenu);
- const onClickOpenImport = useShopStore((state) => state.openImport);
return (
diff --git a/static/js/shop/OrderSummary.jsx b/static/js/shop/OrderSummary.jsx
index f6cc59a..2e3f027 100644
--- a/static/js/shop/OrderSummary.jsx
+++ b/static/js/shop/OrderSummary.jsx
@@ -61,7 +61,7 @@ export function OrderSummary() {
{`${currency} ${formatMoney(crate_type.price)}`}
-
+ clearCrate(crate.id)}>
diff --git a/static/js/shop/Shop.jsx b/static/js/shop/Shop.jsx
index 2f25c4a..8e073f6 100644
--- a/static/js/shop/Shop.jsx
+++ b/static/js/shop/Shop.jsx
@@ -19,6 +19,10 @@ export function Shop() {
cardIndexById: state.cardIndexById
}));
const handleOnDragEnd = (drop_result, _provided) => {
+ if (!drop_result.destination) {
+ console.warn("No drop destination");
+ return;
+ }
if (drop_result.source.droppableId === "backlog")
addCardFromBacklog(drop_result.destination.droppableId, drop_result.source.index, drop_result.destination.index);
else if(drop_result.destination.droppableId === "backlog")
@@ -28,7 +32,7 @@ export function Shop() {
}
useEffect(() => {
- addCardFromBacklog(null, [cardIndexById("eem_pwr_mod"), cardIndexById("kasli")], -1);
+ addCardFromBacklog(null, [cardIndexById("eem_pwr_mod"), cardIndexById("kasli")], -1, true);
}, []);
return (
diff --git a/static/js/shop/count_resources.js b/static/js/shop/count_resources.js
index d9fd374..c56eaef 100644
--- a/static/js/shop/count_resources.js
+++ b/static/js/shop/count_resources.js
@@ -1,5 +1,3 @@
-import {data as shared_data} from "./utils";
-
const count_item_occupied_eem = (item) => {
if (!item.options_data
|| item.options_data.ext_pwr === false
@@ -75,19 +73,4 @@ export function FillResources(data) {
export function hp_to_slots(hp) {
return Math.trunc(hp / 4);
-}
-
-export function crate_type_to_hp(crate_t) {
- return shared_data.crateModes[crate_t].hp;
-}
-
-export function total_order_price(crates) {
- let sum = 0;
- Object.entries(crates).forEach( ([key, crate], _i) => {
- sum += shared_data.crateModes[crate.crate_type].price;
- crate.items.forEach((item, _) => {
- sum += item.price;
- });
- });
- return sum;
}
\ No newline at end of file
diff --git a/static/js/shop/json_porter.js b/static/js/shop/json_porter.js
index d5afd60..260c900 100644
--- a/static/js/shop/json_porter.js
+++ b/static/js/shop/json_porter.js
@@ -33,7 +33,7 @@ export function JSONToCrates(description) {
return Array.from(crates_raw.map((crate, c_i) => ({
id: "crate" + c_i,
crate_mode: crate.type,
- items: Array.from(crate.items.map((card, i) => ({
+ items: Array.from(crate.items.map((card, _i) => ({
...pn_to_card(card.pn),
id: uuidv4(),
options_data: card.options
diff --git a/static/js/shop/options/DialogPopup.jsx b/static/js/shop/options/DialogPopup.jsx
index 5d7c574..d5811a3 100644
--- a/static/js/shop/options/DialogPopup.jsx
+++ b/static/js/shop/options/DialogPopup.jsx
@@ -11,7 +11,7 @@ export function DialogPopup({options, data, target, id, big, first, last, option
);
let div_classes = `overlayVariant border rounded ${big ? "overlay-bigcard" : "overlay-smallcard"} ${(!big && first) ? "overlay-first" : ""} ${(!big && last) ? "overlay-last" : ""} ${options_class || ""}`;
- const handleClick = (event) => {
+ const handleClick = (_event) => {
setShow(!show);
};
diff --git a/static/js/shop/options/SummaryPopup.jsx b/static/js/shop/options/SummaryPopup.jsx
index edac9f0..bb43ef4 100644
--- a/static/js/shop/options/SummaryPopup.jsx
+++ b/static/js/shop/options/SummaryPopup.jsx
@@ -53,7 +53,7 @@ export function SummaryPopup({id, options, data}) {
}
}, [show, size])
- const handleClick = (event) => {
+ const handleClick = (_event) => {
setShow(!show);
if (!show) {
document.addEventListener("scroll", handleScroll, true);
diff --git a/static/js/shop/shop_store.js b/static/js/shop/shop_store.js
index a45ece8..a22a5fa 100644
--- a/static/js/shop/shop_store.js
+++ b/static/js/shop/shop_store.js
@@ -37,11 +37,22 @@ const useLayout = ((set, get) => ({
isTouch: window.isTouchEnabled(),
isMobile: window.deviceIsMobile(),
sideMenuIsOpen: false,
- newCardJustAdded: false,
+ showCardAddedFeedback: false,
+ timerAdded: null,
switchSideMenu: () => set(state => ({
sideMenuIsOpen: !state.sideMenuIsOpen
})),
+ cardAdded: () => set(state => ({
+ showCardAddedFeedback: true,
+ timerAdded: (!!state.timerAdded ? clearTimeout(state.timerAdded) : null) || (state.isMobile && setTimeout(() => {
+ get()._endCardAdded()
+ }, 2000))
+ })),
+ _endCardAdded: () => set(state => ({
+ showCardAddedFeedback: false,
+ timerAdded: !!state.timerAdded ? clearTimeout(state.timerAdded) : null
+ }))
}));
const useImportJSON = ((set, get) => ({
@@ -70,7 +81,6 @@ const useImportJSON = ((set, get) => ({
}));
const useSubmitForm = ((set, get) => ({
- // TODO think about it
isProcessing: false,
shouldShowRFQFeedback: false,
processingResult: {
@@ -102,6 +112,12 @@ const useSubmitForm = ((set, get) => ({
error: validateNote(new_notes)
}
})),
+ resetEmailValidation: () => set(state => ({
+ email: {
+ value: state.email.value,
+ error: Validation.OK
+ }
+ })),
_revalidateForm: () => set(state => ({
email: {
@@ -166,17 +182,22 @@ const useHighlighted = ((set, get) => ({
crate: "",
card: 0
},
+ highlightedTimer: null,
highlightCard: (crate_id, index) => set(state => ({
highlighted: {
crate: crate_id,
card: index
- }
+ },
+ highlightedTimer: (!!state.highlightedTimer ? clearTimeout(state.highlightedTimer) : null) || (state.isTouch && setTimeout(() => {
+ get().highlightReset()
+ }, 2000))
})),
highlightReset: () => set(state => ({
highlighted: {
crate: "",
card: 0
- }
+ },
+ highlightedTimer: !!state.highlightedTimer ? clearTimeout(state.highlightedTimer) : null
})),
}));
@@ -185,15 +206,19 @@ const useCart = ((set, get) => ({
crates: shared_data.columns.crates,
active_crate: "crate0",
- _newCrate: (crate_id) => set((state) => ({crates: state.crates.concat({
+ _newCrate: (crate_id) => set((state) => ({
+ crates: state.crates.concat({
id: crate_id || "crate" + state.crates.length,
crate_mode: "rack",
items: [],
warnings: [],
occupiedHP: 0
- })})),
+ }),
+ active_crate: crate_id || "crate" + state.crates.length
+ })),
delCrate: (id) => set(state => ({
- crates: state.crates.filter((crate => crate.id !== id))
+ crates: state.crates.filter((crate => crate.id !== id)),
+ active_crate: state.active_crate === id ? null : state.active_crate,
})),
_setCrateMode: (id, mode) => set(state => ({
crates: state.crates.map((crate, _i) => {
@@ -209,6 +234,7 @@ const useCart = ((set, get) => ({
_addCardFromBacklog: (crate_to, index_from, index_to) => set(state => {
const take_from = (true_type_of(index_from) === "array" ? index_from : [index_from]).map((item, _i) => (state.cards_list[item]));
const dest = crate_to || state.active_crate;
+ if (!dest) return {};
return {
crates: state.crates.map((crate, _i) => {
if (dest === crate.id) {
@@ -224,7 +250,6 @@ const useCart = ((set, get) => ({
}
}),
_moveCard: (crate_from, index_from, crate_to, index_to) => set(state => {
- console.log(crate_from, index_from, crate_to, index_to)
const the_card = state.crates.find((crate, _) => crate_from === crate.id ).items[index_from];
return {
crates: state.crates.map((crate, _i) => {
@@ -293,6 +318,7 @@ const useCart = ((set, get) => ({
fillWarnings: (crate_id) => set(state => ({
crates: state.crates.map((crate, _i) => {
if (crate_id === crate.id) {
+ //console.log("--- CHECK ALERTS ---")
let itemsCopy = Array.from(crate.items);
itemsCopy = FillResources(itemsCopy);
itemsCopy = TriggerWarnings(itemsCopy);
@@ -332,10 +358,14 @@ const useCart = ((set, get) => ({
get().fillWarnings(id);
},
- addCardFromBacklog: (crate_to, index_from, index_to) => {
+ addCardFromBacklog: (crate_to, index_from, index_to, just_mounted) => {
const dest = crate_to || get().active_crate;
+ if (!dest) return {};
get()._addCardFromBacklog(dest, index_from, index_to)
get().fillWarnings(dest);
+ if (!just_mounted) {
+ get().cardAdded()
+ }
},
moveCard: (crate_from, index_from, crate_to, index_to) => {
@@ -346,6 +376,7 @@ const useCart = ((set, get) => ({
deleteCard: (crate_id, index) => {
get()._deleteCard(crate_id, index);
get().fillWarnings(crate_id);
+ if (crate_id === get().highlighted.crate && index === get().highlighted.card) get().highlightReset()
},
clearCrate: (id) => {
get()._clearCrate(id);
diff --git a/static/js/shop/utils.js b/static/js/shop/utils.js
index 793e9fd..49e472b 100644
--- a/static/js/shop/utils.js
+++ b/static/js/shop/utils.js
@@ -1,73 +1,8 @@
'use strict';
-import {v4 as uuidv4} from "uuid";
-
export const data = window.shop_data;
export const itemsUnfoldedList = Array.from(data.columns.backlog.categories.map(groupId => groupId.itemIds).flat());
-/*export const copy = (
- model,
- source,
- destination,
- draggableSource,
- droppableDestination
-) => {
- const destClone = Array.from(destination.items);
-
- destClone.splice(droppableDestination.index, 0, ...draggableSource.map((dragged_item, _) => {
- return {
- ...model[dragged_item],
- id: uuidv4(),
- }
- }));
-
- return destClone;
-};
-*/
-export const reorder = (list, startIndex, endIndex) => {
- const result = Array.from(list);
- const [removed] = result.splice(startIndex, 1);
- result.splice(endIndex, 0, removed);
-
- return result;
-};
-
-export const remove = (list, startIndex) => {
- const result = Array.from(list);
- result.splice(startIndex, 1);
- return result;
-};
-
-
-export const copyFromBacklog = (source, destination, droppableSource, droppableDestination) => {
- console.log('==> dest', destination);
-
- const destClone = Array.from(destination.items);
- const items = droppableSource.indexes
- ? droppableSource.indexes .map((item, _) => itemsUnfoldedList[item])
- : [itemsUnfoldedList[droppableSource.index]];
-
- destClone.splice(droppableDestination.index, 0, ...items.map((item, _) => {
- return {...source[item], id: uuidv4()}
- }));
- return destClone;
-};
-
-export const move = (source, destination, droppableSource, droppableDestination) => {
- console.log('==> move', source, destination);
- const sourceClone = Array.from(source);
- const destClone = Array.from(destination);
- const [removed] = sourceClone.splice(droppableSource.index, 1);
-
- destClone.splice(droppableDestination.index, 0, removed);
-
- const result = {columns: {}};
- result.columns[droppableSource.droppableId] = sourceClone;
- result.columns[droppableDestination.droppableId] = destClone;
-
- return result;
-};
-
export const productStyle = (style, snapshot, removeAnim, hovered, selected, cart=false) => {
const custom = {
opacity: snapshot.isDragging ? .7 : 1,
@@ -122,4 +57,4 @@ export function formatMoney(amount, decimalCount = 2, decimal = ".", thousands =
} catch (e) {
return amount;
}
-};
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/static/js/shop/warnings.js b/static/js/shop/warnings.js
index 224c135..6e5a91e 100644
--- a/static/js/shop/warnings.js
+++ b/static/js/shop/warnings.js
@@ -5,8 +5,7 @@
* Second - resources indicator should be separate component
*/
-import {crate_type_to_hp, item_occupied_counters, resource_counters} from "./count_resources";
-import {data as shared_data} from "./utils";
+import {item_occupied_counters, resource_counters} from "./count_resources";
import {useShopStore} from "./shop_store";
const Levels = {
diff --git a/static/js/shop_data.js b/static/js/shop_data.js
index 39b0513..8dc690e 100644
--- a/static/js/shop_data.js
+++ b/static/js/shop_data.js
@@ -1,43 +1,8 @@
const shop_data = {
API_RFQ: 'https://hooks.m-labs.hk/rfq',
-
- mobileSideMenuShouldOpen: false,
- currentItemHovered: null,
- currentMode: 'rack',
currency: 'USD',
- crateModeSlots: {
- rack: 21,
- desktop: 10,
- },
-
- crateRules: {
- maxSlot: {
- type: 'crate',
- icon: '/shop/icon-warning.svg',
- color: '#c75e5e',
- name: 'Crate',
- message: 'You have reached the maximum number of slots allowed for this crate. Consider removing cards.',
- },
- compactSlot: {
- type: 'crate',
- icon: '/shop/icon-reminder.svg',
- name: 'Crate',
- message: 'The selected cards fit in a 42hp desktop crate, consider switching to it for a more compact system',
- },
- },
-
- crateModeItems: [{
- id: 'rack',
- name: 'Rack mountable crate',
- price: 550,
- }, {
- id: 'desktop',
- name: 'Desktop crate',
- price: 500,
- }],
-
crateModes: {
rack: {
id: 'rack',
@@ -1194,9 +1159,6 @@ const shop_data = {
}]
},
-
- rules: {},
-
};
--
2.42.0
From c7314801ed6dc9ef7de97522c8eb5265315114cd Mon Sep 17 00:00:00 2001
From: Egor Savkin
Date: Wed, 13 Dec 2023 16:42:18 +0800
Subject: [PATCH 17/42] Fix crate list expansion behavior
Signed-off-by: Egor Savkin
---
static/js/shop/CrateList.jsx | 10 ++++++++--
static/js/shop/shop_store.js | 3 +++
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/static/js/shop/CrateList.jsx b/static/js/shop/CrateList.jsx
index 04e49b6..e23e11c 100644
--- a/static/js/shop/CrateList.jsx
+++ b/static/js/shop/CrateList.jsx
@@ -16,10 +16,16 @@ export function CrateList() {
setActiveCrate: state.setActiveCrate,
}));
return (
-
+ {
+ // if e === null, that means that an accordion item was collapsed rather than expanded. e will be non-null when an item is expanded
+ if (e !== null)
+ setActiveCrate(e);
+ else
+ setActiveCrate("")
+ }}>
{crates.map((crate, index) =>
- setActiveCrate(crate.id)}>Crate #{`${index}`}
+ Crate #{`${index}`}
diff --git a/static/js/shop/shop_store.js b/static/js/shop/shop_store.js
index a22a5fa..a205fef 100644
--- a/static/js/shop/shop_store.js
+++ b/static/js/shop/shop_store.js
@@ -356,6 +356,7 @@ const useCart = ((set, get) => ({
setCrateMode: (id, mode) => {
get()._setCrateMode(id, mode)
get().fillWarnings(id);
+ get().setActiveCrate(crate_to);
},
addCardFromBacklog: (crate_to, index_from, index_to, just_mounted) => {
@@ -363,6 +364,7 @@ const useCart = ((set, get) => ({
if (!dest) return {};
get()._addCardFromBacklog(dest, index_from, index_to)
get().fillWarnings(dest);
+ get().setActiveCrate(dest);
if (!just_mounted) {
get().cardAdded()
}
@@ -371,6 +373,7 @@ const useCart = ((set, get) => ({
moveCard: (crate_from, index_from, crate_to, index_to) => {
get()._moveCard(crate_from, index_from, crate_to, index_to);
get().fillWarnings(crate_to);
+ get().setActiveCrate(crate_to);
if (crate_from !== crate_to) get().fillWarnings(crate_from);
},
deleteCard: (crate_id, index) => {
--
2.42.0
From 07e01bcc93d21105435cc295296e05f9a975f1d6 Mon Sep 17 00:00:00 2001
From: Egor Savkin
Date: Wed, 13 Dec 2023 17:35:17 +0800
Subject: [PATCH 18/42] Crates UI fixes
TODO ex .rfqFeedback fixes
Signed-off-by: Egor Savkin
---
sass/css/_shop.scss | 51 ++++++++++++++++++++++++-----------
static/css/order-hardware.css | 28 ++++++++++++++++---
static/js/shop/Crate.jsx | 11 ++++----
static/js/shop/CrateList.jsx | 5 ++--
static/js/shop/shop_store.js | 2 +-
5 files changed, 67 insertions(+), 30 deletions(-)
diff --git a/sass/css/_shop.scss b/sass/css/_shop.scss
index 02dfa5d..5c71fbc 100644
--- a/sass/css/_shop.scss
+++ b/sass/css/_shop.scss
@@ -201,22 +201,6 @@ button {
width: 50%;
padding-right: 30px;
}
- .crate-mode {
- text-align: right;
- width: 50%;
-
- a {
- cursor: pointer;
- margin-right: 1rem;
- color: inherit;
- text-decoration: none;
- padding-bottom: 5px;
- }
- a.active {
- font-weight: 700;
- border-bottom: 3px solid $btn-primary-2;
- }
- }
}
.summary {
@@ -555,6 +539,41 @@ button {
.crate-info {
padding: 1rem 0 0;
}
+
+ .crate-bar {
+ width: 100%;
+
+ .crate-mode {
+ text-align: left;
+ width: 75%;
+ display: inline;
+
+ a {
+ cursor: pointer;
+ margin-right: 1rem;
+ color: inherit;
+ text-decoration: none;
+ padding-bottom: 5px;
+ }
+ a.active {
+ font-weight: 700;
+ border-bottom: 3px solid $btn-primary-2;
+ }
+ }
+ .delete-crate {
+ text-decoration: none;
+ cursor: pointer;
+ text-align: right;
+ display: inline-flex;
+ width: 25%;
+ color: inherit;
+ img {
+ margin-left: 1rem;
+ align-self: center;
+ }
+ }
+ }
+
}
}
diff --git a/static/css/order-hardware.css b/static/css/order-hardware.css
index 433172d..d7c4ea3 100644
--- a/static/css/order-hardware.css
+++ b/static/css/order-hardware.css
@@ -61,6 +61,26 @@
text-decoration: none;
}
+#accordion_crates #accordion_crates_add .accordion-button:after {
+ background-image: url("/images/shop/icon-add.svg");
+}
+
+#accordion_crates .accordion-header button {
+ font-weight: bold;
+}
+
+#accordion_crates,
+#accordion_crates .accordion-header,
+#accordion_crates .accordion-button,
+#accordion_crates .accordion-item {
+ background-color: inherit;
+}
+
+#accordion_crates .accordion-button:not(.collapsed) {
+ background-color: rgba(26, 109, 147, 0.1);
+}
+
+
/*
##Device = Tablets, Ipads (portrait)
##Screen = B/w 768px to 1024px
@@ -108,11 +128,11 @@
}
#root-shop .panel .control > .description,
- #root-shop .panel .control > .crate-mode {
+ #root-shop .crate-mode {
width: 100%;
}
- #root-shop .panel .control > .crate-mode {
+ #root-shop .crate-mode {
text-align: left;
}
@@ -308,11 +328,11 @@
}
#root-shop .panel .control > .description,
- #root-shop .panel .control > .crate-mode {
+ #root-shop .crate-mode {
width: 100%;
}
- #root-shop .panel .control > .crate-mode {
+ #root-shop .crate-mode {
text-align: left;
}
diff --git a/static/js/shop/Crate.jsx b/static/js/shop/Crate.jsx
index e5f8a37..b59ca3e 100644
--- a/static/js/shop/Crate.jsx
+++ b/static/js/shop/Crate.jsx
@@ -20,13 +20,12 @@ export function Crate({crate_index}) {
return (
-
+
+
-
- Delete crate
-
onDeleteCrate(crate.id)}>
-
-
+
onDeleteCrate(crate.id)}>
+ Delete crate
+
diff --git a/static/js/shop/CrateList.jsx b/static/js/shop/CrateList.jsx
index e23e11c..f99ca71 100644
--- a/static/js/shop/CrateList.jsx
+++ b/static/js/shop/CrateList.jsx
@@ -16,7 +16,7 @@ export function CrateList() {
setActiveCrate: state.setActiveCrate,
}));
return (
-
{
+ {
// if e === null, that means that an accordion item was collapsed rather than expanded. e will be non-null when an item is expanded
if (e !== null)
setActiveCrate(e);
@@ -31,10 +31,9 @@ export function CrateList() {
)}
-
+
Add new crate
-
)
diff --git a/static/js/shop/shop_store.js b/static/js/shop/shop_store.js
index a205fef..e686395 100644
--- a/static/js/shop/shop_store.js
+++ b/static/js/shop/shop_store.js
@@ -356,7 +356,7 @@ const useCart = ((set, get) => ({
setCrateMode: (id, mode) => {
get()._setCrateMode(id, mode)
get().fillWarnings(id);
- get().setActiveCrate(crate_to);
+ get().setActiveCrate(id);
},
addCardFromBacklog: (crate_to, index_from, index_to, just_mounted) => {
--
2.42.0
From 0e60eb9bce2bac79a3e7ea1d9c70ab53cce6b78a Mon Sep 17 00:00:00 2001
From: Egor Savkin
Date: Thu, 14 Dec 2023 14:17:18 +0800
Subject: [PATCH 19/42] Fix buttons colors
Signed-off-by: Egor Savkin
---
sass/css/_base.scss | 2 +-
sass/css/_shop.scss | 120 ++++++++++++++++++------------
sass/css/styles.scss | 3 +-
static/css/order-hardware.css | 20 -----
static/images/shop/icon-clear.svg | 1 +
static/js/shop.bundle.js | 2 +-
static/js/shop/CrateList.jsx | 2 +-
static/js/shop/ImportJSON.jsx | 6 +-
static/js/shop/OrderSummary.jsx | 21 ++++--
static/js/shop/RFQFeedback.jsx | 2 +-
static/js/shop/ShowJSON.jsx | 6 +-
11 files changed, 99 insertions(+), 86 deletions(-)
create mode 100644 static/images/shop/icon-clear.svg
diff --git a/sass/css/_base.scss b/sass/css/_base.scss
index d284f72..4c9679f 100644
--- a/sass/css/_base.scss
+++ b/sass/css/_base.scss
@@ -149,7 +149,7 @@ a {
border: 1px solid $btn-primary-2 !important;
text-decoration: none;
- &:hover {
+ &:hover, &:disabled {
background-color: $btn-secondary-2;
border: 1px solid $btn-secondary-2 !important;
}
diff --git a/sass/css/_shop.scss b/sass/css/_shop.scss
index 5c71fbc..50f86fd 100644
--- a/sass/css/_shop.scss
+++ b/sass/css/_shop.scss
@@ -8,50 +8,38 @@ button {
outline: none!important;
}
-#root-shop {
+.rfqFeedback {
+ button {
+ background-color: inherit;
+ align-self: center;
+ border: 0;
+ position: absolute;
+ right: 10px;
+ top: 10px;
- .layout {
-
- .rfqFeedback {
- display: flex;
- align-items: center;
- padding: 2rem 3rem;
- text-align: center;
- /*position: absolute;
- width: 350px;*/
- background: white;
- /*left: calc(100%/2 - 350px/2);*/
- -webkit-box-shadow: 0px 0px 33px -7px rgba(0,0,0,0.75);
- -moz-box-shadow: 0px 0px 33px -7px rgba(0,0,0,0.75);
- box-shadow: 0px 0px 33px -7px rgba(0,0,0,0.75);
- /*top: calc(50% - 50px);*/
- border: 1px solid $brand-color;
- font-size: .9rem;
-
- button {
- background-color: inherit;
- align-self: center;
- border: 0;
- position: absolute;
- right: 10px;
- top: 10px;
-
- img {
- width: 15px;
- }
- }
-
- .btn.btn-primary.disabled {
- background-color: gray;
- }
-
- .btn-outline-primary,
- .btn-outline-primary:hover {
- color: $btn-primary-2;
- border-color: $btn-primary-2;
- background-color: inherit;
- }
+ img {
+ width: 15px;
}
+ }
+
+ .btn.btn-primary.disabled {
+ background-color: gray;
+ }
+
+ .btn-outline-primary {
+ color: $btn-primary-2;
+ border-color: $btn-primary-2;
+ background-color: inherit;
+ &:hover {
+ background-color: inherit;
+ color: $btn-secondary-2;
+ border-color: $btn-secondary-2;
+ }
+ }
+}
+
+#root-shop {
+ .layout {
display: flex;
@@ -186,11 +174,15 @@ button {
padding-bottom: .5rem;
}
- .btn-outline-primary,
- .btn-outline-primary:hover {
+ .btn-outline-primary {
color: $btn-primary-2;
border-color: $btn-primary-2;
background-color: inherit;
+ &:hover {
+ background-color: inherit;
+ color: $btn-secondary-2;
+ border-color: $btn-secondary-2;
+ }
}
.control {
@@ -300,7 +292,7 @@ button {
button {
background-color: inherit;
border: 0;
- margin-left: 20px;
+ margin-left: 16px;
img {
width: 20px;
@@ -350,11 +342,14 @@ button {
border: 1px solid #e53e3e !important;
}
- .btn-outline-primary,
- .btn-outline-primary:hover {
+ .btn-outline-primary {
color: $btn-primary-2;
border-color: $btn-primary-2;
background-color: inherit;
+ &:hover {
+ background-color: inherit;
+ color: $btn-secondary-2;
+ }
}
}
}
@@ -606,6 +601,37 @@ button {
margin-left: -10px;
}
+ #accordion_crates {
+ background-color: inherit;
+ .accordion_crates_item {
+ .accordion-header {
+ padding-bottom: 0;
+
+ }
+ .accordion-button {
+ background-color: inherit;
+ font-weight: bold;
+ &:hover {
+ background-color: $color-highlight;
+ }
+ }
+ }
+ #accordion_crates_add {
+ .accordion-header {
+ padding-bottom: 0;
+ }
+ .accordion-button {
+ font-weight: bold;
+ &:hover {
+ background-color: $color-highlight;
+ }
+ }
+
+ .accordion-button:after {
+ background-image: url("/images/shop/icon-add.svg");
+ }
+ }
+ }
}
.k-popup-connectors,
diff --git a/sass/css/styles.scss b/sass/css/styles.scss
index 4f6ddc2..cd62f5f 100644
--- a/sass/css/styles.scss
+++ b/sass/css/styles.scss
@@ -24,7 +24,8 @@ $btn-secondary-2: #a88cfd !default;
$link-primary-dark: #c2affd !default;
$link-secondary-dark: #cec2ea !default;
-$color-hover: #eae7f7 !default;
+$color-hover: #eae7f7 !default;
+$color-highlight: #dfe9ff !default;
// Import partials.
@import
diff --git a/static/css/order-hardware.css b/static/css/order-hardware.css
index d7c4ea3..e8b1064 100644
--- a/static/css/order-hardware.css
+++ b/static/css/order-hardware.css
@@ -61,26 +61,6 @@
text-decoration: none;
}
-#accordion_crates #accordion_crates_add .accordion-button:after {
- background-image: url("/images/shop/icon-add.svg");
-}
-
-#accordion_crates .accordion-header button {
- font-weight: bold;
-}
-
-#accordion_crates,
-#accordion_crates .accordion-header,
-#accordion_crates .accordion-button,
-#accordion_crates .accordion-item {
- background-color: inherit;
-}
-
-#accordion_crates .accordion-button:not(.collapsed) {
- background-color: rgba(26, 109, 147, 0.1);
-}
-
-
/*
##Device = Tablets, Ipads (portrait)
##Screen = B/w 768px to 1024px
diff --git a/static/images/shop/icon-clear.svg b/static/images/shop/icon-clear.svg
new file mode 100644
index 0000000..bbe5026
--- /dev/null
+++ b/static/images/shop/icon-clear.svg
@@ -0,0 +1 @@
+
diff --git a/static/js/shop.bundle.js b/static/js/shop.bundle.js
index d97df52..a7a866b 100644
--- a/static/js/shop.bundle.js
+++ b/static/js/shop.bundle.js
@@ -1,2 +1,2 @@
/*! For license information please see shop.bundle.js.LICENSE.txt */
-(()=>{var e={841:(e,t)=>{"use strict";var n=Symbol.for("react.element"),r=Symbol.for("react.portal"),o=Symbol.for("react.fragment"),i=Symbol.for("react.strict_mode"),a=Symbol.for("react.profiler"),l=Symbol.for("react.provider"),s=Symbol.for("react.context"),u=Symbol.for("react.server_context"),c=Symbol.for("react.forward_ref"),d=Symbol.for("react.suspense"),f=Symbol.for("react.suspense_list"),p=Symbol.for("react.memo"),m=Symbol.for("react.lazy");Symbol.for("react.offscreen");Symbol.for("react.module.reference"),t.isContextConsumer=function(e){return function(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case n:switch(e=e.type){case o:case a:case i:case d:case f:return e;default:switch(e=e&&e.$$typeof){case u:case s:case c:case m:case p:case l:return e;default:return t}}case r:return t}}}(e)===s}},366:(e,t,n)=>{"use strict";e.exports=n(841)},184:(e,t)=>{var n;!function(){"use strict";var r={}.hasOwnProperty;function o(){for(var e=[],t=0;t{"use strict";var r=n(296),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},i={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},a={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},l={};function s(e){return r.isMemo(e)?a:l[e.$$typeof]||o}l[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},l[r.Memo]=a;var u=Object.defineProperty,c=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var o=p(n);o&&o!==m&&e(t,o,r)}var a=c(n);d&&(a=a.concat(d(n)));for(var l=s(t),h=s(n),g=0;g{"use strict";var n="function"==typeof Symbol&&Symbol.for,r=n?Symbol.for("react.element"):60103,o=n?Symbol.for("react.portal"):60106,i=n?Symbol.for("react.fragment"):60107,a=n?Symbol.for("react.strict_mode"):60108,l=n?Symbol.for("react.profiler"):60114,s=n?Symbol.for("react.provider"):60109,u=n?Symbol.for("react.context"):60110,c=n?Symbol.for("react.async_mode"):60111,d=n?Symbol.for("react.concurrent_mode"):60111,f=n?Symbol.for("react.forward_ref"):60112,p=n?Symbol.for("react.suspense"):60113,m=n?Symbol.for("react.suspense_list"):60120,h=n?Symbol.for("react.memo"):60115,g=n?Symbol.for("react.lazy"):60116,y=n?Symbol.for("react.block"):60121,b=n?Symbol.for("react.fundamental"):60117,v=n?Symbol.for("react.responder"):60118,w=n?Symbol.for("react.scope"):60119;function E(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case r:switch(e=e.type){case c:case d:case i:case l:case a:case p:return e;default:switch(e=e&&e.$$typeof){case u:case f:case g:case h:case s:return e;default:return t}}case o:return t}}}function S(e){return E(e)===d}t.AsyncMode=c,t.ConcurrentMode=d,t.ContextConsumer=u,t.ContextProvider=s,t.Element=r,t.ForwardRef=f,t.Fragment=i,t.Lazy=g,t.Memo=h,t.Portal=o,t.Profiler=l,t.StrictMode=a,t.Suspense=p,t.isAsyncMode=function(e){return S(e)||E(e)===c},t.isConcurrentMode=S,t.isContextConsumer=function(e){return E(e)===u},t.isContextProvider=function(e){return E(e)===s},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===r},t.isForwardRef=function(e){return E(e)===f},t.isFragment=function(e){return E(e)===i},t.isLazy=function(e){return E(e)===g},t.isMemo=function(e){return E(e)===h},t.isPortal=function(e){return E(e)===o},t.isProfiler=function(e){return E(e)===l},t.isStrictMode=function(e){return E(e)===a},t.isSuspense=function(e){return E(e)===p},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===i||e===d||e===l||e===a||e===p||e===m||"object"==typeof e&&null!==e&&(e.$$typeof===g||e.$$typeof===h||e.$$typeof===s||e.$$typeof===u||e.$$typeof===f||e.$$typeof===b||e.$$typeof===v||e.$$typeof===w||e.$$typeof===y)},t.typeOf=E},296:(e,t,n)=>{"use strict";e.exports=n(103)},143:e=>{"use strict";e.exports=function(e,t,n,r,o,i,a,l){if(!e){var s;if(void 0===t)s=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var u=[n,r,o,i,a,l],c=0;(s=new Error(t.replace(/%s/g,(function(){return u[c++]})))).name="Invariant Violation"}throw s.framesToPop=1,s}}},962:function(e,t,n){var r,o;r=function(){"use strict";Array.isArray||(Array.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)});var e={},t={"==":function(e,t){return e==t},"===":function(e,t){return e===t},"!=":function(e,t){return e!=t},"!==":function(e,t){return e!==t},">":function(e,t){return e>t},">=":function(e,t){return e>=t},"<":function(e,t,n){return void 0===n?e=t?[]:r}};return e.is_logic=function(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)&&1===Object.keys(e).length},e.truthy=function(e){return!(Array.isArray(e)&&0===e.length||!e)},e.get_operator=function(e){return Object.keys(e)[0]},e.get_values=function(t){return t[e.get_operator(t)]},e.apply=function(n,r){if(Array.isArray(n))return n.map((function(t){return e.apply(t,r)}));if(!e.is_logic(n))return n;var o,i,a,l,s,u=e.get_operator(n),c=n[u];if(Array.isArray(c)||(c=[c]),"if"===u||"?:"==u){for(o=0;o0){var d=String(u).split("."),f=t;for(o=0;o{"use strict";var r=n(414);function o(){}function i(){}i.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,i,a){if(a!==r){var l=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw l.name="Invariant Violation",l}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:i,resetWarningCache:o};return n.PropTypes=n,n}},697:(e,t,n)=>{e.exports=n(703)()},414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},448:(e,t,n)=>{"use strict";var r=n(294),o=n(840);function i(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;nt}return!1}(t,n,o,r)&&(n=null),r||null===o?function(e){return!!d.call(m,e)||!d.call(p,e)&&(f.test(e)?m[e]=!0:(p[e]=!0,!1))}(t)&&(null===n?e.removeAttribute(t):e.setAttribute(t,""+n)):o.mustUseProperty?e[o.propertyName]=null===n?3!==o.type&&"":n:(t=o.attributeName,r=o.attributeNamespace,null===n?e.removeAttribute(t):(n=3===(o=o.type)||4===o&&!0===n?"":""+n,r?e.setAttributeNS(r,t,n):e.setAttribute(t,n))))}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach((function(e){var t=e.replace(y,b);g[t]=new h(t,1,!1,e,null,!1,!1)})),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach((function(e){var t=e.replace(y,b);g[t]=new h(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)})),["xml:base","xml:lang","xml:space"].forEach((function(e){var t=e.replace(y,b);g[t]=new h(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)})),["tabIndex","crossOrigin"].forEach((function(e){g[e]=new h(e,1,!1,e.toLowerCase(),null,!1,!1)})),g.xlinkHref=new h("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach((function(e){g[e]=new h(e,1,!1,e.toLowerCase(),null,!0,!0)}));var w=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,E=Symbol.for("react.element"),S=Symbol.for("react.portal"),x=Symbol.for("react.fragment"),k=Symbol.for("react.strict_mode"),O=Symbol.for("react.profiler"),C=Symbol.for("react.provider"),P=Symbol.for("react.context"),I=Symbol.for("react.forward_ref"),D=Symbol.for("react.suspense"),_=Symbol.for("react.suspense_list"),R=Symbol.for("react.memo"),N=Symbol.for("react.lazy");Symbol.for("react.scope"),Symbol.for("react.debug_trace_mode");var T=Symbol.for("react.offscreen");Symbol.for("react.legacy_hidden"),Symbol.for("react.cache"),Symbol.for("react.tracing_marker");var j=Symbol.iterator;function A(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=j&&e[j]||e["@@iterator"])?e:null}var M,L=Object.assign;function B(e){if(void 0===M)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);M=t&&t[1]||""}return"\n"+M+e}var F=!1;function z(e,t){if(!e||F)return"";F=!0;var n=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(t)if(t=function(){throw Error()},Object.defineProperty(t.prototype,"props",{set:function(){throw Error()}}),"object"==typeof Reflect&&Reflect.construct){try{Reflect.construct(t,[])}catch(e){var r=e}Reflect.construct(e,[],t)}else{try{t.call()}catch(e){r=e}e.call(t.prototype)}else{try{throw Error()}catch(e){r=e}e()}}catch(t){if(t&&r&&"string"==typeof t.stack){for(var o=t.stack.split("\n"),i=r.stack.split("\n"),a=o.length-1,l=i.length-1;1<=a&&0<=l&&o[a]!==i[l];)l--;for(;1<=a&&0<=l;a--,l--)if(o[a]!==i[l]){if(1!==a||1!==l)do{if(a--,0>--l||o[a]!==i[l]){var s="\n"+o[a].replace(" at new "," at ");return e.displayName&&s.includes("")&&(s=s.replace("",e.displayName)),s}}while(1<=a&&0<=l);break}}}finally{F=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?B(e):""}function U(e){switch(e.tag){case 5:return B(e.type);case 16:return B("Lazy");case 13:return B("Suspense");case 19:return B("SuspenseList");case 0:case 2:case 15:return z(e.type,!1);case 11:return z(e.type.render,!1);case 1:return z(e.type,!0);default:return""}}function W(e){if(null==e)return null;if("function"==typeof e)return e.displayName||e.name||null;if("string"==typeof e)return e;switch(e){case x:return"Fragment";case S:return"Portal";case O:return"Profiler";case k:return"StrictMode";case D:return"Suspense";case _:return"SuspenseList"}if("object"==typeof e)switch(e.$$typeof){case P:return(e.displayName||"Context")+".Consumer";case C:return(e._context.displayName||"Context")+".Provider";case I:var t=e.render;return(e=e.displayName)||(e=""!==(e=t.displayName||t.name||"")?"ForwardRef("+e+")":"ForwardRef"),e;case R:return null!==(t=e.displayName||null)?t:W(e.type)||"Memo";case N:t=e._payload,e=e._init;try{return W(e(t))}catch(e){}}return null}function $(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=(e=t.render).displayName||e.name||"",t.displayName||(""!==e?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return W(t);case 8:return t===k?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if("function"==typeof t)return t.displayName||t.name||null;if("string"==typeof t)return t}return null}function G(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":case"object":return e;default:return""}}function H(e){var t=e.type;return(e=e.nodeName)&&"input"===e.toLowerCase()&&("checkbox"===t||"radio"===t)}function V(e){e._valueTracker||(e._valueTracker=function(e){var t=H(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&void 0!==n&&"function"==typeof n.get&&"function"==typeof n.set){var o=n.get,i=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return o.call(this)},set:function(e){r=""+e,i.call(this,e)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(e){r=""+e},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}(e))}function q(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=H(e)?e.checked?"true":"false":e.value),(e=r)!==n&&(t.setValue(e),!0)}function Q(e){if(void 0===(e=e||("undefined"!=typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}function Y(e,t){var n=t.checked;return L({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=n?n:e._wrapperState.initialChecked})}function K(e,t){var n=null==t.defaultValue?"":t.defaultValue,r=null!=t.checked?t.checked:t.defaultChecked;n=G(null!=t.value?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:"checkbox"===t.type||"radio"===t.type?null!=t.checked:null!=t.value}}function J(e,t){null!=(t=t.checked)&&v(e,"checked",t,!1)}function X(e,t){J(e,t);var n=G(t.value),r=t.type;if(null!=n)"number"===r?(0===n&&""===e.value||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if("submit"===r||"reset"===r)return void e.removeAttribute("value");t.hasOwnProperty("value")?ee(e,t.type,n):t.hasOwnProperty("defaultValue")&&ee(e,t.type,G(t.defaultValue)),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked)}function Z(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!("submit"!==r&&"reset"!==r||void 0!==t.value&&null!==t.value))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}""!==(n=e.name)&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,""!==n&&(e.name=n)}function ee(e,t,n){"number"===t&&Q(e.ownerDocument)===e||(null==n?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var te=Array.isArray;function ne(e,t,n,r){if(e=e.options,t){t={};for(var o=0;o"+t.valueOf().toString()+"",t=ue.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}},"undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(e,t,n,r){MSApp.execUnsafeLocalFunction((function(){return ce(e,t)}))}:ce);function fe(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t}var pe={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},me=["Webkit","ms","Moz","O"];function he(e,t,n){return null==t||"boolean"==typeof t||""===t?"":n||"number"!=typeof t||0===t||pe.hasOwnProperty(e)&&pe[e]?(""+t).trim():t+"px"}function ge(e,t){for(var n in e=e.style,t)if(t.hasOwnProperty(n)){var r=0===n.indexOf("--"),o=he(n,t[n],r);"float"===n&&(n="cssFloat"),r?e.setProperty(n,o):e[n]=o}}Object.keys(pe).forEach((function(e){me.forEach((function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),pe[t]=pe[e]}))}));var ye=L({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function be(e,t){if(t){if(ye[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML))throw Error(i(137,e));if(null!=t.dangerouslySetInnerHTML){if(null!=t.children)throw Error(i(60));if("object"!=typeof t.dangerouslySetInnerHTML||!("__html"in t.dangerouslySetInnerHTML))throw Error(i(61))}if(null!=t.style&&"object"!=typeof t.style)throw Error(i(62))}}function ve(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var we=null;function Ee(e){return(e=e.target||e.srcElement||window).correspondingUseElement&&(e=e.correspondingUseElement),3===e.nodeType?e.parentNode:e}var Se=null,xe=null,ke=null;function Oe(e){if(e=wo(e)){if("function"!=typeof Se)throw Error(i(280));var t=e.stateNode;t&&(t=So(t),Se(e.stateNode,e.type,t))}}function Ce(e){xe?ke?ke.push(e):ke=[e]:xe=e}function Pe(){if(xe){var e=xe,t=ke;if(ke=xe=null,Oe(e),t)for(e=0;e>>=0)?32:31-(lt(e)/st|0)|0},lt=Math.log,st=Math.LN2,ut=64,ct=4194304;function dt(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return 4194240&e;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return 130023424&e;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function ft(e,t){var n=e.pendingLanes;if(0===n)return 0;var r=0,o=e.suspendedLanes,i=e.pingedLanes,a=268435455&n;if(0!==a){var l=a&~o;0!==l?r=dt(l):0!=(i&=a)&&(r=dt(i))}else 0!=(a=n&~o)?r=dt(a):0!==i&&(r=dt(i));if(0===r)return 0;if(0!==t&&t!==r&&0==(t&o)&&((o=r&-r)>=(i=t&-t)||16===o&&0!=(4194240&i)))return t;if(0!=(4&r)&&(r|=16&n),0!==(t=e.entangledLanes))for(e=e.entanglements,t&=r;0n;n++)t.push(e);return t}function yt(e,t,n){e.pendingLanes|=t,536870912!==t&&(e.suspendedLanes=0,e.pingedLanes=0),(e=e.eventTimes)[t=31-at(t)]=n}function bt(e,t){var n=e.entangledLanes|=t;for(e=e.entanglements;n;){var r=31-at(n),o=1<=An),Bn=String.fromCharCode(32),Fn=!1;function zn(e,t){switch(e){case"keyup":return-1!==Tn.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Un(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}var Wn=!1,$n={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function Gn(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"input"===t?!!$n[e.type]:"textarea"===t}function Hn(e,t,n,r){Ce(r),0<(t=Vr(t,"onChange")).length&&(n=new cn("onChange","change",null,n,r),e.push({event:n,listeners:t}))}var Vn=null,qn=null;function Qn(e){Br(e,0)}function Yn(e){if(q(Eo(e)))return e}function Kn(e,t){if("change"===e)return t}var Jn=!1;if(c){var Xn;if(c){var Zn="oninput"in document;if(!Zn){var er=document.createElement("div");er.setAttribute("oninput","return;"),Zn="function"==typeof er.oninput}Xn=Zn}else Xn=!1;Jn=Xn&&(!document.documentMode||9=t)return{node:r,offset:t-e};e=n}e:{for(;r;){if(r.nextSibling){r=r.nextSibling;break e}r=r.parentNode}r=void 0}r=ur(r)}}function dr(e,t){return!(!e||!t)&&(e===t||(!e||3!==e.nodeType)&&(t&&3===t.nodeType?dr(e,t.parentNode):"contains"in e?e.contains(t):!!e.compareDocumentPosition&&!!(16&e.compareDocumentPosition(t))))}function fr(){for(var e=window,t=Q();t instanceof e.HTMLIFrameElement;){try{var n="string"==typeof t.contentWindow.location.href}catch(e){n=!1}if(!n)break;t=Q((e=t.contentWindow).document)}return t}function pr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&("text"===e.type||"search"===e.type||"tel"===e.type||"url"===e.type||"password"===e.type)||"textarea"===t||"true"===e.contentEditable)}function mr(e){var t=fr(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&dr(n.ownerDocument.documentElement,n)){if(null!==r&&pr(n))if(t=r.start,void 0===(e=r.end)&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if((e=(t=n.ownerDocument||document)&&t.defaultView||window).getSelection){e=e.getSelection();var o=n.textContent.length,i=Math.min(r.start,o);r=void 0===r.end?i:Math.min(r.end,o),!e.extend&&i>r&&(o=r,r=i,i=o),o=cr(n,i);var a=cr(n,r);o&&a&&(1!==e.rangeCount||e.anchorNode!==o.node||e.anchorOffset!==o.offset||e.focusNode!==a.node||e.focusOffset!==a.offset)&&((t=t.createRange()).setStart(o.node,o.offset),e.removeAllRanges(),i>r?(e.addRange(t),e.extend(a.node,a.offset)):(t.setEnd(a.node,a.offset),e.addRange(t)))}for(t=[],e=n;e=e.parentNode;)1===e.nodeType&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for("function"==typeof n.focus&&n.focus(),n=0;n=document.documentMode,gr=null,yr=null,br=null,vr=!1;function wr(e,t,n){var r=n.window===n?n.document:9===n.nodeType?n:n.ownerDocument;vr||null==gr||gr!==Q(r)||(r="selectionStart"in(r=gr)&&pr(r)?{start:r.selectionStart,end:r.selectionEnd}:{anchorNode:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset},br&&sr(br,r)||(br=r,0<(r=Vr(yr,"onSelect")).length&&(t=new cn("onSelect","select",null,t,n),e.push({event:t,listeners:r}),t.target=gr)))}function Er(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n}var Sr={animationend:Er("Animation","AnimationEnd"),animationiteration:Er("Animation","AnimationIteration"),animationstart:Er("Animation","AnimationStart"),transitionend:Er("Transition","TransitionEnd")},xr={},kr={};function Or(e){if(xr[e])return xr[e];if(!Sr[e])return e;var t,n=Sr[e];for(t in n)if(n.hasOwnProperty(t)&&t in kr)return xr[e]=n[t];return e}c&&(kr=document.createElement("div").style,"AnimationEvent"in window||(delete Sr.animationend.animation,delete Sr.animationiteration.animation,delete Sr.animationstart.animation),"TransitionEvent"in window||delete Sr.transitionend.transition);var Cr=Or("animationend"),Pr=Or("animationiteration"),Ir=Or("animationstart"),Dr=Or("transitionend"),_r=new Map,Rr="abort auxClick cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(" ");function Nr(e,t){_r.set(e,t),s(t,[e])}for(var Tr=0;Trko||(e.current=xo[ko],xo[ko]=null,ko--)}function Po(e,t){ko++,xo[ko]=e.current,e.current=t}var Io={},Do=Oo(Io),_o=Oo(!1),Ro=Io;function No(e,t){var n=e.type.contextTypes;if(!n)return Io;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var o,i={};for(o in n)i[o]=t[o];return r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=i),i}function To(e){return null!=e.childContextTypes}function jo(){Co(_o),Co(Do)}function Ao(e,t,n){if(Do.current!==Io)throw Error(i(168));Po(Do,t),Po(_o,n)}function Mo(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,"function"!=typeof r.getChildContext)return n;for(var o in r=r.getChildContext())if(!(o in t))throw Error(i(108,$(e)||"Unknown",o));return L({},n,r)}function Lo(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||Io,Ro=Do.current,Po(Do,e),Po(_o,_o.current),!0}function Bo(e,t,n){var r=e.stateNode;if(!r)throw Error(i(169));n?(e=Mo(e,t,Ro),r.__reactInternalMemoizedMergedChildContext=e,Co(_o),Co(Do),Po(Do,e)):Co(_o),Po(_o,n)}var Fo=null,zo=!1,Uo=!1;function Wo(e){null===Fo?Fo=[e]:Fo.push(e)}function $o(){if(!Uo&&null!==Fo){Uo=!0;var e=0,t=vt;try{var n=Fo;for(vt=1;e>=a,o-=a,Jo=1<<32-at(t)+o|n<h?(g=d,d=null):g=d.sibling;var y=p(o,d,l[h],s);if(null===y){null===d&&(d=g);break}e&&d&&null===y.alternate&&t(o,d),i=a(y,i,h),null===c?u=y:c.sibling=y,c=y,d=g}if(h===l.length)return n(o,d),ii&&Zo(o,h),u;if(null===d){for(;hg?(y=h,h=null):y=h.sibling;var v=p(o,h,b.value,u);if(null===v){null===h&&(h=y);break}e&&h&&null===v.alternate&&t(o,h),l=a(v,l,g),null===d?c=v:d.sibling=v,d=v,h=y}if(b.done)return n(o,h),ii&&Zo(o,g),c;if(null===h){for(;!b.done;g++,b=s.next())null!==(b=f(o,b.value,u))&&(l=a(b,l,g),null===d?c=b:d.sibling=b,d=b);return ii&&Zo(o,g),c}for(h=r(o,h);!b.done;g++,b=s.next())null!==(b=m(h,o,g,b.value,u))&&(e&&null!==b.alternate&&h.delete(null===b.key?g:b.key),l=a(b,l,g),null===d?c=b:d.sibling=b,d=b);return e&&h.forEach((function(e){return t(o,e)})),ii&&Zo(o,g),c}return function e(r,i,a,s){if("object"==typeof a&&null!==a&&a.type===x&&null===a.key&&(a=a.props.children),"object"==typeof a&&null!==a){switch(a.$$typeof){case E:e:{for(var u=a.key,c=i;null!==c;){if(c.key===u){if((u=a.type)===x){if(7===c.tag){n(r,c.sibling),(i=o(c,a.props.children)).return=r,r=i;break e}}else if(c.elementType===u||"object"==typeof u&&null!==u&&u.$$typeof===N&&Yi(u)===c.type){n(r,c.sibling),(i=o(c,a.props)).ref=qi(r,c,a),i.return=r,r=i;break e}n(r,c);break}t(r,c),c=c.sibling}a.type===x?((i=Mu(a.props.children,r.mode,s,a.key)).return=r,r=i):((s=Au(a.type,a.key,a.props,null,r.mode,s)).ref=qi(r,i,a),s.return=r,r=s)}return l(r);case S:e:{for(c=a.key;null!==i;){if(i.key===c){if(4===i.tag&&i.stateNode.containerInfo===a.containerInfo&&i.stateNode.implementation===a.implementation){n(r,i.sibling),(i=o(i,a.children||[])).return=r,r=i;break e}n(r,i);break}t(r,i),i=i.sibling}(i=Fu(a,r.mode,s)).return=r,r=i}return l(r);case N:return e(r,i,(c=a._init)(a._payload),s)}if(te(a))return h(r,i,a,s);if(A(a))return g(r,i,a,s);Qi(r,a)}return"string"==typeof a&&""!==a||"number"==typeof a?(a=""+a,null!==i&&6===i.tag?(n(r,i.sibling),(i=o(i,a)).return=r,r=i):(n(r,i),(i=Bu(a,r.mode,s)).return=r,r=i),l(r)):n(r,i)}}var Ji=Ki(!0),Xi=Ki(!1),Zi={},ea=Oo(Zi),ta=Oo(Zi),na=Oo(Zi);function ra(e){if(e===Zi)throw Error(i(174));return e}function oa(e,t){switch(Po(na,t),Po(ta,e),Po(ea,Zi),e=t.nodeType){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:se(null,"");break;default:t=se(t=(e=8===e?t.parentNode:t).namespaceURI||null,e=e.tagName)}Co(ea),Po(ea,t)}function ia(){Co(ea),Co(ta),Co(na)}function aa(e){ra(na.current);var t=ra(ea.current),n=se(t,e.type);t!==n&&(Po(ta,e),Po(ea,n))}function la(e){ta.current===e&&(Co(ea),Co(ta))}var sa=Oo(0);function ua(e){for(var t=e;null!==t;){if(13===t.tag){var n=t.memoizedState;if(null!==n&&(null===(n=n.dehydrated)||"$?"===n.data||"$!"===n.data))return t}else if(19===t.tag&&void 0!==t.memoizedProps.revealOrder){if(0!=(128&t.flags))return t}else if(null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}var ca=[];function da(){for(var e=0;en?n:4,e(!0);var r=pa.transition;pa.transition={};try{e(!1),t()}finally{vt=n,pa.transition=r}}function el(){return Pa().memoizedState}function tl(e,t,n){var r=nu(e);n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},rl(e)?ol(t,n):null!==(n=Di(e,t,n,r))&&(ru(n,e,r,tu()),il(n,t,r))}function nl(e,t,n){var r=nu(e),o={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(rl(e))ol(t,o);else{var i=e.alternate;if(0===e.lanes&&(null===i||0===i.lanes)&&null!==(i=t.lastRenderedReducer))try{var a=t.lastRenderedState,l=i(a,n);if(o.hasEagerState=!0,o.eagerState=l,lr(l,a)){var s=t.interleaved;return null===s?(o.next=o,Ii(t)):(o.next=s.next,s.next=o),void(t.interleaved=o)}}catch(e){}null!==(n=Di(e,t,o,r))&&(ru(n,e,r,o=tu()),il(n,t,r))}}function rl(e){var t=e.alternate;return e===ha||null!==t&&t===ha}function ol(e,t){va=ba=!0;var n=e.pending;null===n?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function il(e,t,n){if(0!=(4194240&n)){var r=t.lanes;n|=r&=e.pendingLanes,t.lanes=n,bt(e,n)}}var al={readContext:Ci,useCallback:Sa,useContext:Sa,useEffect:Sa,useImperativeHandle:Sa,useInsertionEffect:Sa,useLayoutEffect:Sa,useMemo:Sa,useReducer:Sa,useRef:Sa,useState:Sa,useDebugValue:Sa,useDeferredValue:Sa,useTransition:Sa,useMutableSource:Sa,useSyncExternalStore:Sa,useId:Sa,unstable_isNewReconciler:!1},ll={readContext:Ci,useCallback:function(e,t){return Ca().memoizedState=[e,void 0===t?null:t],e},useContext:Ci,useEffect:$a,useImperativeHandle:function(e,t,n){return n=null!=n?n.concat([e]):null,Ua(4194308,4,qa.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Ua(4194308,4,e,t)},useInsertionEffect:function(e,t){return Ua(4,2,e,t)},useMemo:function(e,t){var n=Ca();return t=void 0===t?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=Ca();return t=void 0!==n?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=tl.bind(null,ha,e),[r.memoizedState,e]},useRef:function(e){return e={current:e},Ca().memoizedState=e},useState:Ba,useDebugValue:Ya,useDeferredValue:function(e){return Ca().memoizedState=e},useTransition:function(){var e=Ba(!1),t=e[0];return e=Za.bind(null,e[1]),Ca().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=ha,o=Ca();if(ii){if(void 0===n)throw Error(i(407));n=n()}else{if(n=t(),null===_s)throw Error(i(349));0!=(30&ma)||Ta(r,t,n)}o.memoizedState=n;var a={value:n,getSnapshot:t};return o.queue=a,$a(Aa.bind(null,r,a,e),[e]),r.flags|=2048,Fa(9,ja.bind(null,r,a,n,t),void 0,null),n},useId:function(){var e=Ca(),t=_s.identifierPrefix;if(ii){var n=Xo;t=":"+t+"R"+(n=(Jo&~(1<<32-at(Jo)-1)).toString(32)+n),0<(n=wa++)&&(t+="H"+n.toString(32)),t+=":"}else t=":"+t+"r"+(n=Ea++).toString(32)+":";return e.memoizedState=t},unstable_isNewReconciler:!1},sl={readContext:Ci,useCallback:Ka,useContext:Ci,useEffect:Ga,useImperativeHandle:Qa,useInsertionEffect:Ha,useLayoutEffect:Va,useMemo:Ja,useReducer:Da,useRef:za,useState:function(){return Da(Ia)},useDebugValue:Ya,useDeferredValue:function(e){return Xa(Pa(),ga.memoizedState,e)},useTransition:function(){return[Da(Ia)[0],Pa().memoizedState]},useMutableSource:Ra,useSyncExternalStore:Na,useId:el,unstable_isNewReconciler:!1},ul={readContext:Ci,useCallback:Ka,useContext:Ci,useEffect:Ga,useImperativeHandle:Qa,useInsertionEffect:Ha,useLayoutEffect:Va,useMemo:Ja,useReducer:_a,useRef:za,useState:function(){return _a(Ia)},useDebugValue:Ya,useDeferredValue:function(e){var t=Pa();return null===ga?t.memoizedState=e:Xa(t,ga.memoizedState,e)},useTransition:function(){return[_a(Ia)[0],Pa().memoizedState]},useMutableSource:Ra,useSyncExternalStore:Na,useId:el,unstable_isNewReconciler:!1};function cl(e,t){try{var n="",r=t;do{n+=U(r),r=r.return}while(r);var o=n}catch(e){o="\nError generating stack: "+e.message+"\n"+e.stack}return{value:e,source:t,stack:o,digest:null}}function dl(e,t,n){return{value:e,source:null,stack:null!=n?n:null,digest:null!=t?t:null}}function fl(e,t){try{console.error(t.value)}catch(e){setTimeout((function(){throw e}))}}var pl="function"==typeof WeakMap?WeakMap:Map;function ml(e,t,n){(n=ji(-1,n)).tag=3,n.payload={element:null};var r=t.value;return n.callback=function(){Hs||(Hs=!0,Vs=r),fl(0,t)},n}function hl(e,t,n){(n=ji(-1,n)).tag=3;var r=e.type.getDerivedStateFromError;if("function"==typeof r){var o=t.value;n.payload=function(){return r(o)},n.callback=function(){fl(0,t)}}var i=e.stateNode;return null!==i&&"function"==typeof i.componentDidCatch&&(n.callback=function(){fl(0,t),"function"!=typeof r&&(null===qs?qs=new Set([this]):qs.add(this));var e=t.stack;this.componentDidCatch(t.value,{componentStack:null!==e?e:""})}),n}function gl(e,t,n){var r=e.pingCache;if(null===r){r=e.pingCache=new pl;var o=new Set;r.set(t,o)}else void 0===(o=r.get(t))&&(o=new Set,r.set(t,o));o.has(n)||(o.add(n),e=Cu.bind(null,e,t,n),t.then(e,e))}function yl(e){do{var t;if((t=13===e.tag)&&(t=null===(t=e.memoizedState)||null!==t.dehydrated),t)return e;e=e.return}while(null!==e);return null}function bl(e,t,n,r,o){return 0==(1&e.mode)?(e===t?e.flags|=65536:(e.flags|=128,n.flags|=131072,n.flags&=-52805,1===n.tag&&(null===n.alternate?n.tag=17:((t=ji(-1,1)).tag=2,Ai(n,t,1))),n.lanes|=1),e):(e.flags|=65536,e.lanes=o,e)}var vl=w.ReactCurrentOwner,wl=!1;function El(e,t,n,r){t.child=null===e?Xi(t,null,n,r):Ji(t,e.child,n,r)}function Sl(e,t,n,r,o){n=n.render;var i=t.ref;return Oi(t,o),r=ka(e,t,n,r,i,o),n=Oa(),null===e||wl?(ii&&n&&ti(t),t.flags|=1,El(e,t,r,o),t.child):(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~o,Hl(e,t,o))}function xl(e,t,n,r,o){if(null===e){var i=n.type;return"function"!=typeof i||Tu(i)||void 0!==i.defaultProps||null!==n.compare||void 0!==n.defaultProps?((e=Au(n.type,null,r,t,t.mode,o)).ref=t.ref,e.return=t,t.child=e):(t.tag=15,t.type=i,kl(e,t,i,r,o))}if(i=e.child,0==(e.lanes&o)){var a=i.memoizedProps;if((n=null!==(n=n.compare)?n:sr)(a,r)&&e.ref===t.ref)return Hl(e,t,o)}return t.flags|=1,(e=ju(i,r)).ref=t.ref,e.return=t,t.child=e}function kl(e,t,n,r,o){if(null!==e){var i=e.memoizedProps;if(sr(i,r)&&e.ref===t.ref){if(wl=!1,t.pendingProps=r=i,0==(e.lanes&o))return t.lanes=e.lanes,Hl(e,t,o);0!=(131072&e.flags)&&(wl=!0)}}return Pl(e,t,n,r,o)}function Ol(e,t,n){var r=t.pendingProps,o=r.children,i=null!==e?e.memoizedState:null;if("hidden"===r.mode)if(0==(1&t.mode))t.memoizedState={baseLanes:0,cachePool:null,transitions:null},Po(js,Ts),Ts|=n;else{if(0==(1073741824&n))return e=null!==i?i.baseLanes|n:n,t.lanes=t.childLanes=1073741824,t.memoizedState={baseLanes:e,cachePool:null,transitions:null},t.updateQueue=null,Po(js,Ts),Ts|=e,null;t.memoizedState={baseLanes:0,cachePool:null,transitions:null},r=null!==i?i.baseLanes:n,Po(js,Ts),Ts|=r}else null!==i?(r=i.baseLanes|n,t.memoizedState=null):r=n,Po(js,Ts),Ts|=r;return El(e,t,o,n),t.child}function Cl(e,t){var n=t.ref;(null===e&&null!==n||null!==e&&e.ref!==n)&&(t.flags|=512,t.flags|=2097152)}function Pl(e,t,n,r,o){var i=To(n)?Ro:Do.current;return i=No(t,i),Oi(t,o),n=ka(e,t,n,r,i,o),r=Oa(),null===e||wl?(ii&&r&&ti(t),t.flags|=1,El(e,t,n,o),t.child):(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~o,Hl(e,t,o))}function Il(e,t,n,r,o){if(To(n)){var i=!0;Lo(t)}else i=!1;if(Oi(t,o),null===t.stateNode)Gl(e,t),Gi(t,n,r),Vi(t,n,r,o),r=!0;else if(null===e){var a=t.stateNode,l=t.memoizedProps;a.props=l;var s=a.context,u=n.contextType;u="object"==typeof u&&null!==u?Ci(u):No(t,u=To(n)?Ro:Do.current);var c=n.getDerivedStateFromProps,d="function"==typeof c||"function"==typeof a.getSnapshotBeforeUpdate;d||"function"!=typeof a.UNSAFE_componentWillReceiveProps&&"function"!=typeof a.componentWillReceiveProps||(l!==r||s!==u)&&Hi(t,a,r,u),Ri=!1;var f=t.memoizedState;a.state=f,Bi(t,r,a,o),s=t.memoizedState,l!==r||f!==s||_o.current||Ri?("function"==typeof c&&(Ui(t,n,c,r),s=t.memoizedState),(l=Ri||$i(t,n,l,r,f,s,u))?(d||"function"!=typeof a.UNSAFE_componentWillMount&&"function"!=typeof a.componentWillMount||("function"==typeof a.componentWillMount&&a.componentWillMount(),"function"==typeof a.UNSAFE_componentWillMount&&a.UNSAFE_componentWillMount()),"function"==typeof a.componentDidMount&&(t.flags|=4194308)):("function"==typeof a.componentDidMount&&(t.flags|=4194308),t.memoizedProps=r,t.memoizedState=s),a.props=r,a.state=s,a.context=u,r=l):("function"==typeof a.componentDidMount&&(t.flags|=4194308),r=!1)}else{a=t.stateNode,Ti(e,t),l=t.memoizedProps,u=t.type===t.elementType?l:yi(t.type,l),a.props=u,d=t.pendingProps,f=a.context,s="object"==typeof(s=n.contextType)&&null!==s?Ci(s):No(t,s=To(n)?Ro:Do.current);var p=n.getDerivedStateFromProps;(c="function"==typeof p||"function"==typeof a.getSnapshotBeforeUpdate)||"function"!=typeof a.UNSAFE_componentWillReceiveProps&&"function"!=typeof a.componentWillReceiveProps||(l!==d||f!==s)&&Hi(t,a,r,s),Ri=!1,f=t.memoizedState,a.state=f,Bi(t,r,a,o);var m=t.memoizedState;l!==d||f!==m||_o.current||Ri?("function"==typeof p&&(Ui(t,n,p,r),m=t.memoizedState),(u=Ri||$i(t,n,u,r,f,m,s)||!1)?(c||"function"!=typeof a.UNSAFE_componentWillUpdate&&"function"!=typeof a.componentWillUpdate||("function"==typeof a.componentWillUpdate&&a.componentWillUpdate(r,m,s),"function"==typeof a.UNSAFE_componentWillUpdate&&a.UNSAFE_componentWillUpdate(r,m,s)),"function"==typeof a.componentDidUpdate&&(t.flags|=4),"function"==typeof a.getSnapshotBeforeUpdate&&(t.flags|=1024)):("function"!=typeof a.componentDidUpdate||l===e.memoizedProps&&f===e.memoizedState||(t.flags|=4),"function"!=typeof a.getSnapshotBeforeUpdate||l===e.memoizedProps&&f===e.memoizedState||(t.flags|=1024),t.memoizedProps=r,t.memoizedState=m),a.props=r,a.state=m,a.context=s,r=u):("function"!=typeof a.componentDidUpdate||l===e.memoizedProps&&f===e.memoizedState||(t.flags|=4),"function"!=typeof a.getSnapshotBeforeUpdate||l===e.memoizedProps&&f===e.memoizedState||(t.flags|=1024),r=!1)}return Dl(e,t,n,r,i,o)}function Dl(e,t,n,r,o,i){Cl(e,t);var a=0!=(128&t.flags);if(!r&&!a)return o&&Bo(t,n,!1),Hl(e,t,i);r=t.stateNode,vl.current=t;var l=a&&"function"!=typeof n.getDerivedStateFromError?null:r.render();return t.flags|=1,null!==e&&a?(t.child=Ji(t,e.child,null,i),t.child=Ji(t,null,l,i)):El(e,t,l,i),t.memoizedState=r.state,o&&Bo(t,n,!0),t.child}function _l(e){var t=e.stateNode;t.pendingContext?Ao(0,t.pendingContext,t.pendingContext!==t.context):t.context&&Ao(0,t.context,!1),oa(e,t.containerInfo)}function Rl(e,t,n,r,o){return mi(),hi(o),t.flags|=256,El(e,t,n,r),t.child}var Nl,Tl,jl,Al,Ml={dehydrated:null,treeContext:null,retryLane:0};function Ll(e){return{baseLanes:e,cachePool:null,transitions:null}}function Bl(e,t,n){var r,o=t.pendingProps,a=sa.current,l=!1,s=0!=(128&t.flags);if((r=s)||(r=(null===e||null!==e.memoizedState)&&0!=(2&a)),r?(l=!0,t.flags&=-129):null!==e&&null===e.memoizedState||(a|=1),Po(sa,1&a),null===e)return ci(t),null!==(e=t.memoizedState)&&null!==(e=e.dehydrated)?(0==(1&t.mode)?t.lanes=1:"$!"===e.data?t.lanes=8:t.lanes=1073741824,null):(s=o.children,e=o.fallback,l?(o=t.mode,l=t.child,s={mode:"hidden",children:s},0==(1&o)&&null!==l?(l.childLanes=0,l.pendingProps=s):l=Lu(s,o,0,null),e=Mu(e,o,n,null),l.return=t,e.return=t,l.sibling=e,t.child=l,t.child.memoizedState=Ll(n),t.memoizedState=Ml,e):Fl(t,s));if(null!==(a=e.memoizedState)&&null!==(r=a.dehydrated))return function(e,t,n,r,o,a,l){if(n)return 256&t.flags?(t.flags&=-257,zl(e,t,l,r=dl(Error(i(422))))):null!==t.memoizedState?(t.child=e.child,t.flags|=128,null):(a=r.fallback,o=t.mode,r=Lu({mode:"visible",children:r.children},o,0,null),(a=Mu(a,o,l,null)).flags|=2,r.return=t,a.return=t,r.sibling=a,t.child=r,0!=(1&t.mode)&&Ji(t,e.child,null,l),t.child.memoizedState=Ll(l),t.memoizedState=Ml,a);if(0==(1&t.mode))return zl(e,t,l,null);if("$!"===o.data){if(r=o.nextSibling&&o.nextSibling.dataset)var s=r.dgst;return r=s,zl(e,t,l,r=dl(a=Error(i(419)),r,void 0))}if(s=0!=(l&e.childLanes),wl||s){if(null!==(r=_s)){switch(l&-l){case 4:o=2;break;case 16:o=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:o=32;break;case 536870912:o=268435456;break;default:o=0}0!==(o=0!=(o&(r.suspendedLanes|l))?0:o)&&o!==a.retryLane&&(a.retryLane=o,_i(e,o),ru(r,e,o,-1))}return gu(),zl(e,t,l,r=dl(Error(i(421))))}return"$?"===o.data?(t.flags|=128,t.child=e.child,t=Iu.bind(null,e),o._reactRetry=t,null):(e=a.treeContext,oi=uo(o.nextSibling),ri=t,ii=!0,ai=null,null!==e&&(Qo[Yo++]=Jo,Qo[Yo++]=Xo,Qo[Yo++]=Ko,Jo=e.id,Xo=e.overflow,Ko=t),(t=Fl(t,r.children)).flags|=4096,t)}(e,t,s,o,r,a,n);if(l){l=o.fallback,s=t.mode,r=(a=e.child).sibling;var u={mode:"hidden",children:o.children};return 0==(1&s)&&t.child!==a?((o=t.child).childLanes=0,o.pendingProps=u,t.deletions=null):(o=ju(a,u)).subtreeFlags=14680064&a.subtreeFlags,null!==r?l=ju(r,l):(l=Mu(l,s,n,null)).flags|=2,l.return=t,o.return=t,o.sibling=l,t.child=o,o=l,l=t.child,s=null===(s=e.child.memoizedState)?Ll(n):{baseLanes:s.baseLanes|n,cachePool:null,transitions:s.transitions},l.memoizedState=s,l.childLanes=e.childLanes&~n,t.memoizedState=Ml,o}return e=(l=e.child).sibling,o=ju(l,{mode:"visible",children:o.children}),0==(1&t.mode)&&(o.lanes=n),o.return=t,o.sibling=null,null!==e&&(null===(n=t.deletions)?(t.deletions=[e],t.flags|=16):n.push(e)),t.child=o,t.memoizedState=null,o}function Fl(e,t){return(t=Lu({mode:"visible",children:t},e.mode,0,null)).return=e,e.child=t}function zl(e,t,n,r){return null!==r&&hi(r),Ji(t,e.child,null,n),(e=Fl(t,t.pendingProps.children)).flags|=2,t.memoizedState=null,e}function Ul(e,t,n){e.lanes|=t;var r=e.alternate;null!==r&&(r.lanes|=t),ki(e.return,t,n)}function Wl(e,t,n,r,o){var i=e.memoizedState;null===i?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:r,tail:n,tailMode:o}:(i.isBackwards=t,i.rendering=null,i.renderingStartTime=0,i.last=r,i.tail=n,i.tailMode=o)}function $l(e,t,n){var r=t.pendingProps,o=r.revealOrder,i=r.tail;if(El(e,t,r.children,n),0!=(2&(r=sa.current)))r=1&r|2,t.flags|=128;else{if(null!==e&&0!=(128&e.flags))e:for(e=t.child;null!==e;){if(13===e.tag)null!==e.memoizedState&&Ul(e,n,t);else if(19===e.tag)Ul(e,n,t);else if(null!==e.child){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;null===e.sibling;){if(null===e.return||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}r&=1}if(Po(sa,r),0==(1&t.mode))t.memoizedState=null;else switch(o){case"forwards":for(n=t.child,o=null;null!==n;)null!==(e=n.alternate)&&null===ua(e)&&(o=n),n=n.sibling;null===(n=o)?(o=t.child,t.child=null):(o=n.sibling,n.sibling=null),Wl(t,!1,o,n,i);break;case"backwards":for(n=null,o=t.child,t.child=null;null!==o;){if(null!==(e=o.alternate)&&null===ua(e)){t.child=o;break}e=o.sibling,o.sibling=n,n=o,o=e}Wl(t,!0,n,null,i);break;case"together":Wl(t,!1,null,null,void 0);break;default:t.memoizedState=null}return t.child}function Gl(e,t){0==(1&t.mode)&&null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2)}function Hl(e,t,n){if(null!==e&&(t.dependencies=e.dependencies),Ls|=t.lanes,0==(n&t.childLanes))return null;if(null!==e&&t.child!==e.child)throw Error(i(153));if(null!==t.child){for(n=ju(e=t.child,e.pendingProps),t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,(n=n.sibling=ju(e,e.pendingProps)).return=t;n.sibling=null}return t.child}function Vl(e,t){if(!ii)switch(e.tailMode){case"hidden":t=e.tail;for(var n=null;null!==t;)null!==t.alternate&&(n=t),t=t.sibling;null===n?e.tail=null:n.sibling=null;break;case"collapsed":n=e.tail;for(var r=null;null!==n;)null!==n.alternate&&(r=n),n=n.sibling;null===r?t||null===e.tail?e.tail=null:e.tail.sibling=null:r.sibling=null}}function ql(e){var t=null!==e.alternate&&e.alternate.child===e.child,n=0,r=0;if(t)for(var o=e.child;null!==o;)n|=o.lanes|o.childLanes,r|=14680064&o.subtreeFlags,r|=14680064&o.flags,o.return=e,o=o.sibling;else for(o=e.child;null!==o;)n|=o.lanes|o.childLanes,r|=o.subtreeFlags,r|=o.flags,o.return=e,o=o.sibling;return e.subtreeFlags|=r,e.childLanes=n,t}function Ql(e,t,n){var r=t.pendingProps;switch(ni(t),t.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return ql(t),null;case 1:case 17:return To(t.type)&&jo(),ql(t),null;case 3:return r=t.stateNode,ia(),Co(_o),Co(Do),da(),r.pendingContext&&(r.context=r.pendingContext,r.pendingContext=null),null!==e&&null!==e.child||(fi(t)?t.flags|=4:null===e||e.memoizedState.isDehydrated&&0==(256&t.flags)||(t.flags|=1024,null!==ai&&(lu(ai),ai=null))),Tl(e,t),ql(t),null;case 5:la(t);var o=ra(na.current);if(n=t.type,null!==e&&null!=t.stateNode)jl(e,t,n,r,o),e.ref!==t.ref&&(t.flags|=512,t.flags|=2097152);else{if(!r){if(null===t.stateNode)throw Error(i(166));return ql(t),null}if(e=ra(ea.current),fi(t)){r=t.stateNode,n=t.type;var a=t.memoizedProps;switch(r[po]=t,r[mo]=a,e=0!=(1&t.mode),n){case"dialog":Fr("cancel",r),Fr("close",r);break;case"iframe":case"object":case"embed":Fr("load",r);break;case"video":case"audio":for(o=0;o<\/script>",e=e.removeChild(e.firstChild)):"string"==typeof r.is?e=s.createElement(n,{is:r.is}):(e=s.createElement(n),"select"===n&&(s=e,r.multiple?s.multiple=!0:r.size&&(s.size=r.size))):e=s.createElementNS(e,n),e[po]=t,e[mo]=r,Nl(e,t,!1,!1),t.stateNode=e;e:{switch(s=ve(n,r),n){case"dialog":Fr("cancel",e),Fr("close",e),o=r;break;case"iframe":case"object":case"embed":Fr("load",e),o=r;break;case"video":case"audio":for(o=0;o$s&&(t.flags|=128,r=!0,Vl(a,!1),t.lanes=4194304)}else{if(!r)if(null!==(e=ua(s))){if(t.flags|=128,r=!0,null!==(n=e.updateQueue)&&(t.updateQueue=n,t.flags|=4),Vl(a,!0),null===a.tail&&"hidden"===a.tailMode&&!s.alternate&&!ii)return ql(t),null}else 2*Je()-a.renderingStartTime>$s&&1073741824!==n&&(t.flags|=128,r=!0,Vl(a,!1),t.lanes=4194304);a.isBackwards?(s.sibling=t.child,t.child=s):(null!==(n=a.last)?n.sibling=s:t.child=s,a.last=s)}return null!==a.tail?(t=a.tail,a.rendering=t,a.tail=t.sibling,a.renderingStartTime=Je(),t.sibling=null,n=sa.current,Po(sa,r?1&n|2:1&n),t):(ql(t),null);case 22:case 23:return fu(),r=null!==t.memoizedState,null!==e&&null!==e.memoizedState!==r&&(t.flags|=8192),r&&0!=(1&t.mode)?0!=(1073741824&Ts)&&(ql(t),6&t.subtreeFlags&&(t.flags|=8192)):ql(t),null;case 24:case 25:return null}throw Error(i(156,t.tag))}function Yl(e,t){switch(ni(t),t.tag){case 1:return To(t.type)&&jo(),65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 3:return ia(),Co(_o),Co(Do),da(),0!=(65536&(e=t.flags))&&0==(128&e)?(t.flags=-65537&e|128,t):null;case 5:return la(t),null;case 13:if(Co(sa),null!==(e=t.memoizedState)&&null!==e.dehydrated){if(null===t.alternate)throw Error(i(340));mi()}return 65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 19:return Co(sa),null;case 4:return ia(),null;case 10:return xi(t.type._context),null;case 22:case 23:return fu(),null;default:return null}}Nl=function(e,t){for(var n=t.child;null!==n;){if(5===n.tag||6===n.tag)e.appendChild(n.stateNode);else if(4!==n.tag&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===t)break;for(;null===n.sibling;){if(null===n.return||n.return===t)return;n=n.return}n.sibling.return=n.return,n=n.sibling}},Tl=function(){},jl=function(e,t,n,r){var o=e.memoizedProps;if(o!==r){e=t.stateNode,ra(ea.current);var i,a=null;switch(n){case"input":o=Y(e,o),r=Y(e,r),a=[];break;case"select":o=L({},o,{value:void 0}),r=L({},r,{value:void 0}),a=[];break;case"textarea":o=re(e,o),r=re(e,r),a=[];break;default:"function"!=typeof o.onClick&&"function"==typeof r.onClick&&(e.onclick=Zr)}for(c in be(n,r),n=null,o)if(!r.hasOwnProperty(c)&&o.hasOwnProperty(c)&&null!=o[c])if("style"===c){var s=o[c];for(i in s)s.hasOwnProperty(i)&&(n||(n={}),n[i]="")}else"dangerouslySetInnerHTML"!==c&&"children"!==c&&"suppressContentEditableWarning"!==c&&"suppressHydrationWarning"!==c&&"autoFocus"!==c&&(l.hasOwnProperty(c)?a||(a=[]):(a=a||[]).push(c,null));for(c in r){var u=r[c];if(s=null!=o?o[c]:void 0,r.hasOwnProperty(c)&&u!==s&&(null!=u||null!=s))if("style"===c)if(s){for(i in s)!s.hasOwnProperty(i)||u&&u.hasOwnProperty(i)||(n||(n={}),n[i]="");for(i in u)u.hasOwnProperty(i)&&s[i]!==u[i]&&(n||(n={}),n[i]=u[i])}else n||(a||(a=[]),a.push(c,n)),n=u;else"dangerouslySetInnerHTML"===c?(u=u?u.__html:void 0,s=s?s.__html:void 0,null!=u&&s!==u&&(a=a||[]).push(c,u)):"children"===c?"string"!=typeof u&&"number"!=typeof u||(a=a||[]).push(c,""+u):"suppressContentEditableWarning"!==c&&"suppressHydrationWarning"!==c&&(l.hasOwnProperty(c)?(null!=u&&"onScroll"===c&&Fr("scroll",e),a||s===u||(a=[])):(a=a||[]).push(c,u))}n&&(a=a||[]).push("style",n);var c=a;(t.updateQueue=c)&&(t.flags|=4)}},Al=function(e,t,n,r){n!==r&&(t.flags|=4)};var Kl=!1,Jl=!1,Xl="function"==typeof WeakSet?WeakSet:Set,Zl=null;function es(e,t){var n=e.ref;if(null!==n)if("function"==typeof n)try{n(null)}catch(n){Ou(e,t,n)}else n.current=null}function ts(e,t,n){try{n()}catch(n){Ou(e,t,n)}}var ns=!1;function rs(e,t,n){var r=t.updateQueue;if(null!==(r=null!==r?r.lastEffect:null)){var o=r=r.next;do{if((o.tag&e)===e){var i=o.destroy;o.destroy=void 0,void 0!==i&&ts(t,n,i)}o=o.next}while(o!==r)}}function os(e,t){if(null!==(t=null!==(t=t.updateQueue)?t.lastEffect:null)){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function is(e){var t=e.ref;if(null!==t){var n=e.stateNode;e.tag,e=n,"function"==typeof t?t(e):t.current=e}}function as(e){var t=e.alternate;null!==t&&(e.alternate=null,as(t)),e.child=null,e.deletions=null,e.sibling=null,5===e.tag&&null!==(t=e.stateNode)&&(delete t[po],delete t[mo],delete t[go],delete t[yo],delete t[bo]),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function ls(e){return 5===e.tag||3===e.tag||4===e.tag}function ss(e){e:for(;;){for(;null===e.sibling;){if(null===e.return||ls(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;5!==e.tag&&6!==e.tag&&18!==e.tag;){if(2&e.flags)continue e;if(null===e.child||4===e.tag)continue e;e.child.return=e,e=e.child}if(!(2&e.flags))return e.stateNode}}function us(e,t,n){var r=e.tag;if(5===r||6===r)e=e.stateNode,t?8===n.nodeType?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(8===n.nodeType?(t=n.parentNode).insertBefore(e,n):(t=n).appendChild(e),null!=(n=n._reactRootContainer)||null!==t.onclick||(t.onclick=Zr));else if(4!==r&&null!==(e=e.child))for(us(e,t,n),e=e.sibling;null!==e;)us(e,t,n),e=e.sibling}function cs(e,t,n){var r=e.tag;if(5===r||6===r)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(4!==r&&null!==(e=e.child))for(cs(e,t,n),e=e.sibling;null!==e;)cs(e,t,n),e=e.sibling}var ds=null,fs=!1;function ps(e,t,n){for(n=n.child;null!==n;)ms(e,t,n),n=n.sibling}function ms(e,t,n){if(it&&"function"==typeof it.onCommitFiberUnmount)try{it.onCommitFiberUnmount(ot,n)}catch(e){}switch(n.tag){case 5:Jl||es(n,t);case 6:var r=ds,o=fs;ds=null,ps(e,t,n),fs=o,null!==(ds=r)&&(fs?(e=ds,n=n.stateNode,8===e.nodeType?e.parentNode.removeChild(n):e.removeChild(n)):ds.removeChild(n.stateNode));break;case 18:null!==ds&&(fs?(e=ds,n=n.stateNode,8===e.nodeType?so(e.parentNode,n):1===e.nodeType&&so(e,n),Wt(e)):so(ds,n.stateNode));break;case 4:r=ds,o=fs,ds=n.stateNode.containerInfo,fs=!0,ps(e,t,n),ds=r,fs=o;break;case 0:case 11:case 14:case 15:if(!Jl&&null!==(r=n.updateQueue)&&null!==(r=r.lastEffect)){o=r=r.next;do{var i=o,a=i.destroy;i=i.tag,void 0!==a&&(0!=(2&i)||0!=(4&i))&&ts(n,t,a),o=o.next}while(o!==r)}ps(e,t,n);break;case 1:if(!Jl&&(es(n,t),"function"==typeof(r=n.stateNode).componentWillUnmount))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(e){Ou(n,t,e)}ps(e,t,n);break;case 21:ps(e,t,n);break;case 22:1&n.mode?(Jl=(r=Jl)||null!==n.memoizedState,ps(e,t,n),Jl=r):ps(e,t,n);break;default:ps(e,t,n)}}function hs(e){var t=e.updateQueue;if(null!==t){e.updateQueue=null;var n=e.stateNode;null===n&&(n=e.stateNode=new Xl),t.forEach((function(t){var r=Du.bind(null,e,t);n.has(t)||(n.add(t),t.then(r,r))}))}}function gs(e,t){var n=t.deletions;if(null!==n)for(var r=0;ro&&(o=l),r&=~a}if(r=o,10<(r=(120>(r=Je()-r)?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*Os(r/1960))-r)){e.timeoutHandle=ro(Su.bind(null,e,Us,Gs),r);break}Su(e,Us,Gs);break;default:throw Error(i(329))}}}return ou(e,Je()),e.callbackNode===n?iu.bind(null,e):null}function au(e,t){var n=zs;return e.current.memoizedState.isDehydrated&&(pu(e,t).flags|=256),2!==(e=yu(e,t))&&(t=Us,Us=n,null!==t&&lu(t)),e}function lu(e){null===Us?Us=e:Us.push.apply(Us,e)}function su(e,t){for(t&=~Fs,t&=~Bs,e.suspendedLanes|=t,e.pingedLanes&=~t,e=e.expirationTimes;0e?16:e,null===Ys)var r=!1;else{if(e=Ys,Ys=null,Ks=0,0!=(6&Ds))throw Error(i(331));var o=Ds;for(Ds|=4,Zl=e.current;null!==Zl;){var a=Zl,l=a.child;if(0!=(16&Zl.flags)){var s=a.deletions;if(null!==s){for(var u=0;uJe()-Ws?pu(e,0):Fs|=n),ou(e,t)}function Pu(e,t){0===t&&(0==(1&e.mode)?t=1:(t=ct,0==(130023424&(ct<<=1))&&(ct=4194304)));var n=tu();null!==(e=_i(e,t))&&(yt(e,t,n),ou(e,n))}function Iu(e){var t=e.memoizedState,n=0;null!==t&&(n=t.retryLane),Pu(e,n)}function Du(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,o=e.memoizedState;null!==o&&(n=o.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(i(314))}null!==r&&r.delete(t),Pu(e,n)}function _u(e,t){return qe(e,t)}function Ru(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Nu(e,t,n,r){return new Ru(e,t,n,r)}function Tu(e){return!(!(e=e.prototype)||!e.isReactComponent)}function ju(e,t){var n=e.alternate;return null===n?((n=Nu(e.tag,t,e.key,e.mode)).elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=14680064&e.flags,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=null===t?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Au(e,t,n,r,o,a){var l=2;if(r=e,"function"==typeof e)Tu(e)&&(l=1);else if("string"==typeof e)l=5;else e:switch(e){case x:return Mu(n.children,o,a,t);case k:l=8,o|=8;break;case O:return(e=Nu(12,n,t,2|o)).elementType=O,e.lanes=a,e;case D:return(e=Nu(13,n,t,o)).elementType=D,e.lanes=a,e;case _:return(e=Nu(19,n,t,o)).elementType=_,e.lanes=a,e;case T:return Lu(n,o,a,t);default:if("object"==typeof e&&null!==e)switch(e.$$typeof){case C:l=10;break e;case P:l=9;break e;case I:l=11;break e;case R:l=14;break e;case N:l=16,r=null;break e}throw Error(i(130,null==e?e:typeof e,""))}return(t=Nu(l,n,t,o)).elementType=e,t.type=r,t.lanes=a,t}function Mu(e,t,n,r){return(e=Nu(7,e,r,t)).lanes=n,e}function Lu(e,t,n,r){return(e=Nu(22,e,r,t)).elementType=T,e.lanes=n,e.stateNode={isHidden:!1},e}function Bu(e,t,n){return(e=Nu(6,e,null,t)).lanes=n,e}function Fu(e,t,n){return(t=Nu(4,null!==e.children?e.children:[],e.key,t)).lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function zu(e,t,n,r,o){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=gt(0),this.expirationTimes=gt(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=gt(0),this.identifierPrefix=r,this.onRecoverableError=o,this.mutableSourceEagerHydrationData=null}function Uu(e,t,n,r,o,i,a,l,s){return e=new zu(e,t,n,l,s),1===t?(t=1,!0===i&&(t|=8)):t=0,i=Nu(3,null,null,t),e.current=i,i.stateNode=e,i.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},Ni(i),e}function Wu(e){if(!e)return Io;e:{if(We(e=e._reactInternals)!==e||1!==e.tag)throw Error(i(170));var t=e;do{switch(t.tag){case 3:t=t.stateNode.context;break e;case 1:if(To(t.type)){t=t.stateNode.__reactInternalMemoizedMergedChildContext;break e}}t=t.return}while(null!==t);throw Error(i(171))}if(1===e.tag){var n=e.type;if(To(n))return Mo(e,n,t)}return t}function $u(e,t,n,r,o,i,a,l,s){return(e=Uu(n,r,!0,e,0,i,0,l,s)).context=Wu(null),n=e.current,(i=ji(r=tu(),o=nu(n))).callback=null!=t?t:null,Ai(n,i,o),e.current.lanes=o,yt(e,o,r),ou(e,r),e}function Gu(e,t,n,r){var o=t.current,i=tu(),a=nu(o);return n=Wu(n),null===t.context?t.context=n:t.pendingContext=n,(t=ji(i,a)).payload={element:e},null!==(r=void 0===r?null:r)&&(t.callback=r),null!==(e=Ai(o,t,a))&&(ru(e,o,a,i),Mi(e,o,a)),a}function Hu(e){return(e=e.current).child?(e.child.tag,e.child.stateNode):null}function Vu(e,t){if(null!==(e=e.memoizedState)&&null!==e.dehydrated){var n=e.retryLane;e.retryLane=0!==n&&n{"use strict";var r=n(935);t.s=r.createRoot,r.hydrateRoot},935:(e,t,n)=>{"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(e){console.error(e)}}(),e.exports=n(448)},251:(e,t,n)=>{"use strict";var r=n(294),o=Symbol.for("react.element"),i=Symbol.for("react.fragment"),a=Object.prototype.hasOwnProperty,l=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,s={key:!0,ref:!0,__self:!0,__source:!0};function u(e,t,n){var r,i={},u=null,c=null;for(r in void 0!==n&&(u=""+n),void 0!==t.key&&(u=""+t.key),void 0!==t.ref&&(c=t.ref),t)a.call(t,r)&&!s.hasOwnProperty(r)&&(i[r]=t[r]);if(e&&e.defaultProps)for(r in t=e.defaultProps)void 0===i[r]&&(i[r]=t[r]);return{$$typeof:o,type:e,key:u,ref:c,props:i,_owner:l.current}}t.Fragment=i,t.jsx=u,t.jsxs=u},408:(e,t)=>{"use strict";var n=Symbol.for("react.element"),r=Symbol.for("react.portal"),o=Symbol.for("react.fragment"),i=Symbol.for("react.strict_mode"),a=Symbol.for("react.profiler"),l=Symbol.for("react.provider"),s=Symbol.for("react.context"),u=Symbol.for("react.forward_ref"),c=Symbol.for("react.suspense"),d=Symbol.for("react.memo"),f=Symbol.for("react.lazy"),p=Symbol.iterator,m={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},h=Object.assign,g={};function y(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n||m}function b(){}function v(e,t,n){this.props=e,this.context=t,this.refs=g,this.updater=n||m}y.prototype.isReactComponent={},y.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")},y.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},b.prototype=y.prototype;var w=v.prototype=new b;w.constructor=v,h(w,y.prototype),w.isPureReactComponent=!0;var E=Array.isArray,S=Object.prototype.hasOwnProperty,x={current:null},k={key:!0,ref:!0,__self:!0,__source:!0};function O(e,t,r){var o,i={},a=null,l=null;if(null!=t)for(o in void 0!==t.ref&&(l=t.ref),void 0!==t.key&&(a=""+t.key),t)S.call(t,o)&&!k.hasOwnProperty(o)&&(i[o]=t[o]);var s=arguments.length-2;if(1===s)i.children=r;else if(1{"use strict";e.exports=n(408)},893:(e,t,n)=>{"use strict";e.exports=n(251)},53:(e,t)=>{"use strict";function n(e,t){var n=e.length;e.push(t);e:for(;0>>1,o=e[r];if(!(0>>1;ri(s,n))ui(c,s)?(e[r]=c,e[u]=n,r=u):(e[r]=s,e[l]=n,r=l);else{if(!(ui(c,n)))break e;e[r]=c,e[u]=n,r=u}}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}if("object"==typeof performance&&"function"==typeof performance.now){var a=performance;t.unstable_now=function(){return a.now()}}else{var l=Date,s=l.now();t.unstable_now=function(){return l.now()-s}}var u=[],c=[],d=1,f=null,p=3,m=!1,h=!1,g=!1,y="function"==typeof setTimeout?setTimeout:null,b="function"==typeof clearTimeout?clearTimeout:null,v="undefined"!=typeof setImmediate?setImmediate:null;function w(e){for(var t=r(c);null!==t;){if(null===t.callback)o(c);else{if(!(t.startTime<=e))break;o(c),t.sortIndex=t.expirationTime,n(u,t)}t=r(c)}}function E(e){if(g=!1,w(e),!h)if(null!==r(u))h=!0,T(S);else{var t=r(c);null!==t&&j(E,t.startTime-e)}}function S(e,n){h=!1,g&&(g=!1,b(C),C=-1),m=!0;var i=p;try{for(w(n),f=r(u);null!==f&&(!(f.expirationTime>n)||e&&!D());){var a=f.callback;if("function"==typeof a){f.callback=null,p=f.priorityLevel;var l=a(f.expirationTime<=n);n=t.unstable_now(),"function"==typeof l?f.callback=l:f===r(u)&&o(u),w(n)}else o(u);f=r(u)}if(null!==f)var s=!0;else{var d=r(c);null!==d&&j(E,d.startTime-n),s=!1}return s}finally{f=null,p=i,m=!1}}"undefined"!=typeof navigator&&void 0!==navigator.scheduling&&void 0!==navigator.scheduling.isInputPending&&navigator.scheduling.isInputPending.bind(navigator.scheduling);var x,k=!1,O=null,C=-1,P=5,I=-1;function D(){return!(t.unstable_now()-Ie||125a?(e.sortIndex=i,n(c,e),null===r(u)&&e===r(c)&&(g?(b(C),C=-1):g=!0,j(E,i-a))):(e.sortIndex=l,n(u,e),h||m||(h=!0,T(S))),e},t.unstable_shouldYield=D,t.unstable_wrapCallback=function(e){var t=p;return function(){var n=p;p=t;try{return e.apply(this,arguments)}finally{p=n}}}},840:(e,t,n)=>{"use strict";e.exports=n(53)},250:(e,t,n)=>{"use strict";var r=n(294),o="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t},i=r.useState,a=r.useEffect,l=r.useLayoutEffect,s=r.useDebugValue;function u(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!o(e,n)}catch(e){return!0}}var c="undefined"==typeof window||void 0===window.document||void 0===window.document.createElement?function(e,t){return t()}:function(e,t){var n=t(),r=i({inst:{value:n,getSnapshot:t}}),o=r[0].inst,c=r[1];return l((function(){o.value=n,o.getSnapshot=t,u(o)&&c({inst:o})}),[e,n,t]),a((function(){return u(o)&&c({inst:o}),e((function(){u(o)&&c({inst:o})}))}),[e]),s(n),n};t.useSyncExternalStore=void 0!==r.useSyncExternalStore?r.useSyncExternalStore:c},139:(e,t,n)=>{"use strict";var r=n(294),o=n(688),i="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t},a=o.useSyncExternalStore,l=r.useRef,s=r.useEffect,u=r.useMemo,c=r.useDebugValue;t.useSyncExternalStoreWithSelector=function(e,t,n,r,o){var d=l(null);if(null===d.current){var f={hasValue:!1,value:null};d.current=f}else f=d.current;d=u((function(){function e(e){if(!s){if(s=!0,a=e,e=r(e),void 0!==o&&f.hasValue){var t=f.value;if(o(t,e))return l=t}return l=e}if(t=l,i(a,e))return t;var n=r(e);return void 0!==o&&o(t,n)?t:(a=e,l=n)}var a,l,s=!1,u=void 0===n?null:n;return[function(){return e(t())},null===u?void 0:function(){return e(u())}]}),[t,n,r,o]);var p=a(e,d[0],d[1]);return s((function(){f.hasValue=!0,f.value=p}),[p]),c(p),p}},688:(e,t,n)=>{"use strict";e.exports=n(250)},798:(e,t,n)=>{"use strict";e.exports=n(139)},473:e=>{"use strict";e.exports=function(){}}},t={};function n(r){var o=t[r];if(void 0!==o)return o.exports;var i=t[r]={exports:{}};return e[r].call(i.exports,i,i.exports,n),i.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{"use strict";var e=n(294),t=n(745),r=n(697),o=n.n(r),i=n(962);function a(e,t){return e.contains?e.contains(t):e.compareDocumentPosition?e===t||!!(16&e.compareDocumentPosition(t)):void 0}function l(){const t=(0,e.useRef)(!0),n=(0,e.useRef)((()=>t.current));return(0,e.useEffect)((()=>(t.current=!0,()=>{t.current=!1})),[]),n.current}const s=2**31-1;function u(e,t,n){const r=n-Date.now();e.current=r<=s?setTimeout(t,r):setTimeout((()=>u(e,t,n)),s)}function c(){const t=l(),n=(0,e.useRef)();return function(t){const n=function(t){const n=(0,e.useRef)(t);return n.current=t,n}(t);(0,e.useEffect)((()=>()=>n.current()),[])}((()=>clearTimeout(n.current))),(0,e.useMemo)((()=>{const e=()=>clearTimeout(n.current);return{set:function(r,o=0){t()&&(e(),o<=s?n.current=setTimeout(r,o):u(n,r,Date.now()+o))},clear:e}}),[])}var d=n(473),f=n.n(d);n(143);const p=e=>e&&"function"!=typeof e?t=>{e.current=t}:e,m=function(t,n){return(0,e.useMemo)((()=>function(e,t){const n=p(e),r=p(t);return e=>{n&&n(e),r&&r(e)}}(t,n)),[t,n])};var h=n(184),g=n.n(h),y=n(935);function b(){return(0,e.useState)(null)}var v=Object.prototype.hasOwnProperty;function w(e,t,n){for(n of e.keys())if(E(n,t))return n}function E(e,t){var n,r,o;if(e===t)return!0;if(e&&t&&(n=e.constructor)===t.constructor){if(n===Date)return e.getTime()===t.getTime();if(n===RegExp)return e.toString()===t.toString();if(n===Array){if((r=e.length)===t.length)for(;r--&&E(e[r],t[r]););return-1===r}if(n===Set){if(e.size!==t.size)return!1;for(r of e){if((o=r)&&"object"==typeof o&&!(o=w(t,o)))return!1;if(!t.has(o))return!1}return!0}if(n===Map){if(e.size!==t.size)return!1;for(r of e){if((o=r[0])&&"object"==typeof o&&!(o=w(t,o)))return!1;if(!E(r[1],t.get(o)))return!1}return!0}if(n===ArrayBuffer)e=new Uint8Array(e),t=new Uint8Array(t);else if(n===DataView){if((r=e.byteLength)===t.byteLength)for(;r--&&e.getInt8(r)===t.getInt8(r););return-1===r}if(ArrayBuffer.isView(e)){if((r=e.byteLength)===t.byteLength)for(;r--&&e[r]===t[r];);return-1===r}if(!n||"object"==typeof e){for(n in r=0,e){if(v.call(e,n)&&++r&&!v.call(t,n))return!1;if(!(n in t)||!E(e[n],t[n]))return!1}return Object.keys(t).length===r}}return e!=e&&t!=t}function S(e){return e.split("-")[0]}function x(e){if(null==e)return window;if("[object Window]"!==e.toString()){var t=e.ownerDocument;return t&&t.defaultView||window}return e}function k(e){return e instanceof x(e).Element||e instanceof Element}function O(e){return e instanceof x(e).HTMLElement||e instanceof HTMLElement}function C(e){return"undefined"!=typeof ShadowRoot&&(e instanceof x(e).ShadowRoot||e instanceof ShadowRoot)}var P=Math.max,I=Math.min,D=Math.round;function _(){var e=navigator.userAgentData;return null!=e&&e.brands&&Array.isArray(e.brands)?e.brands.map((function(e){return e.brand+"/"+e.version})).join(" "):navigator.userAgent}function R(){return!/^((?!chrome|android).)*safari/i.test(_())}function N(e,t,n){void 0===t&&(t=!1),void 0===n&&(n=!1);var r=e.getBoundingClientRect(),o=1,i=1;t&&O(e)&&(o=e.offsetWidth>0&&D(r.width)/e.offsetWidth||1,i=e.offsetHeight>0&&D(r.height)/e.offsetHeight||1);var a=(k(e)?x(e):window).visualViewport,l=!R()&&n,s=(r.left+(l&&a?a.offsetLeft:0))/o,u=(r.top+(l&&a?a.offsetTop:0))/i,c=r.width/o,d=r.height/i;return{width:c,height:d,top:u,right:s+c,bottom:u+d,left:s,x:s,y:u}}function T(e){var t=N(e),n=e.offsetWidth,r=e.offsetHeight;return Math.abs(t.width-n)<=1&&(n=t.width),Math.abs(t.height-r)<=1&&(r=t.height),{x:e.offsetLeft,y:e.offsetTop,width:n,height:r}}function j(e,t){var n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&C(n)){var r=t;do{if(r&&e.isSameNode(r))return!0;r=r.parentNode||r.host}while(r)}return!1}function A(e){return e?(e.nodeName||"").toLowerCase():null}function M(e){return x(e).getComputedStyle(e)}function L(e){return["table","td","th"].indexOf(A(e))>=0}function B(e){return((k(e)?e.ownerDocument:e.document)||window.document).documentElement}function F(e){return"html"===A(e)?e:e.assignedSlot||e.parentNode||(C(e)?e.host:null)||B(e)}function z(e){return O(e)&&"fixed"!==M(e).position?e.offsetParent:null}function U(e){for(var t=x(e),n=z(e);n&&L(n)&&"static"===M(n).position;)n=z(n);return n&&("html"===A(n)||"body"===A(n)&&"static"===M(n).position)?t:n||function(e){var t=/firefox/i.test(_());if(/Trident/i.test(_())&&O(e)&&"fixed"===M(e).position)return null;var n=F(e);for(C(n)&&(n=n.host);O(n)&&["html","body"].indexOf(A(n))<0;){var r=M(n);if("none"!==r.transform||"none"!==r.perspective||"paint"===r.contain||-1!==["transform","perspective"].indexOf(r.willChange)||t&&"filter"===r.willChange||t&&r.filter&&"none"!==r.filter)return n;n=n.parentNode}return null}(e)||t}function W(e){return["top","bottom"].indexOf(e)>=0?"x":"y"}function $(e,t,n){return P(e,I(t,n))}function G(e){return Object.assign({},{top:0,right:0,bottom:0,left:0},e)}function H(e,t){return t.reduce((function(t,n){return t[n]=e,t}),{})}var V="top",q="bottom",Q="right",Y="left",K="auto",J=[V,q,Q,Y],X="start",Z="end",ee="viewport",te="popper",ne=J.reduce((function(e,t){return e.concat([t+"-"+X,t+"-"+Z])}),[]),re=[].concat(J,[K]).reduce((function(e,t){return e.concat([t,t+"-"+X,t+"-"+Z])}),[]),oe=["beforeRead","read","afterRead","beforeMain","main","afterMain","beforeWrite","write","afterWrite"];const ie={name:"arrow",enabled:!0,phase:"main",fn:function(e){var t,n=e.state,r=e.name,o=e.options,i=n.elements.arrow,a=n.modifiersData.popperOffsets,l=S(n.placement),s=W(l),u=[Y,Q].indexOf(l)>=0?"height":"width";if(i&&a){var c=function(e,t){return G("number"!=typeof(e="function"==typeof e?e(Object.assign({},t.rects,{placement:t.placement})):e)?e:H(e,J))}(o.padding,n),d=T(i),f="y"===s?V:Y,p="y"===s?q:Q,m=n.rects.reference[u]+n.rects.reference[s]-a[s]-n.rects.popper[u],h=a[s]-n.rects.reference[s],g=U(i),y=g?"y"===s?g.clientHeight||0:g.clientWidth||0:0,b=m/2-h/2,v=c[f],w=y-d[u]-c[p],E=y/2-d[u]/2+b,x=$(v,E,w),k=s;n.modifiersData[r]=((t={})[k]=x,t.centerOffset=x-E,t)}},effect:function(e){var t=e.state,n=e.options.element,r=void 0===n?"[data-popper-arrow]":n;null!=r&&("string"!=typeof r||(r=t.elements.popper.querySelector(r)))&&j(t.elements.popper,r)&&(t.elements.arrow=r)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function ae(e){return e.split("-")[1]}var le={top:"auto",right:"auto",bottom:"auto",left:"auto"};function se(e){var t,n=e.popper,r=e.popperRect,o=e.placement,i=e.variation,a=e.offsets,l=e.position,s=e.gpuAcceleration,u=e.adaptive,c=e.roundOffsets,d=e.isFixed,f=a.x,p=void 0===f?0:f,m=a.y,h=void 0===m?0:m,g="function"==typeof c?c({x:p,y:h}):{x:p,y:h};p=g.x,h=g.y;var y=a.hasOwnProperty("x"),b=a.hasOwnProperty("y"),v=Y,w=V,E=window;if(u){var S=U(n),k="clientHeight",O="clientWidth";S===x(n)&&"static"!==M(S=B(n)).position&&"absolute"===l&&(k="scrollHeight",O="scrollWidth"),(o===V||(o===Y||o===Q)&&i===Z)&&(w=q,h-=(d&&S===E&&E.visualViewport?E.visualViewport.height:S[k])-r.height,h*=s?1:-1),o!==Y&&(o!==V&&o!==q||i!==Z)||(v=Q,p-=(d&&S===E&&E.visualViewport?E.visualViewport.width:S[O])-r.width,p*=s?1:-1)}var C,P=Object.assign({position:l},u&&le),I=!0===c?function(e,t){var n=e.x,r=e.y,o=t.devicePixelRatio||1;return{x:D(n*o)/o||0,y:D(r*o)/o||0}}({x:p,y:h},x(n)):{x:p,y:h};return p=I.x,h=I.y,s?Object.assign({},P,((C={})[w]=b?"0":"",C[v]=y?"0":"",C.transform=(E.devicePixelRatio||1)<=1?"translate("+p+"px, "+h+"px)":"translate3d("+p+"px, "+h+"px, 0)",C)):Object.assign({},P,((t={})[w]=b?h+"px":"",t[v]=y?p+"px":"",t.transform="",t))}const ue={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(e){var t=e.state,n=e.options,r=n.gpuAcceleration,o=void 0===r||r,i=n.adaptive,a=void 0===i||i,l=n.roundOffsets,s=void 0===l||l,u={placement:S(t.placement),variation:ae(t.placement),popper:t.elements.popper,popperRect:t.rects.popper,gpuAcceleration:o,isFixed:"fixed"===t.options.strategy};null!=t.modifiersData.popperOffsets&&(t.styles.popper=Object.assign({},t.styles.popper,se(Object.assign({},u,{offsets:t.modifiersData.popperOffsets,position:t.options.strategy,adaptive:a,roundOffsets:s})))),null!=t.modifiersData.arrow&&(t.styles.arrow=Object.assign({},t.styles.arrow,se(Object.assign({},u,{offsets:t.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:s})))),t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-placement":t.placement})},data:{}};var ce={passive:!0};const de={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(e){var t=e.state,n=e.instance,r=e.options,o=r.scroll,i=void 0===o||o,a=r.resize,l=void 0===a||a,s=x(t.elements.popper),u=[].concat(t.scrollParents.reference,t.scrollParents.popper);return i&&u.forEach((function(e){e.addEventListener("scroll",n.update,ce)})),l&&s.addEventListener("resize",n.update,ce),function(){i&&u.forEach((function(e){e.removeEventListener("scroll",n.update,ce)})),l&&s.removeEventListener("resize",n.update,ce)}},data:{}};var fe={left:"right",right:"left",bottom:"top",top:"bottom"};function pe(e){return e.replace(/left|right|bottom|top/g,(function(e){return fe[e]}))}var me={start:"end",end:"start"};function he(e){return e.replace(/start|end/g,(function(e){return me[e]}))}function ge(e){var t=x(e);return{scrollLeft:t.pageXOffset,scrollTop:t.pageYOffset}}function ye(e){return N(B(e)).left+ge(e).scrollLeft}function be(e){var t=M(e),n=t.overflow,r=t.overflowX,o=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+o+r)}function ve(e){return["html","body","#document"].indexOf(A(e))>=0?e.ownerDocument.body:O(e)&&be(e)?e:ve(F(e))}function we(e,t){var n;void 0===t&&(t=[]);var r=ve(e),o=r===(null==(n=e.ownerDocument)?void 0:n.body),i=x(r),a=o?[i].concat(i.visualViewport||[],be(r)?r:[]):r,l=t.concat(a);return o?l:l.concat(we(F(a)))}function Ee(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function Se(e,t,n){return t===ee?Ee(function(e,t){var n=x(e),r=B(e),o=n.visualViewport,i=r.clientWidth,a=r.clientHeight,l=0,s=0;if(o){i=o.width,a=o.height;var u=R();(u||!u&&"fixed"===t)&&(l=o.offsetLeft,s=o.offsetTop)}return{width:i,height:a,x:l+ye(e),y:s}}(e,n)):k(t)?function(e,t){var n=N(e,!1,"fixed"===t);return n.top=n.top+e.clientTop,n.left=n.left+e.clientLeft,n.bottom=n.top+e.clientHeight,n.right=n.left+e.clientWidth,n.width=e.clientWidth,n.height=e.clientHeight,n.x=n.left,n.y=n.top,n}(t,n):Ee(function(e){var t,n=B(e),r=ge(e),o=null==(t=e.ownerDocument)?void 0:t.body,i=P(n.scrollWidth,n.clientWidth,o?o.scrollWidth:0,o?o.clientWidth:0),a=P(n.scrollHeight,n.clientHeight,o?o.scrollHeight:0,o?o.clientHeight:0),l=-r.scrollLeft+ye(e),s=-r.scrollTop;return"rtl"===M(o||n).direction&&(l+=P(n.clientWidth,o?o.clientWidth:0)-i),{width:i,height:a,x:l,y:s}}(B(e)))}function xe(e){var t,n=e.reference,r=e.element,o=e.placement,i=o?S(o):null,a=o?ae(o):null,l=n.x+n.width/2-r.width/2,s=n.y+n.height/2-r.height/2;switch(i){case V:t={x:l,y:n.y-r.height};break;case q:t={x:l,y:n.y+n.height};break;case Q:t={x:n.x+n.width,y:s};break;case Y:t={x:n.x-r.width,y:s};break;default:t={x:n.x,y:n.y}}var u=i?W(i):null;if(null!=u){var c="y"===u?"height":"width";switch(a){case X:t[u]=t[u]-(n[c]/2-r[c]/2);break;case Z:t[u]=t[u]+(n[c]/2-r[c]/2)}}return t}function ke(e,t){void 0===t&&(t={});var n=t,r=n.placement,o=void 0===r?e.placement:r,i=n.strategy,a=void 0===i?e.strategy:i,l=n.boundary,s=void 0===l?"clippingParents":l,u=n.rootBoundary,c=void 0===u?ee:u,d=n.elementContext,f=void 0===d?te:d,p=n.altBoundary,m=void 0!==p&&p,h=n.padding,g=void 0===h?0:h,y=G("number"!=typeof g?g:H(g,J)),b=f===te?"reference":te,v=e.rects.popper,w=e.elements[m?b:f],E=function(e,t,n,r){var o="clippingParents"===t?function(e){var t=we(F(e)),n=["absolute","fixed"].indexOf(M(e).position)>=0&&O(e)?U(e):e;return k(n)?t.filter((function(e){return k(e)&&j(e,n)&&"body"!==A(e)})):[]}(e):[].concat(t),i=[].concat(o,[n]),a=i[0],l=i.reduce((function(t,n){var o=Se(e,n,r);return t.top=P(o.top,t.top),t.right=I(o.right,t.right),t.bottom=I(o.bottom,t.bottom),t.left=P(o.left,t.left),t}),Se(e,a,r));return l.width=l.right-l.left,l.height=l.bottom-l.top,l.x=l.left,l.y=l.top,l}(k(w)?w:w.contextElement||B(e.elements.popper),s,c,a),S=N(e.elements.reference),x=xe({reference:S,element:v,strategy:"absolute",placement:o}),C=Ee(Object.assign({},v,x)),D=f===te?C:S,_={top:E.top-D.top+y.top,bottom:D.bottom-E.bottom+y.bottom,left:E.left-D.left+y.left,right:D.right-E.right+y.right},R=e.modifiersData.offset;if(f===te&&R){var T=R[o];Object.keys(_).forEach((function(e){var t=[Q,q].indexOf(e)>=0?1:-1,n=[V,q].indexOf(e)>=0?"y":"x";_[e]+=T[n]*t}))}return _}const Oe={name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name;if(!t.modifiersData[r]._skip){for(var o=n.mainAxis,i=void 0===o||o,a=n.altAxis,l=void 0===a||a,s=n.fallbackPlacements,u=n.padding,c=n.boundary,d=n.rootBoundary,f=n.altBoundary,p=n.flipVariations,m=void 0===p||p,h=n.allowedAutoPlacements,g=t.options.placement,y=S(g),b=s||(y!==g&&m?function(e){if(S(e)===K)return[];var t=pe(e);return[he(e),t,he(t)]}(g):[pe(g)]),v=[g].concat(b).reduce((function(e,n){return e.concat(S(n)===K?function(e,t){void 0===t&&(t={});var n=t,r=n.placement,o=n.boundary,i=n.rootBoundary,a=n.padding,l=n.flipVariations,s=n.allowedAutoPlacements,u=void 0===s?re:s,c=ae(r),d=c?l?ne:ne.filter((function(e){return ae(e)===c})):J,f=d.filter((function(e){return u.indexOf(e)>=0}));0===f.length&&(f=d);var p=f.reduce((function(t,n){return t[n]=ke(e,{placement:n,boundary:o,rootBoundary:i,padding:a})[S(n)],t}),{});return Object.keys(p).sort((function(e,t){return p[e]-p[t]}))}(t,{placement:n,boundary:c,rootBoundary:d,padding:u,flipVariations:m,allowedAutoPlacements:h}):n)}),[]),w=t.rects.reference,E=t.rects.popper,x=new Map,k=!0,O=v[0],C=0;C=0,R=_?"width":"height",N=ke(t,{placement:P,boundary:c,rootBoundary:d,altBoundary:f,padding:u}),T=_?D?Q:Y:D?q:V;w[R]>E[R]&&(T=pe(T));var j=pe(T),A=[];if(i&&A.push(N[I]<=0),l&&A.push(N[T]<=0,N[j]<=0),A.every((function(e){return e}))){O=P,k=!1;break}x.set(P,A)}if(k)for(var M=function(e){var t=v.find((function(t){var n=x.get(t);if(n)return n.slice(0,e).every((function(e){return e}))}));if(t)return O=t,"break"},L=m?3:1;L>0&&"break"!==M(L);L--);t.placement!==O&&(t.modifiersData[r]._skip=!0,t.placement=O,t.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function Ce(e,t,n){return void 0===n&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function Pe(e){return[V,Q,q,Y].some((function(t){return e[t]>=0}))}const Ie={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(e){var t=e.state,n=e.options,r=e.name,o=n.offset,i=void 0===o?[0,0]:o,a=re.reduce((function(e,n){return e[n]=function(e,t,n){var r=S(e),o=[Y,V].indexOf(r)>=0?-1:1,i="function"==typeof n?n(Object.assign({},t,{placement:e})):n,a=i[0],l=i[1];return a=a||0,l=(l||0)*o,[Y,Q].indexOf(r)>=0?{x:l,y:a}:{x:a,y:l}}(n,t.rects,i),e}),{}),l=a[t.placement],s=l.x,u=l.y;null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=s,t.modifiersData.popperOffsets.y+=u),t.modifiersData[r]=a}},De={name:"preventOverflow",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name,o=n.mainAxis,i=void 0===o||o,a=n.altAxis,l=void 0!==a&&a,s=n.boundary,u=n.rootBoundary,c=n.altBoundary,d=n.padding,f=n.tether,p=void 0===f||f,m=n.tetherOffset,h=void 0===m?0:m,g=ke(t,{boundary:s,rootBoundary:u,padding:d,altBoundary:c}),y=S(t.placement),b=ae(t.placement),v=!b,w=W(y),E="x"===w?"y":"x",x=t.modifiersData.popperOffsets,k=t.rects.reference,O=t.rects.popper,C="function"==typeof h?h(Object.assign({},t.rects,{placement:t.placement})):h,D="number"==typeof C?{mainAxis:C,altAxis:C}:Object.assign({mainAxis:0,altAxis:0},C),_=t.modifiersData.offset?t.modifiersData.offset[t.placement]:null,R={x:0,y:0};if(x){if(i){var N,j="y"===w?V:Y,A="y"===w?q:Q,M="y"===w?"height":"width",L=x[w],B=L+g[j],F=L-g[A],z=p?-O[M]/2:0,G=b===X?k[M]:O[M],H=b===X?-O[M]:-k[M],K=t.elements.arrow,J=p&&K?T(K):{width:0,height:0},Z=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},ee=Z[j],te=Z[A],ne=$(0,k[M],J[M]),re=v?k[M]/2-z-ne-ee-D.mainAxis:G-ne-ee-D.mainAxis,oe=v?-k[M]/2+z+ne+te+D.mainAxis:H+ne+te+D.mainAxis,ie=t.elements.arrow&&U(t.elements.arrow),le=ie?"y"===w?ie.clientTop||0:ie.clientLeft||0:0,se=null!=(N=null==_?void 0:_[w])?N:0,ue=L+oe-se,ce=$(p?I(B,L+re-se-le):B,L,p?P(F,ue):F);x[w]=ce,R[w]=ce-L}if(l){var de,fe="x"===w?V:Y,pe="x"===w?q:Q,me=x[E],he="y"===E?"height":"width",ge=me+g[fe],ye=me-g[pe],be=-1!==[V,Y].indexOf(y),ve=null!=(de=null==_?void 0:_[E])?de:0,we=be?ge:me-k[he]-O[he]-ve+D.altAxis,Ee=be?me+k[he]+O[he]-ve-D.altAxis:ye,Se=p&&be?function(e,t,n){var r=$(e,t,n);return r>n?n:r}(we,me,Ee):$(p?we:ge,me,p?Ee:ye);x[E]=Se,R[E]=Se-me}t.modifiersData[r]=R}},requiresIfExists:["offset"]};function _e(e,t,n){void 0===n&&(n=!1);var r,o,i=O(t),a=O(t)&&function(e){var t=e.getBoundingClientRect(),n=D(t.width)/e.offsetWidth||1,r=D(t.height)/e.offsetHeight||1;return 1!==n||1!==r}(t),l=B(t),s=N(e,a,n),u={scrollLeft:0,scrollTop:0},c={x:0,y:0};return(i||!i&&!n)&&(("body"!==A(t)||be(l))&&(u=(r=t)!==x(r)&&O(r)?{scrollLeft:(o=r).scrollLeft,scrollTop:o.scrollTop}:ge(r)),O(t)?((c=N(t,!0)).x+=t.clientLeft,c.y+=t.clientTop):l&&(c.x=ye(l))),{x:s.left+u.scrollLeft-c.x,y:s.top+u.scrollTop-c.y,width:s.width,height:s.height}}function Re(e){var t=new Map,n=new Set,r=[];function o(e){n.add(e.name),[].concat(e.requires||[],e.requiresIfExists||[]).forEach((function(e){if(!n.has(e)){var r=t.get(e);r&&o(r)}})),r.push(e)}return e.forEach((function(e){t.set(e.name,e)})),e.forEach((function(e){n.has(e.name)||o(e)})),r}var Ne={placement:"bottom",modifiers:[],strategy:"absolute"};function Te(){for(var e=arguments.length,t=new Array(e),n=0;n{}},Le={name:"ariaDescribedBy",enabled:!0,phase:"afterWrite",effect:({state:e})=>()=>{const{reference:t,popper:n}=e.elements;if("removeAttribute"in t){const e=(t.getAttribute("aria-describedby")||"").split(",").filter((e=>e.trim()!==n.id));e.length?t.setAttribute("aria-describedby",e.join(",")):t.removeAttribute("aria-describedby")}},fn:({state:e})=>{var t;const{popper:n,reference:r}=e.elements,o=null==(t=n.getAttribute("role"))?void 0:t.toLowerCase();if(n.id&&"tooltip"===o&&"setAttribute"in r){const e=r.getAttribute("aria-describedby");if(e&&-1!==e.split(",").indexOf(n.id))return;r.setAttribute("aria-describedby",e?`${e},${n.id}`:n.id)}}},Be=[],Fe=function(t,n,r={}){let{enabled:o=!0,placement:i="bottom",strategy:a="absolute",modifiers:s=Be}=r,u=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}(r,Ae);const c=(0,e.useRef)(s),d=(0,e.useRef)(),f=(0,e.useCallback)((()=>{var e;null==(e=d.current)||e.update()}),[]),p=(0,e.useCallback)((()=>{var e;null==(e=d.current)||e.forceUpdate()}),[]),[m,h]=function(t){const n=l();return[t[0],(0,e.useCallback)((e=>{if(n())return t[1](e)}),[n,t[1]])]}((0,e.useState)({placement:i,update:f,forceUpdate:p,attributes:{},styles:{popper:{},arrow:{}}})),g=(0,e.useMemo)((()=>({name:"updateStateModifier",enabled:!0,phase:"write",requires:["computeStyles"],fn:({state:e})=>{const t={},n={};Object.keys(e.elements).forEach((r=>{t[r]=e.styles[r],n[r]=e.attributes[r]})),h({state:e,styles:t,attributes:n,update:f,forceUpdate:p,placement:e.placement})}})),[f,p,h]),y=(0,e.useMemo)((()=>(E(c.current,s)||(c.current=s),c.current)),[s]);return(0,e.useEffect)((()=>{d.current&&o&&d.current.setOptions({placement:i,strategy:a,modifiers:[...y,g,Me]})}),[a,i,g,o,y]),(0,e.useEffect)((()=>{if(o&&null!=t&&null!=n)return d.current=je(t,n,Object.assign({},u,{placement:i,strategy:a,modifiers:[...y,Le,g]})),()=>{null!=d.current&&(d.current.destroy(),d.current=void 0,h((e=>Object.assign({},e,{attributes:{},styles:{popper:{}}}))))}}),[o,t,n]),m},ze=!("undefined"==typeof window||!window.document||!window.document.createElement);var Ue=!1,We=!1;try{var $e={get passive(){return Ue=!0},get once(){return We=Ue=!0}};ze&&(window.addEventListener("test",$e,$e),window.removeEventListener("test",$e,!0))}catch(e){}const Ge=function(e,t,n,r){return function(e,t,n,r){if(r&&"boolean"!=typeof r&&!We){var o=r.once,i=r.capture,a=n;!We&&o&&(a=n.__once||function e(r){this.removeEventListener(t,e,i),n.call(this,r)},n.__once=a),e.addEventListener(t,a,Ue?r:i)}e.addEventListener(t,n,r)}(e,t,n,r),function(){!function(e,t,n,r){var o=r&&"boolean"!=typeof r?r.capture:r;e.removeEventListener(t,n,o),n.__once&&e.removeEventListener(t,n.__once,o)}(e,t,n,r)}};function He(e){return e&&e.ownerDocument||document}const Ve=function(t){const n=(0,e.useRef)(t);return(0,e.useEffect)((()=>{n.current=t}),[t]),n};function qe(t){const n=Ve(t);return(0,e.useCallback)((function(...e){return n.current&&n.current(...e)}),[n])}const Qe=()=>{},Ye=e=>e&&("current"in e?e.current:e),Ke={click:"mousedown",mouseup:"mousedown",pointerup:"pointerdown"},Je=()=>{},Xe=function(t,n,{disabled:r,clickTrigger:o}={}){const i=n||Je;!function(t,n=Qe,{disabled:r,clickTrigger:o="click"}={}){const i=(0,e.useRef)(!1),l=(0,e.useRef)(!1),s=(0,e.useCallback)((e=>{const n=Ye(t);var r;f()(!!n,"ClickOutside captured a close event but does not have a ref to compare it to. useClickOutside(), should be passed a ref that resolves to a DOM node"),i.current=!n||!!((r=e).metaKey||r.altKey||r.ctrlKey||r.shiftKey)||!function(e){return 0===e.button}(e)||!!a(n,e.target)||l.current,l.current=!1}),[t]),u=qe((e=>{const n=Ye(t);n&&a(n,e.target)&&(l.current=!0)})),c=qe((e=>{i.current||n(e)}));(0,e.useEffect)((()=>{var e,n;if(r||null==t)return;const i=He(Ye(t)),a=i.defaultView||window;let l=null!=(e=a.event)?e:null==(n=a.parent)?void 0:n.event,d=null;Ke[o]&&(d=Ge(i,Ke[o],u,!0));const f=Ge(i,o,s,!0),p=Ge(i,o,(e=>{e!==l?c(e):l=void 0}));let m=[];return"ontouchstart"in i.documentElement&&(m=[].slice.call(i.body.children).map((e=>Ge(e,"mousemove",Qe)))),()=>{null==d||d(),f(),p(),m.forEach((e=>e()))}}),[t,r,o,s,u,c])}(t,i,{disabled:r,clickTrigger:o});const l=qe((e=>{(function(e){return"Escape"===e.code||27===e.keyCode})(e)&&i(e)}));(0,e.useEffect)((()=>{if(r||null==t)return;const e=He(Ye(t));let n=(e.defaultView||window).event;const o=Ge(e,"keyup",(e=>{e!==n?l(e):n=void 0}));return()=>{o()}}),[t,r,l])},Ze=(0,e.createContext)(ze?window:void 0);Ze.Provider;const et=(e,t)=>ze?null==e?(t||He()).body:("function"==typeof e&&(e=e()),e&&"current"in e&&(e=e.current),e&&("nodeType"in e||e.getBoundingClientRect)?e:null):null;function tt(t,n){const r=(0,e.useContext)(Ze),[o,i]=(0,e.useState)((()=>et(t,null==r?void 0:r.document)));if(!o){const e=et(t);e&&i(e)}return(0,e.useEffect)((()=>{n&&o&&n(o)}),[n,o]),(0,e.useEffect)((()=>{const e=et(t);e!==o&&i(e)}),[t,o]),o}function nt(e={}){return Array.isArray(e)?e:Object.keys(e).map((t=>(e[t].name=t,e[t])))}const rt=void 0!==n.g&&n.g.navigator&&"ReactNative"===n.g.navigator.product,ot="undefined"!=typeof document||rt?e.useLayoutEffect:e.useEffect,it=function({children:t,in:n,onExited:r,mountOnEnter:o,unmountOnExit:i}){const a=(0,e.useRef)(null),l=(0,e.useRef)(n),s=qe(r);(0,e.useEffect)((()=>{n?l.current=!0:s(a.current)}),[n,s]);const u=m(a,t.ref),c=(0,e.cloneElement)(t,{ref:u});return n?c:i||!l.current&&o?null:c};var at=n(893);function lt({children:t,in:n,onExited:r,onEntered:o,transition:i}){const[a,l]=(0,e.useState)(!n);n&&a&&l(!1);const s=function({in:t,onTransition:n}){const r=(0,e.useRef)(null),o=(0,e.useRef)(!0),i=qe(n);return ot((()=>{if(!r.current)return;let e=!1;return i({in:t,element:r.current,initial:o.current,isStale:()=>e}),()=>{e=!0}}),[t,i]),ot((()=>(o.current=!1,()=>{o.current=!0})),[]),r}({in:!!n,onTransition:e=>{Promise.resolve(i(e)).then((()=>{e.isStale()||(e.in?null==o||o(e.element,e.initial):(l(!0),null==r||r(e.element)))}),(t=>{throw e.in||l(!0),t}))}}),u=m(s,t.ref);return a&&!n?null:(0,e.cloneElement)(t,{ref:u})}const st=e.forwardRef(((t,n)=>{const{flip:r,offset:o,placement:i,containerPadding:a,popperConfig:l={},transition:s,runTransition:u}=t,[c,d]=b(),[f,p]=b(),h=m(d,n),g=tt(t.container),v=tt(t.target),[w,E]=(0,e.useState)(!t.show),S=Fe(v,c,function({enabled:e,enableEvents:t,placement:n,flip:r,offset:o,fixed:i,containerPadding:a,arrowElement:l,popperConfig:s={}}){var u,c,d,f,p;const m=function(e){const t={};return Array.isArray(e)?(null==e||e.forEach((e=>{t[e.name]=e})),t):e||t}(s.modifiers);return Object.assign({},s,{placement:n,enabled:e,strategy:i?"fixed":s.strategy,modifiers:nt(Object.assign({},m,{eventListeners:{enabled:t,options:null==(u=m.eventListeners)?void 0:u.options},preventOverflow:Object.assign({},m.preventOverflow,{options:a?Object.assign({padding:a},null==(c=m.preventOverflow)?void 0:c.options):null==(d=m.preventOverflow)?void 0:d.options}),offset:{options:Object.assign({offset:o},null==(f=m.offset)?void 0:f.options)},arrow:Object.assign({},m.arrow,{enabled:!!l,options:Object.assign({},null==(p=m.arrow)?void 0:p.options,{element:l})}),flip:Object.assign({enabled:!!r},m.flip)}))})}({placement:i,enableEvents:!!t.show,containerPadding:a||5,flip:r,offset:o,arrowElement:f,popperConfig:l}));t.show&&w&&E(!1);const x=t.show||!w;if(Xe(c,t.onHide,{disabled:!t.rootClose||t.rootCloseDisabled,clickTrigger:t.rootCloseEvent}),!x)return null;const{onExit:k,onExiting:O,onEnter:C,onEntering:P,onEntered:I}=t;let D=t.children(Object.assign({},S.attributes.popper,{style:S.styles.popper,ref:h}),{popper:S,placement:i,show:!!t.show,arrowProps:Object.assign({},S.attributes.arrow,{style:S.styles.arrow,ref:p})});return D=function(e,t,n){return e?(0,at.jsx)(e,Object.assign({},n)):t?(0,at.jsx)(lt,Object.assign({},n,{transition:t})):(0,at.jsx)(it,Object.assign({},n))}(s,u,{in:!!t.show,appear:!0,mountOnEnter:!0,unmountOnExit:!0,children:D,onExit:k,onExiting:O,onExited:(...e)=>{E(!0),t.onExited&&t.onExited(...e)},onEnter:C,onEntering:P,onEntered:I}),g?y.createPortal(D,g):null}));st.displayName="Overlay";const ut=st;function ct(e,t){return e.classList?!!t&&e.classList.contains(t):-1!==(" "+(e.className.baseVal||e.className)+" ").indexOf(" "+t+" ")}const dt=e.createContext({prefixes:{},breakpoints:["xxl","xl","lg","md","sm","xs"],minBreakpoint:"xs"}),{Consumer:ft,Provider:pt}=dt;function mt(t,n){const{prefixes:r}=(0,e.useContext)(dt);return t||r[n]||n}function ht(){const{dir:t}=(0,e.useContext)(dt);return"rtl"===t}const gt=e.forwardRef((({className:e,bsPrefix:t,as:n="div",...r},o)=>(t=mt(t,"popover-header"),(0,at.jsx)(n,{ref:o,className:g()(e,t),...r}))));gt.displayName="PopoverHeader";const yt=gt,bt=e.forwardRef((({className:e,bsPrefix:t,as:n="div",...r},o)=>(t=mt(t,"popover-body"),(0,at.jsx)(n,{ref:o,className:g()(e,t),...r}))));bt.displayName="PopoverBody";const vt=bt;function wt(e,t){let n=e;return"left"===e?n=t?"end":"start":"right"===e&&(n=t?"start":"end"),n}function Et(e="absolute"){return{position:e,top:"0",left:"0",opacity:"0",pointerEvents:"none"}}e.Component;const St=e.forwardRef((({bsPrefix:e,placement:t="right",className:n,style:r,children:o,body:i,arrowProps:a,hasDoneInitialMeasure:l,popper:s,show:u,...c},d)=>{const f=mt(e,"popover"),p=ht(),[m]=(null==t?void 0:t.split("-"))||[],h=wt(m,p);let y=r;return u&&!l&&(y={...r,...Et(null==s?void 0:s.strategy)}),(0,at.jsxs)("div",{ref:d,role:"tooltip",style:y,"x-placement":m,className:g()(n,f,m&&`bs-popover-${h}`),...c,children:[(0,at.jsx)("div",{className:"popover-arrow",...a}),i?(0,at.jsx)(vt,{children:o}):o]})})),xt=Object.assign(St,{Header:yt,Body:vt,POPPER_OFFSET:[0,8]}),kt=e.forwardRef((({bsPrefix:e,placement:t="right",className:n,style:r,children:o,arrowProps:i,hasDoneInitialMeasure:a,popper:l,show:s,...u},c)=>{e=mt(e,"tooltip");const d=ht(),[f]=(null==t?void 0:t.split("-"))||[],p=wt(f,d);let m=r;return s&&!a&&(m={...r,...Et(null==l?void 0:l.strategy)}),(0,at.jsxs)("div",{ref:c,style:m,role:"tooltip","x-placement":f,className:g()(n,e,`bs-tooltip-${p}`),...u,children:[(0,at.jsx)("div",{className:"tooltip-arrow",...i}),(0,at.jsx)("div",{className:`${e}-inner`,children:o})]})}));kt.displayName="Tooltip";const Ot=Object.assign(kt,{TOOLTIP_OFFSET:[0,6]});function Ct(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}function Pt(e,t){return Pt=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},Pt(e,t)}const It=e.createContext(null);var Dt="unmounted",_t="exited",Rt="entering",Nt="entered",Tt="exiting",jt=function(t){var n,r;function o(e,n){var r;r=t.call(this,e,n)||this;var o,i=n&&!n.isMounting?e.enter:e.appear;return r.appearStatus=null,e.in?i?(o=_t,r.appearStatus=Rt):o=Nt:o=e.unmountOnExit||e.mountOnEnter?Dt:_t,r.state={status:o},r.nextCallback=null,r}r=t,(n=o).prototype=Object.create(r.prototype),n.prototype.constructor=n,Pt(n,r),o.getDerivedStateFromProps=function(e,t){return e.in&&t.status===Dt?{status:_t}:null};var i=o.prototype;return i.componentDidMount=function(){this.updateStatus(!0,this.appearStatus)},i.componentDidUpdate=function(e){var t=null;if(e!==this.props){var n=this.state.status;this.props.in?n!==Rt&&n!==Nt&&(t=Rt):n!==Rt&&n!==Nt||(t=Tt)}this.updateStatus(!1,t)},i.componentWillUnmount=function(){this.cancelNextCallback()},i.getTimeouts=function(){var e,t,n,r=this.props.timeout;return e=t=n=r,null!=r&&"number"!=typeof r&&(e=r.exit,t=r.enter,n=void 0!==r.appear?r.appear:t),{exit:e,enter:t,appear:n}},i.updateStatus=function(e,t){if(void 0===e&&(e=!1),null!==t)if(this.cancelNextCallback(),t===Rt){if(this.props.unmountOnExit||this.props.mountOnEnter){var n=this.props.nodeRef?this.props.nodeRef.current:y.findDOMNode(this);n&&function(e){e.scrollTop}(n)}this.performEnter(e)}else this.performExit();else this.props.unmountOnExit&&this.state.status===_t&&this.setState({status:Dt})},i.performEnter=function(e){var t=this,n=this.props.enter,r=this.context?this.context.isMounting:e,o=this.props.nodeRef?[r]:[y.findDOMNode(this),r],i=o[0],a=o[1],l=this.getTimeouts(),s=r?l.appear:l.enter;e||n?(this.props.onEnter(i,a),this.safeSetState({status:Rt},(function(){t.props.onEntering(i,a),t.onTransitionEnd(s,(function(){t.safeSetState({status:Nt},(function(){t.props.onEntered(i,a)}))}))}))):this.safeSetState({status:Nt},(function(){t.props.onEntered(i)}))},i.performExit=function(){var e=this,t=this.props.exit,n=this.getTimeouts(),r=this.props.nodeRef?void 0:y.findDOMNode(this);t?(this.props.onExit(r),this.safeSetState({status:Tt},(function(){e.props.onExiting(r),e.onTransitionEnd(n.exit,(function(){e.safeSetState({status:_t},(function(){e.props.onExited(r)}))}))}))):this.safeSetState({status:_t},(function(){e.props.onExited(r)}))},i.cancelNextCallback=function(){null!==this.nextCallback&&(this.nextCallback.cancel(),this.nextCallback=null)},i.safeSetState=function(e,t){t=this.setNextCallback(t),this.setState(e,t)},i.setNextCallback=function(e){var t=this,n=!0;return this.nextCallback=function(r){n&&(n=!1,t.nextCallback=null,e(r))},this.nextCallback.cancel=function(){n=!1},this.nextCallback},i.onTransitionEnd=function(e,t){this.setNextCallback(t);var n=this.props.nodeRef?this.props.nodeRef.current:y.findDOMNode(this),r=null==e&&!this.props.addEndListener;if(n&&!r){if(this.props.addEndListener){var o=this.props.nodeRef?[this.nextCallback]:[n,this.nextCallback],i=o[0],a=o[1];this.props.addEndListener(i,a)}null!=e&&setTimeout(this.nextCallback,e)}else setTimeout(this.nextCallback,0)},i.render=function(){var t=this.state.status;if(t===Dt)return null;var n=this.props,r=n.children,o=(n.in,n.mountOnEnter,n.unmountOnExit,n.appear,n.enter,n.exit,n.timeout,n.addEndListener,n.onEnter,n.onEntering,n.onEntered,n.onExit,n.onExiting,n.onExited,n.nodeRef,Ct(n,["children","in","mountOnEnter","unmountOnExit","appear","enter","exit","timeout","addEndListener","onEnter","onEntering","onEntered","onExit","onExiting","onExited","nodeRef"]));return e.createElement(It.Provider,{value:null},"function"==typeof r?r(t,o):e.cloneElement(e.Children.only(r),o))},o}(e.Component);function At(){}jt.contextType=It,jt.propTypes={},jt.defaultProps={in:!1,mountOnEnter:!1,unmountOnExit:!1,appear:!1,enter:!0,exit:!0,onEnter:At,onEntering:At,onEntered:At,onExit:At,onExiting:At,onExited:At},jt.UNMOUNTED=Dt,jt.EXITED=_t,jt.ENTERING=Rt,jt.ENTERED=Nt,jt.EXITING=Tt;const Mt=jt;var Lt=/([A-Z])/g,Bt=/^ms-/;function Ft(e){return function(e){return e.replace(Lt,"-$1").toLowerCase()}(e).replace(Bt,"-ms-")}var zt=/^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i;const Ut=function(e,t){var n="",r="";if("string"==typeof t)return e.style.getPropertyValue(Ft(t))||function(e,t){return function(e){var t=He(e);return t&&t.defaultView||window}(e).getComputedStyle(e,t)}(e).getPropertyValue(Ft(t));Object.keys(t).forEach((function(o){var i=t[o];i||0===i?function(e){return!(!e||!zt.test(e))}(o)?r+=o+"("+i+") ":n+=Ft(o)+": "+i+";":e.style.removeProperty(Ft(o))})),r&&(n+="transform: "+r+";"),e.style.cssText+=";"+n};function Wt(e,t,n,r){var o,i;null==n&&(i=-1===(o=Ut(e,"transitionDuration")||"").indexOf("ms")?1e3:1,n=parseFloat(o)*i||0);var a=function(e,t,n){void 0===n&&(n=5);var r=!1,o=setTimeout((function(){r||function(e,t,n,r){if(void 0===n&&(n=!1),void 0===r&&(r=!0),e){var o=document.createEvent("HTMLEvents");o.initEvent("transitionend",n,r),e.dispatchEvent(o)}}(e,0,!0)}),t+n),i=Ge(e,"transitionend",(function(){r=!0}),{once:!0});return function(){clearTimeout(o),i()}}(e,n,r),l=Ge(e,"transitionend",t);return function(){a(),l()}}function $t(e,t){const n=Ut(e,t)||"",r=-1===n.indexOf("ms")?1e3:1;return parseFloat(n)*r}function Gt(e,t){const n=$t(e,"transitionDuration"),r=$t(e,"transitionDelay"),o=Wt(e,(n=>{n.target===e&&(o(),t(n))}),n+r)}function Ht(e){return e&&"setState"in e?y.findDOMNode(e):null!=e?e:null}const Vt=e.forwardRef((({onEnter:t,onEntering:n,onEntered:r,onExit:o,onExiting:i,onExited:a,addEndListener:l,children:s,childRef:u,...c},d)=>{const f=(0,e.useRef)(null),p=m(f,u),h=e=>{p(Ht(e))},g=e=>t=>{e&&f.current&&e(f.current,t)},y=(0,e.useCallback)(g(t),[t]),b=(0,e.useCallback)(g(n),[n]),v=(0,e.useCallback)(g(r),[r]),w=(0,e.useCallback)(g(o),[o]),E=(0,e.useCallback)(g(i),[i]),S=(0,e.useCallback)(g(a),[a]),x=(0,e.useCallback)(g(l),[l]);return(0,at.jsx)(Mt,{ref:d,...c,onEnter:y,onEntered:v,onEntering:b,onExit:w,onExited:S,onExiting:E,addEndListener:x,nodeRef:f,children:"function"==typeof s?(e,t)=>s(e,{...t,ref:h}):e.cloneElement(s,{ref:h})})})),qt={[Rt]:"show",[Nt]:"show"},Qt=e.forwardRef((({className:t,children:n,transitionClasses:r={},onEnter:o,...i},a)=>{const l={in:!1,timeout:300,mountOnEnter:!1,unmountOnExit:!1,appear:!1,...i},s=(0,e.useCallback)(((e,t)=>{!function(e){e.offsetHeight}(e),null==o||o(e,t)}),[o]);return(0,at.jsx)(Vt,{ref:a,addEndListener:Gt,...l,onEnter:s,childRef:n.ref,children:(o,i)=>e.cloneElement(n,{...i,className:g()("fade",t,n.props.className,qt[o],r[o])})})}));Qt.displayName="Fade";const Yt=Qt,Kt=e.forwardRef((({children:t,transition:n=Yt,popperConfig:r={},rootClose:o=!1,placement:i="top",show:a=!1,...l},s)=>{const u=(0,e.useRef)({}),[c,d]=(0,e.useState)(null),[f,p]=function(t){const n=(0,e.useRef)(null),r=mt(void 0,"popover"),o=mt(void 0,"tooltip"),i=(0,e.useMemo)((()=>({name:"offset",options:{offset:()=>{if(t)return t;if(n.current){if(ct(n.current,r))return xt.POPPER_OFFSET;if(ct(n.current,o))return Ot.TOOLTIP_OFFSET}return[0,0]}}})),[t,r,o]);return[n,[i]]}(l.offset),h=m(s,f),y=!0===n?Yt:n||void 0,b=qe((e=>{d(e),null==r||null==r.onFirstUpdate||r.onFirstUpdate(e)}));return ot((()=>{c&&l.target&&(null==u.current.scheduleUpdate||u.current.scheduleUpdate())}),[c,l.target]),(0,e.useEffect)((()=>{a||d(null)}),[a]),(0,at.jsx)(ut,{...l,ref:h,popperConfig:{...r,modifiers:p.concat(r.modifiers||[]),onFirstUpdate:b},transition:y,rootClose:o,placement:i,show:a,children:(o,{arrowProps:i,popper:a,show:l})=>{var s,d;!function(e,t){const{ref:n}=e,{ref:r}=t;e.ref=n.__wrapped||(n.__wrapped=e=>n(Ht(e))),t.ref=r.__wrapped||(r.__wrapped=e=>r(Ht(e)))}(o,i);const f=null==a?void 0:a.placement,p=Object.assign(u.current,{state:null==a?void 0:a.state,scheduleUpdate:null==a?void 0:a.update,placement:f,outOfBoundaries:(null==a||null==(s=a.state)||null==(d=s.modifiersData.hide)?void 0:d.isReferenceHidden)||!1,strategy:r.strategy}),m=!!c;return"function"==typeof t?t({...o,placement:f,show:l,...!n&&l&&{className:"show"},popper:p,arrowProps:i,hasDoneInitialMeasure:m}):e.cloneElement(t,{...o,placement:f,arrowProps:i,popper:p,hasDoneInitialMeasure:m,className:g()(t.props.className,!n&&l&&"show"),style:{...t.props.style,...o.style}})}})}));Kt.displayName="Overlay";const Jt=Kt;function Xt(e,t,n){const[r]=t,o=r.currentTarget,i=r.relatedTarget||r.nativeEvent[n];i&&i===o||a(o,i)||e(...t)}o().oneOf(["click","hover","focus"]);const Zt=({trigger:t=["hover","focus"],overlay:n,children:r,popperConfig:o={},show:i,defaultShow:a=!1,onToggle:l,delay:s,placement:u,flip:d=u&&-1!==u.indexOf("auto"),...f})=>{const p=(0,e.useRef)(null),h=m(p,r.ref),g=c(),y=(0,e.useRef)(""),[b,v]=(T=i,j=a,A=l,M=(0,e.useRef)(void 0!==T),L=(0,e.useState)(j),B=L[0],F=L[1],z=void 0!==T,U=M.current,M.current=z,!z&&U&&B!==j&&F(j),[z?T:B,(0,e.useCallback)((function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r{g.clear(),y.current="show",w.show?g.set((()=>{"show"===y.current&&v(!0)}),w.show):v(!0)}),[w.show,v,g]),O=(0,e.useCallback)((()=>{g.clear(),y.current="hide",w.hide?g.set((()=>{"hide"===y.current&&v(!1)}),w.hide):v(!1)}),[w.hide,v,g]),C=(0,e.useCallback)(((...e)=>{k(),null==E||E(...e)}),[k,E]),P=(0,e.useCallback)(((...e)=>{O(),null==S||S(...e)}),[O,S]),I=(0,e.useCallback)(((...e)=>{v(!b),null==x||x(...e)}),[x,v,b]),D=(0,e.useCallback)(((...e)=>{Xt(k,e,"fromElement")}),[k]),_=(0,e.useCallback)(((...e)=>{Xt(O,e,"toElement")}),[O]),R=null==t?[]:[].concat(t),N={ref:e=>{h(Ht(e))}};var T,j,A,M,L,B,F,z,U;return-1!==R.indexOf("click")&&(N.onClick=I),-1!==R.indexOf("focus")&&(N.onFocus=C,N.onBlur=P),-1!==R.indexOf("hover")&&(N.onMouseOver=D,N.onMouseOut=_),(0,at.jsxs)(at.Fragment,{children:["function"==typeof r?r(N):(0,e.cloneElement)(r,N),(0,at.jsx)(Jt,{...f,show:b,onHide:O,flip:d,placement:u,popperConfig:o,target:p.current,children:n})]})};function en(t){var n=t.id,r=t.tip;return e.createElement(Zt,{placement:"auto",trigger:["click","hover","focus"],style:{display:"inline"},overlay:e.createElement(Ot,{id:n},r)},e.createElement("img",{src:"/images/shop/icon-reminder.svg",className:"options-icon"}))}function tn(e){return tn="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},tn(e)}function nn(e,t){for(var n=0;ntr,rr=Symbol.for("react-redux-context"),or="undefined"!=typeof globalThis?globalThis:{};function ir(){var t;if(!e.createContext)return{};const n=null!=(t=or[rr])?t:or[rr]=new Map;let r=n.get(e.createContext);return r||(r=e.createContext(null),n.set(e.createContext,r)),r}const ar=ir();let lr=null;function sr(){return sr=Object.assign?Object.assign.bind():function(e){for(var t=1;t{throw new Error(`Invalid value of type ${typeof e} for ${t} argument when connecting component ${r.wrappedComponentName}.`)}}function br(e,t,n){return sr({},n,e,t)}const vr={notify(){},get:()=>[]};function wr(e,t){let n,r=vr,o=0,i=!1;function a(){u.onStateChange&&u.onStateChange()}function l(){o++,n||(n=t?t.addNestedSub(a):e.subscribe(a),r=function(){const e=nr();let t=null,n=null;return{clear(){t=null,n=null},notify(){e((()=>{let e=t;for(;e;)e.callback(),e=e.next}))},get(){let e=[],n=t;for(;n;)e.push(n),n=n.next;return e},subscribe(e){let r=!0,o=n={callback:e,next:null,prev:n};return o.prev?o.prev.next=o:t=o,function(){r&&null!==t&&(r=!1,o.next?o.next.prev=o.prev:n=o.prev,o.prev?o.prev.next=o.next:t=o.next)}}}}())}function s(){o--,n&&0===o&&(n(),n=void 0,r.clear(),r=vr)}const u={addNestedSub:function(e){l();const t=r.subscribe(e);let n=!1;return()=>{n||(n=!0,t(),s())}},notifyNestedSubs:function(){r.notify()},handleChangeWrapper:a,isSubscribed:function(){return i},trySubscribe:function(){i||(i=!0,l())},tryUnsubscribe:function(){i&&(i=!1,s())},getListeners:()=>r};return u}const Er="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?e.useLayoutEffect:e.useEffect;function Sr(e,t){return e===t?0!==e||0!==t||1/e==1/t:e!=e&&t!=t}function xr(e,t){if(Sr(e,t))return!0;if("object"!=typeof e||null===e||"object"!=typeof t||null===t)return!1;const n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(let r=0;r{throw new Error("uSES not initialized!")};const Cr=[null,null];function Pr(e,t,n,r,o,i){e.current=r,n.current=!1,o.current&&(o.current=null,i())}function Ir(e,t){return e===t}const Dr=function(t,n,r,{pure:o,areStatesEqual:i=Ir,areOwnPropsEqual:a=xr,areStatePropsEqual:l=xr,areMergedPropsEqual:s=xr,forwardRef:u=!1,context:c=ar}={}){const d=c,f=function(e){return e?"function"==typeof e?gr(e):yr(e,"mapStateToProps"):mr((()=>({})))}(t),p=function(e){return e&&"object"==typeof e?mr((t=>function(e,t){const n={};for(const r in e){const o=e[r];"function"==typeof o&&(n[r]=(...e)=>t(o(...e)))}return n}(e,t))):e?"function"==typeof e?gr(e):yr(e,"mapDispatchToProps"):mr((e=>({dispatch:e})))}(n),m=function(e){return e?"function"==typeof e?function(e){return function(t,{displayName:n,areMergedPropsEqual:r}){let o,i=!1;return function(t,n,a){const l=e(t,n,a);return i?r(l,o)||(o=l):(i=!0,o=l),o}}}(e):yr(e,"mergeProps"):()=>br}(r),h=Boolean(t);return t=>{const n=t.displayName||t.name||"Component",r=`Connect(${n})`,o={shouldHandleStateChanges:h,displayName:r,wrappedComponentName:n,WrappedComponent:t,initMapStateToProps:f,initMapDispatchToProps:p,initMergeProps:m,areStatesEqual:i,areStatePropsEqual:l,areOwnPropsEqual:a,areMergedPropsEqual:s};function c(n){const[r,i,a]=e.useMemo((()=>{const{reactReduxForwardedRef:e}=n,t=Ct(n,kr);return[n.context,e,t]}),[n]),l=e.useMemo((()=>r&&r.Consumer&&(0,dr.isContextConsumer)(e.createElement(r.Consumer,null))?r:d),[r,d]),s=e.useContext(l),u=Boolean(n.store)&&Boolean(n.store.getState)&&Boolean(n.store.dispatch),c=Boolean(s)&&Boolean(s.store),f=u?n.store:s.store,p=c?s.getServerState:f.getState,m=e.useMemo((()=>function(e,t){let{initMapStateToProps:n,initMapDispatchToProps:r,initMergeProps:o}=t,i=Ct(t,fr);return pr(n(e,i),r(e,i),o(e,i),e,i)}(f.dispatch,o)),[f]),[g,y]=e.useMemo((()=>{if(!h)return Cr;const e=wr(f,u?void 0:s.subscription),t=e.notifyNestedSubs.bind(e);return[e,t]}),[f,u,s]),b=e.useMemo((()=>u?s:sr({},s,{subscription:g})),[u,s,g]),v=e.useRef(),w=e.useRef(a),E=e.useRef(),S=e.useRef(!1),x=(e.useRef(!1),e.useRef(!1)),k=e.useRef();Er((()=>(x.current=!0,()=>{x.current=!1})),[]);const O=e.useMemo((()=>()=>E.current&&a===w.current?E.current:m(f.getState(),a)),[f,a]),C=e.useMemo((()=>e=>g?function(e,t,n,r,o,i,a,l,s,u,c){if(!e)return()=>{};let d=!1,f=null;const p=()=>{if(d||!l.current)return;const e=t.getState();let n,p;try{n=r(e,o.current)}catch(e){p=e,f=e}p||(f=null),n===i.current?a.current||u():(i.current=n,s.current=n,a.current=!0,c())};return n.onStateChange=p,n.trySubscribe(),p(),()=>{if(d=!0,n.tryUnsubscribe(),n.onStateChange=null,f)throw f}}(h,f,g,m,w,v,S,x,E,y,e):()=>{}),[g]);var P,I;let D;P=Pr,I=[w,v,S,a,E,y],Er((()=>P(...I)),undefined);try{D=Or(C,O,p?()=>m(p(),a):O)}catch(e){throw k.current&&(e.message+=`\nThe error may be correlated with this previous error:\n${k.current.stack}\n\n`),e}Er((()=>{k.current=void 0,E.current=void 0,v.current=D}));const _=e.useMemo((()=>e.createElement(t,sr({},D,{ref:i}))),[i,t,D]);return e.useMemo((()=>h?e.createElement(l.Provider,{value:b},_):_),[l,_,b])}const g=e.memo(c);if(g.WrappedComponent=t,g.displayName=c.displayName=r,u){const n=e.forwardRef((function(t,n){return e.createElement(g,sr({},t,{reactReduxForwardedRef:n}))}));return n.displayName=r,n.WrappedComponent=t,cr()(n,t)}return cr()(g,t)}},_r=function({store:t,context:n,children:r,serverState:o,stabilityCheck:i="once",noopCheck:a="once"}){const l=e.useMemo((()=>{const e=wr(t);return{store:t,subscription:e,getServerState:o?()=>o:void 0,stabilityCheck:i,noopCheck:a}}),[t,o,i,a]),s=e.useMemo((()=>t.getState()),[t]);Er((()=>{const{subscription:e}=l;return e.onStateChange=e.notifyNestedSubs,e.trySubscribe(),s!==t.getState()&&e.notifyNestedSubs(),()=>{e.tryUnsubscribe(),e.onStateChange=void 0}}),[l,s]);const u=n||ar;return e.createElement(u.Provider,{value:l},r)};var Rr;function Nr(t,n){var r=(0,e.useState)((function(){return{inputs:n,result:t()}}))[0],o=(0,e.useRef)(!0),i=(0,e.useRef)(r),a=o.current||Boolean(n&&i.current.inputs&&function(e,t){if(e.length!==t.length)return!1;for(var n=0;n{Or=e})(Zn.useSyncExternalStore),Rr=y.unstable_batchedUpdates,tr=Rr;var Tr=Nr,jr=function(e,t){return Nr((function(){return e}),t)},Ar=function(e){var t=e.top,n=e.right,r=e.bottom,o=e.left;return{top:t,right:n,bottom:r,left:o,width:n-o,height:r-t,x:o,y:t,center:{x:(n+o)/2,y:(r+t)/2}}},Mr=function(e,t){return{top:e.top-t.top,left:e.left-t.left,bottom:e.bottom+t.bottom,right:e.right+t.right}},Lr=function(e,t){return{top:e.top+t.top,left:e.left+t.left,bottom:e.bottom-t.bottom,right:e.right-t.right}},Br={top:0,right:0,bottom:0,left:0},Fr=function(e){var t=e.borderBox,n=e.margin,r=void 0===n?Br:n,o=e.border,i=void 0===o?Br:o,a=e.padding,l=void 0===a?Br:a,s=Ar(Mr(t,r)),u=Ar(Lr(t,i)),c=Ar(Lr(u,l));return{marginBox:s,borderBox:Ar(t),paddingBox:u,contentBox:c,margin:r,border:i,padding:l}},zr=function(e){var t=e.slice(0,-2);if("px"!==e.slice(-2))return 0;var n=Number(t);return isNaN(n)&&function(e,t){throw new Error("Invariant failed")}(),n},Ur=function(e,t){var n,r,o=e.borderBox,i=e.border,a=e.margin,l=e.padding,s=(r=t,{top:(n=o).top+r.y,left:n.left+r.x,bottom:n.bottom+r.y,right:n.right+r.x});return Fr({borderBox:s,border:i,margin:a,padding:l})},Wr=function(e,t){return void 0===t&&(t={x:window.pageXOffset,y:window.pageYOffset}),Ur(e,t)},$r=function(e,t){var n={top:zr(t.marginTop),right:zr(t.marginRight),bottom:zr(t.marginBottom),left:zr(t.marginLeft)},r={top:zr(t.paddingTop),right:zr(t.paddingRight),bottom:zr(t.paddingBottom),left:zr(t.paddingLeft)},o={top:zr(t.borderTopWidth),right:zr(t.borderRightWidth),bottom:zr(t.borderBottomWidth),left:zr(t.borderLeftWidth)};return Fr({borderBox:e,margin:n,padding:r,border:o})},Gr=function(e){var t=e.getBoundingClientRect(),n=window.getComputedStyle(e);return $r(t,n)},Hr=Number.isNaN||function(e){return"number"==typeof e&&e!=e};function Vr(e,t){if(e.length!==t.length)return!1;for(var n=0;n{const r=(o=n,i=t.options,{...o,...i});var o,i;return e.addEventListener(t.eventName,t.fn,r),function(){e.removeEventListener(t.eventName,t.fn,r)}}));return function(){r.forEach((e=>{e()}))}}Yr.bind(null,"warn"),Yr.bind(null,"error");const Xr=!0,Zr="Invariant failed";class eo extends Error{}function to(e,t){if(!e)throw new eo(Xr?Zr:`${Zr}: ${t||""}`)}eo.prototype.toString=function(){return this.message};class no extends e.Component{constructor(){super(...arguments),this.callbacks=null,this.unbind=Kr,this.onWindowError=e=>{const t=this.getCallbacks();t.isDragging()&&t.tryAbort(),e.error instanceof eo&&e.preventDefault()},this.getCallbacks=()=>{if(!this.callbacks)throw new Error("Unable to find AppCallbacks in ");return this.callbacks},this.setCallbacks=e=>{this.callbacks=e}}componentDidMount(){this.unbind=Jr(window,[{eventName:"error",fn:this.onWindowError}])}componentDidCatch(e){if(!(e instanceof eo))throw e;this.setState({})}componentWillUnmount(){this.unbind()}render(){return this.props.children(this.setCallbacks)}}const ro=e=>e+1,oo=(e,t)=>{const n=e.droppableId===t.droppableId,r=ro(e.index),o=ro(t.index);return n?`\n You have moved the item from position ${r}\n to position ${o}\n `:`\n You have moved the item from position ${r}\n in list ${e.droppableId}\n to list ${t.droppableId}\n in position ${o}\n `},io=(e,t,n)=>t.droppableId===n.droppableId?`\n The item ${e}\n has been combined with ${n.draggableId}`:`\n The item ${e}\n in list ${t.droppableId}\n has been combined with ${n.draggableId}\n in list ${n.droppableId}\n `,ao=e=>`\n The item has returned to its starting position\n of ${ro(e.index)}\n`,lo={dragHandleUsageInstructions:"\n Press space bar to start a drag.\n When dragging you can use the arrow keys to move the item around and escape to cancel.\n Some screen readers may require you to be in focus mode or to use your pass through key\n",onDragStart:e=>`\n You have lifted an item in position ${ro(e.source.index)}\n`,onDragUpdate:e=>{const t=e.destination;if(t)return oo(e.source,t);const n=e.combine;return n?io(e.draggableId,e.source,n):"You are over an area that cannot be dropped on"},onDragEnd:e=>{if("CANCEL"===e.reason)return`\n Movement cancelled.\n ${ao(e.source)}\n `;const t=e.destination,n=e.combine;return t?`\n You have dropped the item.\n ${oo(e.source,t)}\n `:n?`\n You have dropped the item.\n ${io(e.draggableId,e.source,n)}\n `:`\n The item has been dropped while not over a drop area.\n ${ao(e.source)}\n `}};var so=lo;const uo={x:0,y:0},co=(e,t)=>({x:e.x+t.x,y:e.y+t.y}),fo=(e,t)=>({x:e.x-t.x,y:e.y-t.y}),po=(e,t)=>e.x===t.x&&e.y===t.y,mo=e=>({x:0!==e.x?-e.x:0,y:0!==e.y?-e.y:0}),ho=function(e,t,n){return void 0===n&&(n=0),"x"===e?{x:t,y:n}:{x:n,y:t}},go=(e,t)=>Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2),yo=(e,t)=>Math.min(...t.map((t=>go(e,t)))),bo=e=>t=>({x:e(t.x),y:e(t.y)}),vo=(e,t)=>({top:e.top+t.y,left:e.left+t.x,bottom:e.bottom+t.y,right:e.right+t.x}),wo=e=>[{x:e.left,y:e.top},{x:e.right,y:e.top},{x:e.left,y:e.bottom},{x:e.right,y:e.bottom}],Eo=(e,t)=>t&&t.shouldClipSubject?((e,t)=>{const n=Ar({top:Math.max(t.top,e.top),right:Math.min(t.right,e.right),bottom:Math.min(t.bottom,e.bottom),left:Math.max(t.left,e.left)});return n.width<=0||n.height<=0?null:n})(t.pageMarginBox,e):Ar(e);var So=e=>{let{page:t,withPlaceholder:n,axis:r,frame:o}=e;const i=((e,t)=>t?vo(e,t.scroll.diff.displacement):e)(t.marginBox,o),a=((e,t,n)=>n&&n.increasedBy?{...e,[t.end]:e[t.end]+n.increasedBy[t.line]}:e)(i,r,n);return{page:t,withPlaceholder:n,active:Eo(a,o)}},xo=(e,t)=>{e.frame||to(!1);const n=e.frame,r=fo(t,n.scroll.initial),o=mo(r),i={...n,scroll:{initial:n.scroll.initial,current:t,diff:{value:r,displacement:o},max:n.scroll.max}},a=So({page:e.subject.page,withPlaceholder:e.subject.withPlaceholder,axis:e.axis,frame:i});return{...e,frame:i,subject:a}};const ko=qr((e=>e.reduce(((e,t)=>(e[t.descriptor.id]=t,e)),{}))),Oo=qr((e=>e.reduce(((e,t)=>(e[t.descriptor.id]=t,e)),{}))),Co=qr((e=>Object.values(e))),Po=qr((e=>Object.values(e)));var Io=qr(((e,t)=>{const n=Po(t).filter((t=>e===t.descriptor.droppableId)).sort(((e,t)=>e.descriptor.index-t.descriptor.index));return n}));function Do(e){return e.at&&"REORDER"===e.at.type?e.at.destination:null}function _o(e){return e.at&&"COMBINE"===e.at.type?e.at.combine:null}var Ro=qr(((e,t)=>t.filter((t=>t.descriptor.id!==e.descriptor.id)))),No=(e,t)=>e.descriptor.droppableId===t.descriptor.id;const To={point:uo,value:0},jo={invisible:{},visible:{},all:[]};var Ao={displaced:jo,displacedBy:To,at:null},Mo=(e,t)=>n=>e<=n&&n<=t,Lo=e=>{const t=Mo(e.top,e.bottom),n=Mo(e.left,e.right);return r=>{if(t(r.top)&&t(r.bottom)&&n(r.left)&&n(r.right))return!0;const o=t(r.top)||t(r.bottom),i=n(r.left)||n(r.right);if(o&&i)return!0;const a=r.tope.bottom,l=r.lefte.right;return!(!a||!l)||(a&&i||l&&o)}},Bo=e=>{const t=Mo(e.top,e.bottom),n=Mo(e.left,e.right);return e=>t(e.top)&&t(e.bottom)&&n(e.left)&&n(e.right)};const Fo={direction:"vertical",line:"y",crossAxisLine:"x",start:"top",end:"bottom",size:"height",crossAxisStart:"left",crossAxisEnd:"right",crossAxisSize:"width"},zo={direction:"horizontal",line:"x",crossAxisLine:"y",start:"left",end:"right",size:"width",crossAxisStart:"top",crossAxisEnd:"bottom",crossAxisSize:"height"},Uo=e=>{let{target:t,destination:n,viewport:r,withDroppableDisplacement:o,isVisibleThroughFrameFn:i}=e;const a=o?((e,t)=>{const n=t.frame?t.frame.scroll.diff.displacement:uo;return vo(e,n)})(t,n):t;return((e,t,n)=>!!t.subject.active&&n(t.subject.active)(e))(a,n,i)&&((e,t,n)=>n(t)(e))(a,r,i)},Wo=e=>Uo({...e,isVisibleThroughFrameFn:Lo}),$o=e=>Uo({...e,isVisibleThroughFrameFn:Bo}),Go=(e,t,n)=>{if("boolean"==typeof n)return n;if(!t)return!0;const{invisible:r,visible:o}=t;if(r[e])return!1;const i=o[e];return!i||i.shouldAnimate};function Ho(e){let{afterDragging:t,destination:n,displacedBy:r,viewport:o,forceShouldAnimate:i,last:a}=e;return t.reduce((function(e,t){const l=function(e,t){const n=e.page.marginBox,r={top:t.point.y,right:0,bottom:0,left:t.point.x};return Ar(Mr(n,r))}(t,r),s=t.descriptor.id;if(e.all.push(s),!Wo({target:l,destination:n,viewport:o,withDroppableDisplacement:!0}))return e.invisible[t.descriptor.id]=!0,e;const u={draggableId:s,shouldAnimate:Go(s,a,i)};return e.visible[s]=u,e}),{all:[],visible:{},invisible:{}})}function Vo(e){let{insideDestination:t,inHomeList:n,displacedBy:r,destination:o}=e;const i=function(e,t){if(!e.length)return 0;const n=e[e.length-1].descriptor.index;return t.inHomeList?n:n+1}(t,{inHomeList:n});return{displaced:jo,displacedBy:r,at:{type:"REORDER",destination:{droppableId:o.descriptor.id,index:i}}}}function qo(e){let{draggable:t,insideDestination:n,destination:r,viewport:o,displacedBy:i,last:a,index:l,forceShouldAnimate:s}=e;const u=No(t,r);if(null==l)return Vo({insideDestination:n,inHomeList:u,displacedBy:i,destination:r});const c=n.find((e=>e.descriptor.index===l));if(!c)return Vo({insideDestination:n,inHomeList:u,displacedBy:i,destination:r});const d=Ro(t,n),f=n.indexOf(c);return{displaced:Ho({afterDragging:d.slice(f),destination:r,displacedBy:i,last:a,viewport:o.frame,forceShouldAnimate:s}),displacedBy:i,at:{type:"REORDER",destination:{droppableId:r.descriptor.id,index:l}}}}function Qo(e,t){return Boolean(t.effected[e])}const Yo=(e,t)=>t.margin[e.start]+t.borderBox[e.size]/2,Ko=(e,t,n)=>t[e.crossAxisStart]+n.margin[e.crossAxisStart]+n.borderBox[e.crossAxisSize]/2,Jo=e=>{let{axis:t,moveRelativeTo:n,isMoving:r}=e;return ho(t.line,n.marginBox[t.end]+Yo(t,r),Ko(t,n.marginBox,r))},Xo=e=>{let{axis:t,moveRelativeTo:n,isMoving:r}=e;return ho(t.line,n.marginBox[t.start]-((e,t)=>t.margin[e.end]+t.borderBox[e.size]/2)(t,r),Ko(t,n.marginBox,r))};var Zo=(e,t)=>{const n=e.frame;return n?co(t,n.scroll.diff.displacement):t},ei=e=>{const t=(e=>{let{impact:t,draggable:n,droppable:r,draggables:o,afterCritical:i}=e;const a=n.page.borderBox.center,l=t.at;return r&&l?"REORDER"===l.type?(e=>{let{impact:t,draggable:n,draggables:r,droppable:o,afterCritical:i}=e;const a=Io(o.descriptor.id,r),l=n.page,s=o.axis;if(!a.length)return(e=>{let{axis:t,moveInto:n,isMoving:r}=e;return ho(t.line,n.contentBox[t.start]+Yo(t,r),Ko(t,n.contentBox,r))})({axis:s,moveInto:o.page,isMoving:l});const{displaced:u,displacedBy:c}=t,d=u.all[0];if(d){const e=r[d];if(Qo(d,i))return Xo({axis:s,moveRelativeTo:e.page,isMoving:l});const t=Ur(e.page,c.point);return Xo({axis:s,moveRelativeTo:t,isMoving:l})}const f=a[a.length-1];if(f.descriptor.id===n.descriptor.id)return l.borderBox.center;if(Qo(f.descriptor.id,i)){const e=Ur(f.page,mo(i.displacedBy.point));return Jo({axis:s,moveRelativeTo:e,isMoving:l})}return Jo({axis:s,moveRelativeTo:f.page,isMoving:l})})({impact:t,draggable:n,draggables:o,droppable:r,afterCritical:i}):(e=>{let{afterCritical:t,impact:n,draggables:r}=e;const o=_o(n);o||to(!1);const i=o.draggableId,a=r[i].page.borderBox.center,l=(e=>{let{displaced:t,afterCritical:n,combineWith:r,displacedBy:o}=e;const i=Boolean(t.visible[r]||t.invisible[r]);return Qo(r,n)?i?uo:mo(o.point):i?o.point:uo})({displaced:n.displaced,afterCritical:t,combineWith:i,displacedBy:n.displacedBy});return co(a,l)})({impact:t,draggables:o,afterCritical:i}):a})(e),n=e.droppable;return n?Zo(n,t):t},ti=(e,t)=>{const n=fo(t,e.scroll.initial),r=mo(n);return{frame:Ar({top:t.y,bottom:t.y+e.frame.height,left:t.x,right:t.x+e.frame.width}),scroll:{initial:e.scroll.initial,max:e.scroll.max,current:t,diff:{value:n,displacement:r}}}};function ni(e,t){return e.map((e=>t[e]))}var ri=e=>{let{pageBorderBoxCenter:t,draggable:n,viewport:r}=e;const o=((e,t)=>co(e.scroll.diff.displacement,t))(r,t),i=fo(o,n.page.borderBox.center);return co(n.client.borderBox.center,i)},oi=e=>{let{draggable:t,destination:n,newPageBorderBoxCenter:r,viewport:o,withDroppableDisplacement:i,onlyOnMainAxis:a=!1}=e;const l=fo(r,t.page.borderBox.center),s={target:vo(t.page.borderBox,l),destination:n,withDroppableDisplacement:i,viewport:o};return a?(e=>{return Uo({...e,isVisibleThroughFrameFn:(t=e.destination.axis,e=>{const n=Mo(e.top,e.bottom),r=Mo(e.left,e.right);return e=>t===Fo?n(e.top)&&n(e.bottom):r(e.left)&&r(e.right)})});var t})(s):$o(s)},ii=e=>{let{isMovingForward:t,draggable:n,destination:r,draggables:o,previousImpact:i,viewport:a,previousPageBorderBoxCenter:l,previousClientSelection:s,afterCritical:u}=e;if(!r.isEnabled)return null;const c=Io(r.descriptor.id,o),d=No(n,r),f=(e=>{let{isMovingForward:t,draggable:n,destination:r,insideDestination:o,previousImpact:i}=e;if(!r.isCombineEnabled)return null;if(!Do(i))return null;function a(e){const t={type:"COMBINE",combine:{draggableId:e,droppableId:r.descriptor.id}};return{...i,at:t}}const l=i.displaced.all,s=l.length?l[0]:null;if(t)return s?a(s):null;const u=Ro(n,o);if(!s)return u.length?a(u[u.length-1].descriptor.id):null;const c=u.findIndex((e=>e.descriptor.id===s));-1===c&&to(!1);const d=c-1;return d<0?null:a(u[d].descriptor.id)})({isMovingForward:t,draggable:n,destination:r,insideDestination:c,previousImpact:i})||(e=>{let{isMovingForward:t,isInHomeList:n,draggable:r,draggables:o,destination:i,insideDestination:a,previousImpact:l,viewport:s,afterCritical:u}=e;const c=l.at;if(c||to(!1),"REORDER"===c.type){const e=(e=>{let{isMovingForward:t,isInHomeList:n,insideDestination:r,location:o}=e;if(!r.length)return null;const i=o.index,a=t?i+1:i-1,l=r[0].descriptor.index,s=r[r.length-1].descriptor.index;return a(n?s:s+1)?null:a})({isMovingForward:t,isInHomeList:n,location:c.destination,insideDestination:a});return null==e?null:qo({draggable:r,insideDestination:a,destination:i,viewport:s,last:l.displaced,displacedBy:l.displacedBy,index:e})}const d=(e=>{let{isMovingForward:t,destination:n,draggables:r,combine:o,afterCritical:i}=e;if(!n.isCombineEnabled)return null;const a=o.draggableId,l=r[a].descriptor.index;return Qo(a,i)?t?l:l-1:t?l+1:l})({isMovingForward:t,destination:i,displaced:l.displaced,draggables:o,combine:c.combine,afterCritical:u});return null==d?null:qo({draggable:r,insideDestination:a,destination:i,viewport:s,last:l.displaced,displacedBy:l.displacedBy,index:d})})({isMovingForward:t,isInHomeList:d,draggable:n,draggables:o,destination:r,insideDestination:c,previousImpact:i,viewport:a,afterCritical:u});if(!f)return null;const p=ei({impact:f,draggable:n,droppable:r,draggables:o,afterCritical:u});if(oi({draggable:n,destination:r,newPageBorderBoxCenter:p,viewport:a.frame,withDroppableDisplacement:!1,onlyOnMainAxis:!0}))return{clientSelection:ri({pageBorderBoxCenter:p,draggable:n,viewport:a}),impact:f,scrollJumpRequest:null};const m=fo(p,l),h=(e=>{let{impact:t,viewport:n,destination:r,draggables:o,maxScrollChange:i}=e;const a=ti(n,co(n.scroll.current,i)),l=r.frame?xo(r,co(r.frame.scroll.current,i)):r,s=t.displaced,u=Ho({afterDragging:ni(s.all,o),destination:r,displacedBy:t.displacedBy,viewport:a.frame,last:s,forceShouldAnimate:!1}),c=Ho({afterDragging:ni(s.all,o),destination:l,displacedBy:t.displacedBy,viewport:n.frame,last:s,forceShouldAnimate:!1}),d={},f={},p=[s,u,c];return s.all.forEach((e=>{const t=function(e,t){for(let n=0;n{const t=e.subject.active;return t||to(!1),t},li=(e,t)=>{const n=e.page.borderBox.center;return Qo(e.descriptor.id,t)?fo(n,t.displacedBy.point):n},si=(e,t)=>{const n=e.page.borderBox;return Qo(e.descriptor.id,t)?vo(n,mo(t.displacedBy.point)):n};var ui=qr((function(e,t){const n=t[e.line];return{value:n,point:ho(e.line,n)}}));const ci=(e,t)=>({...e,scroll:{...e.scroll,max:t}}),di=(e,t,n)=>{const r=e.frame;No(t,e)&&to(!1),e.subject.withPlaceholder&&to(!1);const o=ui(e.axis,t.displaceBy).point,i=((e,t,n)=>{const r=e.axis;if("virtual"===e.descriptor.mode)return ho(r.line,t[r.line]);const o=e.subject.page.contentBox[r.size],i=Io(e.descriptor.id,n).reduce(((e,t)=>e+t.client.marginBox[r.size]),0)+t[r.line]-o;return i<=0?null:ho(r.line,i)})(e,o,n),a={placeholderSize:o,increasedBy:i,oldFrameMaxScroll:e.frame?e.frame.scroll.max:null};if(!r){const t=So({page:e.subject.page,withPlaceholder:a,axis:e.axis,frame:e.frame});return{...e,subject:t}}const l=i?co(r.scroll.max,i):r.scroll.max,s=ci(r,l),u=So({page:e.subject.page,withPlaceholder:a,axis:e.axis,frame:s});return{...e,subject:u,frame:s}};var fi=e=>{const t=e.at;return t?"REORDER"===t.type?t.destination.droppableId:t.combine.droppableId:null},pi=e=>{let{state:t,type:n}=e;const r=((e,t)=>{const n=fi(e);return n?t[n]:null})(t.impact,t.dimensions.droppables),o=Boolean(r),i=t.dimensions.droppables[t.critical.droppable.id],a=r||i,l=a.axis.direction,s="vertical"===l&&("MOVE_UP"===n||"MOVE_DOWN"===n)||"horizontal"===l&&("MOVE_LEFT"===n||"MOVE_RIGHT"===n);if(s&&!o)return null;const u="MOVE_DOWN"===n||"MOVE_RIGHT"===n,c=t.dimensions.draggables[t.critical.draggable.id],d=t.current.page.borderBoxCenter,{draggables:f,droppables:p}=t.dimensions;return s?ii({isMovingForward:u,previousPageBorderBoxCenter:d,draggable:c,destination:a,draggables:f,viewport:t.viewport,previousClientSelection:t.current.client.selection,previousImpact:t.impact,afterCritical:t.afterCritical}):(e=>{let{isMovingForward:t,previousPageBorderBoxCenter:n,draggable:r,isOver:o,draggables:i,droppables:a,viewport:l,afterCritical:s}=e;const u=(e=>{let{isMovingForward:t,pageBorderBoxCenter:n,source:r,droppables:o,viewport:i}=e;const a=r.subject.active;if(!a)return null;const l=r.axis,s=Mo(a[l.start],a[l.end]),u=Co(o).filter((e=>e!==r)).filter((e=>e.isEnabled)).filter((e=>Boolean(e.subject.active))).filter((e=>Lo(i.frame)(ai(e)))).filter((e=>{const n=ai(e);return t?a[l.crossAxisEnd]{const t=ai(e),n=Mo(t[l.start],t[l.end]);return s(t[l.start])||s(t[l.end])||n(a[l.start])||n(a[l.end])})).sort(((e,n)=>{const r=ai(e)[l.crossAxisStart],o=ai(n)[l.crossAxisStart];return t?r-o:o-r})).filter(((e,t,n)=>ai(e)[l.crossAxisStart]===ai(n[0])[l.crossAxisStart]));if(!u.length)return null;if(1===u.length)return u[0];const c=u.filter((e=>Mo(ai(e)[l.start],ai(e)[l.end])(n[l.line])));return 1===c.length?c[0]:c.length>1?c.sort(((e,t)=>ai(e)[l.start]-ai(t)[l.start]))[0]:u.sort(((e,t)=>{const r=yo(n,wo(ai(e))),o=yo(n,wo(ai(t)));return r!==o?r-o:ai(e)[l.start]-ai(t)[l.start]}))[0]})({isMovingForward:t,pageBorderBoxCenter:n,source:o,droppables:a,viewport:l});if(!u)return null;const c=Io(u.descriptor.id,i),d=(e=>{let{pageBorderBoxCenter:t,viewport:n,destination:r,insideDestination:o,afterCritical:i}=e;const a=o.filter((e=>$o({target:si(e,i),destination:r,viewport:n.frame,withDroppableDisplacement:!0}))).sort(((e,n)=>{const o=go(t,Zo(r,li(e,i))),a=go(t,Zo(r,li(n,i)));return o{let{previousPageBorderBoxCenter:t,moveRelativeTo:n,insideDestination:r,draggable:o,draggables:i,destination:a,viewport:l,afterCritical:s}=e;if(!n){if(r.length)return null;const e={displaced:jo,displacedBy:To,at:{type:"REORDER",destination:{droppableId:a.descriptor.id,index:0}}},t=ei({impact:e,draggable:o,droppable:a,draggables:i,afterCritical:s}),n=No(o,a)?a:di(a,o,i);return oi({draggable:o,destination:n,newPageBorderBoxCenter:t,viewport:l.frame,withDroppableDisplacement:!1,onlyOnMainAxis:!0})?e:null}const u=Boolean(t[a.axis.line]<=n.page.borderBox.center[a.axis.line]),c=(()=>{const e=n.descriptor.index;return n.descriptor.id===o.descriptor.id||u?e:e+1})(),d=ui(a.axis,o.displaceBy);return qo({draggable:o,insideDestination:r,destination:a,viewport:l,displacedBy:d,last:jo,index:c})})({previousPageBorderBoxCenter:n,destination:u,draggable:r,draggables:i,moveRelativeTo:d,insideDestination:c,viewport:l,afterCritical:s});if(!f)return null;const p=ei({impact:f,draggable:r,droppable:u,draggables:i,afterCritical:s});return{clientSelection:ri({pageBorderBoxCenter:p,draggable:r,viewport:l}),impact:f,scrollJumpRequest:null}})({isMovingForward:u,previousPageBorderBoxCenter:d,draggable:c,isOver:a,draggables:f,droppables:p,viewport:t.viewport,afterCritical:t.afterCritical})};function mi(e){return"DRAGGING"===e.phase||"COLLECTING"===e.phase}function hi(e){const t=Mo(e.top,e.bottom),n=Mo(e.left,e.right);return function(e){return t(e.y)&&n(e.x)}}const gi=(e,t)=>Ar(vo(e,t));function yi(e){let{displaced:t,id:n}=e;return Boolean(t.visible[n]||t.invisible[n])}var bi=e=>{let{pageOffset:t,draggable:n,draggables:r,droppables:o,previousImpact:i,viewport:a,afterCritical:l}=e;const s=gi(n.page.borderBox,t),u=function(e){let{pageBorderBox:t,draggable:n,droppables:r}=e;const o=Co(r).filter((e=>{if(!e.isEnabled)return!1;const n=e.subject.active;if(!n)return!1;if(o=n,!((r=t).lefto.left&&r.topo.top))return!1;var r,o;if(hi(n)(t.center))return!0;const i=e.axis,a=n.center[i.crossAxisLine],l=t[i.crossAxisStart],s=t[i.crossAxisEnd],u=Mo(n[i.crossAxisStart],n[i.crossAxisEnd]),c=u(l),d=u(s);return!c&&!d||(c?la)}));return o.length?1===o.length?o[0].descriptor.id:function(e){let{pageBorderBox:t,draggable:n,candidates:r}=e;const o=n.page.borderBox.center,i=r.map((e=>{const n=e.axis,r=ho(e.axis.line,t.center[n.line],e.page.borderBox.center[n.crossAxisLine]);return{id:e.descriptor.id,distance:go(o,r)}})).sort(((e,t)=>t.distance-e.distance));return i[0]?i[0].id:null}({pageBorderBox:t,draggable:n,candidates:o}):null}({pageBorderBox:s,draggable:n,droppables:o});if(!u)return Ao;const c=o[u],d=Io(c.descriptor.id,r),f=((e,t)=>{const n=e.frame;return n?gi(t,n.scroll.diff.value):t})(c,s);return(e=>{let{draggable:t,pageBorderBoxWithDroppableScroll:n,previousImpact:r,destination:o,insideDestination:i,afterCritical:a}=e;if(!o.isCombineEnabled)return null;const l=o.axis,s=ui(o.axis,t.displaceBy),u=s.value,c=n[l.start],d=n[l.end],f=Ro(t,i).find((e=>{const t=e.descriptor.id,n=e.page.borderBox,o=n[l.size]/4,i=Qo(t,a),s=yi({displaced:r.displaced,id:t});return i?s?d>n[l.start]+o&&dn[l.start]-u+o&&cn[l.start]+u+o&&dn[l.start]+o&&c{let{pageBorderBoxWithDroppableScroll:t,draggable:n,destination:r,insideDestination:o,last:i,viewport:a,afterCritical:l}=e;const s=r.axis,u=ui(r.axis,n.displaceBy),c=u.value,d=t[s.start],f=t[s.end],p=function(e){let{draggable:t,closest:n,inHomeList:r}=e;return n?r&&n.descriptor.index>t.descriptor.index?n.descriptor.index-1:n.descriptor.index:null}({draggable:n,closest:Ro(n,o).find((e=>{const t=e.descriptor.id,n=e.page.borderBox.center[s.line],r=Qo(t,l),o=yi({displaced:i,id:t});return r?o?f<=n:d