Add horizontal items into the cart
Signed-off-by: Egor Savkin <es@m-labs.hk>
This commit is contained in:
parent
bf17a24704
commit
84562f276a
|
@ -117,10 +117,20 @@ button {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
img {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
height: 400px;
|
height: 400px;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
cursor: grab;
|
||||||
|
&.default-icon {
|
||||||
|
height: 144px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
|
@ -487,8 +497,41 @@ button {
|
||||||
|
|
||||||
&.horizontal {
|
&.horizontal {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 50px;
|
min-height: 10px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 5px 3px;
|
||||||
|
}
|
||||||
|
.progress-container {
|
||||||
|
max-width: 40px;
|
||||||
|
padding: 0 10px;
|
||||||
|
justify-self: start;
|
||||||
|
}
|
||||||
|
.product-name {
|
||||||
|
justify-self: start;
|
||||||
|
padding: 0 10px;
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
.removeHorizontal {
|
||||||
|
justify-self: end;
|
||||||
|
padding: 0 10px;
|
||||||
|
img {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<svg width="256" height="256" version="1.1" viewBox="0 0 67.733 67.733" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(1.2797 0 0 1.2797 -4.4788 -4.4788)" stroke-width="1.0001"><g fill-opacity="0" stroke="#fff" stroke-linecap="round" stroke-width="1.0001"><g stroke-linejoin="round" stroke-opacity=".8" stroke-width="1.0001"><path d="m4 28.965v2"/><path d="m4 40.948v2"/><path d="m4 16.983v2"/></g><g stroke-linejoin="round" stroke-opacity=".8" stroke-width="1.0001"><path d="m28.965 4h2"/><path d="m16.983 4h2"/><path d="m40.948 4.0001h2"/></g><g transform="translate(0 3.3081)" stroke-linejoin="round" stroke-opacity=".8" stroke-width="1.0001"><path d="m28.965 52.623h2"/><path d="m40.948 52.623h2"/><path d="m16.983 52.623h2"/></g><g transform="translate(3.3082)" stroke-linejoin="round" stroke-opacity=".8" stroke-width="1.0001"><path d="m52.623 28.965v2"/><path d="m52.623 16.983v2.0001"/><path d="m52.623 40.948v2.0001"/></g><g stroke-linejoin="round"><path d="m7 4h-3v3" stroke-opacity=".8" stroke-width="1.0001"/><path d="m52.931 4h3v3" stroke-opacity=".8" stroke-width="1.0001"/><path d="m7 55.931h-3v-3" stroke-opacity=".8" stroke-width="1.0001"/></g><path d="m28.311 27.311v2.0001m-1-1h2" stroke-opacity=".8" stroke-width="1.0001"/><path d="m52.931 55.931h3v-3" stroke-linejoin="round" stroke-opacity=".8" stroke-width="1.0001"/></g></g><g transform="matrix(.64211 -.68634 .59172 .63248 35.302 51.828)"><path transform="translate(1.6405e-6)" d="m7 13.5v-7c0-0.82842 0.67157-1.5 1.5-1.5s1.5 0.55521 1.5 1.3836v0.11637 2m0-1e-5v-2c0-2.2857 3-2.2857 3 0v0.52708 1.4729m0 3e-5v-1.4729c0-2.2857 3-2.2857 3 0v0.9015 0.57143m-3 0v-1.4729m0-0.52707v0.52707m3 1.4729v-0.57143-0.9015c0-2.2857-3-2.2857-3 0m3 1.4728v-0.57143c0-2.2857 3-2.2857 3 0m-12 2.5715-2.0041 2.6721c-0.57746 0.77-0.52464 1.842 0.12569 2.5515l3.7839 4.1279c0.37882 0.4132 0.91276 0.6485 1.4734 0.6485h4.6211c2.4 0 4-1.5 4-4v-8.5714" fill-opacity="0" stroke="#fff" stroke-opacity=".9"/></g></svg>
|
After Width: | Height: | Size: 1.9 KiB |
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react'
|
import React, {useRef, useEffect, useState} from 'react'
|
||||||
import {Droppable} from "@hello-pangea/dnd";
|
import {Droppable} from "@hello-pangea/dnd";
|
||||||
import {cartStyle, compareArraysWithIds} from "./utils";
|
import {cartStyle, compareArraysWithIds} from "./utils";
|
||||||
import {ProductCartItem} from "./ProductCartItem";
|
import {ProductCartItem} from "./ProductCartItem";
|
||||||
|
@ -9,17 +9,17 @@ import {useShopStore} from "./shop_store";
|
||||||
// #!render_count
|
// #!render_count
|
||||||
import {useRenderCount} from "@uidotdev/usehooks";
|
import {useRenderCount} from "@uidotdev/usehooks";
|
||||||
|
|
||||||
/**
|
|
||||||
* Component that displays a list of <ProductCartItem>
|
|
||||||
*/
|
|
||||||
export function Cart({crate_index}) {
|
export function Cart({crate_index}) {
|
||||||
// #!render_count
|
// #!render_count
|
||||||
const renderCount = useRenderCount();
|
const renderCount = useRenderCount();
|
||||||
|
const containerRef = useRef(null);
|
||||||
|
const [visiblePlaceholders, setVisiblePlaceholders] = useState(0);
|
||||||
|
|
||||||
const crate = useShopStore((state) => state.crates[crate_index], (a, b) => {
|
const crate = useShopStore((state) => state.crates[crate_index], (a, b) => {
|
||||||
return compareArraysWithIds(a.items, b.items) && a.occupiedHP === b.occupiedHP && a.crate_mode === b.crate_mode
|
return compareArraysWithIds(a.items, b.items) && a.occupiedHP === b.occupiedHP && a.crate_mode === b.crate_mode
|
||||||
});
|
});
|
||||||
const crateParams = useShopStore((state) => state.crateParams);
|
const crateParams = useShopStore((state) => state.crateParams);
|
||||||
|
const isCrate = useShopStore((state) => state.modes_order.includes(state.crates[crate_index].crate_mode));
|
||||||
|
|
||||||
// #!render_count
|
// #!render_count
|
||||||
console.log("Cart renders: ", renderCount)
|
console.log("Cart renders: ", renderCount)
|
||||||
|
@ -27,23 +27,43 @@ export function Cart({crate_index}) {
|
||||||
const nbrOccupied = hp_to_slots(crate.occupiedHP);
|
const nbrOccupied = hp_to_slots(crate.occupiedHP);
|
||||||
const nbrSlots = hp_to_slots(crateParams(crate.crate_mode).hp);
|
const nbrSlots = hp_to_slots(crateParams(crate.crate_mode).hp);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const updateVisiblePlaceholders = () => {
|
||||||
|
if (!containerRef.current) return;
|
||||||
|
setVisiblePlaceholders(isCrate ?
|
||||||
|
(nbrSlots - nbrOccupied) :
|
||||||
|
// 10 is padding and 77 is the actual size with all the margins
|
||||||
|
Math.max(1, Math.floor((containerRef.current.offsetWidth - 10) / 77) - nbrOccupied));
|
||||||
|
};
|
||||||
|
updateVisiblePlaceholders();
|
||||||
|
const resizeObserver = new ResizeObserver(updateVisiblePlaceholders);
|
||||||
|
if (containerRef.current) {
|
||||||
|
resizeObserver.observe(containerRef.current);
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
if (containerRef.current) {
|
||||||
|
resizeObserver.unobserve(containerRef.current);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [nbrOccupied, nbrSlots]);
|
||||||
|
|
||||||
const products = crate.items.map((item, index) => {
|
const products = crate.items.map((item, index) => {
|
||||||
return (
|
return (
|
||||||
<ProductCartItem
|
<ProductCartItem
|
||||||
card_index={index}
|
card_index={index}
|
||||||
crate_index={crate_index}
|
crate_index={crate_index}
|
||||||
first={index === 0}
|
|
||||||
last={index === crate.items.length - 1 && nbrOccupied >= nbrSlots}
|
|
||||||
key={item.id}/>
|
key={item.id}/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Droppable droppableId={crate.id} direction="horizontal">
|
<Droppable droppableId={crate.id} direction="horizontal">
|
||||||
|
|
||||||
{(provided, snapshot) => (
|
{(provided, snapshot) => (
|
||||||
<div
|
<div
|
||||||
ref={provided.innerRef}
|
ref={(element) => {
|
||||||
|
containerRef.current = element;
|
||||||
|
provided.innerRef(element);
|
||||||
|
}}
|
||||||
{...provided.droppableProps}
|
{...provided.droppableProps}
|
||||||
style={cartStyle(
|
style={cartStyle(
|
||||||
provided.droppableProps.style,
|
provided.droppableProps.style,
|
||||||
|
@ -60,11 +80,10 @@ export function Cart({crate_index}) {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<FakePlaceholder
|
<FakePlaceholder
|
||||||
nToDraw={nbrSlots - nbrOccupied}
|
nToDraw={visiblePlaceholders}
|
||||||
isDraggingOver={snapshot.isDraggingOver}/>
|
isDraggingOver={snapshot.isDraggingOver}/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</Droppable>
|
</Droppable>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
import React from 'react'
|
||||||
|
import {Droppable} from "@hello-pangea/dnd";
|
||||||
|
import {cartStyle, compareArraysWithIds} from "./utils";
|
||||||
|
import {ProductCartItemHorizontal} from "./ProductCartItemHorizontal";
|
||||||
|
import {HORIZONTAL_CART_MARKER, useShopStore} from "./shop_store";
|
||||||
|
|
||||||
|
// #!render_count
|
||||||
|
import {useRenderCount} from "@uidotdev/usehooks";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component that displays a list of <ProductCartItem>
|
||||||
|
*/
|
||||||
|
export function CartHorizontal({crate_index}) {
|
||||||
|
// #!render_count
|
||||||
|
const renderCount = useRenderCount();
|
||||||
|
|
||||||
|
const crate = useShopStore((state) => state.crates[crate_index], (a, b) => {
|
||||||
|
return compareArraysWithIds(a.h_items, b.h_items)
|
||||||
|
});
|
||||||
|
|
||||||
|
// #!render_count
|
||||||
|
console.log("CartHorizontal renders: ", renderCount)
|
||||||
|
|
||||||
|
|
||||||
|
const products = crate.h_items.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<ProductCartItemHorizontal
|
||||||
|
card_index={index}
|
||||||
|
crate_index={crate_index}
|
||||||
|
key={item.id}/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Droppable droppableId={crate.id+HORIZONTAL_CART_MARKER} direction="vertical">
|
||||||
|
{(provided, snapshot) => (
|
||||||
|
<div
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.droppableProps}
|
||||||
|
style={cartStyle(
|
||||||
|
provided.droppableProps.style,
|
||||||
|
snapshot,
|
||||||
|
)}
|
||||||
|
className="items-cart-list horizontal">
|
||||||
|
|
||||||
|
{products}
|
||||||
|
|
||||||
|
{provided.placeholder && (
|
||||||
|
<div style={{display: 'none'}}>
|
||||||
|
{provided.placeholder}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
</Droppable>
|
||||||
|
);
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ export function Catalog() {
|
||||||
const renderCount = useRenderCount();
|
const renderCount = useRenderCount();
|
||||||
|
|
||||||
const data = useShopStore((state) => state.groups);
|
const data = useShopStore((state) => state.groups);
|
||||||
const items = useShopStore((state) => state.cards);
|
const _items = useShopStore((state) => state.cards);
|
||||||
|
|
||||||
const onClickToggleMobileSideMenu = useShopStore((state) => state.switchSideMenu);
|
const onClickToggleMobileSideMenu = useShopStore((state) => state.switchSideMenu);
|
||||||
const isMobile = useShopStore((state) => state.isMobile);
|
const isMobile = useShopStore((state) => state.isMobile);
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {CrateMode} from "./CrateMode";
|
||||||
import {CrateWarnings} from "./CrateWarnings";
|
import {CrateWarnings} from "./CrateWarnings";
|
||||||
import {useShopStore} from "./shop_store";
|
import {useShopStore} from "./shop_store";
|
||||||
import {CrateOptions} from "./CrateOptions";
|
import {CrateOptions} from "./CrateOptions";
|
||||||
|
import {CartHorizontal} from "./CartHorizontal";
|
||||||
|
|
||||||
// #!render_count
|
// #!render_count
|
||||||
import {useRenderCount} from "@uidotdev/usehooks";
|
import {useRenderCount} from "@uidotdev/usehooks";
|
||||||
|
@ -28,7 +29,7 @@ export function Crate({crate_index}) {
|
||||||
return (
|
return (
|
||||||
<div className="crate">
|
<div className="crate">
|
||||||
{
|
{
|
||||||
modes_order.includes(crate.crate_mode) ? (
|
modes_order.includes(crate.crate_mode) && (
|
||||||
<div className="crate-bar d-inline-flex justify-content-between">
|
<div className="crate-bar d-inline-flex justify-content-between">
|
||||||
<CrateMode crate_index={crate_index}/>
|
<CrateMode crate_index={crate_index}/>
|
||||||
|
|
||||||
|
@ -36,13 +37,17 @@ export function Crate({crate_index}) {
|
||||||
Delete crate <img src="/images/shop/icon-remove.svg" alt="remove"/>
|
Delete crate <img src="/images/shop/icon-remove.svg" alt="remove"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : <></>
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
<div className="crate-products">
|
<div className="crate-products">
|
||||||
|
|
||||||
<Cart crate_index={crate_index}/>
|
<Cart crate_index={crate_index}/>
|
||||||
|
|
||||||
|
{ !modes_order.includes(crate.crate_mode) &&
|
||||||
|
<CartHorizontal crate_index={crate_index}/>
|
||||||
|
}
|
||||||
|
|
||||||
<CrateWarnings crate_index={crate_index} />
|
<CrateWarnings crate_index={crate_index} />
|
||||||
|
|
||||||
<CrateOptions crate_index={crate_index}/>
|
<CrateOptions crate_index={crate_index}/>
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function FakePlaceholder({isDraggingOver, nToDraw}) {
|
||||||
<div key={i} style={{
|
<div key={i} style={{
|
||||||
display: isDraggingOver ? 'none' : 'block',
|
display: isDraggingOver ? 'none' : 'block',
|
||||||
border: '1px dashed #ccc',
|
border: '1px dashed #ccc',
|
||||||
width: '45px',
|
width: '69px',
|
||||||
marginBottom: '5px',
|
marginBottom: '5px',
|
||||||
}}></div>
|
}}></div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,21 +1,23 @@
|
||||||
import {DialogPopup} from "./options/DialogPopup";
|
import {DialogPopup} from "./options/DialogPopup";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {useShopStore} from "./shop_store";
|
import {useShopStore, whichItems} from "./shop_store";
|
||||||
import {SummaryPopup} from "./options/SummaryPopup";
|
import {SummaryPopup} from "./options/SummaryPopup";
|
||||||
|
|
||||||
export function OptionsDialogWrapper({crate_index, card_index, horizontal}) {
|
export function OptionsDialogWrapper({crate_index, card_index, horizontal}) {
|
||||||
|
const whichH = whichItems(horizontal);
|
||||||
const crate_id = useShopStore((state) => state.crates[crate_index].id);
|
const crate_id = useShopStore((state) => state.crates[crate_index].id);
|
||||||
const use_options = useShopStore((state) => state.crateParams(state.crates[crate_index].crate_mode).options);
|
const use_options = useShopStore((state) => state.crateParams(state.crates[crate_index].crate_mode).options);
|
||||||
const options = useShopStore((state) => state.crates[crate_index].items[card_index][use_options]);
|
const options = useShopStore((state) => state.crates[crate_index][whichH][card_index][use_options]);
|
||||||
const options_data = useShopStore((state) => state.crates[crate_index].items[card_index].options_data);
|
const options_data = useShopStore((state) => state.crates[crate_index][whichH][card_index].options_data);
|
||||||
const card_id = useShopStore((state) => state.crates[crate_index].items[card_index].id);
|
const card_id = useShopStore((state) => state.crates[crate_index][whichH][card_index].id);
|
||||||
const options_class = useShopStore((state) => state.crates[crate_index].items[card_index].options_class);
|
const options_class = useShopStore((state) => state.crates[crate_index][whichH][card_index].options_class);
|
||||||
const sideMenuIsOpen = useShopStore((state) => state.sideMenuIsOpen);
|
const sideMenuIsOpen = useShopStore((state) => state.sideMenuIsOpen);
|
||||||
const _notificationTimer = useShopStore((state) => state.notificationTimer);
|
const _notificationTimer = useShopStore((state) => state.notificationTimer);
|
||||||
const hideNotification = useShopStore((state) => state.hideNotification);
|
const hideNotification = useShopStore((state) => state.hideNotification);
|
||||||
const displayNotification = useShopStore((state) =>
|
const displayNotification = useShopStore((state) =>
|
||||||
|
!!state.notificationHorizontal === !!horizontal &&
|
||||||
state.notificationCrateId === crate_id &&
|
state.notificationCrateId === crate_id &&
|
||||||
(state.notificationCardIndex === card_index || (state.crates[crate_index].items.length + (state.notificationCardIndex || -1)) === card_index));
|
(state.notificationCardIndex === card_index || (state.crates[crate_index][whichH].length + (state.notificationCardIndex || -1)) === card_index));
|
||||||
|
|
||||||
const onOptionsUpdate = useShopStore((state) => state.updateOptions);
|
const onOptionsUpdate = useShopStore((state) => state.updateOptions);
|
||||||
|
|
||||||
|
@ -42,18 +44,19 @@ export function OptionsDialogWrapper({crate_index, card_index, horizontal}) {
|
||||||
console.log("update", outvar, value, options_data);
|
console.log("update", outvar, value, options_data);
|
||||||
|
|
||||||
if (outvar in options_data) options_data[outvar] = value;
|
if (outvar in options_data) options_data[outvar] = value;
|
||||||
onOptionsUpdate(crate_id, card_index, {[outvar]: value});
|
onOptionsUpdate(crate_id, card_index, {[outvar]: value}, horizontal);
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function OptionsSummaryWrapper({crate_index, card_index}) {
|
export function OptionsSummaryWrapper({crate_index, card_index, horizontal}) {
|
||||||
const card_id = useShopStore((state) => state.crates[crate_index].items[card_index].id);
|
const whichH = whichItems(horizontal);
|
||||||
|
const card_id = useShopStore((state) => state.crates[crate_index][whichH][card_index].id);
|
||||||
const use_options = useShopStore((state) => state.crateParams(state.crates[crate_index].crate_mode).options);
|
const use_options = useShopStore((state) => state.crateParams(state.crates[crate_index].crate_mode).options);
|
||||||
const options = useShopStore((state) => state.crates[crate_index].items[card_index][use_options]);
|
const options = useShopStore((state) => state.crates[crate_index][whichH][card_index][use_options]);
|
||||||
const options_data = useShopStore((state) => state.crates[crate_index].items[card_index].options_data);
|
const options_data = useShopStore((state) => state.crates[crate_index][whichH][card_index].options_data);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SummaryPopup id={card_id + "options"} options={options}
|
<SummaryPopup id={card_id + "options"} options={options}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import {RFQFeedback} from "./RFQFeedback";
|
||||||
|
|
||||||
// #!render_count
|
// #!render_count
|
||||||
import {useRenderCount} from "@uidotdev/usehooks";
|
import {useRenderCount} from "@uidotdev/usehooks";
|
||||||
import {OrderOptions} from "./OrderOptions";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that renders all things for order.
|
* Component that renders all things for order.
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {useRenderCount} from "@uidotdev/usehooks";
|
||||||
* Component that renders a product.
|
* Component that renders a product.
|
||||||
* Used in the crate
|
* Used in the crate
|
||||||
*/
|
*/
|
||||||
export function ProductCartItem({card_index, crate_index, first, last}) {
|
export function ProductCartItem({card_index, crate_index}) {
|
||||||
// #!render_count
|
// #!render_count
|
||||||
const renderCount = useRenderCount();
|
const renderCount = useRenderCount();
|
||||||
|
|
||||||
|
@ -24,7 +24,10 @@ export function ProductCartItem({card_index, crate_index, first, last}) {
|
||||||
const card_show_warnings = useShopStore(state => state.crates[crate_index].items[card_index].show_warnings, compareObjectsEmptiness);
|
const card_show_warnings = useShopStore(state => state.crates[crate_index].items[card_index].show_warnings, compareObjectsEmptiness);
|
||||||
const card_counted_resources = useShopStore(state => state.crates[crate_index].items[card_index].counted_resources, compareObjectsEmptiness);
|
const card_counted_resources = useShopStore(state => state.crates[crate_index].items[card_index].counted_resources, compareObjectsEmptiness);
|
||||||
|
|
||||||
const highlighted = useShopStore((state) => state.crates[crate_index].id === state.highlighted.crate && card_index === state.highlighted.card);
|
const highlighted = useShopStore((state) =>
|
||||||
|
!state.highlighted.horizontal &&
|
||||||
|
state.crates[crate_index].id === state.highlighted.crate &&
|
||||||
|
card_index === state.highlighted.card);
|
||||||
const warnings_disabled = useShopStore((state) => !!state.crateParams(state.crates[crate_index].crate_mode).warnings_disabled);
|
const warnings_disabled = useShopStore((state) => !!state.crateParams(state.crates[crate_index].crate_mode).warnings_disabled);
|
||||||
const use_options = useShopStore((state) => state.crateParams(state.crates[crate_index].crate_mode).options);
|
const use_options = useShopStore((state) => state.crateParams(state.crates[crate_index].crate_mode).options);
|
||||||
const crate_id = useShopStore((state) => state.crates[crate_index].id);
|
const crate_id = useShopStore((state) => state.crates[crate_index].id);
|
||||||
|
@ -58,7 +61,7 @@ export function ProductCartItem({card_index, crate_index, first, last}) {
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
onMouseEnter={() => setHighlight(crate_id, card_index)}
|
onMouseEnter={() => setHighlight(crate_id, card_index, false)}
|
||||||
onMouseLeave={removeHighlight}
|
onMouseLeave={removeHighlight}
|
||||||
>
|
>
|
||||||
|
|
||||||
|
@ -73,8 +76,6 @@ export function ProductCartItem({card_index, crate_index, first, last}) {
|
||||||
<OptionsDialogWrapper
|
<OptionsDialogWrapper
|
||||||
crate_index={crate_index}
|
crate_index={crate_index}
|
||||||
card_index={card_index}
|
card_index={card_index}
|
||||||
first={first}
|
|
||||||
last={last}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
import React from 'react'
|
||||||
|
import {Draggable} from "@hello-pangea/dnd";
|
||||||
|
import {productStyle} from "./utils";
|
||||||
|
import {useShopStore} from "./shop_store";
|
||||||
|
import {OptionsDialogWrapper} from "./OptionsWrapper";
|
||||||
|
|
||||||
|
// #!render_count
|
||||||
|
import {useRenderCount} from "@uidotdev/usehooks";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component that renders a product.
|
||||||
|
* Used in the crate
|
||||||
|
*/
|
||||||
|
export function ProductCartItemHorizontal({card_index, crate_index}) {
|
||||||
|
// #!render_count
|
||||||
|
const renderCount = useRenderCount();
|
||||||
|
|
||||||
|
const card = useShopStore((state) => state.crates[crate_index].h_items[card_index],
|
||||||
|
(a, b) => a.id === b.id);
|
||||||
|
|
||||||
|
const highlighted = useShopStore((state) =>
|
||||||
|
!!state.highlighted.horizontal &&
|
||||||
|
state.crates[crate_index].id === state.highlighted.crate &&
|
||||||
|
card_index === state.highlighted.card
|
||||||
|
);
|
||||||
|
const use_options = useShopStore((state) => state.crateParams(state.crates[crate_index].crate_mode).options);
|
||||||
|
const crate_id = useShopStore((state) => state.crates[crate_index].id);
|
||||||
|
const setHighlight = useShopStore((state) => state.highlightCard);
|
||||||
|
const removeHighlight = useShopStore((state) => state.highlightReset);
|
||||||
|
const onCardRemove = useShopStore((state) => state.deleteCard);
|
||||||
|
|
||||||
|
// #!render_count
|
||||||
|
console.log("ProductCartItem renders: ", renderCount)
|
||||||
|
|
||||||
|
|
||||||
|
const options = use_options && card && card[use_options] && card[use_options].length > 0;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Draggable draggableId={card.id} index={card_index}>
|
||||||
|
|
||||||
|
{(provided, snapshot) => (
|
||||||
|
<div
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.draggableProps}
|
||||||
|
{...provided.dragHandleProps}
|
||||||
|
style={{
|
||||||
|
...productStyle(
|
||||||
|
provided.draggableProps.style,
|
||||||
|
snapshot,
|
||||||
|
true,
|
||||||
|
!!highlighted,
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
onMouseEnter={() => setHighlight(crate_id, card_index, true)}
|
||||||
|
onMouseLeave={removeHighlight}
|
||||||
|
>
|
||||||
|
|
||||||
|
{/* warning container */}
|
||||||
|
|
||||||
|
<div className="progress-container warning d-flex justify-content-evenly">
|
||||||
|
{options && (
|
||||||
|
<OptionsDialogWrapper
|
||||||
|
crate_index={crate_index}
|
||||||
|
card_index={card_index}
|
||||||
|
horizontal={true}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className="product-name"
|
||||||
|
onMouseEnter={() => setHighlight(crate_id, card_index, true)}
|
||||||
|
onClick={() => setHighlight(crate_id, card_index, true)}
|
||||||
|
>
|
||||||
|
|
||||||
|
{`${card.name_number} ${card.name} ${card.name_codename}`}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* remove container */}
|
||||||
|
<div
|
||||||
|
style={{'display': 'flex'}}
|
||||||
|
className="removeHorizontal"
|
||||||
|
onClick={() => onCardRemove(crate_id, card_index, true)}>
|
||||||
|
|
||||||
|
<img src="/images/shop/icon-remove.svg" alt="rm"/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
</Draggable>
|
||||||
|
);
|
||||||
|
}
|
|
@ -7,6 +7,8 @@ import {useShopStore} from "./shop_store";
|
||||||
import {useRenderCount} from "@uidotdev/usehooks";
|
import {useRenderCount} from "@uidotdev/usehooks";
|
||||||
|
|
||||||
|
|
||||||
|
const DNDIcon = "/images/shop/icon-drag-and-drop.svg";
|
||||||
|
|
||||||
function DatasheetLink({datasheet_file, datasheet_name}) {
|
function DatasheetLink({datasheet_file, datasheet_name}) {
|
||||||
return datasheet_file && datasheet_name && (<div className="ds">
|
return datasheet_file && datasheet_name && (<div className="ds">
|
||||||
<span className='doc-icon'></span>
|
<span className='doc-icon'></span>
|
||||||
|
@ -76,11 +78,12 @@ export function ProductItem({card_index}) {
|
||||||
snapshot,
|
snapshot,
|
||||||
true, // hack: remove weird animation after a drop
|
true, // hack: remove weird animation after a drop
|
||||||
)}
|
)}
|
||||||
src={card.image}/>
|
className={card.image ? "" : "default-icon"}
|
||||||
|
src={card.image || DNDIcon}/>
|
||||||
|
|
||||||
{/* Allows to simulate a clone */}
|
{/* Allows to simulate a clone */}
|
||||||
{snapshot.isDragging && (
|
{snapshot.isDragging && (
|
||||||
<img className="simclone" src={card.image}/>
|
<img className={"simclone " + (card.image ? "" : "default-icon")} src={card.image || DNDIcon}/>
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -15,6 +15,7 @@ export function SummaryCrate({crate_index}) {
|
||||||
|
|
||||||
const crate_id = useShopStore((state) => state.crates[crate_index].id);
|
const crate_id = useShopStore((state) => state.crates[crate_index].id);
|
||||||
const crate_len = useShopStore((state) => state.crates[crate_index].items.length);
|
const crate_len = useShopStore((state) => state.crates[crate_index].items.length);
|
||||||
|
const crate_h_len = useShopStore((state) => state.crates[crate_index].h_items.length);
|
||||||
|
|
||||||
// #!render_count
|
// #!render_count
|
||||||
console.log("SummaryCrate renders: ", renderCount)
|
console.log("SummaryCrate renders: ", renderCount)
|
||||||
|
@ -28,6 +29,14 @@ export function SummaryCrate({crate_index}) {
|
||||||
<SummaryCrateCard crate_index={crate_index} card_index={index} key={"summary_crate_" + crate_id + "_" +index} />
|
<SummaryCrateCard crate_index={crate_index} card_index={index} key={"summary_crate_" + crate_id + "_" +index} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{range(0, crate_h_len).map((index, _i) =>
|
||||||
|
<SummaryCrateCard
|
||||||
|
crate_index={crate_index}
|
||||||
|
card_index={index}
|
||||||
|
horizontal={true}
|
||||||
|
key={"summary_crate_h_" + crate_id + "_" +index} />
|
||||||
|
)}
|
||||||
|
|
||||||
<SummaryCratePricedOptions crate_index={crate_index}/>
|
<SummaryCratePricedOptions crate_index={crate_index}/>
|
||||||
</tbody>
|
</tbody>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,28 +1,39 @@
|
||||||
import {compareObjectsEmptiness, formatMoney} from "./utils";
|
import {compareObjectsEmptiness, formatMoney} from "./utils";
|
||||||
import {WarningIndicator} from "./CardWarnings";
|
import {WarningIndicator} from "./CardWarnings";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {useShopStore} from "./shop_store";
|
import {useShopStore, whichItems} from "./shop_store";
|
||||||
import {OptionsSummaryWrapper} from "./OptionsWrapper";
|
import {OptionsSummaryWrapper} from "./OptionsWrapper";
|
||||||
|
|
||||||
// #!render_count
|
// #!render_count
|
||||||
import {useRenderCount} from "@uidotdev/usehooks";
|
import {useRenderCount} from "@uidotdev/usehooks";
|
||||||
|
|
||||||
|
|
||||||
export function SummaryCrateCard({crate_index, card_index}) {
|
export function SummaryCrateCard({crate_index, card_index, horizontal}) {
|
||||||
// #!render_count
|
// #!render_count
|
||||||
const renderCount = useRenderCount();
|
const renderCount = useRenderCount();
|
||||||
|
|
||||||
|
const whichH = whichItems(horizontal);
|
||||||
|
|
||||||
const currency = useShopStore((state) => state.currency);
|
const currency = useShopStore((state) => state.currency);
|
||||||
const deleteCard = useShopStore((state) => state.deleteCard);
|
const deleteCard = useShopStore((state) => state.deleteCard);
|
||||||
const setHighlight = useShopStore((state) => state.highlightCard);
|
const setHighlight = useShopStore((state) => state.highlightCard);
|
||||||
const resetHighlight = useShopStore((state) => state.highlightReset);
|
const resetHighlight = useShopStore((state) => state.highlightReset);
|
||||||
|
|
||||||
const highlighted = useShopStore((state) => state.crates[crate_index].id === state.highlighted.crate && card_index === state.highlighted.card);
|
const highlighted = useShopStore((state) =>
|
||||||
|
state.highlighted.horizontal === horizontal &&
|
||||||
|
state.crates[crate_index].id === state.highlighted.crate &&
|
||||||
|
card_index === state.highlighted.card);
|
||||||
const crate_id = useShopStore((state) => state.crates[crate_index].id);
|
const crate_id = useShopStore((state) => state.crates[crate_index].id);
|
||||||
const card = useShopStore((state) => state.crates[crate_index].items[card_index],
|
const card = useShopStore((state) =>
|
||||||
|
state.crates[crate_index][whichH][card_index],
|
||||||
(a, b) => a.id === b.id);
|
(a, b) => a.id === b.id);
|
||||||
const card_show_warnings = useShopStore(state => state.crates[crate_index].items[card_index].show_warnings, compareObjectsEmptiness);
|
// additional hooks for updating warning and options
|
||||||
const card_options_data = useShopStore(state => state.crates[crate_index].items[card_index].options_data, compareObjectsEmptiness);
|
const card_show_warnings = useShopStore(state =>
|
||||||
|
state.crates[crate_index][whichH][card_index].show_warnings,
|
||||||
|
compareObjectsEmptiness);
|
||||||
|
const card_options_data = useShopStore(state =>
|
||||||
|
state.crates[crate_index][whichH][card_index].options_data,
|
||||||
|
compareObjectsEmptiness);
|
||||||
const warnings_disabled = useShopStore((state) => !!state.crateParams(state.crates[crate_index].crate_mode).warnings_disabled);
|
const warnings_disabled = useShopStore((state) => !!state.crateParams(state.crates[crate_index].crate_mode).warnings_disabled);
|
||||||
const use_options = useShopStore((state) => state.crateParams(state.crates[crate_index].crate_mode).options);
|
const use_options = useShopStore((state) => state.crateParams(state.crates[crate_index].crate_mode).options);
|
||||||
|
|
||||||
|
@ -38,8 +49,8 @@ export function SummaryCrateCard({crate_index, card_index}) {
|
||||||
<tr
|
<tr
|
||||||
key={"summary_crate_" + crate_id + "_" + card_index}
|
key={"summary_crate_" + crate_id + "_" + card_index}
|
||||||
className={`hoverable ${highlighted ? 'selected' : ''}`}
|
className={`hoverable ${highlighted ? 'selected' : ''}`}
|
||||||
onClick={() => setHighlight(crate_id, card_index)}
|
onClick={() => setHighlight(crate_id, card_index, horizontal)}
|
||||||
onMouseEnter={() => setHighlight(crate_id, card_index)}
|
onMouseEnter={() => setHighlight(crate_id, card_index, horizontal)}
|
||||||
onMouseLeave={() => resetHighlight()}>
|
onMouseLeave={() => resetHighlight()}>
|
||||||
<td className="item-card-name tabbed">
|
<td className="item-card-name tabbed">
|
||||||
<div>{`${card.name_number} ${card.name} ${card.name_codename}`}</div>
|
<div>{`${card.name_number} ${card.name} ${card.name_codename}`}</div>
|
||||||
|
@ -49,7 +60,7 @@ export function SummaryCrateCard({crate_index, card_index}) {
|
||||||
<div className="d-inline-flex align-content-center">
|
<div className="d-inline-flex align-content-center">
|
||||||
{`${currency} ${formatMoney(card.price)}`}
|
{`${currency} ${formatMoney(card.price)}`}
|
||||||
|
|
||||||
<button onClick={() => deleteCard(crate_id, card_index)}>
|
<button onClick={() => deleteCard(crate_id, card_index, horizontal)}>
|
||||||
<img src="/images/shop/icon-remove.svg" className="d-block"/>
|
<img src="/images/shop/icon-remove.svg" className="d-block"/>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -64,7 +75,10 @@ export function SummaryCrateCard({crate_index, card_index}) {
|
||||||
}}> </span>
|
}}> </span>
|
||||||
))}
|
))}
|
||||||
{((options && options_data) ? (
|
{((options && options_data) ? (
|
||||||
<OptionsSummaryWrapper crate_index={crate_index} card_index={card_index}/>
|
<OptionsSummaryWrapper
|
||||||
|
crate_index={crate_index}
|
||||||
|
card_index={card_index}
|
||||||
|
horizontal={horizontal}/>
|
||||||
) : (
|
) : (
|
||||||
<span style={{
|
<span style={{
|
||||||
'display': 'inline-block',
|
'display': 'inline-block',
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import {formatMoney} from "./utils";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {useShopStore} from "./shop_store";
|
import {useShopStore} from "./shop_store";
|
||||||
import {ProcessOptions, ProcessOptionsToData} from "./options/Options";
|
import {ProcessOptions} from "./options/Options";
|
||||||
|
|
||||||
// #!render_count
|
// #!render_count
|
||||||
import {useRenderCount} from "@uidotdev/usehooks";
|
import {useRenderCount} from "@uidotdev/usehooks";
|
||||||
|
|
|
@ -21,10 +21,13 @@ export function validateJSON(description) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (const crate of crates_raw) {
|
for (const crate of crates_raw) {
|
||||||
if (!crate.type || !crate.items || !crate.options || !(crate.type in crate_modes)) return false;
|
if (!crate.type || !crate.items || !crate.h_items || !crate.options || !(crate.type in crate_modes)) return false;
|
||||||
for (const card of crate.items) {
|
for (const card of crate.items) {
|
||||||
if (!(card.pn in pn_to_card) || card.options === undefined) return false;
|
if (!(card.pn in pn_to_card) || card.options === undefined) return false;
|
||||||
}
|
}
|
||||||
|
for (const card of crate.h_items) {
|
||||||
|
if (!(card.pn in pn_to_card) || card.options === undefined) return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -50,6 +53,11 @@ export function JSONToCrates(description) {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
options_data: card.options || {}
|
options_data: card.options || {}
|
||||||
}))),
|
}))),
|
||||||
|
h_items: Array.from(crate.h_items.map((card, _i) => ({
|
||||||
|
...pn_to_card(card.pn),
|
||||||
|
id: uuidv4(),
|
||||||
|
options_data: card.options || {}
|
||||||
|
}))),
|
||||||
warnings: [],
|
warnings: [],
|
||||||
occupiedHP: 0,
|
occupiedHP: 0,
|
||||||
})));
|
})));
|
||||||
|
@ -73,6 +81,10 @@ export function CratesToJSON(crates) {
|
||||||
pn: card.name_number,
|
pn: card.name_number,
|
||||||
options: (card.options_data && card[crateParams(crate.crate_mode).options]) ? FilterOptions(card[crateParams(crate.crate_mode).options], card.options_data) : null
|
options: (card.options_data && card[crateParams(crate.crate_mode).options]) ? FilterOptions(card[crateParams(crate.crate_mode).options], card.options_data) : null
|
||||||
}))),
|
}))),
|
||||||
|
h_items: Array.from(crate.h_items.map((card, _) => ({
|
||||||
|
pn: card.name_number,
|
||||||
|
options: (card.options_data && card[crateParams(crate.crate_mode).options]) ? FilterOptions(card[crateParams(crate.crate_mode).options], card.options_data) : null
|
||||||
|
}))),
|
||||||
type: crate.crate_mode,
|
type: crate.crate_mode,
|
||||||
options: FilterOptions(crateOptions, crate.options_data)
|
options: FilterOptions(crateOptions, crate.options_data)
|
||||||
}))),
|
}))),
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
|
|
||||||
|
|
||||||
const ipv4 = (params) => {
|
const ipv4 = (_params) => {
|
||||||
const ipv4WithMaskPattern = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(0|1[0-9]|2[0-9]|3[0-2]|[0-9])$/;
|
const ipv4WithMaskPattern = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(0|1[0-9]|2[0-9]|3[0-2]|[0-9])$/;
|
||||||
return (text) => {
|
return (text) => {
|
||||||
return ipv4WithMaskPattern.test(text);
|
return ipv4WithMaskPattern.test(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ipv6 = (params) => {
|
const ipv6 = (_params) => {
|
||||||
const ipv6WithMaskPattern = /(^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(\/(\d{1,2}|1[0-1]\d|12[0-8]))(%.+)?\s*$)/;
|
const ipv6WithMaskPattern = /(^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(\/(\d{1,2}|1[0-1]\d|12[0-8]))(%.+)?\s*$)/;
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ const ipv6 = (params) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const hostname = (params) => {
|
const hostname = (_params) => {
|
||||||
const maxHostnameLength = 253;
|
const maxHostnameLength = 253;
|
||||||
const maxLabelLength = 63;
|
const maxLabelLength = 63;
|
||||||
const labelRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/;
|
const labelRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/;
|
||||||
|
|
|
@ -13,6 +13,8 @@ import {ProcessOptionsToData} from "./options/Options";
|
||||||
import {DomainedRFQMessages} from "./Domained";
|
import {DomainedRFQMessages} from "./Domained";
|
||||||
|
|
||||||
|
|
||||||
|
export const HORIZONTAL_CART_MARKER = "_h";
|
||||||
|
|
||||||
const cards_to_pn_map = (cards) => {
|
const cards_to_pn_map = (cards) => {
|
||||||
let result = {};
|
let result = {};
|
||||||
Object.entries(cards).forEach(([key, card], _i) => { result[card.name_number] = key})
|
Object.entries(cards).forEach(([key, card], _i) => { result[card.name_number] = key})
|
||||||
|
@ -23,6 +25,12 @@ const toArray = (arg) => {
|
||||||
return Array.isArray(arg) ? arg : [arg];
|
return Array.isArray(arg) ? arg : [arg];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const unwrapCrateId = (crate_id= "") => {
|
||||||
|
return crate_id.endsWith(HORIZONTAL_CART_MARKER) ? [true, crate_id.substring(0, crate_id.length - HORIZONTAL_CART_MARKER.length)] : [false, crate_id]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const whichItems = (horizontal = false) => horizontal ? "h_items" : "items"
|
||||||
|
|
||||||
const useCatalog = ((set, get) => ({
|
const useCatalog = ((set, get) => ({
|
||||||
cards: shared_data.items,
|
cards: shared_data.items,
|
||||||
groups: shared_data.columns.catalog,
|
groups: shared_data.columns.catalog,
|
||||||
|
@ -37,21 +45,24 @@ const useCatalog = ((set, get) => ({
|
||||||
const useOptionsNotification = ((set, get) => ({
|
const useOptionsNotification = ((set, get) => ({
|
||||||
notificationCrateId: null,
|
notificationCrateId: null,
|
||||||
notificationCardIndex: null,
|
notificationCardIndex: null,
|
||||||
|
notificationHorizontal: false,
|
||||||
notificationTimer: null,
|
notificationTimer: null,
|
||||||
_showNotification: (crate_id, card_index) => set(state => ({
|
_showNotification: (crate_id, card_index, horizontal) => set(state => ({
|
||||||
notificationCrateId: crate_id,
|
notificationCrateId: crate_id,
|
||||||
notificationCardIndex: card_index,
|
notificationCardIndex: card_index,
|
||||||
|
notificationHorizontal: horizontal,
|
||||||
notificationTimer: setTimeout(() => {
|
notificationTimer: setTimeout(() => {
|
||||||
state.hideNotification()
|
state.hideNotification()
|
||||||
}, 5000)
|
}, 5000)
|
||||||
})),
|
})),
|
||||||
showNotification: (crate_id, card_index) => {
|
showNotification: (crate_id, card_index, horizontal) => {
|
||||||
get().hideNotification()
|
get().hideNotification()
|
||||||
setTimeout(() => get()._showNotification(crate_id, card_index), 100);
|
setTimeout(() => get()._showNotification(crate_id, card_index, horizontal), 100);
|
||||||
},
|
},
|
||||||
hideNotification: () => set(state => ({
|
hideNotification: () => set(state => ({
|
||||||
notificationCrateId: null,
|
notificationCrateId: null,
|
||||||
notificationCardIndex: null,
|
notificationCardIndex: null,
|
||||||
|
notificationHorizontal: false,
|
||||||
notificationTimer: (state.notificationTimer && clearTimeout(state.notificationTimer)) || null,
|
notificationTimer: (state.notificationTimer && clearTimeout(state.notificationTimer)) || null,
|
||||||
}))
|
}))
|
||||||
}));
|
}));
|
||||||
|
@ -215,7 +226,7 @@ const useImportJSON = ((set, get) => ({
|
||||||
get().fillExtCrateData(crate.id);
|
get().fillExtCrateData(crate.id);
|
||||||
});
|
});
|
||||||
get()._updateTotalOrderPrice();
|
get()._updateTotalOrderPrice();
|
||||||
get().showNotification(get().active_crate, null);
|
get().showNotification(get().active_crate, null, false);
|
||||||
},
|
},
|
||||||
updateImportDescription: (new_description) => set(state => ({
|
updateImportDescription: (new_description) => set(state => ({
|
||||||
importValue: {
|
importValue: {
|
||||||
|
@ -332,15 +343,17 @@ const useSubmitForm = ((set, get) => ({
|
||||||
const useHighlighted = ((set, get) => ({
|
const useHighlighted = ((set, get) => ({
|
||||||
highlighted: {
|
highlighted: {
|
||||||
crate: "",
|
crate: "",
|
||||||
card: 0
|
card: 0,
|
||||||
|
horizontal: false
|
||||||
},
|
},
|
||||||
highlightedTimer: null,
|
highlightedTimer: null,
|
||||||
|
|
||||||
// #!if disable_card_highlight === false
|
// #!if disable_card_highlight === false
|
||||||
highlightCard: (crate_id, index) => set(state => ({
|
highlightCard: (crate_id, index, horizontal) => set(state => ({
|
||||||
highlighted: {
|
highlighted: {
|
||||||
crate: crate_id,
|
crate: crate_id,
|
||||||
card: index
|
card: index,
|
||||||
|
horizontal: horizontal
|
||||||
},
|
},
|
||||||
highlightedTimer: (!!state.highlightedTimer ? clearTimeout(state.highlightedTimer) : null) || (state.isTouch && setTimeout(() => {
|
highlightedTimer: (!!state.highlightedTimer ? clearTimeout(state.highlightedTimer) : null) || (state.isTouch && setTimeout(() => {
|
||||||
get().highlightReset()
|
get().highlightReset()
|
||||||
|
@ -349,7 +362,8 @@ const useHighlighted = ((set, get) => ({
|
||||||
highlightReset: () => set(state => ({
|
highlightReset: () => set(state => ({
|
||||||
highlighted: {
|
highlighted: {
|
||||||
crate: "",
|
crate: "",
|
||||||
card: 0
|
card: 0,
|
||||||
|
horizontal: false
|
||||||
},
|
},
|
||||||
highlightedTimer: !!state.highlightedTimer ? clearTimeout(state.highlightedTimer) : null
|
highlightedTimer: !!state.highlightedTimer ? clearTimeout(state.highlightedTimer) : null
|
||||||
})),
|
})),
|
||||||
|
@ -388,17 +402,18 @@ const useCart = ((set, get) => ({
|
||||||
})
|
})
|
||||||
})),
|
})),
|
||||||
setActiveCrate: (id) => set(state => ({active_crate: id})),
|
setActiveCrate: (id) => set(state => ({active_crate: id})),
|
||||||
_addCardFromCatalog: (crate_to, index_from, index_to) => set(state => {
|
_addCardFromCatalog: (crate_to, index_from, index_to, horizontal) => set(state => {
|
||||||
|
const whichH = whichItems(horizontal)
|
||||||
const take_from = toArray(index_from).map((item, _i) => (state.cards_list[item]));
|
const take_from = toArray(index_from).map((item, _i) => (state.cards_list[item]));
|
||||||
const dest = crate_to || state.active_crate;
|
const dest = crate_to || state.active_crate;
|
||||||
if (!dest) return {};
|
if (!dest) return {};
|
||||||
return {
|
return {
|
||||||
crates: state.crates.map((crate, _i) => {
|
crates: state.crates.map((crate, _i) => {
|
||||||
if (dest === crate.id) {
|
if (dest === crate.id) {
|
||||||
index_to = index_to != null ? index_to : crate.items.length;
|
index_to = index_to != null ? index_to : crate[whichH].length;
|
||||||
return {
|
return {
|
||||||
...crate,
|
...crate,
|
||||||
items: crate.items.toSpliced(index_to, 0, ...take_from.map((card_name, _) => {
|
[whichH]: crate[whichH].toSpliced(index_to, 0, ...take_from.map((card_name, _) => {
|
||||||
return {...state.cards[card_name], id: uuidv4()}
|
return {...state.cards[card_name], id: uuidv4()}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -406,39 +421,41 @@ const useCart = ((set, get) => ({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
_moveCard: (crate_from, index_from, crate_to, index_to) => set(state => {
|
_moveCard: (crate_from, index_from, crate_to, index_to, horizontal) => set(state => {
|
||||||
const the_card = state.crates.find((crate, _) => crate_from === crate.id ).items[index_from];
|
const whichH = whichItems(horizontal)
|
||||||
|
const the_card = state.crates.find((crate, _) => crate_from === crate.id )[whichH][index_from];
|
||||||
return {
|
return {
|
||||||
crates: state.crates.map((crate, _i) => {
|
crates: state.crates.map((crate, _i) => {
|
||||||
if (crate_to === crate_from && crate_to === crate.id) {
|
if (crate_to === crate_from && crate_to === crate.id) {
|
||||||
let items_copy = Array.from(crate.items);
|
let items_copy = Array.from(crate[whichH]);
|
||||||
let item = items_copy.splice(index_from, 1)[0]
|
let item = items_copy.splice(index_from, 1)[0]
|
||||||
items_copy.splice(index_to, 0, item).filter((item, _) => !!item)
|
items_copy.splice(index_to, 0, item).filter((item, _) => !!item)
|
||||||
return {
|
return {
|
||||||
...crate,
|
...crate,
|
||||||
items: items_copy
|
[whichH]: items_copy
|
||||||
}
|
}
|
||||||
} else if (crate_to === crate.id) {
|
} else if (crate_to === crate.id) {
|
||||||
return {
|
return {
|
||||||
...crate,
|
...crate,
|
||||||
items: crate.items.toSpliced(index_to, 0, the_card)
|
[whichH]: crate[whichH].toSpliced(index_to, 0, the_card)
|
||||||
}
|
}
|
||||||
} else if (crate_from === crate.id) {
|
} else if (crate_from === crate.id) {
|
||||||
return {
|
return {
|
||||||
...crate,
|
...crate,
|
||||||
items: crate.items.toSpliced(index_to, 1)
|
[whichH]: crate[whichH].toSpliced(index_to, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else return crate;
|
else return crate;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
_deleteCard: (crate_id, index) => set(state => ({
|
_deleteCard: (crate_id, index, horizontal) => set(state => ({
|
||||||
crates: state.crates.map((crate, _i) => {
|
crates: state.crates.map((crate, _i) => {
|
||||||
if (crate_id === crate.id) {
|
if (crate_id === crate.id) {
|
||||||
|
const whichH = whichItems(horizontal)
|
||||||
return {
|
return {
|
||||||
...crate,
|
...crate,
|
||||||
items: crate.items.toSpliced(index, 1)
|
[whichH]: crate[whichH].toSpliced(index, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else return crate;
|
else return crate;
|
||||||
|
@ -449,7 +466,8 @@ const useCart = ((set, get) => ({
|
||||||
if (id === crate.id) {
|
if (id === crate.id) {
|
||||||
return {
|
return {
|
||||||
...crate,
|
...crate,
|
||||||
items: []
|
items: [],
|
||||||
|
h_items: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else return crate;
|
else return crate;
|
||||||
|
@ -458,10 +476,11 @@ const useCart = ((set, get) => ({
|
||||||
clearAll: () => set(state => ({
|
clearAll: () => set(state => ({
|
||||||
crates: state._defaultCrates
|
crates: state._defaultCrates
|
||||||
})),
|
})),
|
||||||
_updateOptions: (crate_id, index, new_options) => set(state => ({
|
_updateOptions: (crate_id, index, new_options, horizontal) => set(state => ({
|
||||||
crates: state.crates.map((crate, _i) => {
|
crates: state.crates.map((crate, _i) => {
|
||||||
if (crate_id === crate.id) {
|
if (crate_id === crate.id) {
|
||||||
let itemsCopy = Array.from(crate.items);
|
const whichH = whichItems(horizontal)
|
||||||
|
let itemsCopy = Array.from(crate[whichH]);
|
||||||
itemsCopy[index] = {
|
itemsCopy[index] = {
|
||||||
...itemsCopy[index],
|
...itemsCopy[index],
|
||||||
options_data: {
|
options_data: {
|
||||||
|
@ -470,7 +489,7 @@ const useCart = ((set, get) => ({
|
||||||
}};
|
}};
|
||||||
return {
|
return {
|
||||||
...crate,
|
...crate,
|
||||||
items: itemsCopy
|
[whichH]: itemsCopy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else return crate;
|
else return crate;
|
||||||
|
@ -480,7 +499,7 @@ const useCart = ((set, get) => ({
|
||||||
fillWarnings: (crate_id) => set(state => ({
|
fillWarnings: (crate_id) => set(state => ({
|
||||||
crates: state.crates.map((crate, _i) => {
|
crates: state.crates.map((crate, _i) => {
|
||||||
if (crate_id === crate.id) {
|
if (crate_id === crate.id) {
|
||||||
//console.log("--- CHECK ALERTS ---")
|
// Warnings for horizontal items are not available
|
||||||
let itemsCopy = Array.from(crate.items);
|
let itemsCopy = Array.from(crate.items);
|
||||||
const disabled = !!get().crateParams(crate.crate_mode).warnings_disabled;
|
const disabled = !!get().crateParams(crate.crate_mode).warnings_disabled;
|
||||||
itemsCopy = FillResources(itemsCopy, disabled);
|
itemsCopy = FillResources(itemsCopy, disabled);
|
||||||
|
@ -497,11 +516,13 @@ const useCart = ((set, get) => ({
|
||||||
})
|
})
|
||||||
})),
|
})),
|
||||||
|
|
||||||
fillExtData: (crate_id) => set(state => ({
|
fillExtData: (crate_id, horizontal) => set(state => ({
|
||||||
crates: state.crates.map((crate, _i) => {
|
crates: state.crates.map((crate, _i) => {
|
||||||
|
// horizontal items do not interact with each other for now
|
||||||
if (crate_id === crate.id) {
|
if (crate_id === crate.id) {
|
||||||
|
const whichH = whichItems(horizontal)
|
||||||
const options_name = state.crateParams(crate.crate_mode).options;
|
const options_name = state.crateParams(crate.crate_mode).options;
|
||||||
let itemsCopy = Array.from(crate.items);
|
let itemsCopy = Array.from(crate[whichH]);
|
||||||
|
|
||||||
itemsCopy = itemsCopy.map((item, index) => {
|
itemsCopy = itemsCopy.map((item, index) => {
|
||||||
if (!item[options_name]) return item;
|
if (!item[options_name]) return item;
|
||||||
|
@ -511,7 +532,7 @@ const useCart = ((set, get) => ({
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
...crate,
|
...crate,
|
||||||
items: Array.from(itemsCopy)
|
[whichH]: Array.from(itemsCopy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else return crate;
|
else return crate;
|
||||||
|
@ -524,7 +545,7 @@ const useCart = ((set, get) => ({
|
||||||
sum += get().crate_modes[crate.crate_mode].price;
|
sum += get().crate_modes[crate.crate_mode].price;
|
||||||
const crate_options = ProcessOptionsToData({options: get().crate_prices, data: crate.options_data || {}});
|
const crate_options = ProcessOptionsToData({options: get().crate_prices, data: crate.options_data || {}});
|
||||||
sum += crate_options ? crate_options.reduce((accumulator, currentValue) => accumulator+currentValue.price, 0) : 0;
|
sum += crate_options ? crate_options.reduce((accumulator, currentValue) => accumulator+currentValue.price, 0) : 0;
|
||||||
crate.items.forEach((item, _) => {
|
crate.items.concat(crate.h_items).forEach((item, _) => {
|
||||||
sum += item.price;
|
sum += item.price;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -539,6 +560,7 @@ const useCart = ((set, get) => ({
|
||||||
const crate_id = "crate" + get().crates.length;
|
const crate_id = "crate" + get().crates.length;
|
||||||
get()._newCrate(crate_id)
|
get()._newCrate(crate_id)
|
||||||
get().fillExtData(crate_id);
|
get().fillExtData(crate_id);
|
||||||
|
get().fillExtData(crate_id, true);
|
||||||
get().fillExtCrateData(crate_id);
|
get().fillExtCrateData(crate_id);
|
||||||
get().fillOrderExtData();
|
get().fillOrderExtData();
|
||||||
get().fillWarnings(crate_id);
|
get().fillWarnings(crate_id);
|
||||||
|
@ -548,6 +570,7 @@ const useCart = ((set, get) => ({
|
||||||
setCrateMode: (id, mode) => {
|
setCrateMode: (id, mode) => {
|
||||||
get()._setCrateMode(id, mode)
|
get()._setCrateMode(id, mode)
|
||||||
get().fillExtData(id);
|
get().fillExtData(id);
|
||||||
|
get().fillExtData(id, true);
|
||||||
get().fillExtCrateData(id);
|
get().fillExtCrateData(id);
|
||||||
get().fillOrderExtData();
|
get().fillOrderExtData();
|
||||||
get().fillWarnings(id);
|
get().fillWarnings(id);
|
||||||
|
@ -563,15 +586,17 @@ const useCart = ((set, get) => ({
|
||||||
|
|
||||||
addCardFromCatalog: (crate_to, index_from, index_to, just_mounted) => {
|
addCardFromCatalog: (crate_to, index_from, index_to, just_mounted) => {
|
||||||
const isCrateless = toArray(index_from).some(value => get().getCardDescription(value).crateless === true);
|
const isCrateless = toArray(index_from).some(value => get().getCardDescription(value).crateless === true);
|
||||||
const dest = isCrateless ? "spare" : crate_to || get().active_crate;
|
const [isHorizontal, crateTo] = crate_to ? unwrapCrateId(crate_to) : [false, crate_to];
|
||||||
|
const isHorizontalOnly = toArray(index_from).some(value => !!get().getCardDescription(value).horizontal);
|
||||||
|
const dest = isCrateless ? "spare" : crateTo || get().active_crate;
|
||||||
if (!dest) {
|
if (!dest) {
|
||||||
console.warn("No destination");
|
console.warn("No destination");
|
||||||
get().noDestinationWarning();
|
get().noDestinationWarning();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
get().showNotification(dest, index_to);
|
get().showNotification(dest, index_to, isHorizontalOnly);
|
||||||
get()._addCardFromCatalog(dest, index_from, index_to)
|
get()._addCardFromCatalog(dest, index_from, index_to, isHorizontalOnly)
|
||||||
get().fillExtData(dest);
|
get().fillExtData(dest, isHorizontalOnly);
|
||||||
get().fillWarnings(dest);
|
get().fillWarnings(dest);
|
||||||
get().setActiveCrate(dest);
|
get().setActiveCrate(dest);
|
||||||
get()._updateTotalOrderPrice();
|
get()._updateTotalOrderPrice();
|
||||||
|
@ -581,22 +606,25 @@ const useCart = ((set, get) => ({
|
||||||
},
|
},
|
||||||
|
|
||||||
moveCard: (crate_from, index_from, crate_to, index_to) => {
|
moveCard: (crate_from, index_from, crate_to, index_to) => {
|
||||||
get()._moveCard(crate_from, index_from, crate_to, index_to);
|
const [isHorizontal, crateFrom] = unwrapCrateId(crate_from)
|
||||||
get().fillExtData(crate_to);
|
const [_, crateTo] = unwrapCrateId(crate_to)
|
||||||
get().fillWarnings(crate_to);
|
get()._moveCard(crateFrom, index_from, crateTo, index_to, isHorizontal);
|
||||||
get().setActiveCrate(crate_to);
|
get().fillExtData(crateTo, isHorizontal);
|
||||||
|
get().fillWarnings(crateTo);
|
||||||
|
get().setActiveCrate(crateTo);
|
||||||
get()._updateTotalOrderPrice();
|
get()._updateTotalOrderPrice();
|
||||||
if (crate_from !== crate_to) {
|
if (crateFrom !== crate_to) {
|
||||||
get().fillExtData(crate_from);
|
get().fillExtData(crateFrom, isHorizontal);
|
||||||
get().fillWarnings(crate_from);
|
get().fillWarnings(crateFrom);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deleteCard: (crate_id, index) => {
|
deleteCard: (crate_id, index, horizontal) => {
|
||||||
get()._deleteCard(crate_id, index);
|
const [isHorizontal, crateId] = horizontal ? [horizontal, crate_id] : unwrapCrateId(crate_id);
|
||||||
get().fillExtData(crate_id);
|
get()._deleteCard(crateId, index, isHorizontal);
|
||||||
get().fillWarnings(crate_id);
|
get().fillExtData(crateId, isHorizontal);
|
||||||
|
get().fillWarnings(crateId);
|
||||||
get()._updateTotalOrderPrice();
|
get()._updateTotalOrderPrice();
|
||||||
if (crate_id === get().highlighted.crate && index === get().highlighted.card) get().highlightReset()
|
if (crateId === get().highlighted.crate && index === get().highlighted.card) get().highlightReset()
|
||||||
},
|
},
|
||||||
clearCrate: (id) => {
|
clearCrate: (id) => {
|
||||||
get()._clearCrate(id);
|
get()._clearCrate(id);
|
||||||
|
@ -604,16 +632,19 @@ const useCart = ((set, get) => ({
|
||||||
get()._updateTotalOrderPrice();
|
get()._updateTotalOrderPrice();
|
||||||
},
|
},
|
||||||
|
|
||||||
updateOptions: (crate_id, index, new_options) => {
|
updateOptions: (crate_id, index, new_options, horizontal) => {
|
||||||
get()._updateOptions(crate_id, index, new_options);
|
get()._updateOptions(crate_id, index, new_options, horizontal);
|
||||||
get().fillExtData(crate_id);
|
get().fillExtData(crate_id, horizontal);
|
||||||
get().fillWarnings(crate_id);
|
if (!horizontal) {
|
||||||
|
get().fillWarnings(crate_id);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
initExtData: () => {
|
initExtData: () => {
|
||||||
get().fillOrderExtData();
|
get().fillOrderExtData();
|
||||||
get().crates.forEach((crate, _i) => {
|
get().crates.forEach((crate, _i) => {
|
||||||
get().fillExtData(crate.id);
|
get().fillExtData(crate.id, true);
|
||||||
|
get().fillExtData(crate.id, false);
|
||||||
get().fillExtCrateData(crate.id);
|
get().fillExtCrateData(crate.id);
|
||||||
})
|
})
|
||||||
get()._updateTotalOrderPrice();
|
get()._updateTotalOrderPrice();
|
||||||
|
|
|
@ -1449,7 +1449,8 @@ const shop_data = {
|
||||||
name_number: 'AFWS',
|
name_number: 'AFWS',
|
||||||
name_codename: '',
|
name_codename: '',
|
||||||
price: 800,
|
price: 800,
|
||||||
image: '/images/shop/graphic-03_AFWS.svg',
|
image: null,
|
||||||
|
horizontal: true,
|
||||||
specs: [
|
specs: [
|
||||||
"Artiq Firmware Service for one variant for one year.",
|
"Artiq Firmware Service for one variant for one year.",
|
||||||
"Includes support at helpdesk.",
|
"Includes support at helpdesk.",
|
||||||
|
@ -1530,6 +1531,7 @@ const shop_data = {
|
||||||
crate_mode: "rack",
|
crate_mode: "rack",
|
||||||
fan_tray: false,
|
fan_tray: false,
|
||||||
items: [],
|
items: [],
|
||||||
|
h_items: [],
|
||||||
warnings: [],
|
warnings: [],
|
||||||
occupiedHP: 0,
|
occupiedHP: 0,
|
||||||
},
|
},
|
||||||
|
@ -1538,6 +1540,7 @@ const shop_data = {
|
||||||
name: "Spare items",
|
name: "Spare items",
|
||||||
crate_mode: "no_crate",
|
crate_mode: "no_crate",
|
||||||
items: [],
|
items: [],
|
||||||
|
h_items: [],
|
||||||
warnings: [],
|
warnings: [],
|
||||||
occupiedHP: 0,
|
occupiedHP: 0,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue