Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Draft: QMAPS-panel #1464

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 65 additions & 5 deletions src/components/ui/Panel.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React, { useContext } from 'react';
import React, { useContext, useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { fire, listen, unListen } from 'src/libs/customEvents';
import { DeviceContext } from 'src/libs/device';
import { PanelContext } from 'src/libs/panelContext';
import { CloseButton, FloatingItems } from 'src/components/ui';
import { PanelHeaderHeightContext } from 'src/libs/panelHeaderContext';

const getEventClientY = event =>
event.changedTouches ? event.changedTouches[0].clientY : event.clientY;
Expand Down Expand Up @@ -39,6 +40,7 @@ function getTargetSize(previousSize, startHeight, endHeight, maxSize) {
return size;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
class Panel extends React.Component {
static propTypes = {
children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired,
Expand Down Expand Up @@ -283,9 +285,9 @@ class Panel extends React.Component {
this.getHeight()
);

if (newSize !== this.props.size) {
/* if (newSize !== this.props.size) {
this.props.setSize(newSize);
}
} */

this.setState({
holding: false,
Expand All @@ -296,7 +298,7 @@ class Panel extends React.Component {
handleHeaderClick() {
const size = this.props.size === 'default' ? 'minimized' : 'default';
const translateY = this.getTranslateY(size);
this.props.setSize(size);
//this.props.setSize(size);
this.setState({ translateY });
}

Expand Down Expand Up @@ -376,6 +378,58 @@ class Panel extends React.Component {
}
}

const PanelNew = ({ children, size, headerHeight, setSize }) => {
const panelMinimizedHeight =
window.innerHeight - TOP_BAR_HEIGHT - headerHeight - FIT_CONTENT_PADDING;
const ref = useRef(null);
const [translateY, setTranslateY] = useState(panelMinimizedHeight);

useEffect(() => {
setTranslateY(panelMinimizedHeight);
}, [panelMinimizedHeight]);

const handleHeaderClick = () => {
const newSize = size === 'default' ? 'minimized' : 'default';
const newTranslateY = translateY === 0 ? panelMinimizedHeight : 0;
setSize(newSize);
setTranslateY(newTranslateY);
};

return (
<div
className="panel"
style={{
height: window.innerHeight - 80,
transform: `translate3d(0px, ${translateY}px, 0px)`,
}}
ref={ref}
>
<div
style={{
width: '100%',
height: 20,
paddingTop: 4,
display: 'flex',
justifyContent: 'center',
}}
onClick={handleHeaderClick}
>
<div
style={{
width: '36px',
height: '4px',
backgroundColor: '#d9d9e0',
borderRadius: '3px',
}}
/>
</div>
<div className="panel-content" style={{ height: window.innerHeight - TOP_BAR_HEIGHT - 20 }}>
{children}
</div>
</div>
);
};

// Use React.memo to skip re-renders
// and keep the same inner DOM during the panel manual resizes
const PanelContent = React.memo(({ children, size, isMobile }) =>
Expand All @@ -385,7 +439,13 @@ PanelContent.displayName = 'PanelContent';

const PanelWrapper = props => {
const { size, setSize } = useContext(PanelContext);
return <Panel {...props} size={size} setSize={setSize} />;
const { height } = useContext(PanelHeaderHeightContext);

return (
<PanelNew size={size} setSize={setSize} headerHeight={height}>
{props.children}
</PanelNew>
);
};

export default PanelWrapper;
9 changes: 9 additions & 0 deletions src/libs/panelHeaderContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';

export const PanelHeaderHeightContext = React.createContext({
height: 0,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
setHeight: (number: number) => {
return;
},
});
16 changes: 10 additions & 6 deletions src/panel/PanelManager.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { PoiContext } from 'src/libs/poiContext';
import { getListDescription } from 'src/libs/poiList';
import poiSubClass from 'src/mapbox/poi_subclass';
import { isEcoResponsibleCategory } from 'src/libs/eco-responsible';
import { PanelHeaderHeightContext } from 'src/libs/panelHeaderContext';

function getTopBarAppValue(activePoi, { poiFilters = {}, poi, query } = {}) {
const currentPoi = poi || activePoi;
Expand All @@ -38,6 +39,7 @@ const PanelManager = ({ router }) => {
options: {},
panelSize: 'default',
});
const [height, setHeight] = useState(0);
const [isSuggestOpen, setIsSuggestOpen] = useState(false);
const [topBarValue, setTopBarValue] = useState('');
const setPanelSize = useCallback(
Expand Down Expand Up @@ -268,16 +270,18 @@ const PanelManager = ({ router }) => {
onSuggestToggle={setIsSuggestOpen}
backButtonAction={getTopBarReturnAction()}
/>
<PanelContext.Provider value={{ size: panelSize, setSize: setPanelSize }}>
{/*
<PanelHeaderHeightContext.Provider value={{ height, setHeight }}>
<PanelContext.Provider value={{ size: panelSize, setSize: setPanelSize }}>
{/*
The panel container is made hidden using "display: none;" to avoid unnecessary
mounts and unmounts of the ActivePanel, that would have inappropriate side effects
on map markers, requests to server, etc.
*/}
<div className="panel_container" style={{ display: !isPanelVisible ? 'none' : null }}>
<ActivePanel {...options} />
</div>
</PanelContext.Provider>
<div className="panel_container" style={{ display: !isPanelVisible ? 'none' : null }}>
<ActivePanel {...options} />
</div>
</PanelContext.Provider>
</PanelHeaderHeightContext.Provider>
<Survey />
</div>
);
Expand Down
42 changes: 27 additions & 15 deletions src/panel/poi/PoiPanelContent.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useEffect } from 'react';
import React, { useCallback, useContext, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import Telemetry from 'src/libs/telemetry';
import ActionButtons from './ActionButtons';
Expand All @@ -11,6 +11,7 @@ import { Divider } from 'src/components/ui';
import { useConfig, useI18n, useFavorites, useDevice } from 'src/hooks';
import { Reservation } from './blocks/Reservation/Reservation';
import { findBlock, isFromEcotables } from 'src/libs/pois';
import { PanelHeaderHeightContext } from 'src/libs/panelHeaderContext';

const PoiPanelContent = ({ poi }) => {
const { _ } = useI18n();
Expand All @@ -21,6 +22,15 @@ const PoiPanelContent = ({ poi }) => {
const { isMobile } = useDevice();
const ecoResponsibleBlock = poi ? findBlock(poi.blocks, 'ecoresponsible') : null;
const isEcoResponsibleBlock = isEcoResponsibleActive && !!ecoResponsibleBlock;
const { height: panelHeaderHeight, setHeight: setPanelHeaderHeight } =
useContext(PanelHeaderHeightContext);
const ref = useRef();

useEffect(() => {
if (panelHeaderHeight !== ref?.current?.clientHeight) {
setPanelHeaderHeight(ref?.current?.clientHeight);
}
}, [panelHeaderHeight, setPanelHeaderHeight]);

useEffect(() => {
fire('set_direction_shortcut_callback', openDirection);
Expand Down Expand Up @@ -74,22 +84,24 @@ const PoiPanelContent = ({ poi }) => {

return (
<div className="poi_panel__content">
<PoiItem
poi={poi}
className="u-mb-l poi-panel-poiItem"
withAlternativeName
withOpeningHours
onClick={center}
/>
<div className="u-mb-l">
<ActionButtons
<div ref={ref}>
<PoiItem
poi={poi}
isDirectionActive={isDirectionActive}
openDirection={openDirection}
onClickPhoneNumber={onClickPhoneNumber}
isPoiInFavorite={isInFavorites(poi)}
toggleStorePoi={toggleStorePoi}
className="u-mb-l poi-panel-poiItem"
withAlternativeName
withOpeningHours
onClick={center}
/>
<div className="u-pb-l">
<ActionButtons
poi={poi}
isDirectionActive={isDirectionActive}
openDirection={openDirection}
onClickPhoneNumber={onClickPhoneNumber}
isPoiInFavorite={isInFavorites(poi)}
toggleStorePoi={toggleStorePoi}
/>
</div>
</div>
<div className="poi_panel__fullContent">
{hasReservation && <Reservation url={poi.meta.source_url} mobile={isMobile} />}
Expand Down
10 changes: 9 additions & 1 deletion src/panel/service/ServicePanelMobile.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
/* global _ */
import React, { Fragment } from 'react';
import React, { Fragment, useContext, useEffect } from 'react';
import Panel from 'src/components/ui/Panel';
import CategoryList from 'src/components/CategoryList';
import MainActionButton from 'src/components/ui/MainActionButton';
import VehicleIcon from 'src/panel/direction/VehicleIcon';
import { useConfig } from 'src/hooks';
import Telemetry from 'src/libs/telemetry';
import { QmapsConfig } from 'appTypes/config';
import { PanelHeaderHeightContext } from 'src/libs/panelHeaderContext';

const ServicePanelMobile = () => {
const directionConf = useConfig('direction') as unknown as QmapsConfig['direction'];
const { height: panelHeaderHeight, setHeight: setPanelHeaderHeight } =
useContext(PanelHeaderHeightContext);

useEffect(() => {
if (panelHeaderHeight !== 231) {
setPanelHeaderHeight(231);
}
}, [panelHeaderHeight, setPanelHeaderHeight]);
return (
<Panel
resizable
Expand Down
91 changes: 9 additions & 82 deletions src/scss/includes/components/panel.scss
Original file line number Diff line number Diff line change
@@ -1,89 +1,16 @@
$bottom-margin: 40px;

.panel {
@include long_shadow();
@include panel_radius();
width: 100vw;
background-color: white;
width: $panel_width;
display: flex;
flex-direction: column;

&-drawer {
min-height: 20px;
height: 20px;
pointer-events: all;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
cursor: -webkit-grab;
cursor: grab;
text-align: center;
width: 50%;
align-self: center;
}

&-close {
position: absolute;
right: 9px;
top: 9px;
}
}

@media (min-width: 641px) {
.panel {
max-height: calc(100vh - (92px + #{$bottom-margin})); // 92px is panel.getBoundingClientRect().top

&-header {
z-index: 0;
flex-shrink: 0;
}

&-content {
overflow-y: auto;
}
.panel-content {
width: 100%;
overflow: auto;
}

}

@media (max-width: 640px) {
.panel {
width: 100vw;
position: fixed;
border-radius: 12px 12px 0 0;
bottom: 0;
overflow: unset;

&:not(.panel--holding) {
transition: transform 0.2s ease-in-out;

&.maximized {
box-shadow: none;
}
}

&.maximized {
border-radius: 0;
.panel-content {
overflow: auto;
}
}

.panel-drawer {
flex-shrink: 0;
}

.panel-handle {
width: 40px;
height: 5px;
margin: 4px auto;
border-radius: 2.5px;
background-color: #e0e1e6;
}

.minimizedTitle {
height: 30px;
flex-shrink: 0;
}
hr {
width: 100%;
height: 1px;
margin-bottom: 20px;
background-color: #e0e1e6;
}
}
Loading