forked from Abdulbari/sgeUpdated
Add 'sge-frontend/' from commit '5fa787e054b25ac53edc7ff0275ea7960a709401'
git-subtree-dir: sge-frontend git-subtree-mainline:876c278ac4git-subtree-split:5fa787e054
This commit is contained in:
729
sge-frontend/src/views/Map.js
Normal file
729
sge-frontend/src/views/Map.js
Normal file
@@ -0,0 +1,729 @@
|
||||
import React, { useEffect } from "react";
|
||||
import {
|
||||
MapContainer,
|
||||
Marker,
|
||||
Polygon,
|
||||
Popup,
|
||||
TileLayer,
|
||||
Tooltip,
|
||||
useMap,
|
||||
LayerGroup,
|
||||
} from "react-leaflet";
|
||||
import "../components/leaflet.css";
|
||||
import { useState, useRef } from "react";
|
||||
import {
|
||||
Button,
|
||||
Label,
|
||||
Modal,
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
Row,
|
||||
Col,
|
||||
Input,
|
||||
Card,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "reactstrap";
|
||||
import Select from "react-select";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import DataInputGroup from "../components/data-input/index.js";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { getCities } from "../redux/actions/cities";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { getCity } from "../redux/actions/city";
|
||||
import { getDistrict } from "../redux/actions/district";
|
||||
import {
|
||||
getOrganisations,
|
||||
getOrganisationById,
|
||||
} from "../redux/actions/organisations";
|
||||
import { getAreasWithCriteria } from "../redux/actions/areas";
|
||||
import { ChromePicker } from "react-color";
|
||||
import { customFilterForSelect } from "../utility/Utils";
|
||||
import { permissionCheck } from "../components/permission-check";
|
||||
import { getDataCenters } from "../redux/actions/dataCenter";
|
||||
|
||||
const ColorPicker = ({ selectedColors, setSelectedColors, index }) => {
|
||||
const [showColorPicker, setShowColorPicker] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const storedColors = localStorage.getItem("selectedMapColors");
|
||||
if (storedColors) {
|
||||
setSelectedColors(JSON.parse(storedColors));
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
localStorage.setItem("selectedMapColors", JSON.stringify(selectedColors));
|
||||
}, [selectedColors]);
|
||||
|
||||
const handleColorChange = (color) => {
|
||||
const rgbaColor = `rgba(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b}, 0.3)`;
|
||||
const updatedColors = [...selectedColors];
|
||||
updatedColors[index] = rgbaColor;
|
||||
setSelectedColors(updatedColors);
|
||||
};
|
||||
|
||||
const handlePickerOutsideClick = (event) => {
|
||||
// Renk seçici dışına tıklama kontrolü
|
||||
if (
|
||||
event.target.closest(".color-picker-container") === null &&
|
||||
event.target.closest(".color-box") === null
|
||||
) {
|
||||
setShowColorPicker(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// Tüm belgeye tıklama olayını dinle
|
||||
document.addEventListener("click", handlePickerOutsideClick);
|
||||
|
||||
return () => {
|
||||
// Bileşen kaldırıldığında tıklama olayının dinlemesini kaldır
|
||||
document.removeEventListener("click", handlePickerOutsideClick);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="color-picker-container">
|
||||
<div
|
||||
key={index}
|
||||
className="color-box"
|
||||
style={{
|
||||
backgroundColor: selectedColors[index],
|
||||
width: "30px",
|
||||
height: "15px",
|
||||
display: "inline-block",
|
||||
marginRight: "10px",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
onClick={() => setShowColorPicker(true)}
|
||||
></div>
|
||||
{showColorPicker && (
|
||||
<div style={{ position: "absolute", zIndex: 1000 }}>
|
||||
<ChromePicker
|
||||
color={selectedColors[index]}
|
||||
onChange={handleColorChange}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Map = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const citiesStore = useSelector((state) => state.cities);
|
||||
const cityStore = useSelector((state) => state.city);
|
||||
const districtStore = useSelector((state) => state.district);
|
||||
const OrganisationsStore = useSelector((state) => state.organizations);
|
||||
const areasStore = useSelector((state) => state.areas);
|
||||
const dataCenterStore = useSelector((state) => state.dataCenter);
|
||||
|
||||
const [cities, setCities] = useState([]);
|
||||
const [districts, setDistricts] = useState([]);
|
||||
const [neighborhoods, setNeighborhoods] = useState([]);
|
||||
const [organizationOptions, setOrganizationOptions] = useState([]);
|
||||
const organizationId = localStorage.getItem("organizationId");
|
||||
const roleTag = localStorage.getItem("roleTag");
|
||||
const [selectedOrganization, setSelectedOrganization] = useState({
|
||||
label: localStorage.getItem("organizationName"),
|
||||
value: organizationId,
|
||||
});
|
||||
const [areasOptions, setAreasOptions] = useState([]);
|
||||
|
||||
const [done, setDone] = useState(false);
|
||||
const [selectedCity, setSelectedCity] = useState(null);
|
||||
const [selectedDistrict, setSelectedDistrict] = useState(null);
|
||||
const [districtView, setDistrictView] = useState(false);
|
||||
const [neighbourhoodView, setNeighbourhoodView] = useState(false);
|
||||
const cityRefs = useRef({});
|
||||
const districtRefs = useRef({});
|
||||
const neighbourhoodRefs = useRef({});
|
||||
const [zoom, setZoom] = useState(6.7);
|
||||
const [center, setCenter] = useState({ lat: 38.5, lng: 35.27 });
|
||||
|
||||
const [showDataInputModal, setShowDataInputModal] = useState(false);
|
||||
const [inputData, setInputData] = useState({
|
||||
organization: selectedOrganization,
|
||||
});
|
||||
const [referance, setReferance] = useState(
|
||||
Number(localStorage.getItem("referance")) || 1000
|
||||
);
|
||||
const [referance2, setReferance2] = useState(
|
||||
Number(localStorage.getItem("referance2")) || 2000
|
||||
);
|
||||
const initialColors = [
|
||||
"rgba(44,232,44,0.3)",
|
||||
"rgba(234,234,17,0.3)",
|
||||
"rgba(228,19,19,0.3)",
|
||||
];
|
||||
const [selectedColors, setSelectedColors] = useState(initialColors);
|
||||
|
||||
const currentYear = new Date().getFullYear();
|
||||
const [year, setYear] = useState({ value: currentYear, label: currentYear });
|
||||
const renderYearOptions = () => {
|
||||
const years = [];
|
||||
for (let year = currentYear; year >= 1990; year--) {
|
||||
years.push({ label: year, value: year });
|
||||
}
|
||||
return years;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(getCities());
|
||||
dispatch(getDataCenters());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedOrganization?.value != "undefined") {
|
||||
dispatch(getAreasWithCriteria(selectedOrganization.value));
|
||||
}
|
||||
}, [selectedOrganization]);
|
||||
|
||||
useEffect(() => {
|
||||
setAreasOptions([]);
|
||||
|
||||
const citiesOptions =
|
||||
areasStore?.areasWithCriteria
|
||||
?.map((area) =>
|
||||
Array.isArray(area?.cities) // cities'in bir dizi olup olmadığını kontrol edin
|
||||
? area.cities.map((city) => ({
|
||||
value: city?.id,
|
||||
label: city?.name,
|
||||
type: "city",
|
||||
}))
|
||||
: []
|
||||
)
|
||||
.flat() || []; // Eğer map boş dönerse, `flat` sonrası boş bir dizi kullan
|
||||
|
||||
const districtsOptions = areasStore?.areasWithCriteria
|
||||
?.map((area) => {
|
||||
return area?.districts?.map((district) => {
|
||||
return {
|
||||
value: district?.id,
|
||||
label: district?.name + " (" + district?.city?.name + ")",
|
||||
type: "district",
|
||||
};
|
||||
});
|
||||
})
|
||||
.flat();
|
||||
|
||||
const neighborhoodsOptions = areasStore?.areasWithCriteria
|
||||
?.map((area) => {
|
||||
return area?.neighborhoods?.map((neighborhood) => {
|
||||
return {
|
||||
value: neighborhood?.id,
|
||||
label:
|
||||
neighborhood?.name +
|
||||
" (" +
|
||||
neighborhood?.district?.name +
|
||||
" / " +
|
||||
neighborhood?.district?.city?.name +
|
||||
")",
|
||||
type: "neighborhood",
|
||||
};
|
||||
});
|
||||
})
|
||||
.flat();
|
||||
|
||||
setAreasOptions([
|
||||
...(citiesOptions || []),
|
||||
...(districtsOptions || []),
|
||||
...(neighborhoodsOptions || []),
|
||||
]);
|
||||
}, [areasStore]);
|
||||
|
||||
useEffect(() => {
|
||||
if (roleTag === "SUPER_ADMIN") {
|
||||
dispatch(getOrganisations());
|
||||
} else {
|
||||
dispatch(getOrganisationById(organizationId));
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleDataInputButtonPressed = ({ area, type }) => {
|
||||
const areaName =
|
||||
type === "neighborhood"
|
||||
? `${area?.name} / ${area?.district?.name} / ${area?.district?.city?.name}`
|
||||
: type === "district"
|
||||
? `${area?.name} / ${area?.city?.name}`
|
||||
: area?.name;
|
||||
|
||||
const areaType =
|
||||
type === "district"
|
||||
? "district"
|
||||
: type === "city"
|
||||
? "city"
|
||||
: type === "neighborhood"
|
||||
? "neighborhood"
|
||||
: "";
|
||||
setShowDataInputModal(true);
|
||||
setInputData({
|
||||
...inputData,
|
||||
area: { value: area?.id, label: areaName, type: areaType },
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!citiesStore?.cities || !year?.value) {
|
||||
console.error("Cities or year is not defined.");
|
||||
return;
|
||||
}
|
||||
|
||||
setCities(() => {
|
||||
const updatedCities = citiesStore.cities.map((city) => {
|
||||
const mainDataTables = city.mainDataTables
|
||||
? city.mainDataTables.filter(
|
||||
(data) => data.year === year.value.toString()
|
||||
)
|
||||
: [];
|
||||
|
||||
const total = mainDataTables.reduce(
|
||||
(acc, data) => acc + (data?.totalEmission || 0),
|
||||
0
|
||||
);
|
||||
|
||||
return { ...city, mainDataTables, total };
|
||||
});
|
||||
|
||||
return updatedCities;
|
||||
});
|
||||
}, [citiesStore?.cities, year?.value]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedCity != undefined) {
|
||||
dispatch(getCity(selectedCity?.id));
|
||||
}
|
||||
}, [selectedCity]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedDistrict != undefined && selectedDistrict.length != 0) {
|
||||
dispatch(getDistrict(selectedDistrict?.id));
|
||||
}
|
||||
}, [selectedDistrict]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!cityStore?.city?.districts || !year.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
setDistricts(() => {
|
||||
const updatedDistricts = cityStore.city.districts?.map((district) => {
|
||||
const mainDataTables = district.mainDataTables.filter(
|
||||
(data) => data.year === year.value.toString()
|
||||
);
|
||||
const total = mainDataTables.reduce(
|
||||
(acc, data) => acc + data.totalEmission,
|
||||
0
|
||||
);
|
||||
return { ...district, mainDataTables, total };
|
||||
});
|
||||
|
||||
return updatedDistricts;
|
||||
});
|
||||
}, [selectedCity, cityStore?.city, year.value]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!districtStore?.district?.neighborhoods || !year.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
setNeighborhoods(() => {
|
||||
const updatedNeighborhoods = districtStore.district?.neighborhoods?.map(
|
||||
(neighborhood) => {
|
||||
const mainDataTables = neighborhood.mainDataTables.filter(
|
||||
(data) => data.year === year.value.toString()
|
||||
);
|
||||
const total = mainDataTables.reduce(
|
||||
(acc, data) => acc + data.totalEmission,
|
||||
0
|
||||
);
|
||||
return { ...neighborhood, mainDataTables, total };
|
||||
}
|
||||
);
|
||||
|
||||
return updatedNeighborhoods;
|
||||
});
|
||||
}, [selectedDistrict, districtStore?.district, year.value]);
|
||||
|
||||
useEffect(() => {
|
||||
let organizationOptions = [];
|
||||
|
||||
if (
|
||||
OrganisationsStore.organization &&
|
||||
OrganisationsStore.organization.length !== 0
|
||||
) {
|
||||
organizationOptions.push({
|
||||
value: OrganisationsStore.organization.id,
|
||||
label: OrganisationsStore.organization.tag,
|
||||
});
|
||||
|
||||
if (OrganisationsStore.organization.children) {
|
||||
organizationOptions = [
|
||||
...organizationOptions,
|
||||
...OrganisationsStore.organization.children.map((organization) => ({
|
||||
value: organization.child.id,
|
||||
label: organization.child.tag,
|
||||
})),
|
||||
];
|
||||
}
|
||||
} else {
|
||||
organizationOptions = OrganisationsStore.dataOrganization.map(
|
||||
(organization) => ({
|
||||
value: organization.id,
|
||||
label: organization.tag,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
setOrganizationOptions(organizationOptions);
|
||||
}, [OrganisationsStore]);
|
||||
|
||||
const renderDataInputModal = () => {
|
||||
return (
|
||||
<Modal
|
||||
isOpen={showDataInputModal}
|
||||
toggle={() => setShowDataInputModal(!showDataInputModal)}
|
||||
className="modal-dialog-centered"
|
||||
size="lg"
|
||||
>
|
||||
<ModalHeader toggle={() => setShowDataInputModal(!showDataInputModal)}>
|
||||
{t("DataInput.dataInput")} - {inputData?.area?.label}
|
||||
</ModalHeader>
|
||||
<ModalBody>
|
||||
<DataInputGroup inputData={inputData} setInputData={setInputData} />
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
const grayOptions = {
|
||||
color: "gray",
|
||||
fillColor: "transparent",
|
||||
opacity: 1,
|
||||
};
|
||||
|
||||
const greenOptions = {
|
||||
color: "gray",
|
||||
fillColor: selectedColors[0],
|
||||
opacity: 1,
|
||||
};
|
||||
|
||||
const yellowOptions = {
|
||||
color: "gray",
|
||||
fillColor: selectedColors[1],
|
||||
opacity: 1,
|
||||
};
|
||||
|
||||
const redOptions = {
|
||||
color: "gray",
|
||||
fillColor: selectedColors[2],
|
||||
opacity: 1,
|
||||
};
|
||||
|
||||
const pathOptions = (total) => {
|
||||
return total > referance2
|
||||
? redOptions
|
||||
: referance < total && total < referance2
|
||||
? yellowOptions
|
||||
: total != 0 && total < referance
|
||||
? greenOptions
|
||||
: grayOptions;
|
||||
};
|
||||
|
||||
const turkeyBounds = [
|
||||
[34.42, 44.83],
|
||||
[43.45, 25.62],
|
||||
];
|
||||
|
||||
const RenderDistrictView = () => {
|
||||
return districts?.map((district, index) => {
|
||||
return (
|
||||
<Polygon
|
||||
key={uuidv4()}
|
||||
ref={(c) => {
|
||||
districtRefs.current[index] = c;
|
||||
if (index === district.length - 1 && !done) {
|
||||
setDone(true);
|
||||
}
|
||||
}}
|
||||
fillOpacity={1}
|
||||
pathOptions={pathOptions(district.total)}
|
||||
positions={convertCoordinates(district.coordinates)}
|
||||
eventHandlers={{
|
||||
mouseover: () => {
|
||||
const district = districtRefs.current[index];
|
||||
district.openPopup();
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Tooltip permanent direction="center" className="tooltip">
|
||||
{district.name}
|
||||
</Tooltip>
|
||||
{
|
||||
<Popup closeButton={true} autoPan={false}>
|
||||
<h5 className="w-100 text-center">{district.name}</h5>
|
||||
<Button
|
||||
className="w-100 mb-1"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
setSelectedDistrict(district);
|
||||
setNeighbourhoodView(true);
|
||||
setDistrictView(false);
|
||||
setSelectedCity(null);
|
||||
setZoom(11.0);
|
||||
let convertCordinates = convertCoordinates(
|
||||
district.coordinates
|
||||
);
|
||||
|
||||
let length = convertCordinates[0][0][0].length;
|
||||
let mlength = ((length + 1) / 2).toFixed(0);
|
||||
let lat1 = convertCordinates[0][0][0][0];
|
||||
let lng1 = convertCordinates[0][0][0][1];
|
||||
let lat2 = convertCordinates[0][0][mlength][0];
|
||||
let lng2 = convertCordinates[0][0][mlength][1];
|
||||
|
||||
setCenter({
|
||||
lat: ((lat1 + lat2) / 2).toFixed(2),
|
||||
lng: ((lng1 + lng2) / 2).toFixed(2),
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t("Areas.neighborhoods")}
|
||||
</Button>
|
||||
<br></br>
|
||||
{areaCheck({ areaId: district.id }) &&
|
||||
permissionCheck("dataset_create") && (
|
||||
<Button
|
||||
className="w-100 mb-1"
|
||||
color="primary"
|
||||
onClick={() =>
|
||||
handleDataInputButtonPressed({
|
||||
area: district,
|
||||
type: "district",
|
||||
})
|
||||
}
|
||||
>
|
||||
{t("DataInput.dataInput")}
|
||||
</Button>
|
||||
)}
|
||||
<br></br>
|
||||
<Button
|
||||
className="w-100"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
setDistrictView(false);
|
||||
setCenter({ lat: 38, lng: 37 });
|
||||
setZoom(6.7);
|
||||
}}
|
||||
>
|
||||
{t("Map.goBack")}
|
||||
</Button>
|
||||
</Popup>
|
||||
}
|
||||
</Polygon>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const neighborhoodTooltipBackground = (total) => {
|
||||
return total > referance2
|
||||
? selectedColors[2]
|
||||
: referance < total && total < referance2
|
||||
? selectedColors[1]
|
||||
: total != 0 && total < referance
|
||||
? selectedColors[0]
|
||||
: "white";
|
||||
};
|
||||
|
||||
const renderNeighbourhoodView = () => {
|
||||
return neighborhoods?.map((neighbourhood, index) => {
|
||||
return (
|
||||
<Marker
|
||||
opacity={0}
|
||||
zoom={10.75}
|
||||
key={uuidv4()}
|
||||
ref={(c) => {
|
||||
// <--- add city refs to ref object here
|
||||
neighbourhoodRefs.current[index] = c;
|
||||
if (index === neighbourhood.length - 1 && !done) {
|
||||
setDone(true);
|
||||
}
|
||||
}}
|
||||
fillOpacity={1}
|
||||
pathOptions={pathOptions(neighbourhood.total)}
|
||||
position={[
|
||||
Number(neighbourhood?.minLat + neighbourhood?.maxLat) / 2,
|
||||
Number(neighbourhood?.minLong + neighbourhood?.maxLong) / 2,
|
||||
]}
|
||||
eventHandlers={{
|
||||
mouseover: () => {
|
||||
const neighbourhood = neighbourhoodRefs.current[index];
|
||||
neighbourhood.openPopup();
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Tooltip permanent direction="center" className="tooltip">
|
||||
{neighbourhood.name}
|
||||
</Tooltip>
|
||||
<Popup closeButton={true} autoPan={false}>
|
||||
{areaCheck({ areaId: neighbourhood.id }) &&
|
||||
permissionCheck("dataset_create") && (
|
||||
<Button
|
||||
className="w-100 mb-1"
|
||||
color="primary"
|
||||
onClick={() =>
|
||||
handleDataInputButtonPressed({
|
||||
area: neighbourhood,
|
||||
type: "neighborhood",
|
||||
})
|
||||
}
|
||||
>
|
||||
{t("DataInput.dataInput")}
|
||||
</Button>
|
||||
)}
|
||||
<br></br>
|
||||
<Button
|
||||
className="w-100"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
setNeighbourhoodView(false);
|
||||
setCenter({ lat: 38, lng: 37 });
|
||||
setZoom(6.7);
|
||||
}}
|
||||
>
|
||||
{t("Map.goBack")}
|
||||
</Button>
|
||||
</Popup>
|
||||
</Marker>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
function ChangeZoom({ center, zoom }) {
|
||||
const map = useMap();
|
||||
map.setView(center, zoom);
|
||||
return null;
|
||||
}
|
||||
function convertCoordinates(coords) {
|
||||
const editedCoordinates = JSON.parse(coords);
|
||||
return editedCoordinates;
|
||||
}
|
||||
|
||||
function areaCheck({ areaId }) {
|
||||
return areasOptions?.some((area) => areaId === area.value);
|
||||
}
|
||||
|
||||
const renderDataCenterMarkers = () => {
|
||||
if (!dataCenterStore?.dataCenters) return null;
|
||||
|
||||
return (
|
||||
<LayerGroup>
|
||||
{dataCenterStore.dataCenters.map((dc) => {
|
||||
if (!dc.latitude || !dc.longitude) return null;
|
||||
|
||||
return (
|
||||
<Marker
|
||||
key={dc.id}
|
||||
position={[dc.latitude, dc.longitude]}
|
||||
>
|
||||
<Popup>
|
||||
<div className="data-center-popup">
|
||||
<h5 className="mb-2">{dc.dataCenter}</h5>
|
||||
<p className="mb-1"><strong>{t('DataCenter.number')}:</strong> {dc.number}</p>
|
||||
<p className="mb-1"><strong>{t('DataCenter.externalId')}:</strong> {dc.externalId}</p>
|
||||
<p className="mb-1"><strong>{t('DataCenter.city')}:</strong> {dc.area?.cityNames || "-"}</p>
|
||||
{dc.area && <p className="mb-1"><strong>{t('Area')}:</strong> {dc.area.tag}</p>}
|
||||
{dc.projects?.length > 0 && (
|
||||
<p className="mb-1">
|
||||
<strong>{t('Projects')}:</strong> {dc.projects.length}
|
||||
</p>
|
||||
)}
|
||||
{dc.ayposURL && (
|
||||
<Button
|
||||
className="w-100 mb-1"
|
||||
color="primary"
|
||||
onClick={() => window.open(dc.ayposURL, '_blank')}
|
||||
>
|
||||
Dashboard
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</Popup>
|
||||
<Tooltip>{dc.dataCenter}</Tooltip>
|
||||
</Marker>
|
||||
);
|
||||
})}
|
||||
</LayerGroup>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader className="border-bottom">
|
||||
<CardTitle tag="h4">{t("Map.title")}</CardTitle>
|
||||
</CardHeader>
|
||||
<div style={{ height: "700px", width: "100%" }}>
|
||||
<MapContainer
|
||||
center={center}
|
||||
zoom={zoom}
|
||||
style={{ height: "100%", width: "100%" }}
|
||||
>
|
||||
<TileLayer
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
/>
|
||||
{renderDataCenterMarkers()}
|
||||
{neighbourhoodView
|
||||
? renderNeighbourhoodView(selectedDistrict)
|
||||
: districtView
|
||||
? RenderDistrictView(selectedCity)
|
||||
: cities.map((city, index) => {
|
||||
return (
|
||||
<Polygon
|
||||
key={uuidv4()}
|
||||
ref={(c) => {
|
||||
cityRefs.current[index] = c;
|
||||
if (index === cities.length - 1 && !done) {
|
||||
setDone(true);
|
||||
}
|
||||
}}
|
||||
fillOpacity={1}
|
||||
pathOptions={pathOptions(city.total)}
|
||||
positions={convertCoordinates(city.coordinates)}
|
||||
eventHandlers={{
|
||||
click: () => {
|
||||
setSelectedCity(city);
|
||||
setDistrictView(true);
|
||||
setZoom(8.0);
|
||||
|
||||
let convertCordinates = convertCoordinates(city.coordinates);
|
||||
let length = convertCordinates[0][0][0].length;
|
||||
let mlength = ((length + 1) / 2).toFixed(0);
|
||||
let lat1 = convertCordinates[0][0][0][0];
|
||||
let lng1 = convertCordinates[0][0][0][1];
|
||||
let lat2 = convertCordinates[0][0][mlength][0];
|
||||
let lng2 = convertCordinates[0][0][mlength][1];
|
||||
setCenter({
|
||||
lat: ((lat1 + lat2) / 2).toFixed(2),
|
||||
lng: ((lng1 + lng2) / 2).toFixed(2),
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Tooltip permanent direction="center">
|
||||
{city.name}
|
||||
</Tooltip>
|
||||
</Polygon>
|
||||
);
|
||||
})}
|
||||
{renderDataInputModal()}
|
||||
</MapContainer>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default Map;
|
||||
Reference in New Issue
Block a user