From 38717326737e690895779e396fb25330e31ebc50 Mon Sep 17 00:00:00 2001
From: Anton Akhatov
Date: Fri, 29 Dec 2023 23:39:04 +0000
Subject: [PATCH] use sloy-map
---
.eslintrc.json | 15 +-
README.md | 2 +-
build-scripts/prepare-static/constants.mjs | 2 +-
build-scripts/prepare-static/index.mjs | 70 +-
components/Card/Card.tsx | 53 -
.../Card/DesktopCard/DesktopCard.module.css | 16 -
components/Card/DesktopCard/DesktopCard.tsx | 27 -
components/Card/MobileCard.tsx | 30 -
.../ConstructionInfo/ConstructionInfo.tsx | 38 -
.../Card/components/Header/Header.module.css | 29 -
components/Card/components/Header/Header.tsx | 61 -
.../components/Section/Section.module.css | 11 -
.../Card/components/Section/Section.tsx | 7 -
.../components/Sources/Sources.module.css | 30 -
.../Card/components/Sources/Sources.tsx | 21 -
components/Card/index.ts | 2 -
components/Filters/Filters.module.css | 57 -
components/Filters/Filters.tsx | 51 -
.../components/Filter/Filter.module.css | 24 -
.../Filters/components/Filter/Filter.tsx | 24 -
.../components/Toggle/Toggle.module.css | 85 -
.../Filters/components/Toggle/Toggle.tsx | 42 -
components/Filters/index.ts | 1 -
components/LeftSidebar.tsx | 15 -
components/RightSidebar.tsx | 14 -
constants/colors.ts | 7 -
constants/map.ts | 1 -
constants/sources.ts | 49 -
features/About/AboutProjectContent.tsx | 12 +-
.../AboutProjectIcons.module.css | 9 +-
.../AboutProjectIcons/AboutProjectIcons.tsx | 39 +-
features/About/AboutProjectModal.module.css | 6 +
features/About/AboutProjectModal.tsx | 23 +-
features/About/AboutProjectProvider.tsx | 32 -
features/About/MobileAboutProject.tsx | 22 -
features/App.tsx | 96 +
features/App/App.tsx | 30 -
features/App/Content.config.ts | 47 -
features/App/Filters.config.tsx | 68 -
features/App/Sidebars.tsx | 62 -
features/Buildings/BuildingSource.tsx | 156 -
.../CardContent/CardContent.module.css | 14 -
.../Buildings/CardContent/CardContent.tsx | 202 -
features/Buildings/Filter/HouseBaseFilter.tsx | 29 -
features/Buildings/Houses.constants.ts | 43 -
features/Buildings/houseBase.ts | 54 +-
features/Copyright/Copyright.module.css | 38 -
features/Copyright/Copyright.tsx | 25 -
.../CustomCardContent}/CardContent.module.css | 0
.../DownloadButton/DownloadButton.module.css | 0
.../DownloadButton/DownloadButton.tsx | 4 +-
.../FeedbackButton/FeedbackButton.tsx | 26 +
.../HealthProgress/HealthProgress.module.css | 0
.../HealthProgress/HealthProgress.tsx | 26 +-
.../CustomCardContent}/Info/Info.module.css | 0
.../CustomCardContent}/Info/Info.tsx | 0
.../CustomCardContent}/Info/Info.types.ts | 0
.../OKNInfo/OKNInfo.module.css | 0
.../OKNInfo/OKNInfo.tsx | 24 +-
.../CustomCardContent/OKNInfo/SvgOknIcon.tsx | 2 +-
.../Participant/Participant.module.css | 0
.../Participants/Participant/Participant.tsx | 18 +-
.../Participants/Participants.module.css | 13 +-
.../Participants/Participants.tsx | 108 +
.../Participants/Participants.types.ts | 48 +
features/CustomCardContent/overrideCard.tsx | 96 +
.../FacadeFilter.tsx | 9 +-
.../QuarterFilter.tsx | 24 +-
.../DTP/CardContent/CardContent.module.css | 14 -
features/DTP/CardContent/CardContent.tsx | 120 -
.../components/Participants/Participants.tsx | 115 -
.../Participants/Participants.types.ts | 12 -
features/DTP/DTP.constants.ts | 53 -
features/DTP/DtpSource.tsx | 121 -
features/DTP/Filter/DTPFilter.module.css | 22 -
features/DTP/Filter/DTPFilter.state.ts | 38 -
features/DTP/Filter/DTPFilter.tsx | 195 -
features/DTP/Filter/DTPFilter.types.ts | 14 -
features/DTP/dtp.ts | 106 -
features/DTP/dtpParticipantType.ts | 8 -
features/DTP/dtpSeverityType.ts | 5 -
.../DesignCode/CardContent/CardContent.tsx | 49 -
features/DesignCode/DesignCode.constants.ts | 17 -
features/DesignCode/DesignCodeSource.tsx | 79 -
.../Filter/DesignCodeFilter.module.css | 12 -
.../Filter/DesignCodeFilter.state.ts | 17 -
.../DesignCode/Filter/DesignCodeFilter.tsx | 57 -
.../Filter/DesignCodeFilter.types.ts | 7 -
features/DesignCode/designCode.ts | 31 -
features/DesignCode/designCodeObject.ts | 28 -
.../EditObjectButtonLink.tsx | 18 -
features/Facade/CardContent/Facade.module.css | 12 -
features/Facade/CardContent/Facade.tsx | 18 -
features/Facade/FacadeSource.tsx | 61 -
.../Footer/Footer.module.css | 0
{components => features}/Footer/Footer.tsx | 0
features/HouseAge/HouseAgeFilter.tsx | 42 -
features/HouseFloor/HouseFloorFilter.tsx | 43 -
.../HouseWearTear/HouseWearTearFilter.tsx | 41 -
features/Lines/CardContent/CardContent.tsx | 28 -
features/Lines/Filter/LinesFilter.module.css | 12 -
features/Lines/Filter/LinesFilter.state.ts | 17 -
features/Lines/Filter/LinesFilter.tsx | 69 -
features/Lines/Filter/LinesFilter.types.ts | 8 -
features/Lines/Lines.constants.ts | 16 -
features/Lines/LinesSource.tsx | 85 -
features/Lines/lineType.ts | 18 -
features/Lines/lines.ts | 16 -
features/Map/Map.tsx | 62 -
features/Map/helpers/colorLuminance.ts | 13 -
features/Map/helpers/getFeatureState.ts | 24 -
features/Map/helpers/useMapObjectState.ts | 69 -
features/Map/providers/MapProvider.tsx | 44 -
features/Map/providers/usePopup.ts | 62 -
.../OKN/CardContent/CardContent.module.css | 35 -
features/OKN/CardContent/CardContent.tsx | 79 -
features/OKN/CardContent/index.ts | 1 -
features/OKN/Filter/OknFilter.module.css | 12 -
features/OKN/Filter/OknFilter.state.ts | 43 -
features/OKN/Filter/OknFilter.tsx | 131 -
features/OKN/Okn.constants.ts | 30 -
features/OKN/OknSource.tsx | 191 -
features/OKN/okn.ts | 19 -
features/OKN/oknConstants.ts | 11 -
features/OKN/oknObject.ts | 42 -
features/Privacy/PrivacyPage.tsx | 15 -
.../CardContent/CardContent.module.css | 30 -
features/Quarter/CardContent/CardContent.tsx | 60 -
features/Quarter/QuarterSource.tsx | 73 -
features/Quarter/quarter.ts | 11 -
features/Quarter/quarterObject.ts | 6 -
helpers/isDesktop.tsx | 5 +
package.json | 26 +-
pages/_document.tsx | 4 +-
pages/api/dtp.ts | 10 +-
pages/index.tsx | 2 +-
pages/privacy.tsx | 15 +-
pnpm-lock.yaml | 4885 ++-
public/ekb-crime.json | 27315 ++++++++++++++++
public/ekb-facades.json | 32 +-
public/ekb-loader.svg | 97 +
public/ekb-okn.json | 17710 ++++++++--
...rter_inspectors.json => ekb-quarters.json} | 0
public/okn-meta.json | 12 -
public/okn-static/placemarks.json | 1 -
shared/UI/Button/Button.module.css | 43 -
shared/UI/Button/Button.tsx | 49 -
shared/UI/ButtonLink/ButtonLink.module.css | 32 -
shared/UI/ButtonLink/ButtonLink.tsx | 21 -
shared/UI/Checkbox/Checkbox.module.css | 90 -
shared/UI/Checkbox/Checkbox.svg | 1 -
shared/UI/Checkbox/Checkbox.tsx | 34 -
shared/UI/Close/Close.module.css | 37 -
shared/UI/Close/Close.tsx | 27 -
shared/UI/Close/index.ts | 1 -
shared/UI/Icons/Auto.tsx | 21 -
shared/UI/Icons/Bike.tsx | 21 -
shared/UI/Icons/BrokenHeart.tsx | 47 -
shared/UI/Icons/Bycicle.tsx | 21 -
shared/UI/Icons/Children.tsx | 21 -
shared/UI/Icons/Copy.tsx | 34 -
shared/UI/Icons/Download.tsx | 20 -
shared/UI/Icons/DownloadIcon.tsx | 17 -
shared/UI/Icons/Edit.tsx | 26 -
shared/UI/Icons/External.tsx | 12 -
shared/UI/Icons/Heart.tsx | 35 -
shared/UI/Icons/Icons.constants.ts | 30 -
shared/UI/Icons/Icons.types.ts | 17 -
shared/UI/Icons/Link.tsx | 21 -
shared/UI/Icons/Pdf.tsx | 38 -
shared/UI/Icons/Pedestrian.tsx | 21 -
shared/UI/Icons/PublicTransport.tsx | 21 -
shared/UI/Icons/index.tsx | 14 -
shared/UI/Label/Label.module.css | 33 -
shared/UI/Label/Label.tsx | 66 -
shared/UI/Link/Link.module.css | 24 -
shared/UI/Link/Link.tsx | 23 -
shared/UI/Loader/FilterLoader.tsx | 16 -
shared/UI/Loader/Loader.tsx | 6 -
shared/UI/Modal/MobileModal.tsx | 23 -
shared/UI/RangeHistogram/RangeBaseFilter.tsx | 53 -
.../RangeHistogram/RangeHistogram.module.css | 27 -
shared/UI/RangeHistogram/RangeHistogram.tsx | 92 -
.../RangeHistogram/components/Axis.module.css | 42 -
shared/UI/RangeHistogram/components/Axis.tsx | 67 -
.../components/BarChart.module.css | 65 -
.../UI/RangeHistogram/components/BarChart.tsx | 110 -
.../components/Slider.helpers.ts | 32 -
.../components/Slider.module.css | 85 -
.../UI/RangeHistogram/components/Slider.tsx | 150 -
shared/UI/RangeHistogram/index.ts | 3 -
shared/UI/RangeHistogram/types.ts | 14 -
shared/UI/RangeHistogram/utils/index.ts | 19 -
shared/helpers/copy.ts | 8 -
shared/helpers/fetchApi.ts | 4 -
shared/helpers/getYearNameByValue.ts | 25 -
shared/helpers/hash.ts | 8 -
shared/helpers/isDesktop.ts | 5 -
shared/helpers/round.ts | 5 -
shared/helpers/useCopyHref.ts | 25 -
shared/helpers/useMatchMedia.ts | 33 -
state/config.ts | 1214 +
state/features/dataLayers.ts | 36 -
state/features/selectors.ts | 5 -
state/{index.ts => redux.ts} | 5 +-
state/state.ts | 41 -
styles/globals.css | 1 -
styles/modal.css | 20 -
tsconfig.json | 6 +-
types/Content.types.ts | 18 -
types/Filters.types.ts | 28 -
types/ObjectsBase.types.ts | 11 -
types/Sources.types.ts | 19 -
213 files changed, 47888 insertions(+), 10341 deletions(-)
delete mode 100644 components/Card/Card.tsx
delete mode 100644 components/Card/DesktopCard/DesktopCard.module.css
delete mode 100644 components/Card/DesktopCard/DesktopCard.tsx
delete mode 100644 components/Card/MobileCard.tsx
delete mode 100644 components/Card/components/ConstructionInfo/ConstructionInfo.tsx
delete mode 100644 components/Card/components/Header/Header.module.css
delete mode 100644 components/Card/components/Header/Header.tsx
delete mode 100644 components/Card/components/Section/Section.module.css
delete mode 100644 components/Card/components/Section/Section.tsx
delete mode 100644 components/Card/components/Sources/Sources.module.css
delete mode 100644 components/Card/components/Sources/Sources.tsx
delete mode 100644 components/Card/index.ts
delete mode 100644 components/Filters/Filters.module.css
delete mode 100644 components/Filters/Filters.tsx
delete mode 100644 components/Filters/components/Filter/Filter.module.css
delete mode 100644 components/Filters/components/Filter/Filter.tsx
delete mode 100644 components/Filters/components/Toggle/Toggle.module.css
delete mode 100644 components/Filters/components/Toggle/Toggle.tsx
delete mode 100644 components/Filters/index.ts
delete mode 100644 components/LeftSidebar.tsx
delete mode 100644 components/RightSidebar.tsx
delete mode 100644 constants/colors.ts
delete mode 100644 constants/sources.ts
delete mode 100644 features/About/AboutProjectProvider.tsx
delete mode 100644 features/About/MobileAboutProject.tsx
create mode 100644 features/App.tsx
delete mode 100644 features/App/App.tsx
delete mode 100644 features/App/Content.config.ts
delete mode 100644 features/App/Filters.config.tsx
delete mode 100644 features/App/Sidebars.tsx
delete mode 100644 features/Buildings/BuildingSource.tsx
delete mode 100644 features/Buildings/CardContent/CardContent.module.css
delete mode 100644 features/Buildings/CardContent/CardContent.tsx
delete mode 100644 features/Buildings/Filter/HouseBaseFilter.tsx
delete mode 100644 features/Buildings/Houses.constants.ts
delete mode 100644 features/Copyright/Copyright.module.css
delete mode 100644 features/Copyright/Copyright.tsx
rename {styles => features/CustomCardContent}/CardContent.module.css (100%)
rename {shared/UI => features/CustomCardContent}/DownloadButton/DownloadButton.module.css (100%)
rename {shared/UI => features/CustomCardContent}/DownloadButton/DownloadButton.tsx (84%)
create mode 100644 features/CustomCardContent/FeedbackButton/FeedbackButton.tsx
rename features/{HouseWearTear => CustomCardContent}/HealthProgress/HealthProgress.module.css (100%)
rename features/{HouseWearTear => CustomCardContent}/HealthProgress/HealthProgress.tsx (55%)
rename {components/Card/components => features/CustomCardContent}/Info/Info.module.css (100%)
rename {components/Card/components => features/CustomCardContent}/Info/Info.tsx (100%)
rename {components/Card/components => features/CustomCardContent}/Info/Info.types.ts (100%)
rename features/{OKN/CardContent/components => CustomCardContent}/OKNInfo/OKNInfo.module.css (100%)
rename features/{OKN/CardContent/components => CustomCardContent}/OKNInfo/OKNInfo.tsx (62%)
rename shared/UI/Icons/OKN.tsx => features/CustomCardContent/OKNInfo/SvgOknIcon.tsx (99%)
rename features/{DTP/CardContent/components => CustomCardContent}/Participants/Participant/Participant.module.css (100%)
rename features/{DTP/CardContent/components => CustomCardContent}/Participants/Participant/Participant.tsx (83%)
rename features/{DTP/CardContent/components => CustomCardContent}/Participants/Participants.module.css (81%)
create mode 100644 features/CustomCardContent/Participants/Participants.tsx
create mode 100644 features/CustomCardContent/Participants/Participants.types.ts
create mode 100644 features/CustomCardContent/overrideCard.tsx
rename features/{Facade/Filter => CustomFilterContent}/FacadeFilter.tsx (74%)
rename features/{Quarter/Filter => CustomFilterContent}/QuarterFilter.tsx (64%)
delete mode 100644 features/DTP/CardContent/CardContent.module.css
delete mode 100644 features/DTP/CardContent/CardContent.tsx
delete mode 100644 features/DTP/CardContent/components/Participants/Participants.tsx
delete mode 100644 features/DTP/CardContent/components/Participants/Participants.types.ts
delete mode 100644 features/DTP/DTP.constants.ts
delete mode 100644 features/DTP/DtpSource.tsx
delete mode 100644 features/DTP/Filter/DTPFilter.module.css
delete mode 100644 features/DTP/Filter/DTPFilter.state.ts
delete mode 100644 features/DTP/Filter/DTPFilter.tsx
delete mode 100644 features/DTP/Filter/DTPFilter.types.ts
delete mode 100644 features/DTP/dtp.ts
delete mode 100644 features/DTP/dtpParticipantType.ts
delete mode 100644 features/DTP/dtpSeverityType.ts
delete mode 100644 features/DesignCode/CardContent/CardContent.tsx
delete mode 100644 features/DesignCode/DesignCode.constants.ts
delete mode 100644 features/DesignCode/DesignCodeSource.tsx
delete mode 100644 features/DesignCode/Filter/DesignCodeFilter.module.css
delete mode 100644 features/DesignCode/Filter/DesignCodeFilter.state.ts
delete mode 100644 features/DesignCode/Filter/DesignCodeFilter.tsx
delete mode 100644 features/DesignCode/Filter/DesignCodeFilter.types.ts
delete mode 100644 features/DesignCode/designCode.ts
delete mode 100644 features/DesignCode/designCodeObject.ts
delete mode 100644 features/EditObjectButtonLink/EditObjectButtonLink.tsx
delete mode 100644 features/Facade/CardContent/Facade.module.css
delete mode 100644 features/Facade/CardContent/Facade.tsx
delete mode 100644 features/Facade/FacadeSource.tsx
rename {components => features}/Footer/Footer.module.css (100%)
rename {components => features}/Footer/Footer.tsx (100%)
delete mode 100644 features/HouseAge/HouseAgeFilter.tsx
delete mode 100644 features/HouseFloor/HouseFloorFilter.tsx
delete mode 100644 features/HouseWearTear/HouseWearTearFilter.tsx
delete mode 100644 features/Lines/CardContent/CardContent.tsx
delete mode 100644 features/Lines/Filter/LinesFilter.module.css
delete mode 100644 features/Lines/Filter/LinesFilter.state.ts
delete mode 100644 features/Lines/Filter/LinesFilter.tsx
delete mode 100644 features/Lines/Filter/LinesFilter.types.ts
delete mode 100644 features/Lines/Lines.constants.ts
delete mode 100644 features/Lines/LinesSource.tsx
delete mode 100644 features/Lines/lineType.ts
delete mode 100644 features/Lines/lines.ts
delete mode 100644 features/Map/Map.tsx
delete mode 100644 features/Map/helpers/colorLuminance.ts
delete mode 100644 features/Map/helpers/getFeatureState.ts
delete mode 100644 features/Map/helpers/useMapObjectState.ts
delete mode 100644 features/Map/providers/MapProvider.tsx
delete mode 100644 features/Map/providers/usePopup.ts
delete mode 100644 features/OKN/CardContent/CardContent.module.css
delete mode 100644 features/OKN/CardContent/CardContent.tsx
delete mode 100644 features/OKN/CardContent/index.ts
delete mode 100644 features/OKN/Filter/OknFilter.module.css
delete mode 100644 features/OKN/Filter/OknFilter.state.ts
delete mode 100644 features/OKN/Filter/OknFilter.tsx
delete mode 100644 features/OKN/Okn.constants.ts
delete mode 100644 features/OKN/OknSource.tsx
delete mode 100644 features/OKN/okn.ts
delete mode 100644 features/OKN/oknConstants.ts
delete mode 100644 features/OKN/oknObject.ts
delete mode 100644 features/Privacy/PrivacyPage.tsx
delete mode 100644 features/Quarter/CardContent/CardContent.module.css
delete mode 100644 features/Quarter/CardContent/CardContent.tsx
delete mode 100644 features/Quarter/QuarterSource.tsx
delete mode 100644 features/Quarter/quarter.ts
delete mode 100644 features/Quarter/quarterObject.ts
create mode 100644 helpers/isDesktop.tsx
create mode 100644 public/ekb-crime.json
create mode 100644 public/ekb-loader.svg
rename public/{quarter_inspectors.json => ekb-quarters.json} (100%)
delete mode 100644 public/okn-meta.json
delete mode 100644 public/okn-static/placemarks.json
delete mode 100644 shared/UI/Button/Button.module.css
delete mode 100644 shared/UI/Button/Button.tsx
delete mode 100644 shared/UI/ButtonLink/ButtonLink.module.css
delete mode 100644 shared/UI/ButtonLink/ButtonLink.tsx
delete mode 100644 shared/UI/Checkbox/Checkbox.module.css
delete mode 100644 shared/UI/Checkbox/Checkbox.svg
delete mode 100644 shared/UI/Checkbox/Checkbox.tsx
delete mode 100644 shared/UI/Close/Close.module.css
delete mode 100644 shared/UI/Close/Close.tsx
delete mode 100644 shared/UI/Close/index.ts
delete mode 100644 shared/UI/Icons/Auto.tsx
delete mode 100644 shared/UI/Icons/Bike.tsx
delete mode 100644 shared/UI/Icons/BrokenHeart.tsx
delete mode 100644 shared/UI/Icons/Bycicle.tsx
delete mode 100644 shared/UI/Icons/Children.tsx
delete mode 100644 shared/UI/Icons/Copy.tsx
delete mode 100644 shared/UI/Icons/Download.tsx
delete mode 100644 shared/UI/Icons/DownloadIcon.tsx
delete mode 100644 shared/UI/Icons/Edit.tsx
delete mode 100644 shared/UI/Icons/External.tsx
delete mode 100644 shared/UI/Icons/Heart.tsx
delete mode 100644 shared/UI/Icons/Icons.constants.ts
delete mode 100644 shared/UI/Icons/Icons.types.ts
delete mode 100644 shared/UI/Icons/Link.tsx
delete mode 100644 shared/UI/Icons/Pdf.tsx
delete mode 100644 shared/UI/Icons/Pedestrian.tsx
delete mode 100644 shared/UI/Icons/PublicTransport.tsx
delete mode 100644 shared/UI/Icons/index.tsx
delete mode 100644 shared/UI/Label/Label.module.css
delete mode 100644 shared/UI/Label/Label.tsx
delete mode 100644 shared/UI/Link/Link.module.css
delete mode 100644 shared/UI/Link/Link.tsx
delete mode 100644 shared/UI/Loader/FilterLoader.tsx
delete mode 100644 shared/UI/Loader/Loader.tsx
delete mode 100644 shared/UI/Modal/MobileModal.tsx
delete mode 100644 shared/UI/RangeHistogram/RangeBaseFilter.tsx
delete mode 100644 shared/UI/RangeHistogram/RangeHistogram.module.css
delete mode 100644 shared/UI/RangeHistogram/RangeHistogram.tsx
delete mode 100644 shared/UI/RangeHistogram/components/Axis.module.css
delete mode 100644 shared/UI/RangeHistogram/components/Axis.tsx
delete mode 100644 shared/UI/RangeHistogram/components/BarChart.module.css
delete mode 100644 shared/UI/RangeHistogram/components/BarChart.tsx
delete mode 100644 shared/UI/RangeHistogram/components/Slider.helpers.ts
delete mode 100644 shared/UI/RangeHistogram/components/Slider.module.css
delete mode 100644 shared/UI/RangeHistogram/components/Slider.tsx
delete mode 100644 shared/UI/RangeHistogram/index.ts
delete mode 100644 shared/UI/RangeHistogram/types.ts
delete mode 100644 shared/UI/RangeHistogram/utils/index.ts
delete mode 100644 shared/helpers/copy.ts
delete mode 100644 shared/helpers/fetchApi.ts
delete mode 100644 shared/helpers/getYearNameByValue.ts
delete mode 100644 shared/helpers/hash.ts
delete mode 100644 shared/helpers/isDesktop.ts
delete mode 100644 shared/helpers/round.ts
delete mode 100644 shared/helpers/useCopyHref.ts
delete mode 100644 shared/helpers/useMatchMedia.ts
create mode 100644 state/config.ts
delete mode 100644 state/features/dataLayers.ts
delete mode 100644 state/features/selectors.ts
rename state/{index.ts => redux.ts} (54%)
delete mode 100644 state/state.ts
delete mode 100644 styles/modal.css
delete mode 100644 types/Content.types.ts
delete mode 100644 types/Filters.types.ts
delete mode 100644 types/ObjectsBase.types.ts
delete mode 100644 types/Sources.types.ts
diff --git a/.eslintrc.json b/.eslintrc.json
index bf30dcbd..f31a6b16 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -12,15 +12,16 @@
"project": "./tsconfig.json"
},
"rules": {
+ "react-hooks/exhaustive-deps": "error",
+
"@next/next/no-img-element": "off",
// TODO: remove this rule
"@typescript-eslint/no-explicit-any": "off",
// TODO: remove this rule
"@typescript-eslint/ban-ts-comment": "off",
- // TODO: remove this rule
+
"jsx-a11y/click-events-have-key-events": "off",
- // TODO: remove this rule
"jsx-a11y/no-static-element-interactions": "off",
"no-irregular-whitespace": "off",
@@ -56,7 +57,15 @@
{ "from": "./types", "target": "./shared" },
{ "from": "./state", "target": "./components" },
{ "from": "./constants", "target": "./components" },
- { "from": "./features", "target": "./components" }
+ { "from": "./features", "target": "./components" },
+
+ { "from": "./constants", "target": "./map" },
+ { "from": "./state", "target": "./map" },
+ { "from": "./styles", "target": "./map" },
+ { "from": "./shared", "target": "./map" },
+ { "from": "./pages", "target": "./map" },
+ { "from": "./features", "target": "./map" },
+ { "from": "./components", "target": "./map" }
]
}
]
diff --git a/README.md b/README.md
index 1e7e2ae7..73466144 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@ The map contains layers of data about objects in the city so that urbanists can
| Traffic collision | ⬇️ [dtp](https://github.com/ekaterinburgdev/map/blob/main/public/ekb-dtp.json) | ⬇️ [dtps](https://github.com/ekaterinburgdev/map/blob/main/public/ekb-dtps.json) | [dtp-stat.ru](https://dtp-stat.ru) | 🔄 | ✅ |
| Touristic route (points) | ⬇️ [color-points](https://github.com/ekaterinburgdev/map/blob/main/public/ekb-color-points.json) | | [tourism.ekburg.ru](http://tourism.ekburg.ru) | — | ✅ |
| Touristic route (lines) | ⬇️ [color-lines](https://github.com/ekaterinburgdev/map/blob/main/public/ekb-color-lines.json) | | [ekbredline.ru](http://ekbredline.ru) | — | ✅ |
-| Quarter inspectors | ⬇️ [quarter_inspectors](https://github.com/ekaterinburgdev/map/blob/main/public/quarter_inspectors.json) | | [екатеринбург.рф](https://екатеринбург.рф/справка/квартальные) | — | ✅ |
+| Quarter inspectors | ⬇️ [ekb-quarters](https://github.com/ekaterinburgdev/map/blob/main/public/ekb-quarters.json) | | [екатеринбург.рф](https://екатеринбург.рф/справка/квартальные) | — | ✅ |
| Cultural heritage sites (objects) | ⬇️ [okn‑objects](https://github.com/ekaterinburgdev/map/blob/main/public/ekb-okn-objects.json) | ⬇️ [okn](https://github.com/ekaterinburgdev/map/blob/main/public/ekb-okn.json) | [okn.midural.ru](https://okn.midural.ru/karta-obektov-kulturnogo-naslediya-sverdlovskoy-oblasti.html) | — | 🚧 |
| Cultural heritage sites (protect zone) | ⬇️ [okn‑protect](https://github.com/ekaterinburgdev/map/blob/main/public/ekb-okn-protect.json) | | [okn.midural.ru](https://okn.midural.ru/karta-obektov-kulturnogo-naslediya-sverdlovskoy-oblasti.html) | — | 🚧 |
| Cultural heritage sites (security zone) | ⬇️ [okn‑security](https://github.com/ekaterinburgdev/map/blob/main/public/ekb-okn-security.json) | | [okn.midural.ru](https://okn.midural.ru/karta-obektov-kulturnogo-naslediya-sverdlovskoy-oblasti.html) | — | 🚧 |
diff --git a/build-scripts/prepare-static/constants.mjs b/build-scripts/prepare-static/constants.mjs
index d8ed5c1b..e20bf064 100644
--- a/build-scripts/prepare-static/constants.mjs
+++ b/build-scripts/prepare-static/constants.mjs
@@ -6,4 +6,4 @@ export const VERCEL_PUBLIC_IMAGES_PATH = `${VERCEL_PUBLIC_PATH}images/`;
export const IMAGES_URLS_PATH = `${VERCEL_OUTPUT_PATH}images/`;
-export const PLACEMARKS_CACHE_PATH = `${VERCEL_OUTPUT_PATH}placemarks.json`;
\ No newline at end of file
+export const PLACEMARKS_CACHE_PATH = `${VERCEL_OUTPUT_PATH}ekb-okn.json`;
diff --git a/build-scripts/prepare-static/index.mjs b/build-scripts/prepare-static/index.mjs
index 3c977415..125ba980 100644
--- a/build-scripts/prepare-static/index.mjs
+++ b/build-scripts/prepare-static/index.mjs
@@ -1,13 +1,17 @@
import https from 'node:https';
import fs from 'node:fs';
-import items from '../../public/ekb-okn.json' assert { type: "json" };
+import items from '../../public/ekb-okn.json' assert { type: 'json' };
import { resize, optimize } from './prepareImages.mjs';
-import { IMAGES_URLS_PATH, PLACEMARKS_CACHE_PATH, VERCEL_PUBLIC_IMAGES_PATH } from './constants.mjs';
+import {
+ IMAGES_URLS_PATH,
+ PLACEMARKS_CACHE_PATH,
+ VERCEL_PUBLIC_IMAGES_PATH,
+} from './constants.mjs';
-const start = Date.now()
+const start = Date.now();
async function init() {
- console.log('Prepare images')
+ console.log('Prepare images');
await clearCachedImages(IMAGES_URLS_PATH);
@@ -22,13 +26,13 @@ async function init() {
.then(log('Optimize images'))
.then(optimize)
.catch(console.log);
-
- console.log('Save metadata')
- await saveMetadata(PLACEMARKS_CACHE_PATH, items.features, images)
- console.log(`Finish in ${(Date.now() - start) / 1000} seconds`)
+ console.log('Save metadata');
+ await saveMetadata(PLACEMARKS_CACHE_PATH, items.features, images);
+
+ console.log(`Finish in ${(Date.now() - start) / 1000} seconds`);
}
-init()
+init();
async function clearCachedImages(path) {
if (fs.existsSync(path)) {
@@ -40,13 +44,13 @@ async function clearCachedImages(path) {
function getImagesUrls(items) {
return items.reduce((all, item) => {
- const img = item.properties.img
+ const img = item.properties.img;
if (Boolean(img)) {
if (typeof img === 'string') {
- return all.concat(img)
+ return all.concat(img);
}
- return all.concat(img.url)
+ return all.concat(img.url);
}
return all;
}, []);
@@ -113,7 +117,7 @@ async function saveMetadata(cachPath, items, images) {
}, {});
const updatedItems = items.map((item) => {
- const img = item.properties.img
+ const img = item.properties.img;
if (Boolean(img)) {
let guid = null;
@@ -124,26 +128,36 @@ async function saveMetadata(cachPath, items, images) {
guid = getGUID(img.url);
const image = imagesById[guid];
- if(image) {
+ if (image) {
return {
...item,
- preview: {
- id: image.id,
- m: {
- ...image.m,
- src: `${VERCEL_PUBLIC_IMAGES_PATH}m_${image.path}`,
- },
- s: {
- ...image.s,
- src: `${VERCEL_PUBLIC_IMAGES_PATH}s_${image.path}`,
- },
- }
- }
+ properties: {
+ ...item.properties,
+ preview: {
+ id: image.id,
+ m: {
+ ...image.m,
+ src: `${VERCEL_PUBLIC_IMAGES_PATH}m_${image.path}`,
+ },
+ s: {
+ ...image.s,
+ src: `${VERCEL_PUBLIC_IMAGES_PATH}s_${image.path}`,
+ },
+ },
+ },
+ };
}
}
return item;
});
- fs.writeFileSync(cachPath, JSON.stringify(updatedItems));
-}
\ No newline at end of file
+ fs.writeFileSync(
+ cachPath,
+ JSON.stringify({
+ type: 'FeatureCollection',
+ name: 'ek-okn',
+ features: updatedItems,
+ }),
+ );
+}
diff --git a/components/Card/Card.tsx b/components/Card/Card.tsx
deleted file mode 100644
index c8312a96..00000000
--- a/components/Card/Card.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-import React, { useEffect, useMemo, useState } from 'react';
-import styled from 'styled-components';
-import { ContentConfig, MapItemType } from 'types/Content.types';
-import { Loader } from 'shared/UI/Loader/Loader';
-
-interface Props {
- contentConfig: ContentConfig;
- popupId?: string;
- popupType: MapItemType | null;
-}
-
-const CardLoaderContainer = styled.div`
- position: relative;
- height: 600px;
-`;
-
-export function Card({ contentConfig, popupId, popupType }: Props) {
- const [popupData, setPopupData] = useState();
- const [loading, setLoading] = useState(false);
-
- useEffect(() => {
- async function fetchData() {
- if (!popupId || !popupType) {
- return;
- }
-
- setLoading(true);
-
- const requestFunction = contentConfig[popupType].oneItemRequest;
-
- const data = await requestFunction(popupId);
-
- setPopupData(data);
- setLoading(false);
- }
-
- fetchData();
- }, [contentConfig, popupId, popupType]);
-
- const CardContent = useMemo(() => {
- setLoading(true);
-
- return contentConfig[popupType]?.cardContent || (() => null);
- }, [contentConfig, popupType]);
-
- return loading ? (
-
-
-
- ) : (
-
- );
-}
diff --git a/components/Card/DesktopCard/DesktopCard.module.css b/components/Card/DesktopCard/DesktopCard.module.css
deleted file mode 100644
index 54723f98..00000000
--- a/components/Card/DesktopCard/DesktopCard.module.css
+++ /dev/null
@@ -1,16 +0,0 @@
-.DesktopCard {
- position: relative;
- background: #1e2841 !important;
- border-radius: 10px !important;
- max-height: calc(90vh - 2vw) !important;
- overflow-y: auto;
- overflow-x: hidden;
-
- @mixin scroll;
-}
-
-.DesktopCard__header {
- position: absolute;
- right: 0;
- top: 0;
-}
diff --git a/components/Card/DesktopCard/DesktopCard.tsx b/components/Card/DesktopCard/DesktopCard.tsx
deleted file mode 100644
index d2751952..00000000
--- a/components/Card/DesktopCard/DesktopCard.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import React from 'react';
-import { Card } from 'components/Card/Card';
-import { Close } from 'shared/UI/Close';
-import { ContentConfig, MapItemType } from 'types/Content.types';
-import styles from './DesktopCard.module.css';
-
-interface Props {
- contentConfig: ContentConfig;
- popupId?: string;
- popupType: MapItemType | null;
- closePopup: () => void;
-}
-
-export function DesktopCard({ contentConfig, popupId, popupType, closePopup }: Props) {
- if (!popupId) {
- return <>>;
- }
-
- return (
-
- );
-}
diff --git a/components/Card/MobileCard.tsx b/components/Card/MobileCard.tsx
deleted file mode 100644
index ff2b41a4..00000000
--- a/components/Card/MobileCard.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import Sheet from 'react-modal-sheet';
-import * as React from 'react';
-import { Card } from 'components/Card/Card';
-import { ContentConfig, MapItemType } from 'types/Content.types';
-
-interface Props {
- contentConfig: ContentConfig;
- popupId?: string;
- popupType: MapItemType | null;
- closePopup: () => void;
-}
-
-export function MobileCard({ contentConfig, popupId, popupType, closePopup }: Props) {
- return (
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/components/Card/components/ConstructionInfo/ConstructionInfo.tsx b/components/Card/components/ConstructionInfo/ConstructionInfo.tsx
deleted file mode 100644
index d45cf49e..00000000
--- a/components/Card/components/ConstructionInfo/ConstructionInfo.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import React, { useMemo } from 'react';
-import { getYearNameByValue } from 'shared/helpers/getYearNameByValue';
-import { Info } from 'components/Card/components/Info/Info';
-
-const YEAR_RE = /\d{4}/;
-
-type ConstructionInfoProps = {
- date: string;
-};
-
-export function ConstructionInfo({ date }: ConstructionInfoProps) {
- const constructionDateInfo = useMemo(() => {
- const result = [
- {
- name: 'Когда построили',
- text: date,
- },
- ];
-
- const constructionYearMatch = date.match(YEAR_RE);
-
- if (constructionYearMatch) {
- const constructionYear = Number(constructionYearMatch[0]);
- const age = new Date().getFullYear() - Number(constructionYear);
-
- result.push({
- name: 'Возраст здания',
- text: `${String(age)} ${getYearNameByValue(age)}`,
- });
- }
-
- return result;
- }, [date]);
-
- return (
-
- );
-}
diff --git a/components/Card/components/Header/Header.module.css b/components/Card/components/Header/Header.module.css
deleted file mode 100644
index c443ba4c..00000000
--- a/components/Card/components/Header/Header.module.css
+++ /dev/null
@@ -1,29 +0,0 @@
-.header {
- display: flex;
- flex-wrap: wrap;
- column-gap: 4px;
-}
-
-.header__title {
- margin: 12px 0 0;
- font-size: 30px;
- font-weight: 500;
- line-height: 1;
-}
-
-.header__description {
- margin: 4px 0 0;
- font-size: 14px;
- font-weight: 400;
- line-height: 20px;
-}
-
-@media screen and (width >= 1150px) {
- .header__title {
- font-size: 32px;
- }
-
- .header__description {
- font-size: 16px;
- }
-}
diff --git a/components/Card/components/Header/Header.tsx b/components/Card/components/Header/Header.tsx
deleted file mode 100644
index 45fd8886..00000000
--- a/components/Card/components/Header/Header.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-import React, { useMemo } from 'react';
-import { IconType } from 'shared/UI/Icons/Icons.types';
-import { useCopyHref } from 'shared/helpers/useCopyHref';
-import { Label } from 'shared/UI/Label/Label';
-import styles from './Header.module.css';
-
-export type HeaderProps = {
- coordinates?: [number, number] | number[];
- title?: string;
- description?: string;
-};
-
-const COPY_RESET_TIMEOUT = 2000;
-
-export function Header({ coordinates, title, description }: HeaderProps) {
- const { isCopied: isLinkCopied, onCopy: onCopyLink } = useCopyHref(
- window.location.href,
- COPY_RESET_TIMEOUT,
- );
-
- const coordsString = useMemo(() => {
- if (!coordinates) {
- return null;
- }
-
- const coords = Array.isArray(coordinates[0]) ? coordinates[0] : coordinates;
-
- return `${coords[0]?.toFixed(6)}, ${coords[1]?.toFixed(6)}`;
- }, [coordinates]);
- const { isCopied: isCoordsCopied, onCopy: onCopyCoords } = useCopyHref(
- coordsString,
- COPY_RESET_TIMEOUT,
- );
-
- return (
- <>
-
- {coordsString && (
-
- {isCoordsCopied ? 'Скопировано' : coordsString}
-
- )}
-
- {isLinkCopied ? 'Скопировано' : 'Ссылка на объект'}
-
-
- {title}
- {description && {description}
}
- >
- );
-}
diff --git a/components/Card/components/Section/Section.module.css b/components/Card/components/Section/Section.module.css
deleted file mode 100644
index a47616fe..00000000
--- a/components/Card/components/Section/Section.module.css
+++ /dev/null
@@ -1,11 +0,0 @@
-.block {
- margin-top: 16px;
- padding-top: 16px;
- border-top: 1px solid rgba(256, 256, 256, 0.16);
-}
-
-.block_inline {
- display: flex;
- flex-wrap: wrap;
- gap: 8px;
-}
diff --git a/components/Card/components/Section/Section.tsx b/components/Card/components/Section/Section.tsx
deleted file mode 100644
index 7c82e9cf..00000000
--- a/components/Card/components/Section/Section.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-import React from 'react';
-
-import styles from './Section.module.css';
-
-export function Section({ children }: React.PropsWithChildren) {
- return {children}
;
-}
diff --git a/components/Card/components/Sources/Sources.module.css b/components/Card/components/Sources/Sources.module.css
deleted file mode 100644
index 0b0938b7..00000000
--- a/components/Card/components/Sources/Sources.module.css
+++ /dev/null
@@ -1,30 +0,0 @@
-.sources {
- display: flex;
- gap: 4px;
- flex-direction: column;
-}
-
-.sources__title {
- font-size: 16px;
- line-height: 1.3;
- font-weight: 400;
- margin: 0;
-}
-
-.sources__list {
- margin: 0;
- padding: 0;
- display: flex;
- flex-direction: column;
- gap: 8px;
-}
-
-.sources__listItem {
- list-style: none;
-}
-
-@media screen and (width >= 1440px) {
- .sources__title {
- font-size: 16px;
- }
-}
diff --git a/components/Card/components/Sources/Sources.tsx b/components/Card/components/Sources/Sources.tsx
deleted file mode 100644
index 074e20c6..00000000
--- a/components/Card/components/Sources/Sources.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import React from 'react';
-import { Link } from 'shared/UI/Link/Link';
-import { SourceInfo } from 'types/Sources.types';
-import styles from './Sources.module.css';
-
-export function Sources({ sources }: { sources: SourceInfo[] }) {
- return (
-
-
Источники
-
- {sources.map(({ link, name, data }) => {
- return (
-
-
-
- );
- })}
-
-
- );
-}
diff --git a/components/Card/index.ts b/components/Card/index.ts
deleted file mode 100644
index 984b6544..00000000
--- a/components/Card/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { DesktopCard } from './DesktopCard/DesktopCard';
-export { MobileCard } from './MobileCard';
diff --git a/components/Filters/Filters.module.css b/components/Filters/Filters.module.css
deleted file mode 100644
index ce4ab076..00000000
--- a/components/Filters/Filters.module.css
+++ /dev/null
@@ -1,57 +0,0 @@
-.filters__body {
- display: flex;
- flex-direction: column;
- gap: 2px;
- padding: 0.5em;
- padding-right: 16px;
- border-radius: 16px;
- background: #1e2841;
- font-size: 15px;
- line-height: 1.33;
-
- @mixin scroll;
-}
-
-.filters__item {
- background: #141d34;
-}
-
-.filters__item:first-child {
- border-top-left-radius: 8px;
- border-top-right-radius: 8px;
-}
-
-.filters__item:last-child {
- border-bottom-right-radius: 8px;
- border-bottom-left-radius: 8px;
-}
-
-.filters__notice {
- margin-top: 12px;
- margin-bottom: -4px;
- padding: 12px 16px;
- background: #3a4155;
- color: #9c9ea8;
- font-size: 14px;
- border-radius: 4px;
-}
-
-.filters__notice a {
- text-decoration: underline;
-
- &:hover {
- color: white;
- }
-}
-
-@media screen and (width >= 1440px) {
- .filters__body {
- font-size: 16px;
- }
-}
-
-@media screen and (width >= 1600px) {
- .filters__body {
- font-size: 17px;
- }
-}
diff --git a/components/Filters/Filters.tsx b/components/Filters/Filters.tsx
deleted file mode 100644
index 39d083ed..00000000
--- a/components/Filters/Filters.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import React from 'react';
-import { FilterConfigItem, FilterType } from 'types/Filters.types';
-import { Toggle } from 'components/Filters/components/Toggle/Toggle';
-import { Filter } from 'components/Filters/components/Filter/Filter';
-import styles from './Filters.module.css';
-
-interface Props {
- filters: Record;
- activeFilter: FilterType;
- onToggleClick: (type: FilterType) => void;
-}
-
-export function Filters({ filters, activeFilter, onToggleClick }: Props) {
- return (
-
- {(Object.entries(filters) as [FilterType, FilterConfigItem][]).map(
- ([type, { component, title, isVerified }], idx) => {
- const id = `id:${type}-${idx}`;
- const isActive = type === activeFilter;
-
- return (
-
-
- {component && (
-
- {isActive ? component : null}
- {!isVerified && (
-
- Данные берутся из публичных источников
- и содержат неточности.{' '}
-
- Оставьте фидбек
-
- — помогите улучшить карту.
-
- )}
-
- )}
-
- );
- },
- )}
-
- );
-}
diff --git a/components/Filters/components/Filter/Filter.module.css b/components/Filters/components/Filter/Filter.module.css
deleted file mode 100644
index 6c34a9ea..00000000
--- a/components/Filters/components/Filter/Filter.module.css
+++ /dev/null
@@ -1,24 +0,0 @@
-.filter {
- position: relative;
- padding: 0 16px;
- opacity: 0;
- box-sizing: content-box;
- visibility: hidden;
- max-height: 0;
- will-change: padding;
- transition:
- opacity 0.15s ease,
- padding-top 0.2s ease;
- &:empty {
- display: none;
- }
-}
-
-.filter_active {
- margin: 0;
- padding-top: 16px;
- padding-bottom: 16px;
- opacity: 1;
- visibility: visible;
- max-height: 100vh;
-}
diff --git a/components/Filters/components/Filter/Filter.tsx b/components/Filters/components/Filter/Filter.tsx
deleted file mode 100644
index 34585408..00000000
--- a/components/Filters/components/Filter/Filter.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import React, { PropsWithChildren, useRef } from 'react';
-import classNames from 'classnames';
-
-import styles from './Filter.module.css';
-
-export interface FilterProps extends PropsWithChildren {
- isActive: boolean;
-}
-
-export function Filter({ children, isActive }: FilterProps) {
- const spoilerRef = useRef();
-
- return (
-
- {isActive && children}
-
- );
-}
diff --git a/components/Filters/components/Toggle/Toggle.module.css b/components/Filters/components/Toggle/Toggle.module.css
deleted file mode 100644
index c3189e78..00000000
--- a/components/Filters/components/Toggle/Toggle.module.css
+++ /dev/null
@@ -1,85 +0,0 @@
-.toggle {
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 0.75em;
- position: relative;
- cursor: pointer;
- user-select: none;
- transition: 0.15s ease;
- padding: 0.75em 1em;
-
- --border-width: 2px;
-
- &:focus-within {
- outline: 2px solid white;
- border-radius: 2px;
- }
-
- /* Remove outline on click */
- &:has(:focus:not(:focus-visible)) {
- outline: none;
- }
-}
-
-@media (hover) {
- .toggle:hover {
- background: #11192d;
- }
-}
-
-.toggle:active {
- background: #06112b;
-}
-
-.toggle__control {
- position: relative;
- height: 24px;
- width: 40px;
- border-radius: 24px;
- box-sizing: border-box;
- border: #0f182e var(--border-width) solid;
- background-color: #3a4154;
- transition: 0.15s ease;
- font-size: 9px;
-
- &:after {
- content: '';
- position: absolute;
- top: 0;
- width: 20px;
- height: 20px;
- border-radius: 50%;
- background-color: rgb(240, 240, 240);
- transition: 0.15s ease;
- }
-}
-
-.toggle__background {
- position: absolute;
- opacity: 0;
- cursor: pointer;
- height: 0;
- width: 0;
-
- &:checked ~ .toggle__control {
- background-color: rgba(0, 180, 0, 0.75);
- }
-
- &:checked ~ .toggle__control:after {
- transform: translateX(calc(100% - 2 * var(--border-width)));
- }
-
- &:not(:checked) ~ .toggle__control {
- background-color: rgba(255, 255, 255, 0.16);
- }
-
- &:not(:checked) ~ .toggle__control:after {
- transform: translateX(0);
- background: #9b9ea8;
- }
-
- &:hover ~ .toggle__control:after {
- background-color: rgb(245, 245, 245);
- }
-}
diff --git a/components/Filters/components/Toggle/Toggle.tsx b/components/Filters/components/Toggle/Toggle.tsx
deleted file mode 100644
index 75206c63..00000000
--- a/components/Filters/components/Toggle/Toggle.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import React, { useCallback } from 'react';
-
-import { FilterType } from 'types/Filters.types';
-
-import styles from './Toggle.module.css';
-
-export interface ToggleProps {
- id: string;
- label: string;
- onClick: (type: FilterType) => void;
- type: FilterType;
- isActive: boolean;
-}
-
-export function Toggle({ id, label, onClick, type, isActive }: ToggleProps) {
- const onChange = useCallback(() => {
- onClick(type);
- }, [type, onClick]);
-
- return (
-
- {label}
- {
- if (
- e.key === 'Enter' ||
- (e.key === 'ArrowRight' && !isActive) ||
- (e.key === 'ArrowLeft' && isActive)
- ) {
- onChange();
- }
- }}
- />
-
-
- );
-}
diff --git a/components/Filters/index.ts b/components/Filters/index.ts
deleted file mode 100644
index 194f6207..00000000
--- a/components/Filters/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { Filters } from './Filters';
diff --git a/components/LeftSidebar.tsx b/components/LeftSidebar.tsx
deleted file mode 100644
index 0ed0f9b9..00000000
--- a/components/LeftSidebar.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import styled from 'styled-components';
-
-export const LeftSidebar = styled.div`
- width: 29%;
- min-width: 340px;
- max-width: 435px;
- position: fixed;
- top: 8px;
- left: 8px;
- z-index: 401;
- display: flex;
- flex-direction: column;
- gap: 8px;
- max-height: calc(100vh - 120px);
-`;
diff --git a/components/RightSidebar.tsx b/components/RightSidebar.tsx
deleted file mode 100644
index 82e559bf..00000000
--- a/components/RightSidebar.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import styled from 'styled-components';
-
-export const RightSidebar = styled.div`
- width: 50%;
- max-width: 400px;
- position: fixed;
- top: 8px;
- right: 8px;
- z-index: 401;
- display: flex;
- flex-direction: column;
- gap: 8px;
- max-height: calc(100vh - 120px);
-`;
diff --git a/constants/colors.ts b/constants/colors.ts
deleted file mode 100644
index 6221a34b..00000000
--- a/constants/colors.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { MapItemType } from 'types/Content.types';
-
-export const MARKER_COLOR = {
- [MapItemType.DTP]: '#05B506',
-};
-
-export const DEFAULT_BULDING_COLOR_NORMAL = '#0c1021';
diff --git a/constants/map.ts b/constants/map.ts
index 89bb642d..bdeb3b86 100644
--- a/constants/map.ts
+++ b/constants/map.ts
@@ -1,4 +1,3 @@
export const MIN_ZOOM = 11;
export const MAX_ZOOM = 20;
-export const BUILDING_LAYER_ID = 'building';
export const CENTER_COORDS: [number, number] = [60.605, 56.838011];
diff --git a/constants/sources.ts b/constants/sources.ts
deleted file mode 100644
index 32c45a35..00000000
--- a/constants/sources.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { SourceType, SourcesConfig } from 'types/Sources.types';
-
-export const SOURCES_BY_TYPE: SourcesConfig = {
- [SourceType.osm]: {
- name: 'OpenStreetMap',
- link: 'https://www.openstreetmap.org/',
- data: null,
- },
- [SourceType.okn]: {
- name: 'Объекты культурного наследия Свердловской области',
- link: 'https://okn.midural.ru/kategorii/obekty-kulturnogo-naslediya-sverdlovskoy-oblasti',
- data: null,
- },
- [SourceType.howoldthishouse]: {
- name: 'Карта возраста домов',
- link: 'https://how-old-is-this.house/',
- data: 'https://how-old-is-this.house/dataset?p=h-ekb',
- },
- [SourceType.domaekb]: {
- name: 'Жилые дома Екатеринбурга',
- link: 'https://domaekb.ru',
- data: null,
- },
- [SourceType.mingkh]: {
- name: 'МинЖКХ',
- link: 'https://mingkh.ru',
- data: null,
- },
- [SourceType.ekaterinburgdesign]: {
- name: 'Дизайн-код Ектеринбурга',
- link: 'https://ekaterinburg.design',
- data: 'https://ekaterinburg.design',
- },
- [SourceType.dtp]: {
- name: 'Карта ДТП',
- link: 'https://dtp-stat.ru/',
- data: 'https://dtp-stat.ru/opendata',
- },
- [SourceType.ekb_quarter]: {
- name: 'екатеринбург.рф',
- link: 'https://екатеринбург.рф/справка/квартальные',
- data: null,
- },
- [SourceType.design_objects_map]: {
- name: 'Карта объектов «Дизайн-кода»',
- link: 'https://map.ekaterinburg.design',
- data: 'https://map.ekaterinburg.design',
- },
-};
diff --git a/features/About/AboutProjectContent.tsx b/features/About/AboutProjectContent.tsx
index 69533a9b..3d3325a3 100644
--- a/features/About/AboutProjectContent.tsx
+++ b/features/About/AboutProjectContent.tsx
@@ -1,6 +1,6 @@
import Image from 'next/image';
import React from 'react';
-import { Button, ButtonSize, ButtonType } from 'shared/UI/Button/Button';
+import { Button, ButtonSize, ButtonType } from 'sloy-ui';
import { TeamGrid } from './Team/TeamGrid';
import styles from './AboutProjectModal.module.css';
import mapService from './map-service.svg';
@@ -167,12 +167,12 @@ export function AboutProjectContent() {
Присоединяйся к нам
{}}
- link="https://tally.so#tally-open=wL9Vd1&tally-width=650&tally-overlay=1&tally-emoji-animation=none"
- />
+ href="https://tally.so#tally-open=wL9Vd1&tally-width=650&tally-overlay=1&tally-emoji-animation=none"
+ >
+ Стать частью команды или помочь проекту
+
);
diff --git a/features/About/AboutProjectIcons/AboutProjectIcons.module.css b/features/About/AboutProjectIcons/AboutProjectIcons.module.css
index fa5cdc30..0ffa1e07 100644
--- a/features/About/AboutProjectIcons/AboutProjectIcons.module.css
+++ b/features/About/AboutProjectIcons/AboutProjectIcons.module.css
@@ -4,6 +4,7 @@
right: 8px;
z-index: 401;
display: flex;
+ align-items: flex-end;
gap: 4px;
color: white;
transition: 0.15s ease;
@@ -14,14 +15,6 @@
height: 100%;
}
-.aboutProjectIcons__gh:hover {
- filter: contrast(0.75);
-}
-
-.aboutProjectIcons__gh:active {
- filter: contrast(0.7);
-}
-
@media screen and (width >= 1024px) {
.aboutProjectIcons {
top: auto;
diff --git a/features/About/AboutProjectIcons/AboutProjectIcons.tsx b/features/About/AboutProjectIcons/AboutProjectIcons.tsx
index 28fa981c..e2813905 100644
--- a/features/About/AboutProjectIcons/AboutProjectIcons.tsx
+++ b/features/About/AboutProjectIcons/AboutProjectIcons.tsx
@@ -1,36 +1,37 @@
-import React, { useContext } from 'react';
+import React, { useCallback, useState } from 'react';
import Image from 'next/image';
-import { Button, ButtonSize, ButtonType } from 'shared/UI/Button/Button';
-import { AboutProjectContext } from 'features/About/AboutProjectProvider';
+import { Button, ButtonSize, ButtonType } from 'sloy-ui';
+import { AboutProjectModal } from '../AboutProjectModal';
import styles from './AboutProjectIcons.module.css';
import githubLogo from './github-icon.svg';
export function AboutProjectIcons() {
- const { open } = useContext(AboutProjectContext);
+ const [isOpened, setIsOpened] = useState(false);
+
+ const open = useCallback(() => setIsOpened(true), []);
+ const close = useCallback(() => setIsOpened(false), []);
return (
-
+
+
+ О проекте
+
-
{}}
- link="https://tally.so#tally-open=wLzxEG&tally-width=650&tally-overlay=1&tally-emoji-animation=none"
- />
+ type={ButtonType.ACCENT}
+ size={ButtonSize.MEDIUM}
+ rounded
+ href="https://tally.so#tally-open=wLzxEG&tally-width=650&tally-overlay=1&tally-emoji-animation=none"
+ >
+ Фидбек
+
+
);
}
diff --git a/features/About/AboutProjectModal.module.css b/features/About/AboutProjectModal.module.css
index e1118f9e..fd3e71f8 100644
--- a/features/About/AboutProjectModal.module.css
+++ b/features/About/AboutProjectModal.module.css
@@ -111,3 +111,9 @@
background: rgba(0, 0, 0, 0.6);
touch-action: none;
}
+
+.aboutProjectModalClose {
+ position: absolute;
+ top: 16px;
+ right: 16px;
+}
diff --git a/features/About/AboutProjectModal.tsx b/features/About/AboutProjectModal.tsx
index 5f364fad..8abd2ac9 100644
--- a/features/About/AboutProjectModal.tsx
+++ b/features/About/AboutProjectModal.tsx
@@ -1,11 +1,12 @@
-import React, { useContext, useEffect } from 'react';
+import React, { useEffect } from 'react';
+import { IconType, SheetModal } from 'sloy-ui';
+import { Icon } from 'sloy-ui';
import { AboutProjectContent } from 'features/About/AboutProjectContent';
-import { AboutProjectContext } from 'features/About/AboutProjectProvider';
-import { Close } from 'shared/UI/Close';
+import { useIsDesktop } from 'helpers/isDesktop';
import styles from './AboutProjectModal.module.css';
-export function AboutProjectModal() {
- const { close, isOpened } = useContext(AboutProjectContext);
+export function AboutProjectModal({ close, isOpened }: { close: VoidFunction; isOpened: boolean }) {
+ const isDesktop = useIsDesktop();
useEffect(() => {
const handleKeyDown = (e) => {
@@ -21,10 +22,20 @@ export function AboutProjectModal() {
if (!isOpened) return null;
+ if (!isDesktop) {
+ return (
+
+
+
+ );
+ }
+
return (
<>
diff --git a/features/About/AboutProjectProvider.tsx b/features/About/AboutProjectProvider.tsx
deleted file mode 100644
index a6f6534e..00000000
--- a/features/About/AboutProjectProvider.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import React, { createContext, ReactNode, useMemo, useState } from 'react';
-
-export interface IAboutProjectContext {
- isOpened: boolean;
- open: VoidFunction;
- close: VoidFunction;
-}
-
-export const AboutProjectContext = createContext({
- isOpened: false,
- open: () => {},
- close: () => {},
-});
-
-interface Props {
- children: ReactNode;
-}
-
-export function AboutProjectProvider({ children }: Props) {
- const [isOpened, setIsOpened] = useState(false);
-
- const value = useMemo(
- (): IAboutProjectContext => ({
- isOpened,
- open: () => setIsOpened(true),
- close: () => setIsOpened(false),
- }),
- [isOpened],
- );
-
- return {children} ;
-}
diff --git a/features/About/MobileAboutProject.tsx b/features/About/MobileAboutProject.tsx
deleted file mode 100644
index ee9f669c..00000000
--- a/features/About/MobileAboutProject.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import Sheet from 'react-modal-sheet';
-import * as React from 'react';
-import { useContext } from 'react';
-import { AboutProjectContent } from 'features/About/AboutProjectContent';
-import { AboutProjectContext } from 'features/About/AboutProjectProvider';
-
-export function MobileAboutProject() {
- const { isOpened, close } = useContext(AboutProjectContext);
-
- return (
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/features/App.tsx b/features/App.tsx
new file mode 100644
index 00000000..87ad5546
--- /dev/null
+++ b/features/App.tsx
@@ -0,0 +1,96 @@
+'use client';
+
+import React, { useCallback, useEffect, useState } from 'react';
+import { ThemeProvider } from 'styled-components';
+import { Provider } from 'react-redux';
+import { SloyMap, ILayer, OverrideLayersFn, internalTranslations } from 'sloy-map';
+import { defaultTheme } from 'sloy-ui';
+import { store } from 'state/redux';
+import { AboutProjectIcons } from 'features/About/AboutProjectIcons/AboutProjectIcons';
+import { Footer } from 'features/Footer/Footer';
+import { copyrights, defaultLayers, defaultMapState, defaultSources } from 'state/config';
+import ekbLoader from 'public/ekb-loader.svg';
+import { overrideCard } from './CustomCardContent/overrideCard';
+import { QuarterFilter } from './CustomFilterContent/QuarterFilter';
+import { FacadeFilter } from './CustomFilterContent/FacadeFilter';
+import { getHouseMeta } from './Buildings/houseBase';
+
+import 'sloy-map/style.css';
+
+function AppMap() {
+ const [finalSources, setFinalSources] = useState(defaultSources);
+ const overrideLayers: OverrideLayersFn = useCallback((layer: ILayer) => {
+ switch (layer.id) {
+ case 'ekb-quarter':
+ return ;
+ case 'ekb-facades':
+ return ;
+ default:
+ return null;
+ }
+ }, []);
+
+ useEffect(() => {
+ getHouseMeta().then((houseMeta) => {
+ const setProperties = (properties, fields) =>
+ properties.map((p) => {
+ if (fields[p.id]) {
+ return {
+ ...p,
+ range: p.range.map((item, i) => ({
+ ...item,
+ value: houseMeta[fields[p.id]][i] || 0,
+ })),
+ };
+ }
+
+ return p;
+ });
+
+ setFinalSources(
+ finalSources.map((s) => {
+ if (s.id === 'osmBuilding') {
+ return {
+ ...s,
+ properties: setProperties(s.properties, {
+ 'building:year': 'years',
+ 'building:levels': 'levels',
+ 'building:health': 'health',
+ }),
+ };
+ }
+
+ return s;
+ }),
+ );
+ });
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ return (
+
+ );
+}
+
+export default function App() {
+ return (
+
+
+
+
+
+
+
+ );
+}
diff --git a/features/App/App.tsx b/features/App/App.tsx
deleted file mode 100644
index 663fe805..00000000
--- a/features/App/App.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react';
-import { Provider } from 'react-redux';
-import { MapProvider } from 'react-map-gl';
-import { store } from 'state';
-import { AboutProjectIcons } from 'features/About/AboutProjectIcons/AboutProjectIcons';
-import { AboutProjectProvider } from 'features/About/AboutProjectProvider';
-import { Copyright } from 'features/Copyright/Copyright';
-import { MapContextProvider } from 'features/Map/providers/MapProvider';
-import { Footer } from 'components/Footer/Footer';
-import { Map } from 'features/Map/Map';
-import { FILTERS_CONFIG } from './Filters.config';
-import { Sidebars } from './Sidebars';
-
-export default function App() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/features/App/Content.config.ts b/features/App/Content.config.ts
deleted file mode 100644
index ef1544df..00000000
--- a/features/App/Content.config.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { ContentConfig, MapItemType } from 'types/Content.types';
-import { designCode } from 'features/DesignCode/designCode';
-import { dtp } from 'features/DTP/dtp';
-import { okn } from 'features/OKN/okn';
-import { lines } from 'features/Lines/lines';
-import { LinesCardContent } from 'features/Lines/CardContent/CardContent';
-import { QuarterCardContent } from 'features/Quarter/CardContent/CardContent';
-import { quarter } from 'features/Quarter/quarter';
-import { DesignCodeCardContent } from 'features/DesignCode/CardContent/CardContent';
-import { DTPCardContent } from 'features/DTP/CardContent/CardContent';
-import { HousesCardContent } from 'features/Buildings/CardContent/CardContent';
-import { OKNCardContent } from 'features/OKN/CardContent';
-
-export const CONTENTS_CONFIG: ContentConfig = {
- [MapItemType.Houses]: {
- cardContent: HousesCardContent,
- oneItemRequest: () => Promise.resolve(),
- },
- [MapItemType.DesignCode]: {
- cardContent: DesignCodeCardContent,
- oneItemRequest: designCode.getObject,
- },
- [MapItemType.DTP]: {
- cardContent: DTPCardContent,
- oneItemRequest: dtp.getObject,
- },
- [MapItemType.OKN]: {
- cardContent: OKNCardContent,
- oneItemRequest: okn.getObject,
- },
- [MapItemType.RedLines]: {
- cardContent: LinesCardContent,
- oneItemRequest: lines.getObject,
- },
- [MapItemType.PinkLines]: {
- cardContent: LinesCardContent,
- oneItemRequest: lines.getObject,
- },
- [MapItemType.BlueLines]: {
- cardContent: LinesCardContent,
- oneItemRequest: lines.getObject,
- },
- [MapItemType.Quarter]: {
- cardContent: QuarterCardContent,
- oneItemRequest: quarter.getObject,
- },
-} as const;
diff --git a/features/App/Filters.config.tsx b/features/App/Filters.config.tsx
deleted file mode 100644
index 5d826c60..00000000
--- a/features/App/Filters.config.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import { DTPFilter } from 'features/DTP/Filter/DTPFilter';
-import { DesignCodeFilter } from 'features/DesignCode/Filter/DesignCodeFilter';
-import { HouseAgeFilter } from 'features/HouseAge/HouseAgeFilter';
-import { HouseFloorFilter } from 'features/HouseFloor/HouseFloorFilter';
-import { HouseWearTearFilter } from 'features/HouseWearTear/HouseWearTearFilter';
-import { LinesFilter } from 'features/Lines/Filter/LinesFilter';
-import { OknFilter } from 'features/OKN/Filter/OknFilter';
-import { QuarterFilter } from 'features/Quarter/Filter/QuarterFilter';
-import { SOURCES_BY_TYPE } from 'constants/sources';
-import { SourceType } from 'types/Sources.types';
-import { FilterConfig, FilterType } from 'types/Filters.types';
-import { FacadeFilter } from 'features/Facade/Filter/FacadeFilter';
-
-export const FILTERS_CONFIG: FilterConfig = {
- [FilterType.HouseAge]: {
- title: 'Возраст домов',
- component: ,
- source: [SOURCES_BY_TYPE[SourceType.howoldthishouse]],
- isVerified: false,
- },
- [FilterType.HouseFloor]: {
- title: 'Этажность домов',
- component: ,
- source: [SOURCES_BY_TYPE[SourceType.mingkh], SOURCES_BY_TYPE[SourceType.domaekb]],
- isVerified: false,
- },
- [FilterType.HouseWearTear]: {
- title: 'Степень износа домов',
- component: ,
- source: [SOURCES_BY_TYPE[SourceType.mingkh], SOURCES_BY_TYPE[SourceType.domaekb]],
- isVerified: false,
- },
- [FilterType.OKN]: {
- title: 'Объекты культурного наследия',
- component: ,
- source: [SOURCES_BY_TYPE[SourceType.okn]],
- isVerified: false,
- },
- [FilterType.DesignCode]: {
- title: '«Дизайн-код Екатеринбурга»',
- component: ,
- source: [SOURCES_BY_TYPE[SourceType.design_objects_map]],
- isVerified: true,
- },
- [FilterType.DTP]: {
- title: 'ДТП',
- component: ,
- source: [SOURCES_BY_TYPE[SourceType.dtp]],
- isVerified: true,
- },
- [FilterType.Line]: {
- title: 'Туристические маршруты',
- component: ,
- isVerified: true,
- },
- [FilterType.Quarter]: {
- title: 'Квартальные',
- component: ,
- source: [SOURCES_BY_TYPE[SourceType.ekb_quarter]],
- isVerified: true,
- },
- [FilterType.HouseFacades]: {
- title: 'Дизайн-код фасадов',
- component: ,
- source: [SOURCES_BY_TYPE[SourceType.ekaterinburgdesign]],
- isVerified: true,
- },
-};
diff --git a/features/App/Sidebars.tsx b/features/App/Sidebars.tsx
deleted file mode 100644
index c6c68469..00000000
--- a/features/App/Sidebars.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-import { useCallback, useContext } from 'react';
-import { useDispatch, useSelector } from 'react-redux';
-import { toggleData } from 'state/features/dataLayers';
-import { activeFilterSelector } from 'state/features/selectors';
-import { FilterType } from 'types/Filters.types';
-import { useIsDesktop } from 'shared/helpers/isDesktop';
-import { DesktopCard, MobileCard } from 'components/Card';
-import { LeftSidebar } from 'components/LeftSidebar';
-import { RightSidebar } from 'components/RightSidebar';
-import { AboutProjectModal } from 'features/About/AboutProjectModal';
-import { MobileAboutProject } from 'features/About/MobileAboutProject';
-import { MapContext } from 'features/Map/providers/MapProvider';
-import { Filters } from 'components/Filters';
-import { MobileModal } from 'shared/UI/Modal/MobileModal';
-import { CONTENTS_CONFIG } from './Content.config';
-import { FILTERS_CONFIG } from './Filters.config';
-
-export function Sidebars() {
- const isDesktop = useIsDesktop();
- const popupProps = useContext(MapContext);
- const dispatch = useDispatch();
- const activeFilter = useSelector(activeFilterSelector);
- const onToggleClick = useCallback(
- (type: FilterType) => {
- dispatch(toggleData({ type }));
- },
- [dispatch],
- );
-
- const cardProps = {
- ...popupProps,
- contentConfig: CONTENTS_CONFIG,
- };
-
- const filter = (
-
- );
-
- if (isDesktop) {
- return (
- <>
- {filter}
-
-
-
-
- >
- );
- }
-
- return (
- <>
- {filter}
-
-
- >
- );
-}
diff --git a/features/Buildings/BuildingSource.tsx b/features/Buildings/BuildingSource.tsx
deleted file mode 100644
index 69d010f2..00000000
--- a/features/Buildings/BuildingSource.tsx
+++ /dev/null
@@ -1,156 +0,0 @@
-import {
- ColorSpecification,
- DataDrivenPropertyValueSpecification,
- ExpressionSpecification,
-} from 'maplibre-gl';
-import { useEffect } from 'react';
-import { useMap } from 'react-map-gl';
-import { useSelector } from 'react-redux';
-import { getLayerStyle } from 'features/Map/helpers/getFeatureState';
-import { colorLuminance } from 'features/Map/helpers/colorLuminance';
-import {
- AGE_FILTERS_DATA,
- FLOOR_FILTERS_DATA,
- WEAR_TEAR_FILTERS_DATA,
-} from 'features/Buildings/Houses.constants';
-import { activeFilterParamsSelector, activeFilterSelector } from 'state/features/selectors';
-import { FilterType } from 'types/Filters.types';
-import { MapItemType } from 'types/Content.types';
-import useMapObjectState from 'features/Map/helpers/useMapObjectState';
-import { usePopup } from 'features/Map/providers/usePopup';
-
-const BUILDING_LAYER_ID = 'building';
-
-const DEFAULT_BULDING_COLOR_NORMAL = '#0c1021';
-
-interface SetBuildingStyleProps {
- map: mapboxgl.Map;
- color: DataDrivenPropertyValueSpecification;
- caseCondition?: (string | string[])[];
- layerProps?: Record;
-}
-
-export function setBuildingColor({
- map,
- color,
- caseCondition = ['has', '_unknown_'],
- layerProps,
-}: SetBuildingStyleProps) {
- map.setStyle({
- ...map?.getStyle(),
- layers: map?.getStyle().layers.map((layer: any) => {
- if (layer.id === BUILDING_LAYER_ID) {
- return {
- ...layer,
- ...layerProps,
- paint: {
- ...layer.paint,
- 'fill-extrusion-color': [
- 'case',
- caseCondition,
- color,
- DEFAULT_BULDING_COLOR_NORMAL,
- ],
- ...layerProps?.paint,
- },
- };
- }
- return layer;
- }),
- });
-}
-
-function setBuildingStyle({ map, range, field, rangeData }) {
- if (
- !(
- typeof range?.min === 'number' &&
- typeof range?.max === 'number' &&
- field &&
- rangeData &&
- map?.setStyle &&
- map?.getStyle
- )
- ) {
- setBuildingColor({ map, color: DEFAULT_BULDING_COLOR_NORMAL });
- return;
- }
-
- const colorsInitial = rangeData
- .map((item) => {
- if (item.from >= range.min && item.to <= range.max) {
- return item;
- }
- return { ...item, color: DEFAULT_BULDING_COLOR_NORMAL };
- })
- .map((item) => [item.from, item.color]);
-
- const colorsHover = colorsInitial.map(([from, color]) => [from, colorLuminance(color, 0.4)]);
-
- const colorsActive = colorsInitial.map(([from, color]) => [from, colorLuminance(color, 0.55)]);
-
- const getColor = (style: [number, number][]): ExpressionSpecification => [
- 'interpolate',
- ['linear'],
- ['to-number', ['get', field]],
- ...style.flat(2),
- ];
-
- setBuildingColor({
- map,
- color: getLayerStyle({
- initial: getColor(colorsInitial),
- hover: getColor(colorsHover),
- active: getColor(colorsActive),
- }),
- caseCondition: ['has', field],
- });
-}
-
-const ageRangeData = AGE_FILTERS_DATA.map((item) => ({ ...item, value: 1 }));
-const levelsRangeData = FLOOR_FILTERS_DATA.map((item) => ({ ...item, value: 1 }));
-const healthRangeData = WEAR_TEAR_FILTERS_DATA.map((item) => ({ ...item, value: 1 }));
-
-export function BuildingSource() {
- const ekbMap = useMap();
- const activeFilter = useSelector(activeFilterSelector);
- const activeFilterParams = useSelector(activeFilterParamsSelector);
- const { openPopup } = usePopup();
-
- useEffect(() => {
- const map = ekbMap?.current?.getMap?.();
-
- const field = {
- [FilterType.HouseAge]: 'building:year',
- [FilterType.HouseFloor]: 'building:levels',
- [FilterType.HouseWearTear]: 'building:health',
- [FilterType.HouseFacades]: 'building:facade',
- }[activeFilter];
-
- const rangeData = {
- [FilterType.HouseAge]: ageRangeData,
- [FilterType.HouseFloor]: levelsRangeData,
- [FilterType.HouseWearTear]: healthRangeData,
- }[activeFilter];
-
- setBuildingStyle({
- map,
- field,
- rangeData,
- range: activeFilterParams,
- });
- }, [activeFilter, activeFilterParams, ekbMap]);
-
- useMapObjectState('building');
-
- useEffect(() => {
- const map = ekbMap?.current?.getMap?.();
-
- if (!map) return;
-
- map.on('click', 'building', (e) => {
- openPopup(`${e.lngLat.lat}_${e.lngLat.lng}`, MapItemType.Houses);
- });
- }, [ekbMap, openPopup]);
-
- return null;
-}
diff --git a/features/Buildings/CardContent/CardContent.module.css b/features/Buildings/CardContent/CardContent.module.css
deleted file mode 100644
index 4b149b29..00000000
--- a/features/Buildings/CardContent/CardContent.module.css
+++ /dev/null
@@ -1,14 +0,0 @@
-.popup {
- border-top-left-radius: inherit;
- border-top-right-radius: inherit;
- padding: 16px 8px 16px 16px;
-}
-.popup_mobile {
- border-top-left-radius: inherit;
- border-top-right-radius: inherit;
- padding: 16px;
-}
-
-.popup__emergencyLabel {
- margin-bottom: 12px;
-}
diff --git a/features/Buildings/CardContent/CardContent.tsx b/features/Buildings/CardContent/CardContent.tsx
deleted file mode 100644
index 48207031..00000000
--- a/features/Buildings/CardContent/CardContent.tsx
+++ /dev/null
@@ -1,202 +0,0 @@
-import { useContext, useEffect, useMemo, useState } from 'react';
-import { useMap } from 'react-map-gl';
-import { HouseObject } from 'features/Buildings/houseBase';
-import { MapContext } from 'features/Map/providers/MapProvider';
-import { usePopup } from 'features/Map/providers/usePopup';
-import { ConstructionInfo } from 'components/Card/components/ConstructionInfo/ConstructionInfo';
-import Facade from 'features/Facade/CardContent/Facade';
-import { Header } from 'components/Card/components/Header/Header';
-import { Info } from 'components/Card/components/Info/Info';
-import { Label } from 'shared/UI/Label/Label';
-import { Section } from 'components/Card/components/Section/Section';
-import { Sources } from 'components/Card/components/Sources/Sources';
-import { EditObjectButtonLink } from 'features/EditObjectButtonLink/EditObjectButtonLink';
-import { FilterLoader } from 'shared/UI/Loader/FilterLoader';
-import { getLatLngFromHash } from 'shared/helpers/hash';
-import { useIsDesktop } from 'shared/helpers/isDesktop';
-import { SOURCES_BY_TYPE } from 'constants/sources';
-import { SourceType } from 'types/Sources.types';
-import facades from 'public/ekb-facades.json';
-import HealthProgress from 'features/HouseWearTear/HealthProgress/HealthProgress';
-import styles from './CardContent.module.css';
-
-export function HousesCardContent() {
- const { popupId } = usePopup();
- const { ekbMap } = useMap();
- const { loading } = useContext(MapContext);
- const isDesktop = useIsDesktop();
-
- const [placemark, setPlacemark] = useState(null);
-
- useEffect(() => {
- const map = ekbMap?.getMap?.();
-
- if (!map || !popupId || loading) {
- return;
- }
-
- try {
- const [lat, lng] = getLatLngFromHash();
-
- const house = map.queryRenderedFeatures(map.project({ lat: +lat, lng: +lng }), {
- layers: ['building'],
- })?.[0]?.properties;
-
- if (!house) return;
-
- setPlacemark({
- id: popupId,
- attributes: {
- osmId: house['osm:id'] || null,
- Address: [house['addr:street'], house['addr:housenumber']]
- .filter(Boolean)
- .join(', '),
- Management_company: house['building:management'],
- Series: house['building:series'],
- Condition: house['building:condition'],
- Floors: house['building:levels'],
- Year: house['building:year'],
- Emergency: house['building:emergency'],
- WearAndTear: house['building:health'],
- borders: {
- coordinates: [[+lat, +lng]],
- },
- },
- });
- } catch (error) {
- console.error(error);
- }
- }, [ekbMap, popupId, loading]);
-
- useEffect(() => {
- const map = ekbMap?.getMap?.();
-
- if (!map || !popupId) {
- return;
- }
-
- // center map only on loading step
- if (loading) {
- try {
- const [lat, lng] = popupId.split('_');
-
- map.flyTo({ center: { lat: +lat, lng: +lng } });
- } catch (error) {
- console.error(error);
- }
- }
- }, [ekbMap, popupId, loading]);
-
- const isEmergency = useMemo(
- () => placemark?.attributes?.Condition === 'Аварийный',
- [placemark?.attributes?.Condition],
- );
-
- const aboutHouse = useMemo(() => {
- const result = [];
- if (placemark?.attributes?.Management_company) {
- result.push({
- name: 'Управляющая компания',
- text: placemark?.attributes?.Management_company,
- });
- }
-
- if (placemark?.attributes?.WearAndTear) {
- result.push({
- name: 'Износ',
- text: `${placemark?.attributes?.WearAndTear} %`,
- content: (
-
- ),
- });
- }
-
- if (placemark?.attributes?.Series) {
- result.push({
- name: 'Серия дома',
- text: placemark?.attributes?.Series,
- });
- }
-
- if (placemark?.attributes?.Floors) {
- result.push({
- name: 'Количество этажей',
- text: placemark?.attributes?.Floors,
- });
- }
-
- return result;
- }, [
- placemark?.attributes?.Management_company,
- placemark?.attributes?.WearAndTear,
- placemark?.attributes?.Series,
- placemark?.attributes?.Floors,
- isEmergency,
- ]);
-
- const defaultSources = [
- SOURCES_BY_TYPE[SourceType.osm],
- SOURCES_BY_TYPE[SourceType.howoldthishouse],
- SOURCES_BY_TYPE[SourceType.mingkh],
- SOURCES_BY_TYPE[SourceType.domaekb],
- ];
-
- if (loading) {
- return (
-
-
-
- );
- }
-
- if (!placemark?.attributes) {
- return null;
- }
-
- return (
-
-
- {(isEmergency || aboutHouse?.length > 0) && (
-
- {isEmergency && (
-
-
- {placemark?.attributes.Condition}
-
-
- )}
-
-
- )}
- {placemark?.attributes.Year && (
-
- )}
-
- {facades[placemark?.attributes?.osmId] && (
-
- )}
-
-
-
- );
-}
diff --git a/features/Buildings/Filter/HouseBaseFilter.tsx b/features/Buildings/Filter/HouseBaseFilter.tsx
deleted file mode 100644
index 4842ef9a..00000000
--- a/features/Buildings/Filter/HouseBaseFilter.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import React from 'react';
-import { HistogramData, MinMax } from 'shared/UI/RangeHistogram/types';
-import { RangeBaseFilter } from 'shared/UI/RangeHistogram/RangeBaseFilter';
-
-export interface HouseBaseFilterProps {
- defaultMin: number;
- defaultMax: number;
- units?: string;
- onChangeRequest: (range: MinMax) => void;
- getHistogramData: () => Promise;
-}
-
-export function HouseBaseFilter({
- onChangeRequest,
- defaultMin,
- defaultMax,
- units,
- getHistogramData,
-}: HouseBaseFilterProps) {
- return (
-
- );
-}
diff --git a/features/Buildings/Houses.constants.ts b/features/Buildings/Houses.constants.ts
deleted file mode 100644
index fb2dd5a3..00000000
--- a/features/Buildings/Houses.constants.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import { HistogramDataWithoutValues } from 'shared/UI/RangeHistogram';
-
-export enum HouseSourceType {
- Year = 'Year',
- Floors = 'Floors',
- WearAndTear = 'WearAndTear',
-}
-
-export const AGE_FILTERS_DATA: HistogramDataWithoutValues = [
- { from: 1723, to: 1860, color: '#ff7461' },
- { from: 1860, to: 1917, color: '#ffA34e' },
- { from: 1917, to: 1930, color: '#fee678' },
- { from: 1930, to: 1940, color: '#85e634' },
- { from: 1940, to: 1955, color: '#0f9467' },
- { from: 1955, to: 1991, color: '#71b3ff' },
- { from: 1991, to: 2010, color: '#c270ff' },
- { from: 2010, to: new Date().getFullYear(), color: '#f97bcf' },
-];
-
-export const FLOOR_FILTERS_DATA: HistogramDataWithoutValues = [
- { from: 1, to: 3, color: '#0050f0' },
- { from: 3, to: 5, color: '#0074e5' },
- { from: 5, to: 9, color: '#0095ce' },
- { from: 9, to: 12, color: '#00b49e' },
- { from: 12, to: 16, color: '#5dca13' },
- { from: 16, to: 21, color: '#93d800' },
- { from: 21, to: 25, color: '#b9e500' },
- { from: 25, to: 31, color: '#dcf300' },
- { from: 31, to: 52, color: '#ffff00' },
-];
-
-export const WEAR_TEAR_FILTERS_DATA: HistogramDataWithoutValues = [
- { from: 0, to: 10, color: '#006b29' },
- { from: 10, to: 20, color: '#24782a' },
- { from: 20, to: 30, color: '#73a426' },
- { from: 30, to: 40, color: '#b6c718' },
- { from: 40, to: 50, color: '#e9e005' },
- { from: 50, to: 60, color: '#ffea00' },
- { from: 60, to: 70, color: '#ffdc00' },
- { from: 70, to: 80, color: '#ffbb00' },
- { from: 80, to: 90, color: '#ff8a00' },
- { from: 90, to: 100, color: '#ff0000' },
-];
diff --git a/features/Buildings/houseBase.ts b/features/Buildings/houseBase.ts
index 13f4e394..95c9a0e2 100644
--- a/features/Buildings/houseBase.ts
+++ b/features/Buildings/houseBase.ts
@@ -1,10 +1,4 @@
-import { HistogramDataWithoutValues } from 'shared/UI/RangeHistogram';
-import { HouseSourceType } from './Houses.constants';
-
-type Meta = Record;
-
-let cache: Meta = null;
-async function getHouseMeta(): Promise {
+export async function getHouseMeta() {
return fetch('https://map-backend.netlify.app/house-meta.json')
.then((res) => res.json())
.then((data) => ({
@@ -13,49 +7,3 @@ async function getHouseMeta(): Promise {
health: data.health.map((item) => item.count || null),
}));
}
-
-export const houseBase = {
- async getFilterValues(_: HistogramDataWithoutValues, filterName: HouseSourceType) {
- const houseMeta = cache || (await getHouseMeta());
- cache = houseMeta;
-
- switch (filterName) {
- case HouseSourceType.Year:
- return Promise.resolve(houseMeta.years);
- case HouseSourceType.Floors:
- return Promise.resolve(houseMeta.levels);
- case HouseSourceType.WearAndTear:
- return Promise.resolve(houseMeta.health);
- default:
- return Promise.resolve([]);
- }
- },
-};
-
-export interface HouseClient {
- borders: HouseAttributes['borders']['coordinates'];
- year: number;
- floors: number;
- wearAndTear: number;
- id: string;
-}
-
-export interface HouseObject {
- id: string;
- attributes: HouseAttributes;
-}
-
-export interface HouseAttributes {
- osmId: number | null;
- Address: string;
- Management_company: string;
- Series: string;
- Condition: string;
- Floors: number;
- Year: number;
- Emergency: string;
- WearAndTear?: any;
- borders?: {
- coordinates: [number, number][];
- };
-}
diff --git a/features/Copyright/Copyright.module.css b/features/Copyright/Copyright.module.css
deleted file mode 100644
index cf7cd61a..00000000
--- a/features/Copyright/Copyright.module.css
+++ /dev/null
@@ -1,38 +0,0 @@
-.copyright {
- position: fixed;
- top: 56px;
- right: 0;
- z-index: 1000;
- padding: 4px 0;
- border-radius: 0 4px 4px 0px;
- background: black;
- color: rgba(255, 255, 255, 0.5);
- font-size: 10px;
- line-height: 1.5;
- opacity: 1;
- transform: scale(-1);
- writing-mode: vertical-lr;
-}
-
-.copyright[hidden] {
- display: block;
- opacity: 0;
- visibility: hidden;
-}
-
-.copyright a:not(:first-child):before {
- content: ' · ';
-}
-
-@media screen and (width >= 1150px) {
- .copyright {
- top: auto;
- left: 50%;
- bottom: 0;
- right: auto;
- border-radius: 2px 2px 0 0;
- padding: 0 4px;
- transform: translateX(-50%);
- writing-mode: lr;
- }
-}
diff --git a/features/Copyright/Copyright.tsx b/features/Copyright/Copyright.tsx
deleted file mode 100644
index e0071b92..00000000
--- a/features/Copyright/Copyright.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { useContext } from 'react';
-import { useSelector } from 'react-redux';
-import { activeFilterSelector } from 'state/features/selectors';
-import { MapContext } from 'features/Map/providers/MapProvider';
-import { FilterConfig } from 'types/Filters.types';
-import styles from './Copyright.module.css';
-
-export function Copyright({ filters }: { filters: FilterConfig }) {
- const { loading } = useContext(MapContext);
- const activeFilter = useSelector(activeFilterSelector);
- const copyright = filters[activeFilter]?.source;
-
- return (
-
- );
-}
diff --git a/styles/CardContent.module.css b/features/CustomCardContent/CardContent.module.css
similarity index 100%
rename from styles/CardContent.module.css
rename to features/CustomCardContent/CardContent.module.css
diff --git a/shared/UI/DownloadButton/DownloadButton.module.css b/features/CustomCardContent/DownloadButton/DownloadButton.module.css
similarity index 100%
rename from shared/UI/DownloadButton/DownloadButton.module.css
rename to features/CustomCardContent/DownloadButton/DownloadButton.module.css
diff --git a/shared/UI/DownloadButton/DownloadButton.tsx b/features/CustomCardContent/DownloadButton/DownloadButton.tsx
similarity index 84%
rename from shared/UI/DownloadButton/DownloadButton.tsx
rename to features/CustomCardContent/DownloadButton/DownloadButton.tsx
index a2f18080..1eef6a17 100644
--- a/shared/UI/DownloadButton/DownloadButton.tsx
+++ b/features/CustomCardContent/DownloadButton/DownloadButton.tsx
@@ -1,5 +1,5 @@
import classNames from 'classnames';
-import DownloadIcon from 'shared/UI/Icons/DownloadIcon';
+import { Icon, IconType } from 'sloy-ui';
import styles from './DownloadButton.module.css';
type Props = {
@@ -22,7 +22,7 @@ export function DownloadButton({ type, name, link }: Props) {
rel="noreferrer"
>
diff --git a/features/CustomCardContent/FeedbackButton/FeedbackButton.tsx b/features/CustomCardContent/FeedbackButton/FeedbackButton.tsx
new file mode 100644
index 00000000..efadc0eb
--- /dev/null
+++ b/features/CustomCardContent/FeedbackButton/FeedbackButton.tsx
@@ -0,0 +1,26 @@
+import { Button, ButtonSize, ButtonType, Icon, IconType } from 'sloy-ui';
+
+const getEditObjectLink = (address: string) =>
+ `https://tally.so#tally-open=w2BoVe&tally-width=650&tally-overlay=1&tally-emoji-animation=none&address=${address}`;
+
+type Props = {
+ address?: string;
+};
+
+export function FeedbackButton({ address }: Props) {
+ if (!address) return null;
+
+ const href = getEditObjectLink(address);
+
+ return (
+ }
+ >
+ Дополнить или поправить
+
+ );
+}
diff --git a/features/HouseWearTear/HealthProgress/HealthProgress.module.css b/features/CustomCardContent/HealthProgress/HealthProgress.module.css
similarity index 100%
rename from features/HouseWearTear/HealthProgress/HealthProgress.module.css
rename to features/CustomCardContent/HealthProgress/HealthProgress.module.css
diff --git a/features/HouseWearTear/HealthProgress/HealthProgress.tsx b/features/CustomCardContent/HealthProgress/HealthProgress.tsx
similarity index 55%
rename from features/HouseWearTear/HealthProgress/HealthProgress.tsx
rename to features/CustomCardContent/HealthProgress/HealthProgress.tsx
index a0891058..fe6cdfe4 100644
--- a/features/HouseWearTear/HealthProgress/HealthProgress.tsx
+++ b/features/CustomCardContent/HealthProgress/HealthProgress.tsx
@@ -1,19 +1,23 @@
-import { useMemo } from 'react';
-import BrokenHeart from 'shared/UI/Icons/BrokenHeart';
-import Heart from 'shared/UI/Icons/Heart';
-import { WEAR_TEAR_FILTERS_DATA } from 'features/Buildings/Houses.constants';
+import { Icon, IconType } from 'sloy-ui';
+import { defaultSources } from 'state/config';
import styles from './HealthProgress.module.css';
type Props = {
- percent: number;
+ percent?: number;
isEmergency: boolean;
};
function HealthProgress({ percent, isEmergency }: Props) {
- const healthColor = useMemo(
- () => WEAR_TEAR_FILTERS_DATA.find(({ from, to }) => percent >= from && percent <= to).color,
- [percent],
- );
+ if (!percent) return null;
+
+ const healthColor = defaultSources
+ .find((s) => s.id === 'osmBuilding')
+ ?.properties?.find((p) => p.id === 'building:health')
+ ?.range.find(({ from, to }) => percent >= from && percent <= to).color;
+
+ if (!healthColor) {
+ return null;
+ }
return (
@@ -26,9 +30,9 @@ function HealthProgress({ percent, isEmergency }: Props) {
>
{isEmergency ? (
-
+
) : (
-
+
)}
diff --git a/components/Card/components/Info/Info.module.css b/features/CustomCardContent/Info/Info.module.css
similarity index 100%
rename from components/Card/components/Info/Info.module.css
rename to features/CustomCardContent/Info/Info.module.css
diff --git a/components/Card/components/Info/Info.tsx b/features/CustomCardContent/Info/Info.tsx
similarity index 100%
rename from components/Card/components/Info/Info.tsx
rename to features/CustomCardContent/Info/Info.tsx
diff --git a/components/Card/components/Info/Info.types.ts b/features/CustomCardContent/Info/Info.types.ts
similarity index 100%
rename from components/Card/components/Info/Info.types.ts
rename to features/CustomCardContent/Info/Info.types.ts
diff --git a/features/OKN/CardContent/components/OKNInfo/OKNInfo.module.css b/features/CustomCardContent/OKNInfo/OKNInfo.module.css
similarity index 100%
rename from features/OKN/CardContent/components/OKNInfo/OKNInfo.module.css
rename to features/CustomCardContent/OKNInfo/OKNInfo.module.css
diff --git a/features/OKN/CardContent/components/OKNInfo/OKNInfo.tsx b/features/CustomCardContent/OKNInfo/OKNInfo.tsx
similarity index 62%
rename from features/OKN/CardContent/components/OKNInfo/OKNInfo.tsx
rename to features/CustomCardContent/OKNInfo/OKNInfo.tsx
index e6fcda1d..e0cc53f7 100644
--- a/features/OKN/CardContent/components/OKNInfo/OKNInfo.tsx
+++ b/features/CustomCardContent/OKNInfo/OKNInfo.tsx
@@ -1,11 +1,8 @@
import React, { useMemo } from 'react';
import classNames from 'classnames';
-
-import { Info } from 'components/Card/components/Info/Info';
-import { Label } from 'shared/UI/Label/Label';
-import { Icon } from 'shared/UI/Icons';
-import { IconType } from 'shared/UI/Icons/Icons.types';
-
+import { Tag } from 'sloy-ui';
+import { Info } from 'features/CustomCardContent/Info/Info';
+import { SvgOknIcon } from './SvgOknIcon';
import styles from './OKNInfo.module.css';
export type OKNInfoProps = {
@@ -31,11 +28,7 @@ export function OKNInfo({ number, status }: OKNInfoProps) {
- {isLost && (
-
- Утрачен
-
- )}
+ {isLost &&
Утрачен }
-
+
- {/*
*/}
);
}
diff --git a/shared/UI/Icons/OKN.tsx b/features/CustomCardContent/OKNInfo/SvgOknIcon.tsx
similarity index 99%
rename from shared/UI/Icons/OKN.tsx
rename to features/CustomCardContent/OKNInfo/SvgOknIcon.tsx
index a5ad5eac..3616c023 100644
--- a/shared/UI/Icons/OKN.tsx
+++ b/features/CustomCardContent/OKNInfo/SvgOknIcon.tsx
@@ -1,6 +1,6 @@
import React from 'react';
-export function OKN() {
+export function SvgOknIcon() {
return (
{!noHealthStatus && (
-
+
{/* TODO: make correct gender word ending */}
{healthStatusType}
-
+
)}
diff --git a/features/DTP/CardContent/components/Participants/Participants.module.css b/features/CustomCardContent/Participants/Participants.module.css
similarity index 81%
rename from features/DTP/CardContent/components/Participants/Participants.module.css
rename to features/CustomCardContent/Participants/Participants.module.css
index 29e52226..143c420d 100644
--- a/features/DTP/CardContent/components/Participants/Participants.module.css
+++ b/features/CustomCardContent/Participants/Participants.module.css
@@ -1,12 +1,7 @@
-.participants__title {
- margin: 0;
-}
-
-.participants__filter {
- margin-top: 6px;
- display: flex;
- flex-direction: row;
- gap: 8px;
+.participants__section {
+ margin-top: 16px;
+ padding-top: 16px;
+ border-top: 1px solid rgba(256, 256, 256, 0.16);
}
.participants__participants {
diff --git a/features/CustomCardContent/Participants/Participants.tsx b/features/CustomCardContent/Participants/Participants.tsx
new file mode 100644
index 00000000..45c7afb0
--- /dev/null
+++ b/features/CustomCardContent/Participants/Participants.tsx
@@ -0,0 +1,108 @@
+import React from 'react';
+import { Tag } from 'sloy-ui';
+import { healthStatusToType, HEALTH_STATUS_COLOR, Participant } from './Participant/Participant';
+import {
+ HealthStatusType,
+ DTPParticipant,
+ DTPVehicle,
+ DTPObjectProperties,
+} from './Participants.types';
+
+import styles from './Participants.module.css';
+
+export type ParticipantsProps = {
+ participants: DTPObjectProperties['participants'];
+ vehicles?: DTPObjectProperties['vehicles'];
+};
+
+export const CATEGORY_INSTEAD_OF_BRAND = ['Трамваи', 'Троллейбусы', 'Велосипеды'];
+export const BUSES_CATEGORIES = ['одноэтажные', 'одноярусные'];
+
+export function isBus(category: string) {
+ return BUSES_CATEGORIES.some((busCategory) => category.toLowerCase().includes(busCategory));
+}
+
+export function getVehicleName(vehicle: DTPVehicle) {
+ let car = vehicle.brand || vehicle.category;
+
+ if (CATEGORY_INSTEAD_OF_BRAND.includes(vehicle.category)) {
+ car = vehicle.category;
+ }
+
+ if (isBus(vehicle.category) && !vehicle.brand) {
+ car = 'Автобус';
+ }
+
+ if (vehicle.model && !vehicle.model.toLowerCase().includes('прочие')) {
+ car += ` ${vehicle.model}`;
+ }
+
+ if (vehicle.year) {
+ car += `, ${vehicle.year}`;
+ }
+
+ return car;
+}
+
+export function Participants({ participants, vehicles }: ParticipantsProps) {
+ return (
+
+ <>
+ {vehicles.map((vehicle, i) => {
+ const driverIndex = vehicle.participants.findIndex(
+ (participant) => participant.role === 'Водитель',
+ );
+
+ let driver: DTPParticipant;
+ let driverHealthStatus: HealthStatusType;
+
+ if (driverIndex !== -1) {
+ driver = vehicle.participants[driverIndex];
+ driverHealthStatus = healthStatusToType(driver.health_status);
+ }
+
+ const restParticipants = vehicle.participants.filter(
+ (participant) => participant.role !== 'Водитель',
+ );
+
+ const car = getVehicleName(vehicle);
+
+ return (
+
+
+
+
+
{car}
+
+ {vehicle.color}
+
+
+ {driver && (
+
+ {driverHealthStatus}
+
+ )}
+
+ {driver && (
+
+ )}
+
+ {restParticipants.map((participant, i) => (
+
+ ))}
+
+ );
+ })}
+ {participants.map((participant, i) => (
+
+ ))}
+ >
+
+ );
+}
diff --git a/features/CustomCardContent/Participants/Participants.types.ts b/features/CustomCardContent/Participants/Participants.types.ts
new file mode 100644
index 00000000..e7a6c7cc
--- /dev/null
+++ b/features/CustomCardContent/Participants/Participants.types.ts
@@ -0,0 +1,48 @@
+enum DTPLight {
+ Light = 'Светлое время суток',
+ DarkLightOn = 'В темное время суток, освещение включено',
+ DarkLightOff = 'В темное время суток, освещение не включено',
+ DarkNoLight = 'В темное время суток, освещение отсутствует',
+ Twilight = 'Сумерки',
+}
+
+export type DTPVehicle = {
+ brand: string;
+ color: string;
+ model: string;
+ category: string;
+ year: number;
+ participants: DTPParticipant[];
+};
+
+export type DTPParticipant = {
+ role: string;
+ gender: string;
+ violations: string[];
+ health_status: string;
+ years_of_driving_experience?: number;
+};
+
+export type DTPObjectProperties = {
+ vehicles: DTPVehicle[];
+ dead_count: number;
+ injured_count: number;
+ participants_count: number;
+ participants: DTPParticipant[];
+ road_conditions: string[];
+ participant_categories: string[];
+ weather: string[];
+ nearby: string[];
+ tags: string[];
+ datetime: string;
+ address: string;
+ severity: string;
+ light: DTPLight;
+ category: string;
+};
+
+export enum HealthStatusType {
+ Dead = 'скончался',
+ Injured = 'пострадал',
+ NotInjured = 'не пострадал',
+}
diff --git a/features/CustomCardContent/overrideCard.tsx b/features/CustomCardContent/overrideCard.tsx
new file mode 100644
index 00000000..ab71a79c
--- /dev/null
+++ b/features/CustomCardContent/overrideCard.tsx
@@ -0,0 +1,96 @@
+import { Tag } from 'sloy-ui';
+import { OverrideCardFn } from 'sloy-map';
+import HealthProgress from 'features/CustomCardContent/HealthProgress/HealthProgress';
+import { DownloadButton } from 'features/CustomCardContent/DownloadButton/DownloadButton';
+import { FeedbackButton } from 'features/CustomCardContent/FeedbackButton/FeedbackButton';
+import facades from 'public/ekb-facades.json';
+import styles from 'features/CustomCardContent/CardContent.module.css';
+import { OKNInfo } from 'features/CustomCardContent/OKNInfo/OKNInfo';
+import { Participants } from 'features/CustomCardContent/Participants/Participants';
+
+export const overrideCard: OverrideCardFn = ({ cardProps, values = {}, source }) => {
+ const emergency = values['building:emergency'];
+ const isEmergency = emergency === 'Аварийность';
+ const facade = facades[values['osm:id']];
+
+ if (isEmergency) {
+ cardProps.blocks.push({
+ type: 'value',
+ value: (
+
+ {values['building:condition']}
+
+ ),
+ });
+ }
+
+ cardProps.blocks = cardProps.blocks.map((item) => {
+ if (item.id === 'building:health') {
+ const health = Number(values[item.id]);
+
+ return {
+ ...item,
+ value: (
+
+ {health} %
+
+
+ ),
+ };
+ }
+
+ return item;
+ });
+
+ if (facade) {
+ cardProps.blocks.push({
+ type: 'section',
+ title: 'Дизайн-код фасада',
+ value: ,
+ });
+ }
+
+ if (source.id === 'ekbOknSource') {
+ cardProps.blocks.push({
+ type: 'section',
+ value: ,
+ });
+ }
+
+ if (source.id === 'ekbDtpSource' && values.participants && values.vehicles) {
+ cardProps.blocks.push({
+ type: 'section',
+ value: ,
+ });
+ }
+
+ if (source.id === 'ekbDesigncodeSource') {
+ cardProps.blocks.push({
+ type: 'section',
+ value: (
+ <>
+ {(values.images || []).map((image) => {
+ const imageData = image.m || image.s;
+ const imageSrc = `https://map.ekaterinburg.design${imageData.src}`;
+
+ return (
+
+
+
+ );
+ })}
+ >
+ ),
+ });
+ }
+
+ cardProps.footerActions = ;
+
+ return cardProps;
+};
diff --git a/features/Facade/Filter/FacadeFilter.tsx b/features/CustomFilterContent/FacadeFilter.tsx
similarity index 74%
rename from features/Facade/Filter/FacadeFilter.tsx
rename to features/CustomFilterContent/FacadeFilter.tsx
index 519edd18..f94634e4 100644
--- a/features/Facade/Filter/FacadeFilter.tsx
+++ b/features/CustomFilterContent/FacadeFilter.tsx
@@ -1,12 +1,11 @@
import styled from 'styled-components';
-import { Link } from 'shared/UI/Link/Link';
const Wrapper = styled.div`
font-size: 14px;
line-height: 21px;
p {
- margin: 16px 0 0 0;
+ margin: 8px;
&:first-child {
margin-top: 0;
}
@@ -23,12 +22,6 @@ export function FacadeFilter() {
входят в первый пояс. Чтобы посмотреть регламент оформления фасада, кликните
на дом, а затем на зелёную кнопку скачивания.
-
-
-
);
}
diff --git a/features/Quarter/Filter/QuarterFilter.tsx b/features/CustomFilterContent/QuarterFilter.tsx
similarity index 64%
rename from features/Quarter/Filter/QuarterFilter.tsx
rename to features/CustomFilterContent/QuarterFilter.tsx
index a745a7d3..324e376e 100644
--- a/features/Quarter/Filter/QuarterFilter.tsx
+++ b/features/CustomFilterContent/QuarterFilter.tsx
@@ -1,16 +1,11 @@
-import { useEffect } from 'react';
-import { useDispatch } from 'react-redux';
import styled from 'styled-components';
-import { setFilter } from 'state/features/dataLayers';
-import { FilterType } from 'types/Filters.types';
-import { Link } from 'shared/UI/Link/Link';
const Wrapper = styled.div`
font-size: 14px;
line-height: 21px;
p {
- margin: 16px 0 0 0;
+ margin: 8px;
&:first-child {
margin-top: 0;
}
@@ -29,17 +24,6 @@ const Wrapper = styled.div`
`;
export function QuarterFilter() {
- const dispatch = useDispatch();
-
- useEffect(() => {
- dispatch(
- setFilter({
- activeFilter: FilterType.Quarter,
- activeFilterParams: {},
- }),
- );
- });
-
return (
@@ -54,12 +38,6 @@ export function QuarterFilter() {
самовольные ограничения;
сломанные детские площадки.
-
-
-
);
}
diff --git a/features/DTP/CardContent/CardContent.module.css b/features/DTP/CardContent/CardContent.module.css
deleted file mode 100644
index 8a0279ac..00000000
--- a/features/DTP/CardContent/CardContent.module.css
+++ /dev/null
@@ -1,14 +0,0 @@
-.popup {
- border-top-left-radius: inherit;
- border-top-right-radius: inherit;
- padding: 16px 8px 16px 16px;
-}
-
-.popup__extraText {
- margin: 8px 16px 0 0;
- font-style: normal;
- font-weight: 400;
- line-height: 20px;
- font-size: 16px;
- color: #9baac3;
-}
diff --git a/features/DTP/CardContent/CardContent.tsx b/features/DTP/CardContent/CardContent.tsx
deleted file mode 100644
index 1352db08..00000000
--- a/features/DTP/CardContent/CardContent.tsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import React, { useMemo } from 'react';
-
-import { Section } from 'components/Card/components/Section/Section';
-import { Header } from 'components/Card/components/Header/Header';
-import { Info } from 'components/Card/components/Info/Info';
-import { Sources } from 'components/Card/components/Sources/Sources';
-import { InfoProps } from 'components/Card/components/Info/Info.types';
-import { SourceType } from 'types/Sources.types';
-import { SOURCES_BY_TYPE } from 'constants/sources';
-import { DTPObject } from '../dtp';
-import styles from './CardContent.module.css';
-import { Participants } from './components/Participants/Participants';
-
-export type DTPCardContentProps = {
- placemark: DTPObject;
-};
-
-export function DTPCardContent({ placemark }: DTPCardContentProps) {
- const { title, description } = useMemo(() => {
- const indexOfComma = placemark?.properties.category?.indexOf(',') || -1;
-
- if (indexOfComma === -1) {
- return { title: placemark?.properties.category };
- }
-
- return {
- title: placemark?.properties.category.slice(0, indexOfComma),
- description: placemark?.properties.category.slice(indexOfComma + 1),
- };
- }, [placemark?.properties.category]);
-
- const date = useMemo(() => {
- if (!placemark?.properties.datetime) {
- return null;
- }
-
- const parsedDate = new Date(placemark.properties.datetime);
-
- return parsedDate.toLocaleString('ru-RU', {
- day: 'numeric',
- month: 'long',
- year: 'numeric',
- hour: 'numeric',
- minute: 'numeric',
- });
- }, [placemark?.properties.datetime]);
-
- const environment = useMemo(() => {
- const result: InfoProps['infos'] = [];
-
- if (placemark?.properties.light) {
- result.push({
- name: 'Время суток',
- text: placemark.properties.light,
- });
- }
-
- if (placemark?.properties.weather?.length) {
- const [firstCondition, ...conditions] = placemark.properties.weather;
- const joinedConditions = [
- firstCondition,
- ...conditions.map((condition) => condition.toLowerCase()),
- ].join(', ');
-
- result.push({
- name: 'Погода',
- text: joinedConditions,
- });
- }
-
- if (placemark?.properties.road_conditions?.length) {
- const [firstCondition, ...conditions] = placemark.properties.road_conditions;
- const joinedConditions = [
- firstCondition,
- ...conditions.map((condition) => condition.toLowerCase()),
- ].join(', ');
-
- result.push({
- name: 'Дорожные условия',
- text: joinedConditions,
- });
- }
-
- return result;
- }, [
- placemark?.properties.road_conditions,
- placemark?.properties.weather,
- placemark?.properties.light,
- ]);
-
- return placemark?.properties ? (
-
-
- {date &&
{date}
}
- {placemark?.properties.address && (
-
- {placemark?.properties.address}
-
- )}
-
- {placemark?.properties.participants_count && (
-
- )}
-
-
- ) : null;
-}
diff --git a/features/DTP/CardContent/components/Participants/Participants.tsx b/features/DTP/CardContent/components/Participants/Participants.tsx
deleted file mode 100644
index 6634d2b6..00000000
--- a/features/DTP/CardContent/components/Participants/Participants.tsx
+++ /dev/null
@@ -1,115 +0,0 @@
-import React from 'react';
-
-import { Label } from 'shared/UI/Label/Label';
-
-import { Section } from 'components/Card/components/Section/Section';
-import { DTPParticipant, DTPVehicle } from 'features/DTP/dtp';
-import { healthStatusToType, HEALTH_STATUS_COLOR, Participant } from './Participant/Participant';
-import { ParticipantsProps, HealthStatusType } from './Participants.types';
-
-import styles from './Participants.module.css';
-
-export const CATEGORY_INSTEAD_OF_BRAND = ['Трамваи', 'Троллейбусы', 'Велосипеды'];
-export const BUSES_CATEGORIES = ['одноэтажные', 'одноярусные'];
-
-export function isBus(category: string) {
- return BUSES_CATEGORIES.some((busCategory) => category.toLowerCase().includes(busCategory));
-}
-
-export function getVehicleName(vehicle: DTPVehicle) {
- let car = vehicle.brand || vehicle.category;
-
- if (CATEGORY_INSTEAD_OF_BRAND.includes(vehicle.category)) {
- car = vehicle.category;
- }
-
- if (isBus(vehicle.category) && !vehicle.brand) {
- car = 'Автобус';
- }
-
- if (vehicle.model && !vehicle.model.toLowerCase().includes('прочие')) {
- car += ` ${vehicle.model}`;
- }
-
- if (vehicle.year) {
- car += `, ${vehicle.year}`;
- }
-
- return car;
-}
-
-export function Participants({ participants, vehicles }: ParticipantsProps) {
- return (
-
-
Участники
-
- <>
- {vehicles.map((vehicle, i) => {
- const driverIndex = vehicle.participants.findIndex(
- (participant) => participant.role === 'Водитель',
- );
-
- let driver: DTPParticipant;
- let driverHealthStatus: HealthStatusType;
-
- if (driverIndex !== -1) {
- driver = vehicle.participants[driverIndex];
- driverHealthStatus = healthStatusToType(driver.health_status);
- }
-
- const restParticipants = vehicle.participants.filter(
- (participant) => participant.role !== 'Водитель',
- );
-
- const car = getVehicleName(vehicle);
-
- return (
-
-
-
-
-
- {car}
-
-
- {vehicle.color}
-
-
- {driver && (
-
- {driverHealthStatus}
-
- )}
-
- {driver && (
-
- )}
-
- {restParticipants.map((participant, i) => (
-
- ))}
-
- );
- })}
- {participants.map((participant, i) => (
-
- ))}
- >
-
-
- );
-}
diff --git a/features/DTP/CardContent/components/Participants/Participants.types.ts b/features/DTP/CardContent/components/Participants/Participants.types.ts
deleted file mode 100644
index 33cbbcf0..00000000
--- a/features/DTP/CardContent/components/Participants/Participants.types.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { DTPObjectProperties } from 'features/DTP/dtp';
-
-export type ParticipantsProps = {
- participants: DTPObjectProperties['participants'];
- vehicles?: DTPObjectProperties['vehicles'];
-};
-
-export enum HealthStatusType {
- Dead = 'скончался',
- Injured = 'пострадал',
- NotInjured = 'не пострадал',
-}
diff --git a/features/DTP/DTP.constants.ts b/features/DTP/DTP.constants.ts
deleted file mode 100644
index 681df742..00000000
--- a/features/DTP/DTP.constants.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import { range } from 'lodash';
-
-import { IconType } from 'shared/UI/Icons/Icons.types';
-import { HistogramDataWithoutValues } from 'shared/UI/RangeHistogram';
-import { DtpParticipantType } from './dtpParticipantType';
-import { DtpSeverityType } from './dtpSeverityType';
-
-export type ParticipantConfig = Record;
-
-export const MIN_DTP_YEAR = 2015;
-export const CURRENT_YEAR = new Date().getFullYear();
-
-export const DTP_PARTICIPANT_CONFIG: ParticipantConfig = {
- [DtpParticipantType.Children]: {
- icon: IconType.Children,
- },
- [DtpParticipantType.Auto]: {
- icon: IconType.Auto,
- label: 'Автомобилисты',
- },
- [DtpParticipantType.Cyclists]: {
- icon: IconType.Bycicle,
- },
- [DtpParticipantType.Motorcyclists]: {
- icon: IconType.Bike,
- },
- [DtpParticipantType.Pedestrians]: {
- icon: IconType.Pedestrian,
- },
- [DtpParticipantType.PublicTransport]: {
- icon: IconType.PublicTransport,
- label: 'Общественный транспорт',
- },
-};
-
-export const SEVERITY_CONFIG = {
- [DtpSeverityType.Light]: {
- color: '#36ccaa',
- },
- [DtpSeverityType.Heavy]: {
- color: '#fdcf4e',
- },
- [DtpSeverityType.WithDead]: {
- color: '#ff0000',
- },
-};
-
-export const DTP_YEARS_RANGE = range(MIN_DTP_YEAR, CURRENT_YEAR);
-export const YEARS_FILTERS_DATA: HistogramDataWithoutValues = DTP_YEARS_RANGE.map((year) => ({
- from: year,
- to: year + 1,
- color: '#7793db',
-}));
diff --git a/features/DTP/DtpSource.tsx b/features/DTP/DtpSource.tsx
deleted file mode 100644
index 3d6d35bc..00000000
--- a/features/DTP/DtpSource.tsx
+++ /dev/null
@@ -1,121 +0,0 @@
-import React, { useEffect } from 'react';
-import { Source, Layer, useMap } from 'react-map-gl';
-import type { CircleLayer, HeatmapLayer } from 'react-map-gl';
-import { useSelector } from 'react-redux';
-import { activeFilterSelector, activeFilterParamsSelector } from 'state/features/selectors';
-import { FilterType } from 'types/Filters.types';
-import { SEVERITY_CONFIG } from 'features/DTP/DTP.constants';
-import { MapItemType } from 'types/Content.types';
-import { MAX_ZOOM, MIN_ZOOM } from 'constants/map';
-import dtp from 'public/ekb-dtp.json';
-import { usePopup } from 'features/Map/providers/usePopup';
-import useMapObjectState from 'features/Map/helpers/useMapObjectState';
-
-const DTP_LAYER_ID = 'dtp-point';
-const DTP_LAYER_HEATMAP_ID = 'dtp-point-heatmap';
-
-export function DtpSource() {
- const ekbMap = useMap();
- const { openPopup } = usePopup();
- const activeFilter = useSelector(activeFilterSelector);
- const activeFilterParams = useSelector(activeFilterParamsSelector);
-
- useMapObjectState(DTP_LAYER_ID);
-
- useEffect(() => {
- ekbMap?.current?.on?.('click', DTP_LAYER_ID, (e) => {
- const item = e.target.queryRenderedFeatures(e.point)[0];
- openPopup(item.properties?.id, MapItemType.DTP);
- });
- }, [ekbMap, openPopup]);
-
- if (activeFilter !== FilterType.DTP || !activeFilterParams) {
- return null;
- }
-
- const data = {
- ...dtp,
- features: dtp.features.filter((feature) => {
- const { severity } = feature.properties;
-
- const matchSeverity = activeFilterParams.severity.includes(severity);
-
- const matchYear =
- feature.properties.year >= activeFilterParams.years.from &&
- feature.properties.year < activeFilterParams.years.to;
-
- const matchParticipants = activeFilterParams.participants.some((c) =>
- feature.properties.participant_categories.includes(c),
- );
-
- return matchSeverity && matchParticipants && matchYear;
- }),
- };
-
- const colors = Object.entries(SEVERITY_CONFIG).map(([severity, { color }]) => [
- ['==', ['get', 'severity'], severity],
- color,
- ]);
-
- const strokeColors = Object.entries(SEVERITY_CONFIG).map(([severity]) => [
- ['==', ['get', 'severity'], severity],
- '#000',
- ]);
-
- const layerStyle: CircleLayer = {
- id: DTP_LAYER_ID,
- type: 'circle',
- source: 'ekb-dtp-source',
- paint: {
- // @ts-ignore
- 'circle-color': ['case'].concat(...colors).concat(['rgba(0, 0, 0, 0)']),
- 'circle-stroke-width': 1,
- // @ts-ignore
- 'circle-stroke-color': ['case'].concat(...strokeColors).concat(['rgba(0, 0, 0, 0)']),
- 'circle-radius': ['interpolate', ['linear'], ['zoom'], MIN_ZOOM, 1, MAX_ZOOM, 12],
- },
- };
-
- const heatmapStyle: HeatmapLayer = {
- id: DTP_LAYER_HEATMAP_ID,
- source: 'ekb-dtp-source',
- type: 'heatmap',
- paint: {
- 'heatmap-weight': {
- type: 'exponential',
- property: 'weight',
- stops: [
- [0, 0],
- [1, 1],
- ],
- },
- 'heatmap-intensity': 1,
- 'heatmap-color': [
- 'interpolate',
- ['linear'],
- ['heatmap-density'],
- 0,
- 'rgba(0, 0, 255, 0)',
- 0.2,
- 'rgb(0, 255, 0)',
- 0.4,
- 'rgb(255, 255, 0)',
- 0.6,
- 'rgb(255, 0, 0)',
- 1,
- 'rgb(255, 0, 0)',
- ],
- 'heatmap-radius': ['interpolate', ['linear'], ['zoom'], MIN_ZOOM, 2, MAX_ZOOM, 50],
- 'heatmap-opacity': ['interpolate', ['linear'], ['zoom'], MIN_ZOOM, 1, MAX_ZOOM, 0],
- },
- };
-
- return (
- <>
-
-
-
-
- >
- );
-}
diff --git a/features/DTP/Filter/DTPFilter.module.css b/features/DTP/Filter/DTPFilter.module.css
deleted file mode 100644
index 9beb6982..00000000
--- a/features/DTP/Filter/DTPFilter.module.css
+++ /dev/null
@@ -1,22 +0,0 @@
-.DTPFilter__sectionTitle {
- font-size: 18px;
- margin: 11px 0 8px;
-}
-
-.DTPFilter__checkboxContent {
- width: 100%;
-
- &:not(:last-of-type) {
- margin-bottom: 8px;
- }
-}
-
-.DTPFilter__objectsCount {
- margin-left: 8px;
- color: #9baac3;
-}
-
-.DTPFilter__icon {
- margin-right: 2px;
- vertical-align: text-bottom;
-}
diff --git a/features/DTP/Filter/DTPFilter.state.ts b/features/DTP/Filter/DTPFilter.state.ts
deleted file mode 100644
index 59767cda..00000000
--- a/features/DTP/Filter/DTPFilter.state.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import { DtpParticipantType } from '../dtpParticipantType';
-import { DtpSeverityType } from '../dtpSeverityType';
-import {
- DTPParticipantsAction,
- DTPParticipantsState,
- DTPSeverityAction,
- DTPSeverityState,
-} from './DTPFilter.types';
-
-export function dtpSeverityReducer(state: DTPSeverityState, action: DTPSeverityAction) {
- switch (action.type) {
- case 'toggle':
- return { ...state, [action.severityType]: !state[action.severityType] };
- default:
- return state;
- }
-}
-
-export const dtpSeverityInitalState = Object.values(DtpSeverityType).reduce((acc, type) => {
- acc[type] = true;
-
- return acc;
-}, {} as DTPSeverityState);
-
-export function dtpParticipantReducer(state: DTPParticipantsState, action: DTPParticipantsAction) {
- switch (action.type) {
- case 'toggle':
- return { ...state, [action.participantType]: !state[action.participantType] };
- default:
- return state;
- }
-}
-
-export const dtpParticipantInitalState = Object.values(DtpParticipantType).reduce((acc, type) => {
- acc[type] = true;
-
- return acc;
-}, {} as DTPParticipantsState);
diff --git a/features/DTP/Filter/DTPFilter.tsx b/features/DTP/Filter/DTPFilter.tsx
deleted file mode 100644
index b32e6c82..00000000
--- a/features/DTP/Filter/DTPFilter.tsx
+++ /dev/null
@@ -1,195 +0,0 @@
-import React, { useCallback, useEffect, useMemo, useReducer, useState } from 'react';
-import { useDispatch } from 'react-redux';
-
-import { setFilter } from 'state/features/dataLayers';
-
-import { dtp, DTPFiltersParams } from 'features/DTP/dtp';
-
-import { Checkbox } from 'shared/UI/Checkbox/Checkbox';
-import { FilterLoader } from 'shared/UI/Loader/FilterLoader';
-import { FilterType } from 'types/Filters.types';
-import { MinMax } from 'shared/UI/RangeHistogram/types';
-import { RangeBaseFilter } from 'shared/UI/RangeHistogram/RangeBaseFilter';
-
-import { DtpParticipantType } from '../dtpParticipantType';
-import { DtpSeverityType } from '../dtpSeverityType';
-import {
- MIN_DTP_YEAR,
- CURRENT_YEAR,
- DTP_PARTICIPANT_CONFIG,
- SEVERITY_CONFIG,
- YEARS_FILTERS_DATA,
-} from '../DTP.constants';
-import {
- dtpParticipantInitalState,
- dtpParticipantReducer,
- dtpSeverityInitalState,
- dtpSeverityReducer,
-} from './DTPFilter.state';
-import styles from './DTPFilter.module.css';
-
-type ParticipantCountEntries = [DtpParticipantType, number][];
-type SeverityCountEntries = [DtpSeverityType, number][];
-
-const DEFAULT_MIN_YEAR = CURRENT_YEAR - 1;
-
-export function DTPFilter() {
- const dispatch = useDispatch();
- const [severityState, dispatchSeverity] = useReducer(
- dtpSeverityReducer,
- dtpSeverityInitalState,
- );
- const [participantState, dispatchParticipant] = useReducer(
- dtpParticipantReducer,
- dtpParticipantInitalState,
- );
- const [yearsLoaded, setYearsLoaded] = useState(false);
- const [participantCount, setParticipantCount] = useState(null);
- const [severityCount, setSeverityCount] = useState(null);
- const [yearsState, setYearsState] = useState({
- min: DEFAULT_MIN_YEAR,
- max: CURRENT_YEAR,
- });
-
- useEffect(() => {
- dtp.getParticipantFilters().then((participantFilters: ParticipantCountEntries) => {
- const sortedParticipantCount = participantFilters.sort(
- ([, countA], [, countB]) => countB - countA,
- );
-
- setParticipantCount(sortedParticipantCount);
- });
- }, []);
-
- useEffect(() => {
- dtp.getSeverityFilters().then((severityFilters: SeverityCountEntries) => {
- const sortedSeverityCount = severityFilters.sort(
- ([, countA], [, countB]) => countB - countA,
- );
-
- setSeverityCount(sortedSeverityCount);
- });
- }, []);
-
- const onSeverityChange = useCallback(
- (severityType: DtpSeverityType) => () => {
- dispatchSeverity({ type: 'toggle', severityType });
- },
- [],
- );
-
- const onParticipantChange = useCallback(
- (participantType: DtpParticipantType) => () => {
- dispatchParticipant({ type: 'toggle', participantType });
- },
- [],
- );
-
- const onYearsChange = useCallback((range: MinMax) => setYearsState(range), []);
-
- const getHistogramData = useCallback(async () => {
- const dtpFilters = await dtp.getYearsFilters();
-
- const histogramData = YEARS_FILTERS_DATA.map((yearsItemData, idx) => ({
- ...yearsItemData,
- value: dtpFilters[idx],
- }));
-
- setYearsLoaded(true);
-
- return histogramData;
- }, []);
-
- useEffect(() => {
- const filters: DTPFiltersParams = {
- years: {
- from: yearsState.min,
- to: yearsState.max,
- },
- };
-
- const severities = Object.entries(severityState).reduce((acc, [type, value]) => {
- if (value) {
- acc.push(type);
- }
-
- return acc;
- }, []) as DtpSeverityType[];
- const participants = Object.entries(participantState).reduce((acc, [type, value]) => {
- if (value) {
- acc.push(type);
- }
-
- return acc;
- }, []) as DtpParticipantType[];
-
- filters.severity = severities;
- filters.participants = participants;
-
- dispatch(
- setFilter({
- activeFilter: FilterType.DTP,
- activeFilterParams: filters,
- }),
- );
- }, [dispatch, severityState, participantState, yearsState.min, yearsState.max]);
-
- const shouldShowLoader = useMemo(
- () => !yearsLoaded || !participantCount || !severityCount,
- [yearsLoaded, participantCount, severityCount],
- );
-
- const shouldShowCheckboxes = useMemo(
- () => participantCount && severityCount,
- [participantCount, severityCount],
- );
-
- return (
- <>
-
- {shouldShowCheckboxes && (
- <>
- Участники ДТП
- {participantCount?.map(([type, count], i) => (
-
-
- {DTP_PARTICIPANT_CONFIG[type]?.label || type}
- {count}
-
-
- ))}
- Вред здоровью
- {severityCount?.map(([type, count], i) => (
-
-
- {type}
- {count}
-
-
- ))}
- >
- )}
- {shouldShowLoader && }
- >
- );
-}
diff --git a/features/DTP/Filter/DTPFilter.types.ts b/features/DTP/Filter/DTPFilter.types.ts
deleted file mode 100644
index 96c6c5c6..00000000
--- a/features/DTP/Filter/DTPFilter.types.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { DtpParticipantType } from '../dtpParticipantType';
-import { DtpSeverityType } from '../dtpSeverityType';
-
-export interface DTPSeverityAction {
- type: 'toggle';
- severityType: DtpSeverityType;
-}
-export interface DTPParticipantsAction {
- type: 'toggle';
- participantType: DtpParticipantType;
-}
-
-export type DTPSeverityState = Record;
-export type DTPParticipantsState = Record;
diff --git a/features/DTP/dtp.ts b/features/DTP/dtp.ts
deleted file mode 100644
index 63902da6..00000000
--- a/features/DTP/dtp.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-import groupBy from 'lodash/groupBy';
-import { Range } from 'shared/UI/RangeHistogram/types';
-import { DTP_YEARS_RANGE } from 'features/DTP/DTP.constants';
-import { fetchAPI } from 'shared/helpers/fetchApi';
-
-import dtpData from 'public/ekb-dtp.json';
-
-import { DtpSeverityType } from './dtpSeverityType';
-import { DtpParticipantType } from './dtpParticipantType';
-
-export const dtp = {
- async getObject(id: string): Promise {
- return fetchAPI(`/api/dtp?id=${id}`);
- },
- async getSeverityFilters() {
- const dtpBySeverity = Object.entries(
- groupBy(dtpData.features, (item) => item.properties.severity),
- )
- .map(([type, items]) => [type, items.length])
- .sort((a, b) => (b[1] as number) - (a[1] as number));
-
- return Promise.resolve(dtpBySeverity);
- },
- async getParticipantFilters() {
- const categories = Array.from(
- new Set(dtpData.features.map((item) => item.properties.participant_categories).flat(2)),
- );
-
- const dtpByParticipants = categories
- .map((category) => [
- category,
- dtpData.features.filter((item) =>
- item.properties.participant_categories.includes(category),
- ),
- ])
- .map(([type, items]) => [type, items.length])
- .sort((a, b) => (b[1] as number) - (a[1] as number));
-
- return Promise.resolve(dtpByParticipants);
- },
- async getYearsFilters() {
- const years = DTP_YEARS_RANGE;
-
- const dtpByYear = years.map(
- (year) => dtpData.features.filter((item) => item.properties.year === year).length,
- );
-
- return Promise.resolve(dtpByYear);
- },
-};
-
-export interface DTPFiltersParams {
- severity?: DtpSeverityType[];
- participants?: DtpParticipantType[];
- years: Range;
-}
-
-export type DTPObject = {
- properties: DTPObjectProperties;
- geometry: {
- coordinates: [number, number];
- };
-};
-
-enum DTPLight {
- Light = 'Светлое время суток',
- DarkLightOn = 'В темное время суток, освещение включено',
- DarkLightOff = 'В темное время суток, освещение не включено',
- DarkNoLight = 'В темное время суток, освещение отсутствует',
- Twilight = 'Сумерки',
-}
-
-export type DTPObjectProperties = {
- vehicles: DTPVehicle[];
- dead_count: number;
- injured_count: number;
- participants_count: number;
- participants: DTPParticipant[];
- road_conditions: string[];
- participant_categories: string[];
- weather: string[];
- nearby: string[];
- tags: string[];
- datetime: string;
- address: string;
- severity: DtpSeverityType;
- light: DTPLight;
- category: string;
-};
-
-export type DTPVehicle = {
- brand: string;
- color: string;
- model: string;
- category: string;
- year: number;
- participants: DTPParticipant[];
-};
-
-export type DTPParticipant = {
- role: string;
- gender: string;
- violations: string[];
- health_status: string;
- years_of_driving_experience?: number;
-};
diff --git a/features/DTP/dtpParticipantType.ts b/features/DTP/dtpParticipantType.ts
deleted file mode 100644
index 09750440..00000000
--- a/features/DTP/dtpParticipantType.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export enum DtpParticipantType {
- Pedestrians = 'Пешеходы',
- Cyclists = 'Велосипедисты',
- Motorcyclists = 'Мотоциклисты',
- PublicTransport = 'Общ. транспорт',
- Children = 'Дети',
- Auto = 'Все участники',
-}
diff --git a/features/DTP/dtpSeverityType.ts b/features/DTP/dtpSeverityType.ts
deleted file mode 100644
index e716942e..00000000
--- a/features/DTP/dtpSeverityType.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export enum DtpSeverityType {
- Light = 'Легкий',
- Heavy = 'Тяжёлый',
- WithDead = 'С погибшими',
-}
diff --git a/features/DesignCode/CardContent/CardContent.tsx b/features/DesignCode/CardContent/CardContent.tsx
deleted file mode 100644
index d60a1910..00000000
--- a/features/DesignCode/CardContent/CardContent.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import { Header } from 'components/Card/components/Header/Header';
-import { Label } from 'shared/UI/Label/Label';
-import { Section } from 'components/Card/components/Section/Section';
-import { DESIGN_MAP_HOST } from 'features/DesignCode/designCode';
-import styles from 'styles/CardContent.module.css';
-import { Sources } from 'components/Card/components/Sources/Sources';
-import { SOURCES_BY_TYPE } from 'constants/sources';
-import { SourceType } from 'types/Sources.types';
-import { DesignCodeObject } from '../designCodeObject';
-import { DESIGN_CODE_ITEMS_COLORS } from '../DesignCode.constants';
-
-export function DesignCodeCardContent({ placemark }: { placemark?: DesignCodeObject }) {
- return placemark ? (
-
-
- {placemark.street && (
-
{placemark.street}
- )}
-
-
- {placemark.images.map((image) => {
- const imageData = image.m || image.s;
- const imageSrc = `${DESIGN_MAP_HOST}${imageData.src}`;
-
- return (
-
-
-
- );
- })}
-
-
-
- ) : null;
-}
diff --git a/features/DesignCode/DesignCode.constants.ts b/features/DesignCode/DesignCode.constants.ts
deleted file mode 100644
index 9dc9a1a4..00000000
--- a/features/DesignCode/DesignCode.constants.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { DesignCodeItemType } from './designCodeObject';
-
-export const DESIGN_CODE_ITEMS_COLORS = {
- [DesignCodeItemType.AddressPlate]: '#ff640a',
- [DesignCodeItemType.ChoPlate]: '#e63223',
- [DesignCodeItemType.CommemorativePlaque]: '#f758b6',
- [DesignCodeItemType.HistoricAddressPlate]: '#aa9b46',
- [DesignCodeItemType.LogosAndIdentic]: '#00b400',
- [DesignCodeItemType.NavigationStela]: '#ffd400',
- [DesignCodeItemType.OKN]: '#00b4ff',
- [DesignCodeItemType.StopFreeze]: '#55647d',
- [DesignCodeItemType.StreetFurniture]: '#5820e4',
- [DesignCodeItemType.TrafficLight]: '#965a14',
- [DesignCodeItemType.Transport]: '#006d4e',
- [DesignCodeItemType.WallPlate]: '#a00041',
- [DesignCodeItemType.ColumnsWithArrows]: '#86e621',
-};
diff --git a/features/DesignCode/DesignCodeSource.tsx b/features/DesignCode/DesignCodeSource.tsx
deleted file mode 100644
index e5680cff..00000000
--- a/features/DesignCode/DesignCodeSource.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-import React, { useEffect } from 'react';
-import { useMap, Source, Layer, Marker, CircleLayer } from 'react-map-gl';
-import { useSelector } from 'react-redux';
-import classNames from 'classnames';
-import { activeFilterSelector, activeFilterParamsSelector } from 'state/features/selectors';
-import { FilterType } from 'types/Filters.types';
-import { DESIGN_CODE_ITEMS_COLORS } from 'features/DesignCode/DesignCode.constants';
-import { MapItemType } from 'types/Content.types';
-import { DESIGN_MAP_HOST } from 'features/DesignCode/designCode';
-import { getLayerStyle } from 'features/Map/helpers/getFeatureState';
-import geojson from 'public/ekb-design-code.json';
-import { usePopup } from 'features/Map/providers/usePopup';
-import useMapObjectState from 'features/Map/helpers/useMapObjectState';
-import styles from './DesignCodeMarker.module.css';
-
-const DESIGN_CODE_LAYER_ID = 'design-code-point';
-
-const DESIGN_CODE_MARKER_CLICKABLE_SIZE = 22;
-const DESIGN_CODE_MARKER_IMAGE_SIZE = 40;
-
-export function DesignCodeSource() {
- const ekbMap = useMap();
- const { popupId, openPopup } = usePopup();
- const activeFilter = useSelector(activeFilterSelector);
- const activeFilterParams = useSelector(activeFilterParamsSelector);
-
- useMapObjectState(DESIGN_CODE_LAYER_ID);
-
- useEffect(() => {
- ekbMap?.current?.on?.('click', DESIGN_CODE_LAYER_ID, (e) => {
- const item = e.target.queryRenderedFeatures(e.point)[0];
- openPopup(item.properties?.id, MapItemType.DesignCode);
- });
- }, [ekbMap, openPopup]);
-
- if (activeFilter !== FilterType.DesignCode || !activeFilterParams) {
- return null;
- }
-
- const items = geojson.features.filter((item) => activeFilterParams[item.properties.type]);
-
- const fakeClickableMarkersLayerStyle: CircleLayer = {
- id: DESIGN_CODE_LAYER_ID,
- type: 'circle',
- source: 'ekb-design-code-source',
- paint: {
- 'circle-radius': getLayerStyle({
- initial: DESIGN_CODE_MARKER_CLICKABLE_SIZE,
- hover: DESIGN_CODE_MARKER_CLICKABLE_SIZE * 1.2,
- active: DESIGN_CODE_MARKER_CLICKABLE_SIZE * 1.3,
- }),
- 'circle-opacity': 1,
- },
- };
-
- return (
-
-
- {items.map((feature) => (
-
-
-
- ))}
-
- );
-}
diff --git a/features/DesignCode/Filter/DesignCodeFilter.module.css b/features/DesignCode/Filter/DesignCodeFilter.module.css
deleted file mode 100644
index 699500aa..00000000
--- a/features/DesignCode/Filter/DesignCodeFilter.module.css
+++ /dev/null
@@ -1,12 +0,0 @@
-.DesignCodeFilter__objectsCount {
- color: #9baac3;
- margin-left: 8px;
-}
-
-.DesignCodeFilter__checkboxContent {
- width: 100%;
-
- &:not(:last-of-type) {
- margin-bottom: 14px;
- }
-}
diff --git a/features/DesignCode/Filter/DesignCodeFilter.state.ts b/features/DesignCode/Filter/DesignCodeFilter.state.ts
deleted file mode 100644
index 55063377..00000000
--- a/features/DesignCode/Filter/DesignCodeFilter.state.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { DesignCodeItemType } from '../designCodeObject';
-import { DesignCodeFilterState, DesignCodeFilterAction } from './DesignCodeFilter.types';
-
-export function designCodeReducer(state: DesignCodeFilterState, action: DesignCodeFilterAction) {
- switch (action.type) {
- case 'toggle':
- return { ...state, [action.designCodeItemType]: !state[action.designCodeItemType] };
- default:
- return state;
- }
-}
-
-export const designCondeInitalState = Object.values(DesignCodeItemType).reduce((acc, type) => {
- acc[type] = true;
-
- return acc;
-}, {} as DesignCodeFilterState);
diff --git a/features/DesignCode/Filter/DesignCodeFilter.tsx b/features/DesignCode/Filter/DesignCodeFilter.tsx
deleted file mode 100644
index a051adc8..00000000
--- a/features/DesignCode/Filter/DesignCodeFilter.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import React, { useCallback, useEffect, useReducer } from 'react';
-import { useDispatch } from 'react-redux';
-import groupBy from 'lodash/groupBy';
-import { Checkbox } from 'shared/UI/Checkbox/Checkbox';
-import { FilterType } from 'types/Filters.types';
-import { setFilter } from 'state/features/dataLayers';
-
-import designCode from 'public/ekb-design-code.json';
-import { DESIGN_CODE_ITEMS_COLORS } from '../DesignCode.constants';
-import { DesignCodeItemType } from '../designCodeObject';
-import { designCodeReducer, designCondeInitalState } from './DesignCodeFilter.state';
-import styles from './DesignCodeFilter.module.css';
-
-const DESIGN_CODE_ITEMS = groupBy(designCode.features, (item) => item.properties.type);
-
-export function DesignCodeFilter() {
- const dispatch = useDispatch();
- const [designCodeFilterState, dispatchDesignCodeAction] = useReducer(
- designCodeReducer,
- designCondeInitalState,
- );
-
- const onChange = useCallback(
- (designCodeItemType: DesignCodeItemType) => async () => {
- dispatchDesignCodeAction({ type: 'toggle', designCodeItemType });
- },
- [],
- );
-
- useEffect(() => {
- dispatch(
- setFilter({
- activeFilter: FilterType.DesignCode,
- activeFilterParams: designCodeFilterState,
- }),
- );
- }, [designCodeFilterState, dispatch]);
-
- return (
-
- {Object.entries(DESIGN_CODE_ITEMS).map(([type, items], i) => (
-
- {type}
- {items.length}
-
- ))}
-
- );
-}
diff --git a/features/DesignCode/Filter/DesignCodeFilter.types.ts b/features/DesignCode/Filter/DesignCodeFilter.types.ts
deleted file mode 100644
index 2c0d0807..00000000
--- a/features/DesignCode/Filter/DesignCodeFilter.types.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { DesignCodeItemType } from '../designCodeObject';
-
-export type DesignCodeFilterState = Record;
-export interface DesignCodeFilterAction {
- type: 'toggle';
- designCodeItemType: DesignCodeItemType;
-}
diff --git a/features/DesignCode/designCode.ts b/features/DesignCode/designCode.ts
deleted file mode 100644
index ab00bd47..00000000
--- a/features/DesignCode/designCode.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import groupBy from 'lodash/groupBy';
-import dtp from 'public/ekb-design-code.json';
-import { DesignCodeItemType, DesignCodeObject } from './designCodeObject';
-
-export const DESIGN_MAP_HOST = 'https://map.ekaterinburg.design';
-
-const designByType = Object.entries(groupBy(dtp.features, (item) => item.properties.type))
- .map(([type, items]) => [type, items.length])
- .sort((a, b) => (b[1] as number) - (a[1] as number));
-
-export const designCode = {
- getObject(id: string): Promise {
- try {
- const result = dtp.features.find((item) => item.properties.id === id);
-
- // @ts-ignore
- return Promise.resolve({
- ...result.properties,
- street: result.properties.street,
- type: result.properties.type as DesignCodeItemType,
- coords: [result.geometry.coordinates[0], result.geometry.coordinates[1]],
- });
- } catch (error) {
- console.error(error);
- return Promise.resolve(null);
- }
- },
- async getObjectsCount() {
- return designByType;
- },
-};
diff --git a/features/DesignCode/designCodeObject.ts b/features/DesignCode/designCodeObject.ts
deleted file mode 100644
index fc8f49ca..00000000
--- a/features/DesignCode/designCodeObject.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { Image } from 'types/ObjectsBase.types';
-
-export enum DesignCodeItemType {
- LogosAndIdentic = 'Логотипы и айдентика',
- NavigationStela = 'Навигационные стелы',
- OKN = 'Таблички ОКН',
- ChoPlate = 'Таблички ЧО',
- AddressPlate = 'Обычные адресные таблички',
- StopFreeze = 'Фризы остановок',
- TrafficLight = 'Светофор',
- HistoricAddressPlate = 'Исторические адресные таблички',
- StreetFurniture = 'Уличная мебель',
- CommemorativePlaque = 'Памятные таблички',
- Transport = 'Транспорт',
- WallPlate = 'Настенные таблички',
- ColumnsWithArrows = 'Столбы со стрелками',
-}
-
-export interface DesignCodeObject {
- id: string;
- name: string;
- type: DesignCodeItemType;
- description: string;
- coords: [lat: number, lng: number];
- street: string;
- images: Image[];
- preview: Image;
-}
diff --git a/features/EditObjectButtonLink/EditObjectButtonLink.tsx b/features/EditObjectButtonLink/EditObjectButtonLink.tsx
deleted file mode 100644
index 4635369a..00000000
--- a/features/EditObjectButtonLink/EditObjectButtonLink.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import React from 'react';
-import { ButtonLink } from 'shared/UI/ButtonLink/ButtonLink';
-import { IconType } from 'shared/UI/Icons/Icons.types';
-
-const getEditObjectLink = (address: string) =>
- `https://tally.so#tally-open=w2BoVe&tally-width=650&tally-overlay=1&tally-emoji-animation=none&address=${address}`;
-
-type TEditObjectButtonLinkProps = {
- text?: string;
- address: string;
-};
-
-export function EditObjectButtonLink({
- text = 'Дополнить или поправить',
- address,
-}: TEditObjectButtonLinkProps) {
- return ;
-}
diff --git a/features/Facade/CardContent/Facade.module.css b/features/Facade/CardContent/Facade.module.css
deleted file mode 100644
index c8b0c5b1..00000000
--- a/features/Facade/CardContent/Facade.module.css
+++ /dev/null
@@ -1,12 +0,0 @@
-.facade {
- display: flex;
- gap: 8px;
- flex-direction: column;
-}
-
-.facade_title {
- font-size: 16px;
- line-height: 1.3;
- font-weight: 400;
- margin: 0;
-}
diff --git a/features/Facade/CardContent/Facade.tsx b/features/Facade/CardContent/Facade.tsx
deleted file mode 100644
index 4c29234e..00000000
--- a/features/Facade/CardContent/Facade.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import { DownloadButton } from 'shared/UI/DownloadButton/DownloadButton';
-import styles from './Facade.module.css';
-
-type Props = {
- facade: {
- name: string;
- link: string;
- };
-};
-
-export default function Facade({ facade }: Props) {
- return (
-
-
Дизайн-код фасада
-
-
- );
-}
diff --git a/features/Facade/FacadeSource.tsx b/features/Facade/FacadeSource.tsx
deleted file mode 100644
index 33320348..00000000
--- a/features/Facade/FacadeSource.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-import { useEffect } from 'react';
-import { useMap } from 'react-map-gl';
-import { useSelector } from 'react-redux';
-import { getLayerStyle } from 'features/Map/helpers/getFeatureState';
-import { BUILDING_LAYER_ID } from 'constants/map';
-import { DEFAULT_BULDING_COLOR_NORMAL } from 'constants/colors';
-import { activeFilterSelector } from 'state/features/selectors';
-import { FilterType } from 'types/Filters.types';
-import facades from 'public/ekb-facades.json';
-import useMapObjectState from 'features/Map/helpers/useMapObjectState';
-
-const FACADES_IDS = Object.keys(facades);
-
-function FacadeStyles() {
- const ekbMap = useMap();
-
- useEffect(() => {
- const map = ekbMap?.current?.getMap?.();
-
- map.setStyle({
- ...map?.getStyle(),
- layers: map?.getStyle().layers.map((layer) => {
- if (layer.id === BUILDING_LAYER_ID) {
- return {
- ...layer,
- paint: {
- // @ts-ignore
- ...layer.paint,
- 'fill-extrusion-color': [
- 'match',
- ['get', 'osm:id'],
- ['literal'].concat(FACADES_IDS),
- getLayerStyle({
- initial: 'rgba(129, 255, 0, 0.75)',
- hover: 'rgba(129, 255, 0, 0.90)',
- active: 'rgba(129, 255, 0, 1)',
- }),
- DEFAULT_BULDING_COLOR_NORMAL,
- ],
- },
- };
- }
- return layer;
- }),
- });
- }, [ekbMap]);
-
- useMapObjectState('building');
-
- return null;
-}
-
-export function FacadeSource() {
- const activeFilter = useSelector(activeFilterSelector);
-
- if (activeFilter !== FilterType.HouseFacades) {
- return null;
- }
-
- return ;
-}
diff --git a/components/Footer/Footer.module.css b/features/Footer/Footer.module.css
similarity index 100%
rename from components/Footer/Footer.module.css
rename to features/Footer/Footer.module.css
diff --git a/components/Footer/Footer.tsx b/features/Footer/Footer.tsx
similarity index 100%
rename from components/Footer/Footer.tsx
rename to features/Footer/Footer.tsx
diff --git a/features/HouseAge/HouseAgeFilter.tsx b/features/HouseAge/HouseAgeFilter.tsx
deleted file mode 100644
index 04d6f36e..00000000
--- a/features/HouseAge/HouseAgeFilter.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import React, { useCallback } from 'react';
-import { useDispatch } from 'react-redux';
-import { MinMax } from 'shared/UI/RangeHistogram/types';
-import { houseBase } from 'features/Buildings/houseBase';
-import { AGE_FILTERS_DATA, HouseSourceType } from 'features/Buildings/Houses.constants';
-import { setFilterParams } from 'state/features/dataLayers';
-import { HouseBaseFilter } from '../Buildings/Filter/HouseBaseFilter';
-
-export const EKATERINBURG_FOUNDATION_YEAR = 1723;
-
-export const CURRENT_YEAR = new Date().getFullYear();
-
-export function HouseAgeFilter() {
- const dispatch = useDispatch();
-
- const getHouses = useCallback(
- async (range: MinMax) => {
- dispatch(setFilterParams({ activeFilterParams: range }));
- },
- [dispatch],
- );
-
- const getHistogramData = useCallback(
- async () =>
- houseBase.getFilterValues(AGE_FILTERS_DATA, HouseSourceType.Year).then((values) =>
- AGE_FILTERS_DATA.map((ageItemData, idx) => ({
- ...ageItemData,
- value: values[idx],
- })),
- ),
- [],
- );
-
- return (
-
- );
-}
diff --git a/features/HouseFloor/HouseFloorFilter.tsx b/features/HouseFloor/HouseFloorFilter.tsx
deleted file mode 100644
index c4066ef1..00000000
--- a/features/HouseFloor/HouseFloorFilter.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import React, { useCallback } from 'react';
-import { useDispatch } from 'react-redux';
-
-import { MinMax } from 'shared/UI/RangeHistogram/types';
-import { houseBase } from 'features/Buildings/houseBase';
-import { setFilterParams } from 'state/features/dataLayers';
-
-import { FLOOR_FILTERS_DATA, HouseSourceType } from 'features/Buildings/Houses.constants';
-import { HouseBaseFilter } from '../Buildings/Filter/HouseBaseFilter';
-
-export const MIN_FLOOR = 1;
-export const MAX_FLOOR = 52;
-
-export function HouseFloorFilter() {
- const dispatch = useDispatch();
-
- const getHouses = useCallback(
- async (range: MinMax) => {
- dispatch(setFilterParams({ activeFilterParams: range }));
- },
- [dispatch],
- );
-
- const getHistogramData = useCallback(
- async () =>
- houseBase.getFilterValues(FLOOR_FILTERS_DATA, HouseSourceType.Floors).then((values) =>
- FLOOR_FILTERS_DATA.map((floorItemData, idx) => ({
- ...floorItemData,
- value: values[idx],
- })),
- ),
- [],
- );
-
- return (
-
- );
-}
diff --git a/features/HouseWearTear/HouseWearTearFilter.tsx b/features/HouseWearTear/HouseWearTearFilter.tsx
deleted file mode 100644
index 575b1d61..00000000
--- a/features/HouseWearTear/HouseWearTearFilter.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import React, { useCallback } from 'react';
-import { useDispatch } from 'react-redux';
-import { HouseBaseFilter } from 'features/Buildings/Filter/HouseBaseFilter';
-import { houseBase } from 'features/Buildings/houseBase';
-import { HouseSourceType, WEAR_TEAR_FILTERS_DATA } from 'features/Buildings/Houses.constants';
-import { MinMax } from 'shared/UI/RangeHistogram/types';
-import { setFilterParams } from 'state/features/dataLayers';
-
-export function HouseWearTearFilter() {
- const dispatch = useDispatch();
-
- const getHouses = useCallback(
- async (range: MinMax) => {
- dispatch(setFilterParams({ activeFilterParams: range }));
- },
- [dispatch],
- );
-
- const getHistogramData = useCallback(
- async () =>
- houseBase
- .getFilterValues(WEAR_TEAR_FILTERS_DATA, HouseSourceType.WearAndTear)
- .then((values) =>
- WEAR_TEAR_FILTERS_DATA.map((floorItemData, idx) => ({
- ...floorItemData,
- value: values[idx],
- })),
- ),
- [],
- );
-
- return (
-
- );
-}
diff --git a/features/Lines/CardContent/CardContent.tsx b/features/Lines/CardContent/CardContent.tsx
deleted file mode 100644
index 3c20c77b..00000000
--- a/features/Lines/CardContent/CardContent.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import React from 'react';
-import { Header } from 'components/Card/components/Header/Header';
-import { Section } from 'components/Card/components/Section/Section';
-import { Link } from 'shared/UI/Link/Link';
-import styles from 'styles/CardContent.module.css';
-import { LineObject } from '../lineType';
-
-type TLinesCardContentProps = {
- placemark?: LineObject;
-};
-
-export function LinesCardContent({ placemark }: TLinesCardContentProps) {
- if (!placemark) return null;
-
- return (
-
-
- {placemark.properties.description?.startsWith('http') && (
-
- )}
-
- );
-}
diff --git a/features/Lines/Filter/LinesFilter.module.css b/features/Lines/Filter/LinesFilter.module.css
deleted file mode 100644
index d03be0da..00000000
--- a/features/Lines/Filter/LinesFilter.module.css
+++ /dev/null
@@ -1,12 +0,0 @@
-.LinesFilter__objectsCount {
- margin-left: 8px;
- color: #9baac3;
-}
-
-.LinesFilter__checkboxContent:not(:last-of-type) {
- margin-bottom: 14px;
-}
-
-.LinesFilter__description {
- color: #9baac3;
-}
diff --git a/features/Lines/Filter/LinesFilter.state.ts b/features/Lines/Filter/LinesFilter.state.ts
deleted file mode 100644
index 0508d6ad..00000000
--- a/features/Lines/Filter/LinesFilter.state.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { LineType } from '../lineType';
-import { LinesState, LinesAction } from './LinesFilter.types';
-
-export function linesReducer(state: LinesState, action: LinesAction) {
- switch (action.type) {
- case 'toggle':
- return { ...state, [action.lineType]: !state[action.lineType] };
- default:
- return state;
- }
-}
-
-export const linesInitalState = Object.values(LineType).reduce((acc, type) => {
- acc[type] = true;
-
- return acc;
-}, {} as LinesState);
diff --git a/features/Lines/Filter/LinesFilter.tsx b/features/Lines/Filter/LinesFilter.tsx
deleted file mode 100644
index a2740d88..00000000
--- a/features/Lines/Filter/LinesFilter.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-import React, { useCallback, useEffect, useReducer, useState } from 'react';
-import { useDispatch } from 'react-redux';
-
-import { setFilter } from 'state/features/dataLayers';
-import { FilterType } from 'types/Filters.types';
-import { lines } from 'features/Lines/lines';
-import { Checkbox } from 'shared/UI/Checkbox/Checkbox';
-import { FilterLoader } from 'shared/UI/Loader/FilterLoader';
-
-import { LineType } from '../lineType';
-import { LINES_CONFIG } from '../Lines.constants';
-import { linesInitalState, linesReducer } from './LinesFilter.state';
-import styles from './LinesFilter.module.css';
-
-type LinesCountEntries = [LineType, number][];
-
-export function LinesFilter() {
- const dispatch = useDispatch();
- const [linesState, dispatchLines] = useReducer(linesReducer, linesInitalState);
- const [linesCount, setLinesCount] = useState(null);
-
- useEffect(() => {
- lines.getFilters().then((linesFilters: LinesCountEntries) => {
- const sortedLinesCount = linesFilters.sort(([, countA], [, countB]) => countB - countA);
-
- setLinesCount(sortedLinesCount);
- });
- }, []);
-
- useEffect(() => {
- dispatch(
- setFilter({
- activeFilter: FilterType.Line,
- activeFilterParams: linesState,
- }),
- );
- }, [dispatch, linesState]);
-
- const onLinesChange = useCallback(
- (lineType: LineType) => () => {
- dispatchLines({ type: 'toggle', lineType });
- },
- [],
- );
-
- if (!linesCount) return ;
-
- return (
- <>
- {linesCount.map(([type, count], i) => (
-
- {type}
- {count}
-
-
- {LINES_CONFIG[type].description}
-
-
- ))}
- >
- );
-}
diff --git a/features/Lines/Filter/LinesFilter.types.ts b/features/Lines/Filter/LinesFilter.types.ts
deleted file mode 100644
index 54877233..00000000
--- a/features/Lines/Filter/LinesFilter.types.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { LineType } from '../lineType';
-
-export interface LinesAction {
- type: 'toggle';
- lineType: LineType;
-}
-
-export type LinesState = Record;
diff --git a/features/Lines/Lines.constants.ts b/features/Lines/Lines.constants.ts
deleted file mode 100644
index 82e96aa2..00000000
--- a/features/Lines/Lines.constants.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { LineType } from './lineType';
-
-export const LINES_CONFIG = {
- [LineType.RedLine]: {
- color: '#e31e24',
- description: 'Маршрут по\u00A0историческому центру города',
- },
- [LineType.BlueLine]: {
- color: '#189eda',
- description: 'Маршрут по\u00A0местам, связанным с\u00A0царской семьей',
- },
- [LineType.PurpleLine]: {
- color: '#9747ff',
- description: 'Арт-объекты фестиваля уличного искусства «Стенограффия»',
- },
-};
diff --git a/features/Lines/LinesSource.tsx b/features/Lines/LinesSource.tsx
deleted file mode 100644
index bb546746..00000000
--- a/features/Lines/LinesSource.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-import React, { useEffect } from 'react';
-import { Source, Layer, useMap } from 'react-map-gl';
-import type { CircleLayer, LineLayer } from 'react-map-gl';
-import { useSelector } from 'react-redux';
-import { activeFilterSelector, activeFilterParamsSelector } from 'state/features/selectors';
-import { FilterType } from 'types/Filters.types';
-import { LINES_CONFIG } from 'features/Lines/Lines.constants';
-import { MapItemType } from 'types/Content.types';
-import { usePopup } from 'features/Map/providers/usePopup';
-import { getLayerStyle } from 'features/Map/helpers/getFeatureState';
-import { LineType } from 'features/Lines/lineType';
-import useMapObjectState from 'features/Map/helpers/useMapObjectState';
-
-export function LinesSource() {
- const ekbMap = useMap();
- const { openPopup } = usePopup();
- const activeFilter = useSelector(activeFilterSelector);
- const activeFilterParams = useSelector(activeFilterParamsSelector);
-
- useMapObjectState('ekb-points-layer');
-
- useEffect(() => {
- ekbMap?.current?.on?.('click', 'ekb-points-layer', (e) => {
- const item = e.target.queryRenderedFeatures(e.point)[0];
- const lineType = item.properties.type;
- if (lineType === LineType.RedLine) {
- openPopup(item.properties?.id, MapItemType.RedLines);
- }
- if (lineType === LineType.PurpleLine) {
- openPopup(item.properties?.id, MapItemType.PinkLines);
- }
- if (lineType === LineType.BlueLine) {
- openPopup(item.properties?.id, MapItemType.BlueLines);
- }
- });
- }, [ekbMap, openPopup]);
-
- if (activeFilter !== FilterType.Line || !activeFilterParams) {
- return null;
- }
-
- const activeItems = Object.entries(activeFilterParams)
- .filter(([, value]) => value)
- .map(([type]) => [type, LINES_CONFIG[type]]);
-
- const colors = activeItems.map(([type, { color }]) => [['==', ['get', 'type'], type], color]);
-
- const strokeColors = activeItems.map(([type]) => [['==', ['get', 'type'], type], '#000']);
-
- const pointLayerStyle: CircleLayer = {
- id: 'ekb-points-layer',
- type: 'circle',
- source: 'ekb-points-source',
- paint: {
- 'circle-radius': getLayerStyle({ initial: 8, hover: 10, active: 12 }),
- // @ts-ignore
- 'circle-color': ['case'].concat(...colors).concat(['rgba(0, 0, 0, 0)']),
- 'circle-stroke-width': 1,
- // @ts-ignore
- 'circle-stroke-color': ['case'].concat(...strokeColors).concat(['rgba(0, 0, 0, 0)']),
- },
- };
-
- const linesLayerStyle: LineLayer = {
- id: 'lines',
- type: 'line',
- source: 'ekb-lines-source',
- paint: {
- // @ts-ignore
- 'line-color': ['case'].concat(...colors).concat(['rgba(0, 0, 0, 0)']),
- 'line-width': 3,
- },
- };
-
- return (
- <>
-
-
-
-
-
-
- >
- );
-}
diff --git a/features/Lines/lineType.ts b/features/Lines/lineType.ts
deleted file mode 100644
index eb5d96ad..00000000
--- a/features/Lines/lineType.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-export enum LineType {
- RedLine = 'Красная линия',
- BlueLine = 'Синяя линия',
- PurpleLine = 'Фиолетовая линия',
-}
-
-export interface LineObject {
- properties: {
- id: number;
- title?: string;
- description: null | string;
- };
- geometry: {
- id: string;
- coordinates: [lat: number, lng: number];
- type?: string;
- };
-}
diff --git a/features/Lines/lines.ts b/features/Lines/lines.ts
deleted file mode 100644
index 4e97720c..00000000
--- a/features/Lines/lines.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import groupBy from 'lodash/groupBy';
-import data from 'public/ekb-color-points.json';
-
-const linesByType = Object.entries(groupBy(data.features, (item) => item.properties.type))
- .map(([type, items]) => [type, items.length])
- .sort((a, b) => (b[1] as number) - (a[1] as number));
-
-export const lines = {
- async getObject(id: string): Promise {
- return data.features.find((f) => String(f.properties.id) === id);
- },
-
- async getFilters() {
- return Promise.resolve(linesByType);
- },
-};
diff --git a/features/Map/Map.tsx b/features/Map/Map.tsx
deleted file mode 100644
index 965c0de3..00000000
--- a/features/Map/Map.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-'use client';
-
-import { useContext } from 'react';
-
-import maplibregl from 'maplibre-gl';
-import MapGl from 'react-map-gl';
-import { MAX_ZOOM, MIN_ZOOM, CENTER_COORDS } from 'constants/map';
-
-import { BuildingSource } from 'features/Buildings/BuildingSource';
-import { DesignCodeSource } from 'features/DesignCode/DesignCodeSource';
-import { DtpSource } from 'features/DTP/DtpSource';
-import { LinesSource } from 'features/Lines/LinesSource';
-import { OknSource } from 'features/OKN/OknSource';
-import { QuarterSource } from 'features/Quarter/QuarterSource';
-import { FacadeSource } from 'features/Facade/FacadeSource';
-import { MapContext } from './providers/MapProvider';
-
-import 'maplibre-gl/dist/maplibre-gl.css';
-
-function MapLayers() {
- return (
- <>
-
-
-
-
-
-
-
- >
- );
-}
-
-export function Map() {
- const { loading, setLoading } = useContext(MapContext);
-
- return (
- setLoading(false)}
- // Disable RTL plugin
- RTLTextPlugin={null}
- >
- {!loading && }
-
- );
-}
diff --git a/features/Map/helpers/colorLuminance.ts b/features/Map/helpers/colorLuminance.ts
deleted file mode 100644
index dfb234e4..00000000
--- a/features/Map/helpers/colorLuminance.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-export function colorLuminance(hexColor: string, luminance: number) {
- const hex = hexColor.replace(/[^0-9a-f]/gi, '');
- let color = '#';
-
- for (let i = 0; i < 3; i++) {
- let component = parseInt(hex.substr(i * 2, 2), 16);
- component = Math.round(Math.min(Math.max(0, component + component * luminance), 255));
- const hexComponent = component.toString(16).padStart(2, '0');
- color += hexComponent;
- }
-
- return color;
-}
diff --git a/features/Map/helpers/getFeatureState.ts b/features/Map/helpers/getFeatureState.ts
deleted file mode 100644
index 9b871e87..00000000
--- a/features/Map/helpers/getFeatureState.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import type {
- DataDrivenPropertyValueSpecification,
- ExpressionInputType,
- ExpressionSpecification,
-} from 'maplibre-gl';
-
-export function getLayerStyle({
- initial,
- active,
- hover,
-}: {
- initial: T;
- active?: T;
- hover: T;
-}): DataDrivenPropertyValueSpecification {
- return [
- 'case',
- ['boolean', ['feature-state', 'active'], false],
- active,
- ['boolean', ['feature-state', 'hover'], false],
- hover,
- initial,
- ];
-}
diff --git a/features/Map/helpers/useMapObjectState.ts b/features/Map/helpers/useMapObjectState.ts
deleted file mode 100644
index 6d2177d0..00000000
--- a/features/Map/helpers/useMapObjectState.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import { FeatureIdentifier } from 'maplibre-gl';
-import { MapRef, useMap } from 'react-map-gl';
-import { useEffect, useRef } from 'react';
-
-function setObjectState(
- map: MapRef,
- mapObject: FeatureIdentifier,
- settings: { [key: string]: boolean },
- cursorPointer = true,
-) {
- map.getCanvas().style.cursor = cursorPointer ? 'pointer' : 'default';
- map.setFeatureState(mapObject, settings);
-}
-
-function useMapObjectState(layerId: string) {
- const map = useMap().current;
- const activeObject = useRef(null);
- const hoverObject = useRef(null);
-
- const getItem = (point: mapboxgl.Point) =>
- map.queryRenderedFeatures(point, { layers: [layerId] })[0];
-
- useEffect(() => {
- const handleClick = (e: mapboxgl.MapMouseEvent) => {
- const item = getItem(e.point);
- if (activeObject.current && item.id !== activeObject.current.id) {
- setObjectState(map, activeObject.current, { active: false });
- activeObject.current = null;
- }
-
- if (item) {
- activeObject.current = item;
- setObjectState(map, activeObject.current, { active: true });
- }
- };
-
- const handleMouseMove = (e: mapboxgl.MapMouseEvent) => {
- const item = getItem(e.point);
- if (item) {
- if (hoverObject.current && item.id !== hoverObject.current.id) {
- setObjectState(map, hoverObject.current, { hover: false }, false);
- }
- hoverObject.current = item;
- setObjectState(map, item, { hover: true });
- }
- };
-
- const handleMouseLeave = () => {
- if (hoverObject?.current?.id) {
- setObjectState(map, hoverObject.current, { hover: false }, false);
- }
- hoverObject.current = null;
- };
-
- map.on('click', layerId, handleClick);
- map.on('mousemove', layerId, handleMouseMove);
- map.on('mouseleave', layerId, handleMouseLeave);
-
- return () => {
- map.off('click', layerId, handleClick);
- map.off('mousemove', layerId, handleMouseMove);
- map.off('mouseleave', layerId, handleMouseLeave);
- };
- });
-
- return hoverObject.current;
-}
-
-export default useMapObjectState;
diff --git a/features/Map/providers/MapProvider.tsx b/features/Map/providers/MapProvider.tsx
deleted file mode 100644
index 17daa9fc..00000000
--- a/features/Map/providers/MapProvider.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import React, { ReactNode, useMemo, useState } from 'react';
-import { MapItemType } from 'types/Content.types';
-import { usePopup } from './usePopup';
-
-export interface IMapContext {
- popupId: string | null;
- popupType: MapItemType | null;
- openPopup: (p: string, t: MapItemType) => void;
- closePopup: VoidFunction;
- loading: boolean;
- setLoading: (l: boolean) => void;
-}
-
-export const MapContext = React.createContext({
- popupId: null,
- popupType: null,
- openPopup: () => {},
- closePopup: () => {},
- loading: true,
- setLoading: () => {},
-});
-
-interface Props {
- children: ReactNode;
-}
-
-export function MapContextProvider({ children }: Props) {
- const [loading, setLoading] = useState(true);
- const { popupId, popupType, openPopup, closePopup } = usePopup();
-
- const value = useMemo(
- () => ({
- popupId,
- popupType,
- openPopup,
- closePopup,
- loading,
- setLoading,
- }),
- [popupId, popupType, openPopup, closePopup, loading, setLoading],
- );
-
- return {children} ;
-}
diff --git a/features/Map/providers/usePopup.ts b/features/Map/providers/usePopup.ts
deleted file mode 100644
index 82635699..00000000
--- a/features/Map/providers/usePopup.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { useCallback, useContext, useEffect, useState } from 'react';
-import { useSelector } from 'react-redux';
-import { setHash } from 'shared/helpers/hash';
-import { activeFilterSelector } from 'state/features/selectors';
-import { AboutProjectContext } from 'features/About/AboutProjectProvider';
-import { MapItemType } from 'types/Content.types';
-
-type PopupId = string;
-
-export function usePopup() {
- const { close: closeAboutProject } = useContext(AboutProjectContext);
-
- const [popupId, setOpenedPopup] = useState(null);
- const [popupType, setPopupType] = useState(null);
-
- const activeFilter: string = useSelector(activeFilterSelector);
-
- const openPopup = useCallback(
- (id: PopupId, type: MapItemType) => {
- closeAboutProject();
- setHash(type, id, activeFilter);
- },
- [activeFilter, closeAboutProject],
- );
-
- const closePopup = useCallback(() => {
- setPopupType(null);
- setOpenedPopup(null);
-
- window.location.hash = '';
- }, []);
-
- const handleOpenPopup = useCallback(() => {
- const [type, ...id] = window.location.hash.slice(1).split('/')[0].split('-');
-
- setOpenedPopup(id.join('-'));
- setPopupType(type as MapItemType);
- }, []);
-
- useEffect(() => {
- window.addEventListener('hashchange', handleOpenPopup, false);
-
- return () => {
- window.removeEventListener('hashchange', handleOpenPopup, false);
- };
- }, [handleOpenPopup]);
-
- useEffect(() => {
- if (!window.location.hash) {
- return;
- }
-
- handleOpenPopup();
- }, [handleOpenPopup]);
-
- return {
- popupId,
- popupType,
- openPopup,
- closePopup,
- };
-}
diff --git a/features/OKN/CardContent/CardContent.module.css b/features/OKN/CardContent/CardContent.module.css
deleted file mode 100644
index 7352beca..00000000
--- a/features/OKN/CardContent/CardContent.module.css
+++ /dev/null
@@ -1,35 +0,0 @@
-.popup {
- border-top-left-radius: inherit;
- border-top-right-radius: inherit;
-}
-
-.popup__content {
- padding: 16px 8px 16px 16px;
-}
-
-.popup__address {
- margin: 8px 16px 0 0;
- font-style: normal;
- font-weight: 400;
- line-height: 20px;
- font-size: 16px;
- color: #9baac3;
-}
-
-.popup__imageLink {
- display: flex;
- border-top-left-radius: inherit;
- border-top-right-radius: inherit;
-}
-
-.popup__image {
- display: block;
- width: 100%;
- height: auto;
- min-height: 100px;
- background-color: #2e2e2e;
- border-top-left-radius: inherit;
- border-top-right-radius: inherit;
- object-fit: contain;
- object-position: top center;
-}
diff --git a/features/OKN/CardContent/CardContent.tsx b/features/OKN/CardContent/CardContent.tsx
deleted file mode 100644
index 31ad703f..00000000
--- a/features/OKN/CardContent/CardContent.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-import React, { useMemo } from 'react';
-import { Sources } from 'components/Card/components/Sources/Sources';
-import { ConstructionInfo } from 'components/Card/components/ConstructionInfo/ConstructionInfo';
-import { Header } from 'components/Card/components/Header/Header';
-import { Section } from 'components/Card/components/Section/Section';
-import { EditObjectButtonLink } from 'features/EditObjectButtonLink/EditObjectButtonLink';
-import { SOURCES_BY_TYPE } from 'constants/sources';
-import { SourceType } from 'types/Sources.types';
-import { OknObject } from '../oknObject';
-import { OKNInfo } from './components/OKNInfo/OKNInfo';
-import styles from './CardContent.module.css';
-
-export function OKNCardContent({ placemark }: { placemark: OknObject }) {
- const { title, description } = useMemo(() => {
- const indexOfComma = placemark?.properties.name?.indexOf(',') || -1;
-
- if (indexOfComma === -1) {
- return { title: placemark?.properties.name };
- }
-
- return {
- title: placemark?.properties.name.slice(0, indexOfComma),
- description: placemark?.properties.name.slice(indexOfComma + 1),
- };
- }, [placemark?.properties.name]);
-
- return placemark?.properties ? (
-
- {placemark?.properties.img && placemark?.preview && (
-
-
-
- )}
-
-
- {placemark?.properties.address && (
-
- {placemark?.properties.address}
-
- )}
- {placemark?.properties.date && (
-
- )}
-
-
- {placemark?.properties?.address && (
-
- )}
-
-
- ) : null;
-}
diff --git a/features/OKN/CardContent/index.ts b/features/OKN/CardContent/index.ts
deleted file mode 100644
index 4342f0a8..00000000
--- a/features/OKN/CardContent/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { OKNCardContent } from './CardContent';
diff --git a/features/OKN/Filter/OknFilter.module.css b/features/OKN/Filter/OknFilter.module.css
deleted file mode 100644
index 6e96fa83..00000000
--- a/features/OKN/Filter/OknFilter.module.css
+++ /dev/null
@@ -1,12 +0,0 @@
-.OknFilter__checkboxDescription {
- color: #9baac3;
-}
-
-.OknFilter__checkboxContent:not(:last-of-type) {
- margin-bottom: 14px;
-}
-
-.OknFilter__objectsCount {
- margin-left: 8px;
- color: #9baac3;
-}
diff --git a/features/OKN/Filter/OknFilter.state.ts b/features/OKN/Filter/OknFilter.state.ts
deleted file mode 100644
index 4efdad3f..00000000
--- a/features/OKN/Filter/OknFilter.state.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import { OknAreaType, OknObjectSignificanceType } from '../oknConstants';
-
-export interface AreaAction {
- type: 'toggle';
- areaType: OknAreaType;
-}
-export interface ObjectsAction {
- type: 'toggle';
- objectsType: OknObjectSignificanceType;
-}
-
-export type AreaState = Record;
-export type ObjectsState = Record;
-
-export function areaReducer(state: AreaState, action: AreaAction) {
- switch (action.type) {
- case 'toggle':
- return { ...state, [action.areaType]: !state[action.areaType] };
- default:
- return state;
- }
-}
-
-export const areaInitalState = Object.values(OknAreaType).reduce((acc, type) => {
- acc[type] = false;
-
- return acc;
-}, {} as AreaState);
-
-export function objectsReducer(state: ObjectsState, action: ObjectsAction) {
- switch (action.type) {
- case 'toggle':
- return { ...state, [action.objectsType]: !state[action.objectsType] };
- default:
- return state;
- }
-}
-
-export const objectsInitalState = Object.values(OknObjectSignificanceType).reduce((acc, type) => {
- acc[type] = true;
-
- return acc;
-}, {} as ObjectsState);
diff --git a/features/OKN/Filter/OknFilter.tsx b/features/OKN/Filter/OknFilter.tsx
deleted file mode 100644
index d0731742..00000000
--- a/features/OKN/Filter/OknFilter.tsx
+++ /dev/null
@@ -1,131 +0,0 @@
-import React, { useCallback, useEffect, useReducer, useState } from 'react';
-import { useDispatch, useSelector } from 'react-redux';
-
-import { setFilter } from 'state/features/dataLayers';
-
-import { okn } from 'features/OKN/okn';
-
-import { Checkbox } from 'shared/UI/Checkbox/Checkbox';
-import { FilterLoader } from 'shared/UI/Loader/FilterLoader';
-import { Section } from 'components/Card/components/Section/Section';
-import { FilterType } from 'types/Filters.types';
-import { activeFilterParamsSelector, activeFilterSelector } from 'state/features/selectors';
-
-import { AREA_CONFIG, OBJECTS_CONFIG } from '../Okn.constants';
-import { OknObjectSignificanceType, OknAreaType } from '../oknConstants';
-import {
- areaInitalState,
- areaReducer,
- objectsInitalState,
- objectsReducer,
-} from './OknFilter.state';
-import styles from './OknFilter.module.css';
-
-type ObjectsCountEntries = [OknObjectSignificanceType, number][];
-
-export function OknFilter() {
- const dispatch = useDispatch();
- const activeFilter = useSelector(activeFilterSelector);
- const activeFilterParams = useSelector(activeFilterParamsSelector);
- const [areaState, dispatchArea] = useReducer(areaReducer, areaInitalState);
- const [objectsState, dispatchObjects] = useReducer(objectsReducer, objectsInitalState);
- const [objectsCount, setObjectsCount] = useState(null);
- const [areaCount, setAreaCount] = useState<[OknAreaType, number][]>(null);
-
- useEffect(() => {
- okn.getObjectsCount().then((objectsCountResult: ObjectsCountEntries) => {
- const sortedObjectsCount = objectsCountResult.sort(
- ([, countA], [, countB]) => countB - countA,
- );
-
- setObjectsCount(sortedObjectsCount);
- });
- }, []);
-
- useEffect(() => {
- okn.getZonesCount().then((areaCountResult: [OknAreaType, number][]) => {
- const sortedObjectsCount = areaCountResult.sort(
- ([, countA], [, countB]) => countB - countA,
- );
-
- setAreaCount(sortedObjectsCount);
- });
- }, []);
-
- const onAreaChange = useCallback(
- (oknArea: OknAreaType) => async () => {
- dispatchArea({ type: 'toggle', areaType: oknArea });
- },
- [],
- );
-
- const onObjectsChange = useCallback(
- (oknObjectType: OknObjectSignificanceType) => async () => {
- dispatchObjects({ type: 'toggle', objectsType: oknObjectType });
- },
- [],
- );
-
- useEffect(() => {
- dispatch(
- setFilter({
- activeFilter: FilterType.OKN,
- activeFilterParams: {
- ...Object.entries(areaState).reduce(
- (all, [id, value]) => ({ ...all, [id]: { value, type: 'area' } }),
- {},
- ),
- ...Object.entries(objectsState).reduce(
- (all, [id, value]) => ({ ...all, [id]: { value, type: 'objects' } }),
- {},
- ),
- },
- }),
- );
- }, [dispatch, areaState, objectsState]);
-
- if (activeFilter !== FilterType.OKN && !activeFilterParams.filter) {
- return null;
- }
-
- if (!(objectsCount && areaCount)) {
- return ;
- }
-
- return (
- <>
- {objectsCount?.map(([type, count], i) => (
-
- {type}
- {count}
-
- ))}
-
- {areaCount?.map(([type, count], i) => (
-
- {type}
- {count}
-
-
- {AREA_CONFIG[type].description}
-
-
- ))}
-
- >
- );
-}
diff --git a/features/OKN/Okn.constants.ts b/features/OKN/Okn.constants.ts
deleted file mode 100644
index e254db9b..00000000
--- a/features/OKN/Okn.constants.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { OknObjectSignificanceType, OknAreaType } from './oknConstants';
-
-export const OBJECTS_CONFIG = {
- [OknObjectSignificanceType.Federal]: {
- color: '#e65000',
- },
- [OknObjectSignificanceType.Regional]: {
- color: '#ae00ff',
- },
- [OknObjectSignificanceType.Municipal]: {
- color: '#03a600',
- },
-};
-
-export const AREA_CONFIG = {
- [OknAreaType.ObjectZone]: {
- color: '#ff640f',
- description: 'Объект культурного наследия и\u00A0неотделимая от\u00A0него территория',
- },
- [OknAreaType.SecurityZone]: {
- color: '#00b4ff',
- description:
- 'Территории, в\u00A0пределах которых запрещены любые работы, так как они могут причинить вред объекту',
- },
- [OknAreaType.ProtectZone]: {
- color: '#e800b5',
- description:
- 'Временная зона в\u00A0100\u2013250 метров вокруг объекта, у\u00A0которого пока не\u00A0указана зона охраны',
- },
-};
diff --git a/features/OKN/OknSource.tsx b/features/OKN/OknSource.tsx
deleted file mode 100644
index 8ed6714a..00000000
--- a/features/OKN/OknSource.tsx
+++ /dev/null
@@ -1,191 +0,0 @@
-import { Source, Layer, useMap } from 'react-map-gl';
-import { useSelector } from 'react-redux';
-import React, { useEffect } from 'react';
-import { CircleLayer, FillLayer, LineLayer, Marker } from 'react-map-gl';
-import classNames from 'classnames';
-import { activeFilterSelector, activeFilterParamsSelector } from 'state/features/selectors';
-import { AREA_CONFIG, OBJECTS_CONFIG } from 'features/OKN/Okn.constants';
-import { FilterType } from 'types/Filters.types';
-import { getLayerStyle } from 'features/Map/helpers/getFeatureState';
-import { OknAreaType } from 'features/OKN/oknConstants';
-import { MapItemType } from 'types/Content.types';
-import { usePopup } from 'features/Map/providers/usePopup';
-import useMapObjectState from 'features/Map/helpers/useMapObjectState';
-import geojson from 'public/okn-static/placemarks.json';
-import styles from './OknMarker.module.css';
-
-const LAYERS = {
- points: {
- dataPath: '/ekb-okn.json',
- layerId: 'ekb-okn-layer',
- sourceId: 'ekb-okn-source',
- zone: null,
- },
- protect: {
- dataPath: '/ekb-okn-protect.json',
- layerId: 'ekb-okn-protect-layer',
- sourceId: 'ekb-okn-protect-source',
- zone: OknAreaType.ProtectZone,
- },
- security: {
- dataPath: '/ekb-okn-security.json',
- layerId: 'ekb-okn-security-layer',
- sourceId: 'ekb-okn-security-source',
- zone: OknAreaType.SecurityZone,
- },
- objects: {
- dataPath: '/ekb-okn-objects.json',
- layerId: 'ekb-okn-objects-layer',
- sourceId: 'ekb-okn-objects-source',
- zone: OknAreaType.ObjectZone,
- },
-};
-
-const OKN_MARKER_CLICKABLE_SIZE = 15;
-const OKN_MARKER_IMAGE_SIZE = (OKN_MARKER_CLICKABLE_SIZE + 2) * 2;
-// because the main marker larger than the image marker
-
-const isOneObject = (coordinates: number[] | number[][]): coordinates is number[] => {
- return typeof coordinates[0] === 'number' && typeof coordinates[1] === 'number';
-};
-
-export function OknSource() {
- const ekbMap = useMap();
- const { openPopup, popupId } = usePopup();
- const activeFilter = useSelector(activeFilterSelector);
- const activeFilterParams = useSelector(activeFilterParamsSelector);
-
- useMapObjectState(LAYERS.points.layerId);
- useMapObjectState(LAYERS.protect.layerId);
- useMapObjectState(LAYERS.security.layerId);
- useMapObjectState(LAYERS.objects.layerId);
-
- useEffect(() => {
- const map = ekbMap.current;
-
- const handlePointClick = (e) => {
- const item = e.target.queryRenderedFeatures(e.point)[0];
- openPopup(item?.properties?.id, MapItemType.OKN);
- };
-
- map.on('click', 'ekb-okn-layer', handlePointClick);
-
- return () => {
- map.off('click', 'ekb-okn-layer', handlePointClick);
- };
- }, [ekbMap, openPopup]);
-
- if (activeFilter !== FilterType.OKN || !activeFilterParams) {
- return null;
- }
-
- const activeItems = Object.entries(activeFilterParams)
- // @ts-ignore
- .filter(([, { value, type }]) => value && type === 'objects');
-
- if (activeItems.length === 0) {
- return null;
- }
-
- const layerStyle: CircleLayer = {
- id: LAYERS.points.layerId,
- type: 'circle',
- source: LAYERS.points.sourceId,
- paint: {
- 'circle-radius': getLayerStyle({
- initial: OKN_MARKER_CLICKABLE_SIZE,
- hover: OKN_MARKER_CLICKABLE_SIZE * 1.4,
- active: OKN_MARKER_CLICKABLE_SIZE * 1.7,
- }),
- // @ts-ignore
- 'circle-opacity': 0,
- },
- };
-
- const getZoneStyle = (type: string): FillLayer => ({
- id: LAYERS[type].layerId,
- type: 'fill',
- source: LAYERS[type].sourceId,
- paint: {
- 'fill-color': AREA_CONFIG[LAYERS[type].zone].color,
- 'fill-opacity': getLayerStyle({
- initial: 0.5,
- hover: 0.8,
- active: 0.8,
- }),
- },
- });
-
- const getZoneOutlineStyle = (type: string): LineLayer => ({
- id: `${LAYERS[type].layerId}-outline`,
- type: 'line',
- source: LAYERS[type].sourceId,
- paint: {
- 'line-color': AREA_CONFIG[LAYERS[type].zone].color,
- 'line-width': 3,
- 'line-dasharray': [2, 2],
- },
- });
-
- const items = geojson.filter((item) => activeFilterParams[item.properties.category].value);
-
- return (
- <>
- {Object.keys(LAYERS).map(
- (layerKey, i) =>
- activeFilterParams[LAYERS[layerKey].zone]?.value && (
-
-
-
-
- ),
- )}
-
-
- {items.map((feature) => {
- if (isOneObject(feature.geometry.coordinates)) {
- const props = {
- className: classNames(styles.marker, {
- [styles.marker_open]: popupId === String(feature.properties.id),
- }),
- style: {
- color: OBJECTS_CONFIG[feature.properties.category].color,
- width: OKN_MARKER_IMAGE_SIZE,
- height: OKN_MARKER_IMAGE_SIZE,
- },
- };
-
- return (
-
- {feature.preview?.s.src ? (
-
- ) : (
-
- )}
-
- );
- }
- })}
-
- >
- );
-}
diff --git a/features/OKN/okn.ts b/features/OKN/okn.ts
deleted file mode 100644
index 39e19ced..00000000
--- a/features/OKN/okn.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import oknMeta from 'public/okn-meta.json';
-import oknObjects from 'public/okn-static/placemarks.json';
-import { OknObject } from './oknObject';
-
-export const okn = {
- getObject(id: string): Promise {
- return Promise.resolve(
- oknObjects.find((f) => String(f.properties.id) === id) as unknown as OknObject,
- );
- },
-
- async getObjectsCount() {
- return Promise.resolve(oknMeta.points);
- },
-
- async getZonesCount() {
- return Promise.resolve(oknMeta.zones);
- },
-};
diff --git a/features/OKN/oknConstants.ts b/features/OKN/oknConstants.ts
deleted file mode 100644
index fd78aae6..00000000
--- a/features/OKN/oknConstants.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-export enum OknObjectSignificanceType {
- Municipal = 'Местного (муниципального) значения',
- Regional = 'Регионального значения',
- Federal = 'Федерального значения',
-}
-
-export enum OknAreaType {
- ProtectZone = 'Защитные зоны',
- SecurityZone = 'Зоны охраны ОКН',
- ObjectZone = 'Границы территорий ОКН',
-}
diff --git a/features/OKN/oknObject.ts b/features/OKN/oknObject.ts
deleted file mode 100644
index 5ef23d3d..00000000
--- a/features/OKN/oknObject.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { OknObjectSignificanceType } from './oknConstants';
-
-export interface OknObject {
- properties: OknProperties;
- geometry: OknGeometry;
- preview?: OknPreview;
-}
-
-export interface OknProperties {
- id: number;
- name: string;
- address: string;
- okn_number: string;
- date: string;
- type: string;
- category: OknObjectSignificanceType;
- img?: { url: string; title: string; preview?: string };
- document: {
- archive: { id: number; url: string };
- date: string;
- name: string;
- number: string;
- }[];
- isExist?: string;
- comment?: string;
-}
-
-export interface OknGeometry {
- coordinates: [lat: number, lng: number];
- type?: string;
-}
-
-export interface OknPreview {
- m: PreviewImage;
- s: PreviewImage;
-}
-
-interface PreviewImage {
- width: number;
- height: number;
- src: string;
-}
diff --git a/features/Privacy/PrivacyPage.tsx b/features/Privacy/PrivacyPage.tsx
deleted file mode 100644
index 413569ef..00000000
--- a/features/Privacy/PrivacyPage.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import React from 'react';
-
-export default function PrivacyPage() {
- return (
-
- );
-}
diff --git a/features/Quarter/CardContent/CardContent.module.css b/features/Quarter/CardContent/CardContent.module.css
deleted file mode 100644
index 71958db5..00000000
--- a/features/Quarter/CardContent/CardContent.module.css
+++ /dev/null
@@ -1,30 +0,0 @@
-.popup {
- border-top-left-radius: inherit;
- border-top-right-radius: inherit;
- padding: 16px 8px 16px 16px;
-}
-
-.mainLink {
- color: inherit;
- font-size: inherit;
- line-height: inherit;
-}
-
-.description {
- margin-top: 8px;
- position: relative;
- svg {
- position: relative;
- top: 2px;
- left: 2px;
- path {
- fill: #000;
- }
- }
- a {
- border-radius: 8px;
- font-size: 16px;
- width: 100%;
- text-align: center;
- }
-}
diff --git a/features/Quarter/CardContent/CardContent.tsx b/features/Quarter/CardContent/CardContent.tsx
deleted file mode 100644
index 5d44a2b0..00000000
--- a/features/Quarter/CardContent/CardContent.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import { QuarterObject } from 'features/Quarter/quarterObject';
-import { Button, ButtonSize, ButtonType } from 'shared/UI/Button/Button';
-import { Header } from 'components/Card/components/Header/Header';
-import { Info } from 'components/Card/components/Info/Info';
-import { Section } from 'components/Card/components/Section/Section';
-import sectionStyles from 'components/Card/components/Section/Section.module.css';
-import { Sources } from 'components/Card/components/Sources/Sources';
-import { EditObjectButtonLink } from 'features/EditObjectButtonLink/EditObjectButtonLink';
-import { Icon } from 'shared/UI/Icons';
-import { IconType } from 'shared/UI/Icons/Icons.types';
-import { SOURCES_BY_TYPE } from 'constants/sources';
-import { SourceType } from 'types/Sources.types';
-import styles from './CardContent.module.css';
-
-type QuarterCardContentProps = {
- placemark?: QuarterObject;
-};
-
-export function QuarterCardContent({ placemark }: QuarterCardContentProps) {
- if (!placemark) return null;
-
- return (
-
-
-
-
- {}}
- link={placemark.url}
- type={ButtonType.YELLOW}
- >
- Посмотреть телефон и почту квартального
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/features/Quarter/QuarterSource.tsx b/features/Quarter/QuarterSource.tsx
deleted file mode 100644
index 9ad692e2..00000000
--- a/features/Quarter/QuarterSource.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import React, { useEffect } from 'react';
-import { FillLayer, Layer, LineLayer, Source, useMap } from 'react-map-gl';
-import { useSelector } from 'react-redux';
-import { activeFilterSelector } from 'state/features/selectors';
-import { FilterType } from 'types/Filters.types';
-import { getLayerStyle } from 'features/Map/helpers/getFeatureState';
-import { MapItemType } from 'types/Content.types';
-import { usePopup } from 'features/Map/providers/usePopup';
-import useMapObjectState from 'features/Map/helpers/useMapObjectState';
-import { colorLuminance } from 'features/Map/helpers/colorLuminance';
-
-const QUARTER_LAYER_ID = 'ekb-quarter-inspectors-layer';
-const QUARTER_SOURCE_ID = 'ekb-quarter-inspectors-source';
-
-export function QuarterSource() {
- const ekbMap = useMap();
- const { openPopup } = usePopup();
- const activeFilter = useSelector(activeFilterSelector);
-
- useMapObjectState(QUARTER_LAYER_ID);
-
- useEffect(() => {
- const map = ekbMap.current;
-
- const handlePointClick = (e) => {
- const item = e.target.queryRenderedFeatures(e.point)[0];
-
- openPopup(item?.properties?.id, MapItemType.Quarter);
- };
-
- map.on('click', QUARTER_LAYER_ID, handlePointClick);
-
- return () => {
- map.off('click', QUARTER_LAYER_ID, handlePointClick);
- };
- }, [ekbMap, openPopup]);
-
- const layerStyle: FillLayer = {
- type: 'fill',
- id: QUARTER_LAYER_ID,
- source: QUARTER_SOURCE_ID,
- paint: {
- 'fill-color': getLayerStyle({
- initial: '#9AADCC',
- hover: colorLuminance('#9AADCC', 0.2),
- active: colorLuminance('#9AADCC', 0.4),
- }),
- 'fill-opacity': 0.6,
- },
- };
-
- const layerStrokeStyle: LineLayer = {
- id: `${QUARTER_LAYER_ID}-outline`,
- type: 'line',
- source: QUARTER_SOURCE_ID,
- paint: {
- 'line-color': '#000',
- 'line-opacity': 0.5,
- 'line-width': 1.5,
- },
- };
-
- if (activeFilter !== FilterType.Quarter) {
- return null;
- }
-
- return (
-
-
-
-
- );
-}
diff --git a/features/Quarter/quarter.ts b/features/Quarter/quarter.ts
deleted file mode 100644
index 5a699450..00000000
--- a/features/Quarter/quarter.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import quarterObjects from 'public/quarter_inspectors.json';
-import { QuarterObject } from './quarterObject';
-
-export const quarter = {
- getObject(quarterId: string): Promise {
- return Promise.resolve(
- quarterObjects.features.find((f) => f.properties.id === quarterId)
- .properties as unknown as QuarterObject,
- );
- },
-};
diff --git a/features/Quarter/quarterObject.ts b/features/Quarter/quarterObject.ts
deleted file mode 100644
index ed648def..00000000
--- a/features/Quarter/quarterObject.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface QuarterObject {
- districtTitle: string;
- quarterTitle: string;
- quarterDescription: string;
- url: string;
-}
diff --git a/helpers/isDesktop.tsx b/helpers/isDesktop.tsx
new file mode 100644
index 00000000..db6db9ee
--- /dev/null
+++ b/helpers/isDesktop.tsx
@@ -0,0 +1,5 @@
+import { useMediaQuery } from '@uidotdev/usehooks';
+
+export const useIsDesktop = () => {
+ return useMediaQuery('only screen and (min-width : 1024px)');
+};
diff --git a/package.json b/package.json
index ed61781f..47921607 100644
--- a/package.json
+++ b/package.json
@@ -16,12 +16,11 @@
},
"dependencies": {
"@reduxjs/toolkit": "^2.0.1",
- "@types/lodash": "^4.14.202",
- "@types/node": "20.10.5",
- "@types/react": "^18.2.45",
+ "@uidotdev/usehooks": "^2.4.1",
"classnames": "^2.4.0",
- "ekb": "^1.1.5",
+ "ekb": "1.2.0-rc.2",
"framer-motion": "^10.16.16",
+ "geojson": "^0.5.0",
"imagemin": "^8.0.1",
"imagemin-mozjpeg": "^10.0.0",
"imagemin-pngquant": "^9.0.2",
@@ -30,21 +29,20 @@
"mapbox-gl": "npm:empty-npm-package@1.0.0",
"maplibre-gl": "^3.6.2",
"next": "14.0.4",
- "postcss-flexbugs-fixes": "^5.0.2",
- "postcss-mixins": "^9.0.4",
- "postcss-nesting": "^12.0.2",
- "postcss-preset-env": "^9.3.0",
- "react": "18.2.0",
- "react-dom": "18.2.0",
- "react-map-gl": "7.1.3",
- "react-modal-sheet": "^2.2.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"react-redux": "^9.0.4",
"redux": "^5.0.1",
"sharp": "0.32.6",
+ "sloy-map": "^0.0.6",
+ "sloy-ui": "0.0.1-rc.17",
"styled-components": "^6.1.6",
"typescript": "^5.3.3"
},
"devDependencies": {
+ "@types/lodash": "^4.14.202",
+ "@types/node": "20.10.5",
+ "@types/react": "^18.2.45",
"@typescript-eslint/eslint-plugin": "^6.16.0",
"@typescript-eslint/parser": "^6.16.0",
"eslint": "^8.56.0",
@@ -57,6 +55,10 @@
"eslint-plugin-react-hooks": "^4.6.0",
"husky": "^8.0.3",
"lint-staged": "^15.2.0",
+ "postcss-flexbugs-fixes": "^5.0.2",
+ "postcss-mixins": "^9.0.4",
+ "postcss-nesting": "^12.0.2",
+ "postcss-preset-env": "^9.3.0",
"prettier": "3.1.1"
}
}
diff --git a/pages/_document.tsx b/pages/_document.tsx
index 65eaac43..07845291 100644
--- a/pages/_document.tsx
+++ b/pages/_document.tsx
@@ -41,13 +41,13 @@ export default function Document() {
{/* eslint-disable-next-line react/no-danger */}
- {process.env.YANDEX_METRIKA && (
+ {/* {process.env.YANDEX_METRIKA && (
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)}) (window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");ym(${process.env.YANDEX_METRIKA}, "init", { clickmap:true, trackLinks:true, accurateTrackBounce:true });
`,
}}
/>
- )}
+ )} */}