2023-11-30 17:26:17 +08:00
|
|
|
import React, {useEffect, useState} from "react";
|
2023-12-01 11:52:37 +08:00
|
|
|
import {useClickAway} from "./useClickAway";
|
2023-11-30 17:26:17 +08:00
|
|
|
import {FilterOptions, true_type_of} from "./utils";
|
|
|
|
|
|
|
|
export function SummaryPopup({id, options, data}) {
|
|
|
|
const [show, setShow] = useState(false);
|
|
|
|
const [position, setPosition] = useState({x: 0, y: 0});
|
|
|
|
const [size, setSize] = useState({w: 0, h: 0});
|
|
|
|
let display_options = FilterOptions(options, data);
|
|
|
|
const close = () => {
|
|
|
|
setShow(false);
|
|
|
|
document.removeEventListener("scroll", handleScroll, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
const ref = useClickAway(close);
|
|
|
|
|
|
|
|
const reposition = () => {
|
|
|
|
let popup_button = document.getElementById(id + "img");
|
|
|
|
if (!popup_button) {
|
|
|
|
document.removeEventListener("scroll", handleScroll, true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let rect = popup_button.getBoundingClientRect()
|
|
|
|
let pos_x = (rect.left + rect.right) / 2;
|
|
|
|
let pos_y = (rect.top + rect.bottom) / 2;
|
|
|
|
if (pos_x + size.w > window.innerWidth) {
|
|
|
|
setPosition({x: pos_x - size.w - 20, y: pos_y - size.h / 2});
|
|
|
|
} else {
|
|
|
|
setPosition({x: pos_x - size.w / 2, y: pos_y - size.h - 20});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const handleScroll = (e) => {
|
|
|
|
if (e.target !== document.getElementById(id)) {
|
|
|
|
close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (show) {
|
|
|
|
let popup = document.getElementById(id);
|
|
|
|
let width = popup.offsetWidth;
|
|
|
|
let height = popup.offsetHeight;
|
|
|
|
setSize({w: width, h: height});
|
|
|
|
reposition()
|
|
|
|
}
|
|
|
|
}, [show])
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (show) {
|
|
|
|
reposition();
|
|
|
|
}
|
|
|
|
}, [show, size])
|
|
|
|
|
2023-12-13 15:17:14 +08:00
|
|
|
const handleClick = (_event) => {
|
2023-11-30 17:26:17 +08:00
|
|
|
setShow(!show);
|
|
|
|
if (!show) {
|
|
|
|
document.addEventListener("scroll", handleScroll, true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const stringify = (value) => {
|
|
|
|
let value_type = true_type_of(value);
|
|
|
|
if (value_type === "string") {
|
|
|
|
return value;
|
|
|
|
} else if (value_type === "object") {
|
|
|
|
if (value.checked === false) {
|
|
|
|
return "off";
|
|
|
|
} else if (value.checked === true && value.text) {
|
|
|
|
return value.text;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return JSON.stringify(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div ref={ref}>
|
2024-01-23 11:36:56 +08:00
|
|
|
<img className="alert-info d-block" src={show ? "/images/shop/icon-close.svg" : "/images/shop/icon-customize.svg"}
|
2023-11-30 17:26:17 +08:00
|
|
|
id={id + "img"}
|
|
|
|
onClick={handleClick}/>
|
|
|
|
<div style={{'display': show ? 'flex' : 'none', 'top': position.y, 'left': position.x}}
|
|
|
|
className="overlayVariant card border rounded"
|
|
|
|
id={id}>
|
|
|
|
<div className="card-body">
|
|
|
|
{Array.from(Object.entries(display_options)
|
|
|
|
.filter(([key, value], _) => key !== "ext_data")
|
|
|
|
.map(([key, value], _) => {
|
|
|
|
return (<p className="card-text" key={id + key}><i>{key}</i>: {stringify(value)}</p>);
|
|
|
|
}))}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|