web2019/static/js/shop/Cart.jsx
Egor Savkin 84562f276a Add horizontal items into the cart
Signed-off-by: Egor Savkin <es@m-labs.hk>
2024-11-06 17:18:23 +08:00

89 lines
3.2 KiB
JavaScript

import React, {useRef, useEffect, useState} from 'react'
import {Droppable} from "@hello-pangea/dnd";
import {cartStyle, compareArraysWithIds} from "./utils";
import {ProductCartItem} from "./ProductCartItem";
import {FakePlaceholder} from "./FakePlaceholder";
import {hp_to_slots} from "./count_resources";
import {useShopStore} from "./shop_store";
// #!render_count
import {useRenderCount} from "@uidotdev/usehooks";
export function Cart({crate_index}) {
// #!render_count
const renderCount = useRenderCount();
const containerRef = useRef(null);
const [visiblePlaceholders, setVisiblePlaceholders] = useState(0);
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
});
const crateParams = useShopStore((state) => state.crateParams);
const isCrate = useShopStore((state) => state.modes_order.includes(state.crates[crate_index].crate_mode));
// #!render_count
console.log("Cart renders: ", renderCount)
const nbrOccupied = hp_to_slots(crate.occupiedHP);
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) => {
return (
<ProductCartItem
card_index={index}
crate_index={crate_index}
key={item.id}/>
);
});
return (
<Droppable droppableId={crate.id} direction="horizontal">
{(provided, snapshot) => (
<div
ref={(element) => {
containerRef.current = element;
provided.innerRef(element);
}}
{...provided.droppableProps}
style={cartStyle(
provided.droppableProps.style,
snapshot,
)}
className="items-cart-list">
{products}
{provided.placeholder && (
<div style={{display: 'none'}}>
{provided.placeholder}
</div>
)}
<FakePlaceholder
nToDraw={visiblePlaceholders}
isDraggingOver={snapshot.isDraggingOver}/>
</div>
)}
</Droppable>
);
}