Skip to content

Commit

Permalink
add facades section
Browse files Browse the repository at this point in the history
  • Loading branch information
gcor committed Nov 19, 2023
1 parent b839ad9 commit da1d0c7
Show file tree
Hide file tree
Showing 22 changed files with 8,228 additions and 229 deletions.
5 changes: 5 additions & 0 deletions components/Layers/Filters.config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,9 @@ export const FILTERS_CONFIG: FilterConfig = {
source: [SOURCES_BY_TYPE.ekb_quarter],
isVerified: true,
},
[FilterType.HouseFacades]: {
title: '«Дизайн фасадов Екатеринбурга»',
component: null,
isVerified: true,
},
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.popup {
border-top-left-radius: inherit;
border-top-right-radius: inherit;
padding: 16px 8px 16px 16px;
padding: 16px;
}

.popup__emergencyLabel {
Expand Down
13 changes: 9 additions & 4 deletions components/Layers/Houses/CardContent/CardContent.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
'use client';

import { useContext, useEffect, useMemo, useState } from 'react';
import { useMap } from 'react-map-gl';

import { HouseObject } from 'components/Layers/Houses/houseBase';
import { MapContext } from 'components/Map/providers/MapProvider';
import { usePopup } from 'components/Map/providers/usePopup';
import { ConstructionInfo } from 'components/UI/Card/components/ConstructionInfo/ConstructionInfo';
import Facade from 'components/UI/Card/components/Facade/Facade';
import { Header } from 'components/UI/Card/components/Header/Header';
import { Info } from 'components/UI/Card/components/Info/Info';
import { Label } from 'components/UI/Card/components/Label/Label';
import { Section } from 'components/UI/Card/components/Section/Section';
import { Sources } from 'components/UI/Card/components/Sources/Sources';
import { EditObjectButtonLink } from 'components/UI/EditObjectButtonLink/EditObjectButtonLink';
import { FilterLoader } from 'components/UI/Filters/components/Loader/FilterLoader';

import { getLatLngFromHash } from 'helpers/hash';
import facades from '../../../../public/ekb-facades.json';
import HealthProgress from '../HealthProgress/HealthProgress';
import styles from './CardContent.module.css';

Expand Down Expand Up @@ -45,6 +43,7 @@ export function HousesCardContent() {
setPlacemark({
id: popupId,
attributes: {
osmId: house['osm:id'] || null,
Address: [house['addr:street'], house['addr:housenumber']]
.filter(Boolean)
.join(', '),
Expand Down Expand Up @@ -170,6 +169,12 @@ export function HousesCardContent() {
<ConstructionInfo date={String(placemark?.attributes.Year)} />
</Section>
)}

{facades[placemark?.attributes?.osmId] && (
<Section>
<Facade facade={facades[placemark?.attributes?.osmId]} />
</Section>
)}
<Section>
<Sources sources={['osm', 'howoldthishouse', 'mingkh', 'domaekb']} />
</Section>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export function HouseFacadeFilter() {}
1 change: 1 addition & 0 deletions components/Layers/Houses/houseBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface HouseObject {
}

export interface HouseAttributes {
osmId: number | null;
Address: string;
Management_company: string;
Series: string;
Expand Down
12 changes: 7 additions & 5 deletions components/Map/Map.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
'use client';

import React, { useContext } from 'react';
import { useContext } from 'react';

import MapGl from 'react-map-gl';
import maplibregl from 'maplibre-gl';
import MapGl from 'react-map-gl';
import { COORDS_EKATERINBURG } from 'constants/coords';
import { MAX_ZOOM, MIN_ZOOM } from 'constants/map';

import { BuildingSource } from './layers/BuildingSource';
import { OknSource } from './layers/OknSource';
import { DesignCodeSource } from './layers/DesignCodeSource';
import { DtpSource } from './layers/DtpSource';
import { LinesSource } from './layers/LinesSource';
import { DesignCodeSource } from './layers/DesignCodeSource';
import { OknSource } from './layers/OknSource';
import { QuarterSource } from './layers/QuarterSource';
import { FacadeSource } from './layers/FacadeSource';
import { MapContext } from './providers/MapProvider';

import 'maplibre-gl/dist/maplibre-gl.css';
Expand All @@ -26,6 +27,7 @@ function MapLayers() {
<LinesSource />
<DesignCodeSource />
<QuarterSource />
<FacadeSource />
</>
);
}
Expand All @@ -40,7 +42,7 @@ export function Map() {
latitude: COORDS_EKATERINBURG[1],
longitude: COORDS_EKATERINBURG[0],
zoom: 15,
pitch: 30,
pitch: 0,
}}
minZoom={MIN_ZOOM}
maxZoom={MAX_ZOOM}
Expand Down
43 changes: 31 additions & 12 deletions components/Map/layers/BuildingSource.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import {
ColorSpecification,
DataDrivenPropertyValueSpecification,
ExpressionSpecification,
} from 'maplibre-gl';
import { useEffect } from 'react';
import { useMap } from 'react-map-gl';
import { useSelector } from 'react-redux';
import { ExpressionSpecification } from 'maplibre-gl';
import { getLayerStyle } from 'components/Map/helpers/getFeatureState';
import { colorLuminance } from 'components/Map/helpers/colorLuminance';
import {
AGE_FILTERS_DATA,
FLOOR_FILTERS_DATA,
Expand All @@ -10,30 +16,42 @@ import {
import { activeFilterParamsSelector, activeFilterSelector } from 'state/features/selectors';
import { FilterType } from 'types/Filters.types';
import { MapItemType } from 'types/map-item';
import { colorLuminance } from 'components/Map/helpers/colorLuminance';
import { getLayerStyle } from 'components/Map/helpers/getFeatureState';
import { usePopup } from '../providers/usePopup';
import useMapObjectState from '../providers/useMapObjectState';
import { usePopup } from '../providers/usePopup';

const BUILDING_LAYER_ID = 'building';

const DEFAULT_BULDING_COLOR_NORMAL = '#0c1021';

function setBuildingColor(map, color, field: string = '_unknown_') {
interface SetBuildingStyleProps {
map: mapboxgl.Map;
color: DataDrivenPropertyValueSpecification<ColorSpecification | ExpressionSpecification>;
caseCondition?: (string | string[])[];
layerProps?: Record<string, any>;
}

export function setBuildingColor({
map,
color,
caseCondition = ['has', '_unknown_'],
layerProps,
}: SetBuildingStyleProps) {
map.setStyle({
...map?.getStyle(),
layers: map?.getStyle().layers.map((layer) => {
layers: map?.getStyle().layers.map((layer: any) => {
if (layer.id === BUILDING_LAYER_ID) {
return {
...layer,
...layerProps,
paint: {
...layer.paint,
'fill-extrusion-color': [
'case',
['has', field],
caseCondition,
color,
DEFAULT_BULDING_COLOR_NORMAL,
],
...layerProps?.paint,
},
};
}
Expand All @@ -53,7 +71,7 @@ function setBuildingStyle({ map, range, field, rangeData }) {
map?.getStyle
)
) {
setBuildingColor(map, DEFAULT_BULDING_COLOR_NORMAL);
setBuildingColor({ map, color: DEFAULT_BULDING_COLOR_NORMAL });
return;
}

Expand All @@ -77,15 +95,15 @@ function setBuildingStyle({ map, range, field, rangeData }) {
...style.flat(2),
];

setBuildingColor(
setBuildingColor({
map,
getLayerStyle<ExpressionSpecification>({
color: getLayerStyle<ExpressionSpecification>({
initial: getColor(colorsInitial),
hover: getColor(colorsHover),
active: getColor(colorsActive),
}),
field,
);
caseCondition: ['has', field],
});
}

const ageRangeData = AGE_FILTERS_DATA.map((item) => ({ ...item, value: 1 }));
Expand All @@ -105,6 +123,7 @@ export function BuildingSource() {
[FilterType.HouseAge]: 'building:year',
[FilterType.HouseFloor]: 'building:levels',
[FilterType.HouseWearTear]: 'building:health',
[FilterType.HouseFacades]: 'building:facade',
}[activeFilter];

const rangeData = {
Expand Down
61 changes: 61 additions & 0 deletions components/Map/layers/FacadeSource.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { useEffect } from 'react';
import { useMap } from 'react-map-gl';
import { useSelector } from 'react-redux';
import { activeFilterSelector } from 'state/features/selectors';
import { FilterType } from 'types/Filters.types';
import { BUILDING_LAYER_ID } from 'constants/map';
import { DEFAULT_BULDING_COLOR_NORMAL } from 'constants/colors';
import useMapObjectState from '../providers/useMapObjectState';
import { getLayerStyle } from '../helpers/getFeatureState';
import facades from '../../../public/ekb-facades.json';

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<string>({
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 <FacadeStyles />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.download_button {
height: 34px;
width: 100%;
display: flex;
align-items: center;
border-radius: 8px;
padding: 8px 12px;
transition: all 0.15 ease;
}
.primary {
color: #81ff00;
background-color: rgba(129, 255, 0, 0.16);
}
.primary:hover {
background-color: rgba(129, 255, 0, 0.24);
}
.primary:active {
background-color: rgba(129, 255, 0, 0.32);
}
.secondary {
color: #c8a563;
background-color: rgba(200, 165, 99, 0.16);
}
.secondary:hover {
background-color: rgba(200, 165, 99, 0.24);
}
.secondary:active {
background-color: rgba(200, 165, 99, 0.32);
}
.file_name {
display: flex;
align-items: center;
font-size: 14px;
gap: 4px;
}
/* .file_size {
font-size: 12px;
line-height: 14px;
} */
30 changes: 30 additions & 0 deletions components/UI/Card/components/DownloadButton/DownloadButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import classNames from 'classnames';
import DownloadIcon from '../../../Icons/DownloadIcon';
import styles from './DownloadButton.module.css';

type Props = {
type: 'primary' | 'secondary';
name: string;
link: string;
};

const COLORS = {
primary: '#81FF00',
secondary: '#C8A563',
} as const;

export default function DownloadButton({ type, name, link }: Props) {
return (
<a
href={link}
className={classNames(styles.download_button, styles[type])}
target="_blank"
rel="noreferrer"
>
<div className={styles.file_name}>
<DownloadIcon color={COLORS[type]} />
<p>{name}</p>
</div>
</a>
);
}
12 changes: 12 additions & 0 deletions components/UI/Card/components/Facade/Facade.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.facade {
display: flex;
gap: 8px;
flex-direction: column;
}

.facade_title {
font-size: 16px;
line-height: 1.3;
font-weight: 400;
margin: 0;
}
18 changes: 18 additions & 0 deletions components/UI/Card/components/Facade/Facade.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import DownloadButton from '../DownloadButton/DownloadButton';
import styles from './Facade.module.css';

type Props = {
facade: {
name: string;
link: string;
};
};

export default function Facade({ facade }: Props) {
return (
<div className={styles.facade}>
<h3 className={styles.facade_title}>Дизайн-код фасада</h3>
<DownloadButton type="primary" name={facade.name} link={facade.link} />
</div>
);
}
Loading

1 comment on commit da1d0c7

@ekbdev
Copy link

@ekbdev ekbdev commented on da1d0c7 Nov 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for map ready!

✅ Preview
https://map-mbztf83nx-ekbdev.vercel.app
https://ekbdev-map-facades.vercel.app

Built with commit da1d0c7.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.