From cd4d77d8bc8db12922aae50626c7b01f5a1bbb7d Mon Sep 17 00:00:00 2001 From: Egor Lukashev Date: Tue, 13 Apr 2021 10:06:47 +0300 Subject: [PATCH 1/3] Multiple schools on the point. Separate route for school --- src/@/country/effects/remove-country-fx.ts | 2 +- src/@/country/effects/update-country-fx.ts | 2 +- src/@/country/init.ts | 74 +------ src/@/country/model.ts | 7 - src/@/history-modal/init.ts | 10 +- src/@/popup/effects/add-school-popup-fx.ts | 41 ---- src/@/popup/effects/close-school-popup-fx.ts | 18 ++ src/@/popup/effects/create-school-popup-fx.ts | 5 + .../popup/effects/handle-schools-click-fx.ts | 34 +++ src/@/popup/effects/index.ts | 4 +- src/@/popup/effects/open-school-popup-jx.ts | 44 ++++ src/@/popup/init.ts | 204 +++++++++++++++++- src/@/popup/model.ts | 14 +- src/@/popup/types.ts | 6 +- src/@/popup/ui/popup.tsx | 53 ++++- .../styles/components/_school-popup.scss | 16 +- src/assets/styles/components/_week-graph.scss | 1 + src/core/root.tsx | 7 +- src/core/routes.ts | 4 +- 19 files changed, 407 insertions(+), 139 deletions(-) delete mode 100644 src/@/popup/effects/add-school-popup-fx.ts create mode 100644 src/@/popup/effects/close-school-popup-fx.ts create mode 100644 src/@/popup/effects/handle-schools-click-fx.ts create mode 100644 src/@/popup/effects/open-school-popup-jx.ts diff --git a/src/@/country/effects/remove-country-fx.ts b/src/@/country/effects/remove-country-fx.ts index 4d24e575..4c941ced 100644 --- a/src/@/country/effects/remove-country-fx.ts +++ b/src/@/country/effects/remove-country-fx.ts @@ -1,8 +1,8 @@ import { createEffect } from 'effector'; -import { clickSchool } from '@/country/model'; import { getDefaultCountryOpacity } from '@/map/constants'; import { Map, StylePaintData } from '@/map/types'; +import { clickSchool } from '@/popup/model'; export const removeCountryFx = createEffect( ({ map, paintData }: { map: Map | null; paintData: StylePaintData }) => { diff --git a/src/@/country/effects/update-country-fx.ts b/src/@/country/effects/update-country-fx.ts index 2c98fa84..962c288d 100644 --- a/src/@/country/effects/update-country-fx.ts +++ b/src/@/country/effects/update-country-fx.ts @@ -1,7 +1,7 @@ import { createEffect } from 'effector'; -import { clickSchool } from '@/country/model'; import { UpdateCountry } from '@/country/types'; +import { clickSchool } from '@/popup/model'; export const updateCountryFx = createEffect( ({ map, paintData, country }: UpdateCountry) => { diff --git a/src/@/country/init.ts b/src/@/country/init.ts index 547df33a..896a53e6 100644 --- a/src/@/country/init.ts +++ b/src/@/country/init.ts @@ -6,8 +6,6 @@ import { fetchCountryDailyStatsFx, fetchCountryFx, fetchCountryWeeklyStatsFx, - fetchSchoolDailyStatsFx, - fetchSchoolFx, fetchSchoolsFx, fetchSchoolsGlobal, } from '~/api/project-connect'; @@ -28,8 +26,7 @@ import { } from '@/country/effects'; import { getCountriesGeoJson } from '@/country/lib'; import { $map, $mapType, $stylePaintData, changeMapType } from '@/map/model'; -import { addSchoolPopupFx } from '@/popup/effects'; -import { $isOpenPopup, $popup } from '@/popup/model'; +import { $popup, $schoolId } from '@/popup/model'; import { $week, nextWeek, previousWeek } from '@/sidebar/model'; import { @@ -43,15 +40,10 @@ import { $countryHasCoverage, $countryInfoPending, $countryWeeklyStats, - $school, - $schoolDailyStats, - $schoolId, $schools, $schoolsGlobal, $zoomedCountryCode, changeCountryCode, - changeSchoolId, - clickSchool, } from './model'; $countries.on(fetchCountriesFx.doneData, setPayload); @@ -60,16 +52,11 @@ $schoolsGlobal.on(fetchSchoolsGlobal.doneData, setPayload); $country.on(fetchCountryFx.doneData, setPayload); $countryCode.on(changeCountryCode, setPayload); $schools.on(fetchSchoolsFx.doneData, setPayload); - -$school.on(fetchSchoolFx.doneData, setPayload); -$schoolId.on(changeSchoolId, setPayload); -$countryWeeklyStats.on(fetchCountryWeeklyStatsFx.doneData, setPayload); $countryDailyStats.on(fetchCountryDailyStatsFx.doneData, setPayload); -$schoolDailyStats.on(fetchSchoolDailyStatsFx.doneData, setPayload); +$countryWeeklyStats.on(fetchCountryWeeklyStatsFx.doneData, setPayload); $country.reset(changeCountryCode, fetchCountryFx.fail); $schools.reset(changeCountryCode, fetchSchoolsFx.fail); -$school.reset(fetchSchoolFx.fail); sample({ source: guard($country, { filter: Boolean }), @@ -99,9 +86,6 @@ sample({ target: changeMapType, }); -const onClosePopup = guard($isOpenPopup, { filter: getInverted }); -$schoolId.reset(onClosePopup); - $countryWeeklyStats.reset( changeCountryCode, fetchCountryWeeklyStatsFx, @@ -116,14 +100,7 @@ $countryDailyStats.reset( previousWeek ); -$schoolDailyStats.reset( - changeSchoolId, - fetchSchoolDailyStatsFx, - nextWeek, - previousWeek -); - -const $mapContext = combine({ +export const $mapContext = combine({ map: $map, mapType: $mapType, countriesGeometry: $countriesGeometry, @@ -139,8 +116,12 @@ const $mapContext = combine({ // Routing sample({ - source: combine([mapCountry.params]), - fn: ([params]) => params?.code ?? '', + source: guard({ + source: combine([$countryCode, mapCountry.params]), + filter: ([countryCode, params]) => countryCode !== params?.code, + }), + // eslint-disable-next-line @typescript-eslint/no-unused-vars + fn: ([_, params]) => params?.code ?? '', target: changeCountryCode, }); @@ -168,15 +149,6 @@ guard({ target: fetchCountryDailyStatsFx, }); -guard({ - source: combine([$schoolId, $week], ([schoolId, week]) => ({ - schoolId, - interval: week, - })), - filter: ({ schoolId }) => Boolean(schoolId), - target: fetchSchoolDailyStatsFx, -}); - // Zoom to country bounds sample({ source: guard($mapContext, { @@ -312,34 +284,6 @@ sample({ target: addCountriesFx, }); -// Close an opened school popup on click by another school -sample({ - source: guard($schoolId, { filter: Boolean }), - clock: clickSchool, - fn: () => false, - target: $isOpenPopup, -}); - -// Add school popup -sample({ - source: $mapContext, - clock: clickSchool, - fn: ({ map, popup }, event) => ({ - map, - popup, - event, - }), - target: addSchoolPopupFx, -}); - -// Fetch school data -sample({ - source: $mapContext, - clock: guard($schoolId, { filter: Boolean }), - fn: ({ countryCode, schoolId }) => ({ countryCode, schoolId }), - target: fetchSchoolFx, -}); - // Change map type sample({ source: $mapContext, diff --git a/src/@/country/model.ts b/src/@/country/model.ts index dacfcf63..e697dcec 100644 --- a/src/@/country/model.ts +++ b/src/@/country/model.ts @@ -1,6 +1,5 @@ import { createEvent, createStore } from 'effector'; import { FeatureCollection } from 'geojson'; -import { MapMouseEvent } from 'mapbox-gl'; import { fetchSchoolFx } from '~/api/project-connect'; import { @@ -9,26 +8,20 @@ import { CountryGeometry, CountryWeeklyStats, DailyStats, - School, } from '~/api/types'; export const changeCountryCode = createEvent(); -export const changeSchoolId = createEvent(); -export const clickSchool = createEvent(); export const $countryCode = createStore(''); -export const $schoolId = createStore(0); export const $countriesGeometry = createStore(null); export const $countries = createStore(null); export const $countriesGeoJson = createStore(null); export const $schoolsGlobal = createStore(null); export const $schools = createStore(null); export const $country = createStore(null); -export const $school = createStore(null); export const $schoolPending = fetchSchoolFx.pending; export const $countryWeeklyStats = createStore(null); export const $countryDailyStats = createStore(null); -export const $schoolDailyStats = createStore(null); export const $zoomedCountryCode = createStore(''); export const $countryInfoPending = createStore(false); export const $countryHasConnectivity = createStore(false); diff --git a/src/@/history-modal/init.ts b/src/@/history-modal/init.ts index c36d9897..f949c4db 100644 --- a/src/@/history-modal/init.ts +++ b/src/@/history-modal/init.ts @@ -8,14 +8,7 @@ import { import { getInterval, isCurrentInterval } from '~/lib/date-fns-kit'; import { getInverted, setPayload } from '~/lib/effector-kit'; -import { - $country, - $countryCode, - $countryDailyStats, - $school, - $schoolDailyStats, - $schoolId, -} from '@/country/model'; +import { $country, $countryCode, $countryDailyStats } from '@/country/model'; import { $historyData, $historyDataPending, @@ -33,6 +26,7 @@ import { nextHistoryInterval, previousHistoryInterval, } from '@/history-modal/model'; +import { $school, $schoolDailyStats, $schoolId } from '@/popup/model'; import { $week } from '@/sidebar/model'; $historyIntervalUnit.on(changeHistoryIntervalUnit, setPayload); diff --git a/src/@/popup/effects/add-school-popup-fx.ts b/src/@/popup/effects/add-school-popup-fx.ts deleted file mode 100644 index 38e01652..00000000 --- a/src/@/popup/effects/add-school-popup-fx.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { createEffect } from 'effector'; -import { Point } from 'geojson'; -import { PointLike } from 'mapbox-gl'; - -import { changeSchoolId } from '@/country/model'; -import { AddSchoolPopup } from '@/popup/types'; - -const nextTick = async () => new Promise((resolve) => setTimeout(resolve, 0)); - -export const addSchoolPopupFx = createEffect( - async ({ map, popup, event }: AddSchoolPopup) => { - if (!map || !popup) return; - - const bbox: [PointLike, PointLike] = [ - [event.point.x - 10, event.point.y - 10], - [event.point.x + 10, event.point.y + 10], - ]; - - const features = map.queryRenderedFeatures(bbox, { - layers: ['schools'], - }); - - if (!features?.length) { - return; - } - - changeSchoolId(Number(features[0]?.id) ?? 0); - - const point = features[0].geometry as Point; - const coordinates = [...point.coordinates]; - - // Close popup - popup.remove(); - - // Fix bug when popup closes and new one doesn't open - await nextTick(); - - // Open new popup - popup.setLngLat([coordinates[0], coordinates[1]]).addTo(map); - } -); diff --git a/src/@/popup/effects/close-school-popup-fx.ts b/src/@/popup/effects/close-school-popup-fx.ts new file mode 100644 index 00000000..8968818f --- /dev/null +++ b/src/@/popup/effects/close-school-popup-fx.ts @@ -0,0 +1,18 @@ +import { createEffect } from 'effector'; +import mapboxGl from 'mapbox-gl'; + +import { mapCountry } from '~/core/routes'; + +export const closeSchoolPopupFx = createEffect( + ({ + countryCode, + popup, + }: { + countryCode: string; + popup: mapboxGl.Popup | null; + }) => { + popup?.remove(); + + mapCountry.navigate({ code: countryCode }); + } +); diff --git a/src/@/popup/effects/create-school-popup-fx.ts b/src/@/popup/effects/create-school-popup-fx.ts index 66dfa899..2dbd2140 100644 --- a/src/@/popup/effects/create-school-popup-fx.ts +++ b/src/@/popup/effects/create-school-popup-fx.ts @@ -8,7 +8,12 @@ export const createSchoolPopupFx = createEffect(() => maxWidth: '100%', className: 'school-popup', anchor: 'bottom', + closeButton: false, + closeOnClick: false, + closeOnMove: false, }) .on('open', () => changeIsOpenPopup(true)) .on('close', () => changeIsOpenPopup(false)) + .off('open', () => changeIsOpenPopup(true)) + .off('close', () => changeIsOpenPopup(false)) ); diff --git a/src/@/popup/effects/handle-schools-click-fx.ts b/src/@/popup/effects/handle-schools-click-fx.ts new file mode 100644 index 00000000..1e49ff96 --- /dev/null +++ b/src/@/popup/effects/handle-schools-click-fx.ts @@ -0,0 +1,34 @@ +import { createEffect } from 'effector'; +import { PointLike } from 'mapbox-gl'; + +import { mapCountry } from '~/core/routes'; + +import { HandleSchoolClickFx } from '@/popup/types'; + +const nextTick = async () => new Promise((resolve) => setTimeout(resolve, 0)); + +export const handleSchoolClickFx = createEffect( + async ({ map, event, countryCode }: HandleSchoolClickFx) => { + if (!map) return; + + const bbox: [PointLike, PointLike] = [ + [event.point.x - 10, event.point.y - 10], + [event.point.x + 10, event.point.y + 10], + ]; + + const features = map.queryRenderedFeatures(bbox, { + layers: ['schools'], + }); + + if (!features?.length) { + return; + } + + await nextTick(); + + mapCountry.navigate({ + code: countryCode, + schoolId: `${features[0]?.id ?? ''}`, + }); + } +); diff --git a/src/@/popup/effects/index.ts b/src/@/popup/effects/index.ts index a9342cad..ca6556a6 100644 --- a/src/@/popup/effects/index.ts +++ b/src/@/popup/effects/index.ts @@ -1,2 +1,4 @@ -export { addSchoolPopupFx } from './add-school-popup-fx'; +export { handleSchoolClickFx } from './handle-schools-click-fx'; +export { openSchoolPopupFx } from './open-school-popup-jx'; +export { closeSchoolPopupFx } from './close-school-popup-fx'; export { createSchoolPopupFx } from './create-school-popup-fx'; diff --git a/src/@/popup/effects/open-school-popup-jx.ts b/src/@/popup/effects/open-school-popup-jx.ts new file mode 100644 index 00000000..007b67eb --- /dev/null +++ b/src/@/popup/effects/open-school-popup-jx.ts @@ -0,0 +1,44 @@ +import { createEffect } from 'effector'; +import { FeatureCollection, Point } from 'geojson'; +import mapboxGl from 'mapbox-gl'; + +import { mapCountry } from '~/core/routes'; + +import { Map } from '@/map/types'; + +const nextTick = async () => new Promise((resolve) => setTimeout(resolve, 0)); + +export const openSchoolPopupFx = createEffect( + async ({ + popup, + schools, + schoolId, + map, + countryCode, + }: { + popup: mapboxGl.Popup | null; + schools: FeatureCollection | null; + schoolId: number; + map: Map | null; + countryCode: string; + }) => { + if (!map || !popup || !schools || !schoolId) { + return; + } + + const geometry = schools.features.find((school) => school.id === schoolId) + ?.geometry as Point; + + if (!geometry) { + mapCountry.navigate({ code: countryCode }); + } + + const { coordinates } = geometry; + + // Fix bug when popup closes and new one doesn't open + await nextTick(); + + // Open new popup + popup.setLngLat([coordinates[0], coordinates[1]]).addTo(map); + } +); diff --git a/src/@/popup/init.ts b/src/@/popup/init.ts index 60a26449..bd88627f 100644 --- a/src/@/popup/init.ts +++ b/src/@/popup/init.ts @@ -1,12 +1,57 @@ -import { sample } from 'effector'; +import { combine, guard, merge, sample } from 'effector'; +import { Point } from 'geojson'; -import { getVoid, setPayload } from '~/lib/effector-kit'; +import { + fetchSchoolDailyStatsFx, + fetchSchoolFx, + fetchSchoolsFx, +} from '~/api/project-connect'; +import { mapCountry } from '~/core/routes'; +import { getInverted, getVoid, setPayload } from '~/lib/effector-kit'; +import { leaveCountryRouteFx } from '@/country/effects'; +import { $mapContext } from '@/country/init'; +import { $countryCode, $schools } from '@/country/model'; import { initMapFx } from '@/map/effects'; -import { createSchoolPopupFx } from '@/popup/effects'; -import { $isOpenPopup, $popup, changeIsOpenPopup } from '@/popup/model'; +import { $map } from '@/map/model'; +import { + closeSchoolPopupFx, + createSchoolPopupFx, + handleSchoolClickFx, + openSchoolPopupFx, +} from '@/popup/effects'; +import { + $isMultipleSchoolsOnPoint, + $isOpenPopup, + $popup, + $school, + $schoolDailyStats, + $schoolId, + $schoolsOnPoint, + changeIsOpenPopup, + changeSchoolId, + clickSchool, + handleClosePopup, + nextSchoolOnPoint, + previousSchoolOnPoint, +} from '@/popup/model'; +import { $week, nextWeek, previousWeek } from '@/sidebar/model'; $isOpenPopup.on(changeIsOpenPopup, setPayload); +$schoolId.on(changeSchoolId, setPayload); +$schoolDailyStats.on(fetchSchoolDailyStatsFx.doneData, setPayload); + +$schoolId.reset(leaveCountryRouteFx.doneData); +$school.on(fetchSchoolFx.doneData, setPayload); +$school.reset(fetchSchoolFx.fail); +$schoolsOnPoint.reset(leaveCountryRouteFx.doneData); + +$schoolDailyStats.reset( + changeSchoolId, + fetchSchoolDailyStatsFx, + nextWeek, + previousWeek +); // Create school popup sample({ @@ -19,3 +64,154 @@ sample({ source: createSchoolPopupFx.doneData, target: $popup, }); + +// Handle click on school point +sample({ + source: $mapContext, + clock: clickSchool, + fn: ({ map, popup, countryCode }, event) => ({ + map, + popup, + event, + countryCode, + }), + target: handleSchoolClickFx, +}); + +// Open school popup after init map if school id exist in the url +sample({ + source: guard({ + source: $mapContext, + filter: ({ schoolId }) => Boolean(schoolId), + }), + clock: merge([fetchSchoolsFx.doneData, $map]), + fn: ({ schoolId, schools, popup, map, countryCode }) => ({ + schoolId, + schools, + popup, + map, + countryCode, + }), + target: openSchoolPopupFx, +}); + +// Open school popup +sample({ + source: guard({ + source: $mapContext, + filter: ({ schools }) => Boolean(schools), + }), + clock: changeSchoolId, + fn: ({ schoolId, schools, popup, map, countryCode }) => ({ + schoolId, + schools, + popup, + map, + countryCode, + }), + target: openSchoolPopupFx, +}); + +// Fetch school data +guard({ + source: combine([$schoolId, $week], ([schoolId, week]) => ({ + schoolId, + interval: week, + })), + filter: ({ schoolId }) => Boolean(schoolId), + target: fetchSchoolDailyStatsFx, +}); + +// Handle close popup after changing url +sample({ + source: guard(combine([mapCountry.params, $popup]), { + filter: ([params]) => getInverted(params?.schoolId), + }), + target: handleClosePopup, +}); + +// Handle close popup +sample({ + source: combine([$popup, $countryCode]), + clock: handleClosePopup, + fn: ([popup, countryCode]) => ({ popup, countryCode }), + target: closeSchoolPopupFx, +}); + +// Open popup if school id exist in the url +sample({ + source: guard({ + source: mapCountry.params, + filter: (params) => Boolean(params?.schoolId), + }), + fn: (params) => Number(params?.schoolId) ?? 0, + target: changeSchoolId, +}); + +// Fetch school data +sample({ + source: $mapContext, + clock: guard($schoolId, { filter: Boolean }), + fn: ({ countryCode, schoolId }) => ({ countryCode, schoolId }), + target: fetchSchoolFx, +}); + +// Multiple school on the point +sample({ + source: combine([$schools, $schoolId]), + fn: ([schools, schoolId]) => { + if (!schools || !schoolId) { + return []; + } + const schoolCoordinates = (schools.features.find( + (school) => school.id === schoolId + )?.geometry as Point)?.coordinates; + + if (!schoolCoordinates) { + return []; + } + + const schoolsOnPoint: number[] = []; + schools.features.forEach((school) => { + if ( + (school.geometry as Point).coordinates[0] === schoolCoordinates[0] && + (school.geometry as Point).coordinates[1] === schoolCoordinates[1] + ) { + schoolsOnPoint.push(school.id as number); + } + }); + return schoolsOnPoint.reverse(); + }, + target: $schoolsOnPoint, +}); + +sample({ + source: $schoolsOnPoint, + fn: (schoolsOnPoint) => schoolsOnPoint.length > 1, + target: $isMultipleSchoolsOnPoint, +}); + +// Navigation for schools in the popup +sample({ + source: combine([$schoolsOnPoint, $schoolId, $countryCode]), + clock: nextSchoolOnPoint, + fn: ([schoolsOnPoint, schoolId, countryCode]) => { + const activeIndex = schoolsOnPoint.findIndex((id) => id === schoolId); + const nextIndex = + activeIndex + 1 >= schoolsOnPoint.length ? 0 : activeIndex + 1; + return { code: countryCode, schoolId: `${schoolsOnPoint[nextIndex]}` }; + }, + target: mapCountry.navigate, +}); + +sample({ + source: combine([$schoolsOnPoint, $schoolId, $countryCode]), + clock: previousSchoolOnPoint, + fn: ([schoolsOnPoint, schoolId, countryCode]) => { + const activeIndex = schoolsOnPoint.findIndex((id) => id === schoolId); + const previousIndex = + activeIndex - 1 < 0 ? schoolsOnPoint.length - 1 : activeIndex - 1; + return { code: countryCode, schoolId: `${schoolsOnPoint[previousIndex]}` }; + }, + target: mapCountry.navigate, +}); diff --git a/src/@/popup/model.ts b/src/@/popup/model.ts index c8616e6e..f92dc449 100644 --- a/src/@/popup/model.ts +++ b/src/@/popup/model.ts @@ -1,7 +1,19 @@ import { createEvent, createStore } from 'effector'; -import mapboxGL from 'mapbox-gl'; +import mapboxGL, { MapMouseEvent } from 'mapbox-gl'; + +import { DailyStats, School } from '~/api/types'; export const changeIsOpenPopup = createEvent(); +export const changeSchoolId = createEvent(); +export const clickSchool = createEvent(); +export const nextSchoolOnPoint = createEvent(); +export const previousSchoolOnPoint = createEvent(); +export const handleClosePopup = createEvent(); export const $popup = createStore(null); +export const $schoolId = createStore(0); +export const $school = createStore(null); export const $isOpenPopup = createStore(false); +export const $schoolsOnPoint = createStore([]); +export const $isMultipleSchoolsOnPoint = createStore(false); +export const $schoolDailyStats = createStore(null); diff --git a/src/@/popup/types.ts b/src/@/popup/types.ts index 06b84d24..95b451d8 100644 --- a/src/@/popup/types.ts +++ b/src/@/popup/types.ts @@ -1,4 +1,4 @@ -import mapboxGl, { MapMouseEvent } from 'mapbox-gl'; +import { MapMouseEvent } from 'mapbox-gl'; import { ConnectionStatus } from '~/api/types'; @@ -23,8 +23,8 @@ export type SchoolInfo = { isVerified: boolean; }; -export type AddSchoolPopup = { +export type HandleSchoolClickFx = { map: Map | null; - popup: mapboxGl.Popup | null; event: MapMouseEvent; + countryCode: string; }; diff --git a/src/@/popup/ui/popup.tsx b/src/@/popup/ui/popup.tsx index ebeb5c69..3c82b227 100644 --- a/src/@/popup/ui/popup.tsx +++ b/src/@/popup/ui/popup.tsx @@ -2,14 +2,24 @@ import { combine, createEvent, createStore } from 'effector'; import { useStore } from 'effector-react'; import React from 'react'; +import Chevron from '~/assets/images/chevron.svg'; import IconLocation from '~/assets/images/icon-location.svg'; import { setPayload } from '~/lib/effector-kit'; import { ProgressBar } from '~/ui'; -import { $school, $schoolDailyStats, $schoolPending } from '@/country/model'; +import { $schoolPending } from '@/country/model'; import { $stylePaintData, changeMap } from '@/map/model'; import { getSchoolInfo } from '@/popup/lib'; -import { $popup } from '@/popup/model'; +import { + $isMultipleSchoolsOnPoint, + $popup, + $school, + $schoolDailyStats, + $schoolsOnPoint, + handleClosePopup, + nextSchoolOnPoint, + previousSchoolOnPoint, +} from '@/popup/model'; import { $controlsMapType } from '@/sidebar/model'; import { getWeekGraphData } from '@/week-graph/lib/get-week-graph-data'; import { WeekGraph } from '@/week-graph/ui'; @@ -35,6 +45,10 @@ export const Popup = () => { const weekGraphData = useStore($weekGraphData); const mapType = useStore($controlsMapType); const paintData = useStore($stylePaintData); + const isMultipleSchoolsOnPoint = useStore($isMultipleSchoolsOnPoint); + const schoolsOnPoint = useStore($schoolsOnPoint); + + const activeIndex = schoolsOnPoint.findIndex((id) => id === school?.id) + 1; if (!school || pending) { return ( @@ -72,13 +86,37 @@ export const Popup = () => { return (
+ + + {isMultipleSchoolsOnPoint && ( + + )} +
+ {isMultipleSchoolsOnPoint && ( + {`${activeIndex} / ${schoolsOnPoint.length}`} + )}

{name}

{address}

@@ -150,6 +188,15 @@ export const Popup = () => { )}

+ {isMultipleSchoolsOnPoint && ( + + )}
); }; diff --git a/src/assets/styles/components/_school-popup.scss b/src/assets/styles/components/_school-popup.scss index c46ce55e..e1ff08de 100644 --- a/src/assets/styles/components/_school-popup.scss +++ b/src/assets/styles/components/_school-popup.scss @@ -6,6 +6,20 @@ } } +.school-popup-container { + position: relative; + display: flex; + flex-direction: row; + align-items: center; + padding: 0 1rem; +} + +.school-popup__close { + position: absolute; + top: 0.6rem; + right: 0.6rem; +} + /* stylelint-disable-next-line selector-no-qualifying-type */ .school-popup > div[class*='progress-bar__HorizontalLine'] { margin-right: 0.4rem; @@ -16,7 +30,7 @@ .school-popup__content { display: flex; flex-direction: column; - padding: 2rem 2rem 2.9rem; + padding: 2rem 1rem 2.9rem; } .school-popup__title { diff --git a/src/assets/styles/components/_week-graph.scss b/src/assets/styles/components/_week-graph.scss index cb43e473..72fa7e6a 100644 --- a/src/assets/styles/components/_week-graph.scss +++ b/src/assets/styles/components/_week-graph.scss @@ -20,6 +20,7 @@ font-size: 2rem; background-color: transparent; border: none; + outline: none; cursor: pointer; &--prev { diff --git a/src/core/root.tsx b/src/core/root.tsx index 06507ce4..26aadb81 100644 --- a/src/core/root.tsx +++ b/src/core/root.tsx @@ -14,6 +14,7 @@ import { useRoute } from '~/lib/router'; import { changeCountryCode } from '@/country/model'; import { MapPage } from '@/map/ui'; +import { changeSchoolId } from '@/popup/model'; import { ProjectPage } from '@/project/ui'; const NotFound = () => ( @@ -21,7 +22,7 @@ const NotFound = () => ( ); export const Root = () => { - const { code = '' } = useStore(mapCountry.params) ?? {}; + const { code = '', schoolId = '' } = useStore(mapCountry.params) ?? {}; useEffect(() => { void fetchCountriesFx(); @@ -32,6 +33,10 @@ export const Root = () => { if (code) { changeCountryCode(code); } + + if (schoolId) { + changeSchoolId(Number(schoolId)); + } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); diff --git a/src/core/routes.ts b/src/core/routes.ts index 0d9798a2..699327d6 100644 --- a/src/core/routes.ts +++ b/src/core/routes.ts @@ -11,13 +11,13 @@ export const router = createRouter({ history }); // This route is only for redirection export const exactRoot = router.add({ path: '/' }); -type Code = { code: string }; +type Code = { code?: string; schoolId?: string }; // Map section export const map = router.add('/map:path(/.*)?'); export const mapOverview = router.add('/map'); export const mapCountries = router.add('/map/countries:path(/.*)?'); -export const mapCountry = router.add('/map/country/:code:path(/.*)?'); +export const mapCountry = router.add('/map/country/:code/:schoolId?'); // Project section export const media = router.add('/media'); From 4fc9204dcc9c20e2f6b6247b5c21806d3ef8d523 Mon Sep 17 00:00:00 2001 From: Egor Lukashev Date: Tue, 13 Apr 2021 10:42:48 +0300 Subject: [PATCH 2/3] Show daily speed graph with empty data --- src/@/popup/ui/popup.tsx | 24 ++++++++++++------------ src/@/week-graph/ui/week-graph.tsx | 25 +++++++++++++++---------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/@/popup/ui/popup.tsx b/src/@/popup/ui/popup.tsx index 3c82b227..d8328705 100644 --- a/src/@/popup/ui/popup.tsx +++ b/src/@/popup/ui/popup.tsx @@ -22,6 +22,7 @@ import { } from '@/popup/model'; import { $controlsMapType } from '@/sidebar/model'; import { getWeekGraphData } from '@/week-graph/lib/get-week-graph-data'; +import { WeekGraphData } from '@/week-graph/types'; import { WeekGraph } from '@/week-graph/ui'; const onChangeRef = createEvent(); @@ -175,18 +176,17 @@ export const Popup = () => { - {weekGraphData && ( - <> -
-
- -
- - )} + + <> +
+
+ +
+ {isMultipleSchoolsOnPoint && (