You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
6.0 KiB
211 lines
6.0 KiB
import "./style.scss";
|
|
import React, { useState, useEffect } from "react";
|
|
|
|
import search from "./search.png";
|
|
import close from "./close.png";
|
|
import go from "./go.png";
|
|
import arrow from "./arrow.png";
|
|
import ShopsWithFilter from "../ShopsWithFilter/ShopsWithFilter";
|
|
const STATES = {
|
|
init: 0,
|
|
moreFac: 1,
|
|
facList: 2,
|
|
};
|
|
export const DefaultPopupStates = STATES;
|
|
const initMarginBottom = 47;
|
|
const DefaultPopup = ({
|
|
state,
|
|
setState,
|
|
onSearch,
|
|
facilities,
|
|
onClickFac,
|
|
mall,
|
|
onClick,
|
|
setEnd,
|
|
hasTab,
|
|
blurMap = () => {},
|
|
}) => {
|
|
const marginBottomStateMap = {
|
|
0: 47,
|
|
1: hasTab
|
|
? window.innerHeight - 52 - 179 - 98
|
|
: window.innerHeight - 52 - 179,
|
|
};
|
|
const baseMarginBottom = marginBottomStateMap[state];
|
|
const [facList, setFacList] = useState(null);
|
|
const [focused, setFocused] = useState(null);
|
|
const [start, setStart] = useState(null);
|
|
const [marginBottom, setMarginBottom] = useState(null);
|
|
const [doTransition, setdoTransition] = useState(false);
|
|
useEffect(() => {
|
|
setdoTransition(true);
|
|
setMarginBottom(baseMarginBottom);
|
|
setTimeout(() => {
|
|
setdoTransition(false);
|
|
}, 500);
|
|
}, [state]);
|
|
const handleTouchStart = (e) => {
|
|
if (start) return;
|
|
setStart({
|
|
identifier: e.changedTouches[0].identifier,
|
|
y: e.changedTouches[0].clientY,
|
|
});
|
|
};
|
|
const handleTouchMove = (e) => {
|
|
if (!start) return;
|
|
const touch = Array.from(e.changedTouches).find(
|
|
({ identifier }) => identifier === start.identifier
|
|
);
|
|
if (!touch) return;
|
|
const delta = touch.clientY - start.y;
|
|
setMarginBottom(baseMarginBottom - delta);
|
|
};
|
|
const handleTouchEnd = (e) => {
|
|
if (!start) return;
|
|
const touch = Array.from(e.changedTouches).find(
|
|
({ identifier }) => identifier === start.identifier
|
|
);
|
|
if (!touch) return;
|
|
setStart(null);
|
|
const delta = touch.clientY - start.y;
|
|
const newState =
|
|
state === STATES.init && delta < -100
|
|
? STATES.moreFac
|
|
: state === STATES.moreFac && delta > 100
|
|
? STATES.init
|
|
: state;
|
|
|
|
if (state === newState) {
|
|
setdoTransition(true);
|
|
setMarginBottom(baseMarginBottom);
|
|
setTimeout(() => {
|
|
setdoTransition(false);
|
|
}, 500);
|
|
} else setState(newState);
|
|
};
|
|
|
|
return (
|
|
<>
|
|
{state === STATES.init || state === STATES.moreFac ? (
|
|
<div
|
|
className={"dp" + (state === STATES.moreFac ? " more-fac" : "")}
|
|
style={{
|
|
marginBottom: marginBottom + "px",
|
|
transition: !doTransition ? "none" : "margin-bottom 0.5s ease",
|
|
}}
|
|
onTouchStart={handleTouchStart}
|
|
onTouchMove={handleTouchMove}
|
|
onTouchCancel={handleTouchEnd}
|
|
onTouchEnd={handleTouchEnd}
|
|
>
|
|
<div
|
|
className="ts"
|
|
onClick={() =>
|
|
setState(state === STATES.moreFac ? STATES.init : STATES.moreFac)
|
|
}
|
|
>
|
|
<img className="t1" src={arrow} />
|
|
</div>
|
|
|
|
<div className="search" onClick={onSearch}>
|
|
<img className="icon" src={search}></img>
|
|
<div className="sep"></div>
|
|
搜索店铺
|
|
</div>
|
|
<div className="facs">
|
|
{Object.entries(facilities).map(([name, list]) => (
|
|
<div
|
|
className="fac"
|
|
key={name}
|
|
onClick={() => {
|
|
list.sort((a, b) => a.floorOrder - b.floorOrder);
|
|
setFacList(list);
|
|
setState(STATES.facList);
|
|
}}
|
|
>
|
|
<img src={list[0].url}></img>
|
|
{name}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<>
|
|
<img
|
|
src={close}
|
|
className="close"
|
|
onClick={(e) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
setState(STATES.init);
|
|
setFacList(null);
|
|
blurMap();
|
|
}}
|
|
></img>
|
|
<div className="dp1">
|
|
{facList &&
|
|
facList.map((fac, i) => {
|
|
const showRow1 =
|
|
i === 0 || fac.floorName !== facList[i - 1].floorName;
|
|
const isActive = focused === fac.id;
|
|
return (
|
|
<div key={fac.id}>
|
|
{showRow1 && (
|
|
<div className={"row1" + (i === 0 ? "" : " has-border")}>
|
|
{fac.floorName}
|
|
</div>
|
|
)}
|
|
<div
|
|
className={[
|
|
"row2",
|
|
isActive ? "active" : "",
|
|
!showRow1 ? "has-margin" : "",
|
|
].join(" ")}
|
|
onClick={() => {
|
|
setFocused(fac.id);
|
|
onClickFac(fac.id);
|
|
}}
|
|
>
|
|
{fac.name}
|
|
<span className="meta">{fac.floorName}</span>
|
|
{isActive && (
|
|
<div
|
|
className="go"
|
|
src={go}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
setState(STATES.init);
|
|
onClickFac(fac.id);
|
|
}}
|
|
>
|
|
GO
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</>
|
|
)}
|
|
{state !== STATES.facList && (
|
|
<div
|
|
className="sf"
|
|
onClick={() => {
|
|
setState(STATES.moreFac);
|
|
}}
|
|
>
|
|
<ShopsWithFilter
|
|
mall={mall}
|
|
onClick={(e) => {
|
|
setState(STATES.init);
|
|
onClick(e);
|
|
}}
|
|
wingHeight="calc(100vh - 310px)"
|
|
></ShopsWithFilter>
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
};
|
|
export default DefaultPopup;
|
|
|