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 (
setShowColorPicker(true)}
>
{showColorPicker && (
)}
);
};
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 (
setShowDataInputModal(!showDataInputModal)}
className="modal-dialog-centered"
size="lg"
>
setShowDataInputModal(!showDataInputModal)}>
{t("DataInput.dataInput")} - {inputData?.area?.label}
);
};
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 (
{
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();
},
}}
>
{district.name}
{
{district.name}
{areaCheck({ areaId: district.id }) &&
permissionCheck("dataset_create") && (
)}
}
);
});
};
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 (
{
// <--- 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();
},
}}
>
{neighbourhood.name}
{areaCheck({ areaId: neighbourhood.id }) &&
permissionCheck("dataset_create") && (
)}
);
});
};
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 (
{dataCenterStore.dataCenters.map((dc) => {
if (!dc.latitude || !dc.longitude) return null;
return (
{dc.dataCenter}
{t('DataCenter.number')}: {dc.number}
{t('DataCenter.externalId')}: {dc.externalId}
{t('DataCenter.city')}: {dc.area?.cities?.map(city => city.name).join(', ') || "-"}
{dc.area &&
{t('Area')}: {dc.area.tag}
}
{dc.projects?.length > 0 && (
{t('Projects')}: {dc.projects.length}
)}
{dc.ayposURL && (
)}
{dc.dataCenter}
);
})}
);
};
return (
{t("Map.title")}
{renderDataCenterMarkers()}
{neighbourhoodView
? renderNeighbourhoodView(selectedDistrict)
: districtView
? RenderDistrictView(selectedCity)
: cities.map((city, index) => {
return (
{
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),
});
}
}}
>
{city.name}
);
})}
{renderDataInputModal()}
);
};
export default Map;