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:
204
sge-frontend/src/components/data-input-waste/solid-waste.js
Normal file
204
sge-frontend/src/components/data-input-waste/solid-waste.js
Normal file
@@ -0,0 +1,204 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Label, Input } from "reactstrap";
|
||||
import Select from "react-select";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { getMcfTypes, getConsuptionUnits } from "../../redux/actions/datas";
|
||||
|
||||
const DataInputSolidWaste = ({ inputData, setInputData }) => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const datasStore = useSelector((state) => state.datas);
|
||||
const [mcfTypesOptions, setMcfTypesOptions] = useState([]);
|
||||
const [consuptionUnitsOptions, setConsuptionUnitsOptions] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(getMcfTypes());
|
||||
dispatch(getConsuptionUnits({ sector: "Atık" }));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setMcfTypesOptions(
|
||||
datasStore?.mcfTypes?.map((mcfType) => {
|
||||
return {
|
||||
value: mcfType?.id,
|
||||
label: `${mcfType?.typeName} (${mcfType?.value})`,
|
||||
};
|
||||
})
|
||||
);
|
||||
}, [datasStore?.mcfTypes]);
|
||||
|
||||
useEffect(() => {
|
||||
setConsuptionUnitsOptions(
|
||||
datasStore?.consuptionUnits
|
||||
?.filter(
|
||||
(consuptionUnit) =>
|
||||
consuptionUnit.tag === "kg" ||
|
||||
consuptionUnit.tag === "g" ||
|
||||
consuptionUnit.tag === "t"
|
||||
)
|
||||
.map((consuptionUnit) => {
|
||||
return {
|
||||
value: consuptionUnit?.id,
|
||||
label: consuptionUnit?.description,
|
||||
};
|
||||
})
|
||||
);
|
||||
}, [datasStore?.consuptionUnits]);
|
||||
|
||||
let solidWasteTypes = [
|
||||
{ label: "Evsel", value: "domestic" },
|
||||
{ label: "Bahçe", value: "garden" },
|
||||
{ label: "Kağıt", value: "paper" },
|
||||
{ label: "Ağaç", value: "tree" },
|
||||
{ label: "Tekstil", value: "textile" },
|
||||
{ label: "Endüstriyel", value: "industrial" },
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="d-flex flex-md-row flex-column">
|
||||
<div className="mb-2 col-md-6">
|
||||
<Label className="form-label" for="solid-waste-types">
|
||||
Atık Türü: *
|
||||
</Label>
|
||||
<div className="row ml-2">
|
||||
{solidWasteTypes.map((type, index) => (
|
||||
<div className="mb-2 col-4" key={index}>
|
||||
<Label className="form-label" for="solid-waste-type">
|
||||
{type.label} %:
|
||||
</Label>
|
||||
<Input
|
||||
id="solid-waste-type"
|
||||
placeholder="0-100"
|
||||
type="text"
|
||||
value={inputData?.[type.value] || ""}
|
||||
onChange={(e) => {
|
||||
const inputValue = e.target.value;
|
||||
const onlyNumbers = inputValue.replace(/[^0-9]/g, "");
|
||||
const parsedNumber = Math.min(
|
||||
100,
|
||||
Math.max(0, parseInt(onlyNumbers, 10))
|
||||
);
|
||||
setInputData({
|
||||
...inputData,
|
||||
[type.value]: parsedNumber,
|
||||
});
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "e" || e.key === "E") {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex flex-md-row flex-column">
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="mcfType">
|
||||
MCF: *
|
||||
</Label>
|
||||
<Select
|
||||
id="mcfType"
|
||||
isClearable={false}
|
||||
closeMenuOnSelect={true}
|
||||
maxMenuHeight={150}
|
||||
menuPlacement="auto"
|
||||
className="react-select"
|
||||
placeholder=""
|
||||
options={mcfTypesOptions}
|
||||
value={inputData?.mcfType || ""}
|
||||
onChange={(value) => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
mcfType: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="frec">
|
||||
Metan Yakalama Oranı %:*
|
||||
</Label>
|
||||
<Input
|
||||
id="frec"
|
||||
placeholder="0-100"
|
||||
type="text"
|
||||
value={inputData?.frec || ""}
|
||||
onChange={(e) => {
|
||||
const inputValue = e.target.value;
|
||||
const onlyNumbers = inputValue.replace(/[^0-9]/g, "");
|
||||
const parsedNumber = Math.min(
|
||||
100,
|
||||
Math.max(0, parseInt(onlyNumbers, 10))
|
||||
);
|
||||
setInputData({
|
||||
...inputData,
|
||||
frec: parsedNumber,
|
||||
});
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "e" || e.key === "E") {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex flex-md-row flex-column">
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="consumption-amount">
|
||||
{t("DataInput.consumptionAmount")}: *
|
||||
</Label>
|
||||
<Input
|
||||
id="consumption-amount"
|
||||
placeholder="xxxxx.xx"
|
||||
type="text"
|
||||
value={inputData?.consumptionAmount || ""}
|
||||
onChange={(e) => {
|
||||
const inputValue = e.target.value;
|
||||
const onlyNumbers = inputValue.replace(/[^0-9.]/g, "");
|
||||
setInputData({
|
||||
...inputData,
|
||||
consumptionAmount: onlyNumbers,
|
||||
});
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "e" || e.key === "E") {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="consumption-unit">
|
||||
{t("DataInput.consumptionUnit")}: *
|
||||
</Label>
|
||||
<Select
|
||||
id="consumption-unit"
|
||||
isClearable={false}
|
||||
closeMenuOnSelect={true}
|
||||
maxMenuHeight={150}
|
||||
menuPlacement="auto"
|
||||
className="react-select"
|
||||
placeholder=""
|
||||
options={consuptionUnitsOptions}
|
||||
value={inputData?.consumptionUnit || ""}
|
||||
onChange={(value) => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
consumptionUnit: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DataInputSolidWaste;
|
||||
828
sge-frontend/src/components/data-input/index.js
Normal file
828
sge-frontend/src/components/data-input/index.js
Normal file
@@ -0,0 +1,828 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { Label, Input, ModalFooter, Button } from "reactstrap";
|
||||
import Select from "react-select";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useSnackbar } from "notistack";
|
||||
import {
|
||||
getSectors,
|
||||
getSectorById,
|
||||
getSubSectorById,
|
||||
getConsuptionUnits,
|
||||
} from "../../redux/actions/datas";
|
||||
import { getAllEmissionSources } from "../../redux/actions/emissionSources";
|
||||
import {
|
||||
addDataInput,
|
||||
createSolidWasteMainDataTable,
|
||||
createWasteMainDataTable,
|
||||
} from "../../redux/actions/mainDataTables";
|
||||
import { editNumbers } from "../edit-numbers";
|
||||
import DataInputSolidWaste from "../data-input-waste/solid-waste";
|
||||
import { customFilterForSelect } from "../../utility/Utils";
|
||||
|
||||
const DataInputGroup = ({
|
||||
inputData,
|
||||
setInputData,
|
||||
selectedOrganization,
|
||||
selectedDataCenter,
|
||||
hideSectorSelection = false,
|
||||
sectorOptions = [],
|
||||
subSectorOptions = []
|
||||
}) => {
|
||||
const history = useHistory();
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const datasStore = useSelector((state) => state.datas);
|
||||
const emissionSourceStore = useSelector((state) => state.emissionSources);
|
||||
const mainDataTablesStore = useSelector(
|
||||
(state) => state.mainDataTables.mainDataTable
|
||||
);
|
||||
const [selectedSector, setSelectedSector] = useState(null);
|
||||
const [sectorsOptions, setSectorsOptions] = useState([]);
|
||||
const [selectedSubSector, setSelectedSubSector] = useState(null);
|
||||
const [subSectorsOptions, setSubSectorsOptions] = useState([]);
|
||||
const [activitySubUnitsOptions, setActivitySubUnitsOptions] = useState([]);
|
||||
const [emissionSourcesOptions, setEmissionSourcesOptions] = useState([]);
|
||||
const [consuptionUnitsOptions, setConsuptionUnitsOptions] = useState([]);
|
||||
const [emissionScopesOptions, setEmissionScopesOptions] = useState([]);
|
||||
const [result, setResult] = useState(false);
|
||||
const [resultData, setResultData] = useState({});
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
const renderYearOptions = () => {
|
||||
const years = [];
|
||||
for (let year = currentYear; year >= 1990; year--) {
|
||||
years.push({ label: year, value: year });
|
||||
}
|
||||
return years;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
year: { label: currentYear, value: currentYear },
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(getSectors());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (inputData?.emissionSource)
|
||||
dispatch(
|
||||
getConsuptionUnits({
|
||||
id: inputData?.emissionSource?.value,
|
||||
sector: inputData?.sector?.label,
|
||||
})
|
||||
);
|
||||
}, [inputData?.emissionSource?.value]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedSubSector != null)
|
||||
dispatch(getAllEmissionSources(selectedSubSector));
|
||||
}, [selectedSubSector]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedSector != null) dispatch(getSectorById(selectedSector));
|
||||
}, [selectedSector]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedSubSector != null)
|
||||
dispatch(getSubSectorById(selectedSubSector));
|
||||
}, [selectedSubSector]);
|
||||
|
||||
useEffect(() => {
|
||||
setSectorsOptions(
|
||||
datasStore?.sectors?.map((sector) => {
|
||||
return {
|
||||
value: sector?.id,
|
||||
label: sector?.tag,
|
||||
};
|
||||
})
|
||||
);
|
||||
}, [datasStore?.sectors]);
|
||||
|
||||
useEffect(() => {
|
||||
setSubSectorsOptions([]);
|
||||
setSubSectorsOptions(
|
||||
datasStore?.sector?.subSectors?.map((subSector) => {
|
||||
return {
|
||||
value: subSector?.id,
|
||||
label: subSector?.tag,
|
||||
};
|
||||
})
|
||||
);
|
||||
}, [datasStore?.sector]);
|
||||
|
||||
useEffect(() => {
|
||||
setActivitySubUnitsOptions(
|
||||
datasStore?.subSector?.activitySubUnits?.map((activitySubUnit) => {
|
||||
return {
|
||||
value: activitySubUnit?.id,
|
||||
label: activitySubUnit?.tag,
|
||||
};
|
||||
})
|
||||
);
|
||||
}, [datasStore?.subSector]);
|
||||
|
||||
useEffect(() => {
|
||||
setEmissionSourcesOptions(
|
||||
emissionSourceStore?.emissionSources
|
||||
?.filter((source) => source.convertUnitCheck != false)
|
||||
?.map((source) => {
|
||||
return {
|
||||
value: source?.id,
|
||||
label: source?.tag,
|
||||
};
|
||||
})
|
||||
);
|
||||
}, [emissionSourceStore?.emissionSources]);
|
||||
|
||||
useEffect(() => {
|
||||
if (inputData?.sector?.label === "Atık") {
|
||||
setConsuptionUnitsOptions(
|
||||
datasStore?.consuptionUnits
|
||||
?.filter(
|
||||
(consuptionUnit) =>
|
||||
consuptionUnit.tag === "kg" ||
|
||||
consuptionUnit.tag === "g" ||
|
||||
consuptionUnit.tag === "t"
|
||||
)
|
||||
.map((consuptionUnit) => {
|
||||
return {
|
||||
value: consuptionUnit?.id,
|
||||
label: consuptionUnit?.description,
|
||||
};
|
||||
})
|
||||
);
|
||||
} else {
|
||||
setConsuptionUnitsOptions(
|
||||
datasStore?.consuptionUnits?.map((consuptionUnit) => {
|
||||
return {
|
||||
value: consuptionUnit?.unit?.id,
|
||||
label: consuptionUnit?.unit?.description,
|
||||
};
|
||||
})
|
||||
);
|
||||
}
|
||||
}, [datasStore?.consuptionUnits]);
|
||||
|
||||
useEffect(() => {
|
||||
setEmissionScopesOptions([
|
||||
{
|
||||
label: "Şehir İçi",
|
||||
value: false,
|
||||
},
|
||||
{
|
||||
label: "Şehir Dışı",
|
||||
value: true,
|
||||
},
|
||||
]);
|
||||
}, []);
|
||||
|
||||
const onSaveDataButtonPressed = () => {
|
||||
setLoading(true);
|
||||
|
||||
let areaType = inputData?.area?.type;
|
||||
let areaValue = inputData?.area?.value;
|
||||
|
||||
const newDataInput = {
|
||||
[areaType]: areaValue,
|
||||
year: inputData?.year?.value.toString(),
|
||||
month: inputData?.month?.value.toString(),
|
||||
sector:
|
||||
inputData?.sector?.label != "Atık" ? inputData?.sector?.value : null,
|
||||
subSector: inputData?.subSector?.value,
|
||||
activitySubUnit: inputData?.activitySubUnit?.value,
|
||||
emissionSource: inputData?.emissionSource?.value,
|
||||
scope: inputData?.scope?.value,
|
||||
consuptionAmount: inputData?.consumptionAmount,
|
||||
consuptionUnit: inputData?.consumptionUnit?.value,
|
||||
organization: inputData?.organization
|
||||
? inputData?.organization.value
|
||||
: selectedOrganization?.value,
|
||||
dataCenter: inputData?.dataCenter
|
||||
? inputData?.dataCenter.value
|
||||
: selectedDataCenter?.value,
|
||||
mcfType: inputData?.mcfType?.value,
|
||||
frec:
|
||||
inputData?.subSector?.label === "Katı Atık Bertarafı"
|
||||
? Number(inputData?.frec)
|
||||
: null,
|
||||
domestic:
|
||||
inputData?.subSector?.label === "Katı Atık Bertarafı"
|
||||
? inputData?.domestic?.toString() || "0"
|
||||
: null,
|
||||
garden:
|
||||
inputData?.subSector?.label === "Katı Atık Bertarafı"
|
||||
? inputData?.garden?.toString() || "0"
|
||||
: null,
|
||||
paper:
|
||||
inputData?.subSector?.label === "Katı Atık Bertarafı"
|
||||
? inputData?.paper?.toString() || "0"
|
||||
: null,
|
||||
tree:
|
||||
inputData?.subSector?.label === "Katı Atık Bertarafı"
|
||||
? inputData?.tree?.toString() || "0"
|
||||
: null,
|
||||
textile:
|
||||
inputData?.subSector?.label === "Katı Atık Bertarafı"
|
||||
? inputData?.textile?.toString() || "0"
|
||||
: null,
|
||||
industrial:
|
||||
inputData?.subSector?.label === "Katı Atık Bertarafı"
|
||||
? inputData?.industrial?.toString() || "0"
|
||||
: null,
|
||||
burnOrOpenBurn: inputData?.burnOrOpenBurn?.value,
|
||||
weightType: inputData?.weightType?.value,
|
||||
personCount:
|
||||
inputData?.emissionSource?.label === "Deniz, Nehir ve Göl Deşarjı"
|
||||
? Number(inputData?.personCount)
|
||||
: null,
|
||||
proteinAmount: inputData?.proteinAmount,
|
||||
};
|
||||
|
||||
const check = JSON.parse(JSON.stringify(newDataInput), (key, value) =>
|
||||
value === null || value === "" ? undefined : value
|
||||
);
|
||||
dispatch(
|
||||
inputData?.subSector?.label === "Katı Atık Bertarafı"
|
||||
? createSolidWasteMainDataTable(check)
|
||||
: inputData?.subSector?.label != "Katı Atık Bertarafı" &&
|
||||
inputData?.sector?.label === "Atık"
|
||||
? createWasteMainDataTable(check)
|
||||
: addDataInput(check)
|
||||
)
|
||||
.then(() => {
|
||||
setResult(true);
|
||||
enqueueSnackbar(`${t("Warnings.addedSuccessfully")}`, {
|
||||
variant: "success",
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
if (e === "11020" || e === "11030") {
|
||||
enqueueSnackbar(
|
||||
`Bu emisyon kaynağı için seçilen ağırlık tipiyle hesaplama yapılamaz`,
|
||||
{
|
||||
variant: "error",
|
||||
}
|
||||
);
|
||||
} else if (e === "11050" || e === "11040") {
|
||||
enqueueSnackbar(
|
||||
`Bu emisyon kaynağı için seçilen tüketim birimiyle hesaplama yapılamaz`,
|
||||
{
|
||||
variant: "error",
|
||||
}
|
||||
);
|
||||
} else {
|
||||
enqueueSnackbar(`${t("Warnings.addedFail")}`, {
|
||||
variant: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const onAddNewDataButtonPresssed = () => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
emissionSource: "",
|
||||
mcfType: "",
|
||||
frec: "",
|
||||
domestic: "",
|
||||
garden: "",
|
||||
paper: "",
|
||||
tree: "",
|
||||
textile: "",
|
||||
industrial: "",
|
||||
burnOrOpenBurn: "",
|
||||
weightType: "",
|
||||
proteinAmount: "",
|
||||
personCount: "",
|
||||
consumptionAmount: "",
|
||||
consumptionUnit: "",
|
||||
});
|
||||
|
||||
setResult(false);
|
||||
setResultData({});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (mainDataTablesStore?.id) {
|
||||
setResultData({
|
||||
id: mainDataTablesStore?.id,
|
||||
ch4: editNumbers(mainDataTablesStore?.ch4),
|
||||
co2: editNumbers(mainDataTablesStore?.co2),
|
||||
n2o: editNumbers(mainDataTablesStore?.n2o),
|
||||
totalEmission: editNumbers(mainDataTablesStore?.totalEmission),
|
||||
});
|
||||
}
|
||||
}, [mainDataTablesStore]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{inputData?.area && (inputData?.organization || selectedOrganization || inputData?.dataCenter || selectedDataCenter) && (
|
||||
<div className="d-flex flex-md-row flex-column">
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="select-year">
|
||||
{t("DataInput.year")}: *
|
||||
</Label>
|
||||
<Select
|
||||
id="select-year"
|
||||
isClearable={false}
|
||||
closeMenuOnSelect={true}
|
||||
maxMenuHeight={150}
|
||||
menuPlacement="auto"
|
||||
className="react-select"
|
||||
placeholder=""
|
||||
options={renderYearOptions()}
|
||||
defaultValue={inputData?.year}
|
||||
onChange={(value) => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
year: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="select-month">
|
||||
{t("DataInput.month")}:
|
||||
</Label>
|
||||
<Select
|
||||
id="select-month"
|
||||
isClearable={false}
|
||||
closeMenuOnSelect={true}
|
||||
maxMenuHeight={150}
|
||||
menuPlacement="auto"
|
||||
className="react-select"
|
||||
placeholder=""
|
||||
options={[
|
||||
{ label: t(`Months.null`), value: null },
|
||||
{ label: "Ocak", value: 1 },
|
||||
{ label: "Şubat", value: 2 },
|
||||
{ label: "Mart", value: 3 },
|
||||
{ label: "Nisan", value: 4 },
|
||||
{ label: "Mayıs", value: 5 },
|
||||
{ label: "Haziran", value: 6 },
|
||||
{ label: "Temmuz", value: 7 },
|
||||
{ label: "Ağustos", value: 8 },
|
||||
{ label: "Eylül", value: 9 },
|
||||
{ label: "Ekim", value: 10 },
|
||||
{ label: "Kasım", value: 11 },
|
||||
{ label: "Aralık", value: 12 },
|
||||
]}
|
||||
defaultValue={
|
||||
inputData?.month || { label: t(`Months.null`), value: null }
|
||||
}
|
||||
onChange={(value) => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
month: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="d-flex flex-md-row flex-column">
|
||||
{inputData?.area &&
|
||||
(inputData?.organization || selectedOrganization || inputData?.dataCenter || selectedDataCenter) && (
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="emission-scope">
|
||||
{t("EmissionSources.emissionScopes")}: *
|
||||
</Label>
|
||||
<Select
|
||||
id="emission-scope"
|
||||
isClearable={false}
|
||||
closeMenuOnSelect={true}
|
||||
maxMenuHeight={150}
|
||||
menuPlacement="auto"
|
||||
className="react-select"
|
||||
placeholder=""
|
||||
options={emissionScopesOptions}
|
||||
defaultValue={inputData?.scope || ""}
|
||||
onChange={(value) => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
scope: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="d-flex flex-md-row flex-column">
|
||||
{inputData?.area &&
|
||||
inputData?.scope &&
|
||||
(inputData?.organization || selectedOrganization || inputData?.dataCenter || selectedDataCenter) && (
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="data-sector">
|
||||
{t("EmissionSources.sector")}: *
|
||||
</Label>
|
||||
<Select
|
||||
id="data-sector"
|
||||
isClearable={false}
|
||||
closeMenuOnSelect={true}
|
||||
maxMenuHeight={150}
|
||||
menuPlacement="auto"
|
||||
className="react-select"
|
||||
placeholder=""
|
||||
options={sectorsOptions}
|
||||
defaultValue={inputData?.sector || ""}
|
||||
onChange={(value) => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
sector: value,
|
||||
subSector: "",
|
||||
mcfType: "",
|
||||
frec: "",
|
||||
burnOrOpenBurn: "",
|
||||
weightType: "",
|
||||
proteinAmount: "",
|
||||
personCount: "",
|
||||
});
|
||||
setSelectedSector(value.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{inputData?.sector && (
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="sector-subCategory">
|
||||
{t("EmissionSources.subSector")}: *
|
||||
</Label>
|
||||
<Select
|
||||
id="sector-subCategory"
|
||||
isClearable={false}
|
||||
closeMenuOnSelect={true}
|
||||
maxMenuHeight={150}
|
||||
menuPlacement="auto"
|
||||
className="react-select"
|
||||
placeholder=""
|
||||
filterOption={customFilterForSelect}
|
||||
options={subSectorsOptions}
|
||||
value={inputData?.subSector || ""}
|
||||
onChange={(value) => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
subSector: value,
|
||||
activitySubUnit: "",
|
||||
emissionSource: "",
|
||||
mcfType: "",
|
||||
frec: "",
|
||||
burnOrOpenBurn: "",
|
||||
weightType: "",
|
||||
proteinAmount: "",
|
||||
personCount: "",
|
||||
});
|
||||
setSelectedSubSector(value.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{inputData?.sector?.label != "Atık" && inputData?.subSector && (
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="activity-subunit">
|
||||
{t("EmissionSources.subUnit")}:
|
||||
</Label>
|
||||
<Select
|
||||
id="activity-subunit"
|
||||
isClearable={false}
|
||||
closeMenuOnSelect={true}
|
||||
maxMenuHeight={150}
|
||||
menuPlacement="auto"
|
||||
className="react-select"
|
||||
placeholder=""
|
||||
filterOption={customFilterForSelect}
|
||||
options={activitySubUnitsOptions}
|
||||
value={inputData?.activitySubUnit || ""}
|
||||
onChange={(value) => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
activitySubUnit: value,
|
||||
proteinAmount: "",
|
||||
personCount: "",
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{inputData?.subSector?.label != "Katı Atık Bertarafı" &&
|
||||
inputData?.subSector && (
|
||||
<>
|
||||
<div className="d-flex flex-md-row flex-column">
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="emission-source">
|
||||
{t("EmissionSources.emissionSource")}: *
|
||||
</Label>
|
||||
<Select
|
||||
id="emission-source"
|
||||
isClearable={false}
|
||||
closeMenuOnSelect={true}
|
||||
maxMenuHeight={150}
|
||||
menuPlacement="auto"
|
||||
className="react-select"
|
||||
placeholder=""
|
||||
filterOption={customFilterForSelect}
|
||||
options={emissionSourcesOptions}
|
||||
value={inputData?.emissionSource || ""}
|
||||
onChange={(value) => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
emissionSource: value,
|
||||
proteinAmount: "",
|
||||
personCount: "",
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{inputData?.emissionSource &&
|
||||
inputData?.subSector?.label ===
|
||||
"Atıkların Biyolojik Arıtılması" && (
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="weightType">
|
||||
Ağırlık Tipi:*
|
||||
</Label>
|
||||
<Select
|
||||
id="weightType"
|
||||
isClearable={false}
|
||||
closeMenuOnSelect={true}
|
||||
maxMenuHeight={150}
|
||||
menuPlacement="auto"
|
||||
className="react-select"
|
||||
placeholder=""
|
||||
options={[
|
||||
{ label: "Kuru", value: "1" },
|
||||
{ label: "Yaş", value: "2" },
|
||||
]}
|
||||
value={inputData?.weightType || ""}
|
||||
onChange={(value) => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
weightType: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{inputData?.emissionSource &&
|
||||
inputData?.subSector?.label === "Yakma ve Açık Yanma" && (
|
||||
<>
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="burnOrOpenBurn">
|
||||
Tipi:*
|
||||
</Label>
|
||||
<Select
|
||||
id="burnOrOpenBurn"
|
||||
isClearable={false}
|
||||
closeMenuOnSelect={true}
|
||||
maxMenuHeight={150}
|
||||
menuPlacement="auto"
|
||||
className="react-select"
|
||||
placeholder=""
|
||||
options={[
|
||||
{ label: "Yakma", value: true },
|
||||
{ label: "Açık Yanma", value: false },
|
||||
]}
|
||||
value={inputData?.burnOrOpenBurn || ""}
|
||||
onChange={(value) => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
burnOrOpenBurn: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="weightType">
|
||||
Ağırlık Tipi:*
|
||||
</Label>
|
||||
<Select
|
||||
id="weightType"
|
||||
isClearable={false}
|
||||
closeMenuOnSelect={true}
|
||||
maxMenuHeight={150}
|
||||
menuPlacement="auto"
|
||||
className="react-select"
|
||||
placeholder=""
|
||||
options={[
|
||||
{ label: "Kuru", value: "1" },
|
||||
{ label: "Yaş", value: "2" },
|
||||
]}
|
||||
value={inputData?.weightType || ""}
|
||||
onChange={(value) => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
weightType: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{inputData?.emissionSource?.label ===
|
||||
"Deniz, Nehir ve Göl Deşarjı" && (
|
||||
<>
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="PersonCount">
|
||||
Nüfus Miktarı (Kişi):*
|
||||
</Label>
|
||||
<Input
|
||||
id="PersonCount"
|
||||
placeholder=""
|
||||
type="text"
|
||||
value={inputData?.personCount || ""}
|
||||
onChange={(e) => {
|
||||
const inputValue = e.target.value;
|
||||
const onlyNumbers = inputValue.replace(/[^0-9]/g, "");
|
||||
setInputData({
|
||||
...inputData,
|
||||
personCount: onlyNumbers,
|
||||
});
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "e" || e.key === "E") {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="ProteinAmount">
|
||||
Kişi Başı Protein Miktarı (Kg/Kişi Yıl):*
|
||||
</Label>
|
||||
<Input
|
||||
id="ProteinAmount"
|
||||
placeholder=""
|
||||
type="text"
|
||||
value={inputData?.proteinAmount || ""}
|
||||
onChange={(e) => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
proteinAmount: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{inputData?.emissionSource && (
|
||||
<div className="d-flex flex-md-row flex-column">
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="consumption-amount">
|
||||
{inputData?.emissionSource?.label?.includes(
|
||||
"Elektrik Üretimi"
|
||||
)
|
||||
? "Üretim Miktarı"
|
||||
: t("DataInput.consumptionAmount")}
|
||||
: *
|
||||
</Label>
|
||||
<Input
|
||||
id="consumption-amount"
|
||||
placeholder="xxxxx.xx"
|
||||
type="text"
|
||||
value={inputData?.consumptionAmount || ""}
|
||||
onChange={(e) => {
|
||||
const inputValue = e.target.value;
|
||||
const onlyNumbers = inputValue.replace(/[^0-9.]/g, "");
|
||||
setInputData({
|
||||
...inputData,
|
||||
consumptionAmount: onlyNumbers,
|
||||
});
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "e" || e.key === "E") {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2 col-md-3">
|
||||
<Label className="form-label" for="consumption-unit">
|
||||
{t("DataInput.consumptionUnit")}: *
|
||||
</Label>
|
||||
<Select
|
||||
id="consumption-unit"
|
||||
isClearable={false}
|
||||
closeMenuOnSelect={true}
|
||||
maxMenuHeight={150}
|
||||
menuPlacement="auto"
|
||||
className="react-select"
|
||||
placeholder=""
|
||||
options={consuptionUnitsOptions}
|
||||
value={inputData?.consumptionUnit || ""}
|
||||
onChange={(value) => {
|
||||
setInputData({
|
||||
...inputData,
|
||||
consumptionUnit: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{inputData?.subSector?.label === "Katı Atık Bertarafı" && (
|
||||
<DataInputSolidWaste
|
||||
inputData={inputData}
|
||||
setInputData={setInputData}
|
||||
/>
|
||||
)}
|
||||
<ModalFooter className="align-items-start mb-5 flex-column">
|
||||
{inputData?.subSector && (
|
||||
<div>
|
||||
<Button
|
||||
color="primary"
|
||||
onClick={onSaveDataButtonPressed}
|
||||
disabled={
|
||||
!(
|
||||
!result &&
|
||||
inputData?.area &&
|
||||
inputData?.scope &&
|
||||
inputData?.sector &&
|
||||
inputData?.subSector &&
|
||||
(inputData?.organization || selectedOrganization || inputData?.dataCenter || selectedDataCenter) &&
|
||||
inputData?.consumptionAmount &&
|
||||
inputData?.consumptionUnit &&
|
||||
(inputData?.emissionSource ||
|
||||
(inputData?.mcfType && inputData?.frec))
|
||||
)
|
||||
}
|
||||
>
|
||||
{t("DataInput.save")}
|
||||
</Button>
|
||||
<Label className="ml-1">{"( * ) Zorunlu Alan"}</Label>
|
||||
</div>
|
||||
)}
|
||||
{resultData?.id && result && (
|
||||
<div className="d-flex flex-column mt-1">
|
||||
<Label className="form-label h5" for="input-result">
|
||||
{t("DataInput.result")}
|
||||
</Label>
|
||||
<Label className="form-label h7 mb-2">
|
||||
<span>
|
||||
CH<sub>{"4(CO\u2082e)"}</sub>
|
||||
</span>
|
||||
: {resultData.ch4 + " "}
|
||||
<span>
|
||||
tCO<sub>2</sub>e
|
||||
</span>
|
||||
</Label>
|
||||
<Label className="form-label h7 mb-2">
|
||||
<span>
|
||||
CO<sub>{"2(CO\u2082e)"}</sub>
|
||||
</span>
|
||||
: {resultData.co2 + " "}
|
||||
<span>
|
||||
tCO<sub>2</sub>e
|
||||
</span>
|
||||
</Label>
|
||||
<Label className="form-label h7 mb-2">
|
||||
<span>
|
||||
N<sub>2</sub>O<sub>{"(CO\u2082e)"}</sub>
|
||||
</span>
|
||||
: {resultData.n2o + " "}
|
||||
<span>
|
||||
tCO<sub>2</sub>e
|
||||
</span>
|
||||
</Label>
|
||||
<Label className="form-label h7 mb-2">
|
||||
{t("DataInput.total") + " "}
|
||||
<span>
|
||||
CO<sub>2</sub>e
|
||||
</span>
|
||||
: {resultData.totalEmission + " "}
|
||||
<span>
|
||||
tCO<sub>2</sub>e
|
||||
</span>
|
||||
</Label>
|
||||
<div>
|
||||
<Button
|
||||
className="mr-1"
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
history.replace("/raporlar");
|
||||
}}
|
||||
>
|
||||
{t("DataInput.directToAllDatas")}
|
||||
</Button>
|
||||
<Button color="primary" onClick={onAddNewDataButtonPresssed}>
|
||||
{t("DataInput.addNewData")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</ModalFooter>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DataInputGroup;
|
||||
6
sge-frontend/src/components/edit-numbers/index.js
Normal file
6
sge-frontend/src/components/edit-numbers/index.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export function editNumbers(number) {
|
||||
return number?.toLocaleString("tr-TR", {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { Label } from "reactstrap";
|
||||
import Factor from "../factor";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const ConstantEnergy = ({
|
||||
editingEmissionSourceData,
|
||||
setEditingEmissionSourceData,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
// useEffect(() => {
|
||||
// setEditingEmissionSourceData({
|
||||
// ...editingEmissionSourceData,
|
||||
// constantEnergy: [],
|
||||
// });
|
||||
// }, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="d-flex flex-column">
|
||||
<div className="mb-2">
|
||||
<Label className="form-label" for="energyIndustries">
|
||||
{t("EmissionSources.energyIndustries")}
|
||||
</Label>
|
||||
<Factor
|
||||
editingEmissionSourceData={editingEmissionSourceData}
|
||||
setEditingEmissionSourceData={setEditingEmissionSourceData}
|
||||
name={"energyIndustries"}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<Label className="form-label" for="manufacturings">
|
||||
{t("EmissionSources.manufacturing")}
|
||||
</Label>
|
||||
<Factor
|
||||
editingEmissionSourceData={editingEmissionSourceData}
|
||||
setEditingEmissionSourceData={setEditingEmissionSourceData}
|
||||
name={"manufacturing"}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<Label className="form-label" for="buildings">
|
||||
{t("EmissionSources.buildings")}
|
||||
</Label>
|
||||
<Factor
|
||||
editingEmissionSourceData={editingEmissionSourceData}
|
||||
setEditingEmissionSourceData={setEditingEmissionSourceData}
|
||||
name={"buildings"}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<Label className="form-label" for="homes">
|
||||
{t("EmissionSources.homes")}
|
||||
</Label>
|
||||
<Factor
|
||||
editingEmissionSourceData={editingEmissionSourceData}
|
||||
setEditingEmissionSourceData={setEditingEmissionSourceData}
|
||||
name={"homes"}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<Label className="form-label" for="agricultures">
|
||||
{t("EmissionSources.agricultures")}
|
||||
</Label>
|
||||
<Factor
|
||||
editingEmissionSourceData={editingEmissionSourceData}
|
||||
setEditingEmissionSourceData={setEditingEmissionSourceData}
|
||||
name={"agricultures"}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(ConstantEnergy);
|
||||
72
sge-frontend/src/components/emission-source/factor.js
Normal file
72
sge-frontend/src/components/emission-source/factor.js
Normal file
@@ -0,0 +1,72 @@
|
||||
import React from "react";
|
||||
import { Label, Input } from "reactstrap";
|
||||
|
||||
const Factor = ({
|
||||
editingEmissionSourceData,
|
||||
setEditingEmissionSourceData,
|
||||
name,
|
||||
}) => {
|
||||
return (
|
||||
<div className="d-flex flex-column flex-md-row">
|
||||
<div className="d-flex flex-row mr-2 align-items-center">
|
||||
<Label className="form-label w-25 mr-1" for="co2">
|
||||
CO2:
|
||||
</Label>
|
||||
<Input
|
||||
id="co2"
|
||||
type="text"
|
||||
defaultValue={editingEmissionSourceData?.[name]?.co2 || ""}
|
||||
onChange={(e) => {
|
||||
setEditingEmissionSourceData({
|
||||
...editingEmissionSourceData,
|
||||
[name]: {
|
||||
...editingEmissionSourceData?.[name],
|
||||
co2: e.target.value,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="d-flex flex-row mr-2 align-items-center">
|
||||
<Label className="form-label w-25 mr-1" for="ch4">
|
||||
CH4: (CO2e)
|
||||
</Label>
|
||||
<Input
|
||||
id="ch4"
|
||||
type="text"
|
||||
defaultValue={editingEmissionSourceData?.[name]?.ch4 || ""}
|
||||
onChange={(e) => {
|
||||
setEditingEmissionSourceData({
|
||||
...editingEmissionSourceData,
|
||||
[name]: {
|
||||
...editingEmissionSourceData?.[name],
|
||||
ch4: e.target.value,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="d-flex flex-row mr-2 align-items-center">
|
||||
<Label className="form-label w-25 mr-1" for="n2o">
|
||||
N20: (CO2e)
|
||||
</Label>
|
||||
<Input
|
||||
id="n2o"
|
||||
type="text"
|
||||
defaultValue={editingEmissionSourceData?.[name]?.n2o || ""}
|
||||
onChange={(e) => {
|
||||
setEditingEmissionSourceData({
|
||||
...editingEmissionSourceData,
|
||||
[name]: {
|
||||
...editingEmissionSourceData?.[name],
|
||||
n2o: e.target.value,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(Factor);
|
||||
70
sge-frontend/src/components/emission-source/factors/index.js
Normal file
70
sge-frontend/src/components/emission-source/factors/index.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import React from "react";
|
||||
import { Label, Input } from "reactstrap";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const Factors = ({
|
||||
editingEmissionSourceData,
|
||||
setEditingEmissionSourceData,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Label className="form-label mb-1">
|
||||
{t("EmissionSources.emissionFactors")} (kg/TJ):
|
||||
</Label>
|
||||
<div className="d-flex flex-column flex-md-row">
|
||||
<div className="d-flex flex-row mr-2 align-items-center">
|
||||
<Label className="form-label w-25 mr-1" for="co2">
|
||||
CO<sub>2</sub>:
|
||||
</Label>
|
||||
<Input
|
||||
id="co2"
|
||||
type="text"
|
||||
defaultValue={editingEmissionSourceData?.co2 || 0}
|
||||
onChange={(e) => {
|
||||
setEditingEmissionSourceData({
|
||||
...editingEmissionSourceData,
|
||||
co2: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="d-flex flex-row mr-2 align-items-center">
|
||||
<Label className="form-label w-25 mr-1" for="ch4">
|
||||
CH<sub>4</sub>: (CO<sub>2</sub>e)
|
||||
</Label>
|
||||
<Input
|
||||
id="ch4"
|
||||
type="text"
|
||||
defaultValue={editingEmissionSourceData?.ch4 || 0}
|
||||
onChange={(e) => {
|
||||
setEditingEmissionSourceData({
|
||||
...editingEmissionSourceData,
|
||||
ch4: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="d-flex flex-row mr-2 align-items-center">
|
||||
<Label className="form-label w-25 mr-1" for="n2o">
|
||||
N<sub>2</sub>O: (CO<sub>2</sub>e)
|
||||
</Label>
|
||||
<Input
|
||||
id="n2o"
|
||||
type="text"
|
||||
defaultValue={editingEmissionSourceData?.n2o || 0}
|
||||
onChange={(e) => {
|
||||
setEditingEmissionSourceData({
|
||||
...editingEmissionSourceData,
|
||||
n2o: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(Factors);
|
||||
85
sge-frontend/src/components/export-excel/index.js
Normal file
85
sge-frontend/src/components/export-excel/index.js
Normal file
@@ -0,0 +1,85 @@
|
||||
import * as FileSaver from "file-saver";
|
||||
import * as XLSX from "xlsx";
|
||||
import { editNumbers } from "../edit-numbers";
|
||||
|
||||
export function ExportToExcel({ exportData, exportColumns, t }) {
|
||||
const fileType =
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8";
|
||||
const fileExtension = ".xlsx";
|
||||
|
||||
const filteredColumns = exportColumns.filter(
|
||||
(a) => a.header !== "Aksiyonlar" && a.accessorKey !== "area"
|
||||
);
|
||||
|
||||
const areaName =
|
||||
exportData?.[0]?.district?.name ||
|
||||
exportData?.[0]?.city?.name ||
|
||||
exportData?.[0]?.neighborhood?.name;
|
||||
|
||||
const formattedData = exportData.map((item) =>
|
||||
filteredColumns.reduce((acc, column) => {
|
||||
if (item[column.accessorKey]?.id) {
|
||||
acc[column.header] = String(
|
||||
item[column.accessorKey]?.tag ||
|
||||
item[column.accessorKey]?.name ||
|
||||
item[column.accessorKey]?.referenceNumber
|
||||
);
|
||||
} else if (column.accessorKey === "month") {
|
||||
acc[column.header] =
|
||||
item[column.accessorKey] != undefined
|
||||
? t(`Months.${item[column.accessorKey]}`)
|
||||
: "";
|
||||
} else if (column.accessorKey === "scopeCheck") {
|
||||
acc[column.header] =
|
||||
item[column.accessorKey] === true
|
||||
? "Şehir Dışı"
|
||||
: item[column.accessorKey] === false
|
||||
? "Şehir İçi"
|
||||
: "";
|
||||
} else if (column.accessorKey === "co2") {
|
||||
acc["CO\u2082 Ton CO\u2082e"] = editNumbers(item[column.accessorKey]);
|
||||
} else if (column.accessorKey === "ch4") {
|
||||
acc["CH\u2084 (CO\u2082e) Ton CO\u2082e"] = editNumbers(
|
||||
item[column.accessorKey]
|
||||
);
|
||||
} else if (column.accessorKey === "n2o") {
|
||||
acc["N\u2082O (CO\u2082e) Ton CO\u2082e"] = editNumbers(
|
||||
item[column.accessorKey]
|
||||
);
|
||||
} else if (column.accessorKey === "totalEmission") {
|
||||
acc["Toplam (CO\u2082e) Ton CO\u2082e"] = editNumbers(
|
||||
item[column.accessorKey]
|
||||
);
|
||||
} else {
|
||||
if (column.accessorKey.endsWith(".tag")) {
|
||||
const newAccessorKey = column.accessorKey.slice(0, -4); // Remove '.tag' from the end
|
||||
acc[column.header] = item[newAccessorKey]?.tag;
|
||||
} else {
|
||||
acc[column.header] = editNumbers(item[column.accessorKey]);
|
||||
}
|
||||
}
|
||||
return acc;
|
||||
}, {})
|
||||
);
|
||||
|
||||
const worksheet = XLSX.utils.json_to_sheet(formattedData, {
|
||||
origin: "A2", // Specify the starting cell for writing data (A2)
|
||||
});
|
||||
|
||||
XLSX.utils.sheet_add_aoa(worksheet, [[areaName]], {
|
||||
origin: "A1",
|
||||
});
|
||||
|
||||
const columnWidths = filteredColumns.map(() => ({ width: 25 }));
|
||||
worksheet["!cols"] = columnWidths;
|
||||
|
||||
const workbook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, "Data");
|
||||
|
||||
const excelBuffer = XLSX.write(workbook, {
|
||||
bookType: "xlsx",
|
||||
type: "array",
|
||||
});
|
||||
const data = new Blob([excelBuffer], { type: fileType });
|
||||
FileSaver.saveAs(data, areaName + fileExtension);
|
||||
}
|
||||
252
sge-frontend/src/components/graphics/index.js
Normal file
252
sge-frontend/src/components/graphics/index.js
Normal file
@@ -0,0 +1,252 @@
|
||||
import { Bar, Pie, Doughnut } from "react-chartjs-2";
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
ArcElement,
|
||||
Tooltip,
|
||||
Legend,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
BarElement,
|
||||
Title,
|
||||
} from "chart.js";
|
||||
import ChartDataLabels from "chartjs-plugin-datalabels";
|
||||
import { editNumbers } from "../edit-numbers";
|
||||
|
||||
ChartJS.register(
|
||||
ArcElement,
|
||||
Tooltip,
|
||||
Legend,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
BarElement,
|
||||
Title,
|
||||
ChartDataLabels
|
||||
);
|
||||
|
||||
export const PieChart = ({
|
||||
data,
|
||||
setIndexNumber,
|
||||
indexNumber,
|
||||
type,
|
||||
colors,
|
||||
}) => {
|
||||
if (type === "subSector") {
|
||||
data = data[indexNumber]?.filter((a) => a.subSector.tag != "Genel Toplam");
|
||||
}
|
||||
|
||||
const subSectorColors = colors.slice(3);
|
||||
|
||||
const chartData = {
|
||||
labels:
|
||||
type === "sector"
|
||||
? data.map((item) => item.sector.tag)
|
||||
: data.map((item) => item.subSector.tag),
|
||||
datasets: [
|
||||
{
|
||||
data: data.map((item) => item.totalEmission),
|
||||
backgroundColor: type === "sector" ? colors : subSectorColors,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const options = {
|
||||
onClick: function (evt, element) {
|
||||
if (element.length > 0 && type === "sector") {
|
||||
setIndexNumber(element[0].index);
|
||||
//console.log(chartData.labels[element[0].index]); // sector/subsector tag
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text:
|
||||
type === "sector"
|
||||
? "Sektörlere Göre Sera Gazı Emisyonları"
|
||||
: "Alt Sektöre Göre Sera Gazı Emisyonları",
|
||||
font: {
|
||||
size: 30,
|
||||
family: "Montserrat",
|
||||
weight: "normal",
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
position: "top",
|
||||
labels: {
|
||||
font: {
|
||||
size: 15,
|
||||
family: "Montserrat",
|
||||
weight: "normal",
|
||||
},
|
||||
},
|
||||
},
|
||||
datalabels: {
|
||||
formatter: function (value, context) {
|
||||
const percentage = (
|
||||
(value / context.chart.getDatasetMeta(0).total) *
|
||||
100
|
||||
).toFixed(2);
|
||||
return percentage === "0.00"
|
||||
? null
|
||||
: type === "sector"
|
||||
? [context.chart.data.labels[context.dataIndex], percentage + "%"]
|
||||
: [percentage + "%"];
|
||||
},
|
||||
color: "white",
|
||||
anchor: "center",
|
||||
align: "center",
|
||||
font: {
|
||||
size: 23,
|
||||
family: "Montserrat",
|
||||
weight: "normal",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return <Pie data={chartData} options={options} />;
|
||||
};
|
||||
|
||||
export const VerticalBarChart = ({ data, filterSubSector, colors }) => {
|
||||
data = data?.filter((data) => data.subSector?.tag !== "Genel Toplam");
|
||||
let newData = data?.filter(
|
||||
(data) => filterSubSector?.[data.subSector.tag] != false
|
||||
);
|
||||
|
||||
const totalEmission = newData?.reduce(
|
||||
(acc, item) => acc + item.totalEmission,
|
||||
0
|
||||
);
|
||||
const chartData = {
|
||||
labels: newData.map((item) => item.subSector?.tag || ""),
|
||||
datasets: [
|
||||
{
|
||||
data: newData.map((item) =>
|
||||
((item.totalEmission / totalEmission) * 100).toFixed(2)
|
||||
),
|
||||
backgroundColor: [colors[0]],
|
||||
totalEmission: newData.map((item) => editNumbers(item.totalEmission)),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const options = {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: `${newData?.[0]?.sector?.tag} SGE Dağılımı`,
|
||||
padding: {
|
||||
bottom: 50,
|
||||
},
|
||||
font: {
|
||||
size: 30,
|
||||
family: "Montserrat",
|
||||
weight: "normal",
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: (context) =>
|
||||
`${context.dataset.totalEmission[context.dataIndex]} tCO₂e`,
|
||||
},
|
||||
},
|
||||
datalabels: {
|
||||
anchor: "end",
|
||||
align: "end",
|
||||
font: {
|
||||
size: 23,
|
||||
family: "Montserrat",
|
||||
weight: "normal",
|
||||
},
|
||||
formatter: (value, context) =>
|
||||
`${context.dataset.totalEmission[context.dataIndex]} tCO₂e`,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
ticks: {
|
||||
callback: (value) => `${value}%`,
|
||||
font: {
|
||||
size: 20,
|
||||
family: "Montserrat",
|
||||
weight: "normal",
|
||||
},
|
||||
},
|
||||
},
|
||||
x: {
|
||||
ticks: {
|
||||
font: {
|
||||
size: 20,
|
||||
family: "Montserrat",
|
||||
weight: "normal",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
barThickness: 70,
|
||||
};
|
||||
|
||||
return <Bar data={chartData} options={options} />;
|
||||
};
|
||||
|
||||
export const DoughnutChart = ({ data, colors }) => {
|
||||
const filteredData = data?.filter(
|
||||
(data) => data.emissionSource?.tag !== "Genel Toplam"
|
||||
);
|
||||
|
||||
const chartData = {
|
||||
labels: filteredData.map((item) => item.emissionSource?.tag || ""),
|
||||
datasets: [
|
||||
{
|
||||
data: filteredData.map((item) => item.totalEmission),
|
||||
backgroundColor: colors,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const options = {
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: `${data[0].subSector.tag} Yakıt Bazlı Sera Gazı Emisyon Miktarları`,
|
||||
font: {
|
||||
size: 30,
|
||||
family: "Montserrat",
|
||||
weight: "normal",
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
position: "top",
|
||||
labels: {
|
||||
font: {
|
||||
size: 15,
|
||||
family: "Montserrat",
|
||||
weight: "normal",
|
||||
},
|
||||
},
|
||||
},
|
||||
datalabels: {
|
||||
formatter: function (value, context) {
|
||||
const percentage = (
|
||||
(value / context.chart.getDatasetMeta(0).total) *
|
||||
100
|
||||
).toFixed(2);
|
||||
return percentage === "0.00" ? null : [percentage + "%"];
|
||||
},
|
||||
color: "white",
|
||||
anchor: "center",
|
||||
align: "center",
|
||||
font: {
|
||||
size: 23,
|
||||
family: "Montserrat",
|
||||
weight: "normal",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
return <Doughnut data={chartData} options={options} />;
|
||||
};
|
||||
12
sge-frontend/src/components/leaflet.css
Normal file
12
sge-frontend/src/components/leaflet.css
Normal file
@@ -0,0 +1,12 @@
|
||||
.leaflet-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
color: black;
|
||||
font-weight: 800;
|
||||
background-color: white;
|
||||
border: 0;
|
||||
border-radius: 5px;
|
||||
}
|
||||
23
sge-frontend/src/components/logout-timer/index.js
Normal file
23
sge-frontend/src/components/logout-timer/index.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import { useEffect } from "react";
|
||||
|
||||
const LogoutTimer = () => {
|
||||
useEffect(() => {
|
||||
const resetTimerOnInteraction = () => {
|
||||
localStorage.setItem("lastActivity", Date.now().toString());
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", resetTimerOnInteraction);
|
||||
window.addEventListener("touchstart", resetTimerOnInteraction);
|
||||
window.addEventListener("click", resetTimerOnInteraction);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("keydown", resetTimerOnInteraction);
|
||||
window.removeEventListener("touchstart", resetTimerOnInteraction);
|
||||
window.removeEventListener("click", resetTimerOnInteraction);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default LogoutTimer;
|
||||
@@ -0,0 +1,137 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Label, Input } from "reactstrap";
|
||||
import Select from "react-select";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { getMcfTypes } from "../../redux/actions/datas";
|
||||
|
||||
const DataUpdateSolidWaste = ({ editingDataInput, setEditingDataInput }) => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const datasStore = useSelector((state) => state.datas);
|
||||
const [mcfTypesOptions, setMcfTypesOptions] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
setMcfTypesOptions(
|
||||
datasStore?.mcfTypes?.map((mcfType) => {
|
||||
return {
|
||||
value: mcfType?.id,
|
||||
label: `${mcfType?.typeName} (${mcfType?.value})`,
|
||||
};
|
||||
})
|
||||
);
|
||||
}, [datasStore?.mcfTypes]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(getMcfTypes());
|
||||
}, []);
|
||||
|
||||
let solidWasteTypes = [
|
||||
{ label: "Evsel", value: "domestic" },
|
||||
{ label: "Bahçe", value: "garden" },
|
||||
{ label: "Kağıt", value: "paper" },
|
||||
{ label: "Ağaç", value: "tree" },
|
||||
{ label: "Tekstil", value: "textile" },
|
||||
{ label: "Endüstriyel", value: "industrial" },
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-2">
|
||||
<Label className="form-label" for="solid-waste-types">
|
||||
Atık Türü:
|
||||
</Label>
|
||||
{solidWasteTypes.map((type, index) => (
|
||||
<div className="d-flex flex-md-row flex-column" key={index}>
|
||||
<div className="mb-2 col-3">
|
||||
<Label className="form-label" for="solid-waste-type">
|
||||
{type.label}:
|
||||
</Label>
|
||||
</div>
|
||||
<div className="mb-2 col-6">
|
||||
<Input
|
||||
id="solid-waste-type"
|
||||
placeholder="0-100"
|
||||
type="text"
|
||||
value={editingDataInput?.[type.value]?.inputValue || ""}
|
||||
onChange={(e) => {
|
||||
const inputValue = e.target.value;
|
||||
const onlyNumbers = inputValue.replace(/[^0-9]/g, "");
|
||||
const parsedNumber = Math.min(
|
||||
100,
|
||||
Math.max(0, parseInt(onlyNumbers, 10))
|
||||
);
|
||||
setEditingDataInput({
|
||||
...editingDataInput,
|
||||
[type.value]: {
|
||||
...editingDataInput?.[type.value],
|
||||
inputValue: parsedNumber,
|
||||
},
|
||||
});
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "e" || e.key === "E") {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<Label className="form-label" for="mcfType">
|
||||
MCF:
|
||||
</Label>
|
||||
<Select
|
||||
id="mcfType"
|
||||
isClearable={false}
|
||||
closeMenuOnSelect={true}
|
||||
maxMenuHeight={150}
|
||||
menuPlacement="auto"
|
||||
className="react-select"
|
||||
placeholder=""
|
||||
options={mcfTypesOptions}
|
||||
value={editingDataInput?.mcfType || ""}
|
||||
onChange={(value) => {
|
||||
setEditingDataInput({
|
||||
...editingDataInput,
|
||||
mcfType: value,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<Label className="form-label" for="frec">
|
||||
Metan Yakalama Oranı %:
|
||||
</Label>
|
||||
<Input
|
||||
id="frec"
|
||||
placeholder="0-100"
|
||||
type="text"
|
||||
value={editingDataInput?.frec || ""}
|
||||
onChange={(e) => {
|
||||
const inputValue = e.target.value;
|
||||
const onlyNumbers = inputValue.replace(/[^0-9]/g, "");
|
||||
const parsedNumber = Math.min(
|
||||
100,
|
||||
Math.max(0, parseInt(onlyNumbers, 10))
|
||||
);
|
||||
setEditingDataInput({
|
||||
...editingDataInput,
|
||||
frec: parsedNumber,
|
||||
});
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "e" || e.key === "E") {
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DataUpdateSolidWaste;
|
||||
92
sge-frontend/src/components/map.js
Normal file
92
sge-frontend/src/components/map.js
Normal file
@@ -0,0 +1,92 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import {
|
||||
MapContainer,
|
||||
Marker,
|
||||
TileLayer,
|
||||
useMap,
|
||||
useMapEvents,
|
||||
} from "react-leaflet";
|
||||
import { Icon } from "leaflet";
|
||||
import markerIconPng from "leaflet/dist/images/marker-icon.png";
|
||||
import "./leaflet.css";
|
||||
|
||||
const MapComponent = ({
|
||||
editingNeighborhoodData,
|
||||
setEditingNeighborhoodData,
|
||||
}) => {
|
||||
const [position, setPosition] = useState({
|
||||
lat: Number(editingNeighborhoodData?.lat) || 39.92,
|
||||
lng: Number(editingNeighborhoodData?.long) || 32.8,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setEditingNeighborhoodData({
|
||||
...editingNeighborhoodData,
|
||||
lat: position.lat,
|
||||
long: position.lng,
|
||||
});
|
||||
}, [position]);
|
||||
|
||||
useEffect(() => {
|
||||
if (editingNeighborhoodData?.lat && editingNeighborhoodData?.long) {
|
||||
setPosition({
|
||||
lat: editingNeighborhoodData?.lat,
|
||||
lng: editingNeighborhoodData?.long,
|
||||
});
|
||||
}
|
||||
}, [editingNeighborhoodData?.lat, editingNeighborhoodData?.long]);
|
||||
|
||||
function ClickOnMap() {
|
||||
const map = useMapEvents({
|
||||
click: (event) => {
|
||||
const { lat, lng } = event.latlng;
|
||||
setPosition({
|
||||
lat: lat.toFixed(6),
|
||||
lng: lng.toFixed(6),
|
||||
});
|
||||
setEditingNeighborhoodData({
|
||||
...editingNeighborhoodData,
|
||||
lat: position.lat,
|
||||
long: position.lng,
|
||||
});
|
||||
},
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
function ChangeCenter({ center }) {
|
||||
const map = useMap();
|
||||
map.setView(center);
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<MapContainer
|
||||
center={position}
|
||||
zoom={13}
|
||||
scrollWheelZoom={false}
|
||||
style={{ height: "300px", zIndex: 0 }}
|
||||
>
|
||||
<ChangeCenter center={position} />
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
/>
|
||||
<ClickOnMap />
|
||||
{editingNeighborhoodData?.lat && editingNeighborhoodData?.long && (
|
||||
<Marker
|
||||
position={position}
|
||||
icon={
|
||||
new Icon({
|
||||
iconUrl: markerIconPng,
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41],
|
||||
})
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</MapContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default MapComponent;
|
||||
219
sge-frontend/src/components/password-change/index.js
Normal file
219
sge-frontend/src/components/password-change/index.js
Normal file
@@ -0,0 +1,219 @@
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useDispatch } from "react-redux";
|
||||
import {
|
||||
Button,
|
||||
Input,
|
||||
Label,
|
||||
Modal,
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
ModalFooter,
|
||||
} from "reactstrap";
|
||||
import { updatePassword } from "../../redux/actions/user/index";
|
||||
import { useSnackbar } from "notistack";
|
||||
|
||||
const PasswordModal = ({ showPasswordModal, setShowPasswordModal, userId }) => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [editingPasswordData, setEditingPasswordData] = useState({
|
||||
oldPassword: "",
|
||||
newPassword: "",
|
||||
newConfirmPassword: "",
|
||||
});
|
||||
const [passwordError, setPasswordError] = useState({
|
||||
oldPassword: "",
|
||||
newPassword: "",
|
||||
newConfirmPassword: "",
|
||||
});
|
||||
|
||||
const onInputChange = (e) => {
|
||||
const { name, value } = e.target;
|
||||
setEditingPasswordData((prev) => ({
|
||||
...prev,
|
||||
[name]: value,
|
||||
}));
|
||||
validateInput(e);
|
||||
};
|
||||
|
||||
const validateInput = (e) => {
|
||||
let { name, value } = e.target;
|
||||
setPasswordError((prev) => {
|
||||
const stateObj = { ...prev, [name]: "" };
|
||||
|
||||
switch (name) {
|
||||
case "oldPassword":
|
||||
if (!value) {
|
||||
stateObj[name] =
|
||||
t("PasswordLabel.oldPassword") +
|
||||
t("PasswordLabel.cannotbeleftblank");
|
||||
}
|
||||
break;
|
||||
|
||||
case "newPassword":
|
||||
if (!value) {
|
||||
stateObj[name] =
|
||||
t("PasswordLabel.newPassword") +
|
||||
t("PasswordLabel.cannotbeleftblank");
|
||||
} else if (
|
||||
editingPasswordData.newConfirmPassword &&
|
||||
value !== editingPasswordData.newConfirmPassword
|
||||
) {
|
||||
stateObj["newConfirmPassword"] = t("PasswordLabel.passwordNotSame");
|
||||
} else {
|
||||
stateObj["newConfirmPassword"] =
|
||||
editingPasswordData.newConfirmPassword
|
||||
? ""
|
||||
: passwordError.newConfirmPassword;
|
||||
}
|
||||
break;
|
||||
|
||||
case "newConfirmPassword":
|
||||
if (!value) {
|
||||
stateObj[name] =
|
||||
t("PasswordLabel.newConfirmPassword") +
|
||||
t("PasswordLabel.cannotbeleftblank");
|
||||
} else if (
|
||||
editingPasswordData.newPassword &&
|
||||
value !== editingPasswordData.newPassword
|
||||
) {
|
||||
stateObj[name] = t("PasswordLabel.passwordNotSame");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return stateObj;
|
||||
});
|
||||
};
|
||||
|
||||
const isPassword = (password) =>
|
||||
/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,20}$/.test(password);
|
||||
|
||||
const onUpdatePasswordModalButtonPressed = () => {
|
||||
if (!isPassword(editingPasswordData.newPassword)) {
|
||||
setPasswordError({
|
||||
...passwordError,
|
||||
newPassword: t("PasswordLabel.passwordValidation"),
|
||||
});
|
||||
} else if (
|
||||
passwordError.oldPassword === "" &&
|
||||
passwordError.newPassword === "" &&
|
||||
passwordError.newConfirmPassword === ""
|
||||
) {
|
||||
setLoading(true);
|
||||
let newPassword = editingPasswordData?.newPassword;
|
||||
let oldPassword = editingPasswordData?.oldPassword;
|
||||
dispatch(updatePassword({ newPassword, oldPassword, userId }))
|
||||
.then(() => {
|
||||
enqueueSnackbar(t("Warnings.updatedSuccessfully"), {
|
||||
variant: "success",
|
||||
});
|
||||
setLoading(false);
|
||||
setShowPasswordModal(!showPasswordModal);
|
||||
})
|
||||
.catch((e) => {
|
||||
setLoading(false);
|
||||
if (e === "5030") {
|
||||
enqueueSnackbar(`Eski şifre hatalıdır!`, {
|
||||
variant: "error",
|
||||
});
|
||||
} else {
|
||||
enqueueSnackbar(` ${t("Warnings.updatedFail")},`, {
|
||||
variant: "error",
|
||||
});
|
||||
}
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={showPasswordModal}
|
||||
toggle={() => setShowPasswordModal(!showPasswordModal)}
|
||||
className="modal-dialog-centered"
|
||||
>
|
||||
<ModalHeader toggle={() => setShowPasswordModal(!showPasswordModal)}>
|
||||
{t("UserProfile.changePassword")}
|
||||
</ModalHeader>
|
||||
<ModalBody>
|
||||
<div className="mb-2">
|
||||
<Label className="form-label" for="old-password">
|
||||
{t("PasswordLabel.oldPassword")}
|
||||
</Label>
|
||||
<Input
|
||||
id="old-password"
|
||||
type="password"
|
||||
name="oldPassword"
|
||||
placeholder={t("PasswordLabel.oldPassword")}
|
||||
value={editingPasswordData?.oldPassword}
|
||||
onChange={onInputChange}
|
||||
onBlur={validateInput}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<Label className="form-label" for="new-password">
|
||||
{t("PasswordLabel.newPassword")}
|
||||
</Label>
|
||||
<Input
|
||||
type="password"
|
||||
id="new-password"
|
||||
name="newPassword"
|
||||
placeholder={t("PasswordLabel.newPassword")}
|
||||
value={editingPasswordData?.newPassword}
|
||||
onChange={onInputChange}
|
||||
onBlur={validateInput}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<Label className="form-label" for="new-password-confirm">
|
||||
{t("PasswordLabel.newConfirmPassword")}
|
||||
</Label>
|
||||
<Input
|
||||
type="password"
|
||||
id="new-password-confirm"
|
||||
name="newConfirmPassword"
|
||||
placeholder={t("PasswordLabel.newConfirmPassword")}
|
||||
value={editingPasswordData?.newConfirmPassword}
|
||||
onChange={onInputChange}
|
||||
onBlur={validateInput}
|
||||
/>
|
||||
</div>
|
||||
{(passwordError.oldPassword ||
|
||||
passwordError.newPassword ||
|
||||
passwordError.newConfirmPassword) && (
|
||||
<div className="mt-2 d-flex flex-column">
|
||||
<span className="text-danger">{passwordError.oldPassword}</span>
|
||||
<span className="text-danger">{passwordError.newPassword}</span>
|
||||
<span className="text-danger">
|
||||
{passwordError.newConfirmPassword}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button
|
||||
disabled={
|
||||
!(
|
||||
editingPasswordData?.oldPassword &&
|
||||
editingPasswordData?.newPassword &&
|
||||
editingPasswordData?.newConfirmPassword
|
||||
)
|
||||
}
|
||||
color="primary"
|
||||
onClick={onUpdatePasswordModalButtonPressed}
|
||||
>
|
||||
{loading ? t("Cruds.saving") : t("Cruds.save")}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default PasswordModal;
|
||||
34
sge-frontend/src/components/pdf-header/index.js
Normal file
34
sge-frontend/src/components/pdf-header/index.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import React from "react";
|
||||
import { Row } from "reactstrap";
|
||||
|
||||
const PdfHeader = ({ areaName, year }) => {
|
||||
return (
|
||||
<Row className="mx-0 mt-2 mb-5 p-2 border-bottom">
|
||||
<div className="d-flex align-items-center justify-content-between">
|
||||
<div>
|
||||
<img alt="SecapSoft" src="./Secapsoft.png" width={"110"} height={"110"} />
|
||||
</div>
|
||||
<div>
|
||||
<span style={{ fontSize: "30px", fontWeight: "bold" }}>
|
||||
{areaName} Sera Gazı Emisyonu {year} Yılı Envanteri
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<img
|
||||
alt="Enerji İstanbul"
|
||||
src="./enerji-istanbul-logo.png"
|
||||
width={"200"}
|
||||
height={"80"}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
||||
export default PdfHeader;
|
||||
|
||||
6
sge-frontend/src/components/permission-check/index.js
Normal file
6
sge-frontend/src/components/permission-check/index.js
Normal file
@@ -0,0 +1,6 @@
|
||||
const permissions = JSON.parse(localStorage.getItem("permissions"));
|
||||
const permissionsList = permissions?.map(({ tag }) => tag);
|
||||
|
||||
export function permissionCheck(permission) {
|
||||
return permissionsList?.includes(permission);
|
||||
}
|
||||
@@ -0,0 +1,402 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Col, Label, Row } from "reactstrap";
|
||||
import DataTable from "react-data-table-component";
|
||||
import { editNumbers } from "../edit-numbers";
|
||||
import { VerticalBarChart } from "../graphics";
|
||||
import PdfHeader from "../pdf-header";
|
||||
|
||||
const ConstantEnergyGraphics = ({
|
||||
mainDataTablesFilterByYear,
|
||||
constantEnergyData,
|
||||
isPDFDownloading,
|
||||
hideTables,
|
||||
colors,
|
||||
hideComponents,
|
||||
handleCheckboxChange,
|
||||
areaName,
|
||||
year,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [scopeOfConstantEnergyData, setScopeOfConstantEnergyData] = useState(
|
||||
[]
|
||||
);
|
||||
const [filterSubSector, setFilterSubSector] = useState({});
|
||||
|
||||
const serverSideColumnsOfConstantEmergy = [
|
||||
{
|
||||
name: t("EmissionSources.subSector"),
|
||||
selector: (row) => row.subSector,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight:
|
||||
row?.subSector?.tag === "Genel Toplam" ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{row.subSector?.tag || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: `Sera Gazı Miktarı (${t("DataInput.total")} tCO₂e)`,
|
||||
selector: (row) => row.selector,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight:
|
||||
row?.subSector?.tag === "Genel Toplam" ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{editNumbers(row.totalEmission) || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: `${t("Oransal Dağılım")} %`,
|
||||
selector: (row) => row.percentage,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight:
|
||||
row?.subSector?.tag === "Genel Toplam" ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{row.percentage + "%" || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const serverSideColumnsOfScopeOfConstantEmergy = [
|
||||
{
|
||||
name: t("EmissionSources.subSector"),
|
||||
selector: (row) => row.subSector,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight: !row?.emissionSource?.tag ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{row.subSector?.tag || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: t("EmissionSources.emissionSource"),
|
||||
selector: (row) => row.emissionSource,
|
||||
sortable: false,
|
||||
cell: (row) => <span>{row.emissionSource?.tag || ""}</span>,
|
||||
},
|
||||
{
|
||||
name: `Sera Gazı Miktarı (${t("DataInput.total")} tCO₂e)`,
|
||||
selector: (row) => row.totalEmission,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight: !row?.emissionSource?.tag ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{editNumbers(row.totalEmission) || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: t("EmissionSources.emissionScopes"),
|
||||
selector: (row) => row.emissionScopes,
|
||||
sortable: false,
|
||||
cell: (row) => <span>{row.emissionScope?.tag || "-"}</span>,
|
||||
},
|
||||
];
|
||||
|
||||
const calculateScopeData = (filteredData) => {
|
||||
if (!filteredData || filteredData.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const reduceByEmissionSourceData = filteredData.reduce((result, item) => {
|
||||
const existingItem = result.find(
|
||||
(resultItem) => resultItem.emissionSource.id === item.emissionSource.id
|
||||
);
|
||||
if (existingItem) {
|
||||
existingItem.totalEmission += item.totalEmission;
|
||||
} else {
|
||||
result.push({
|
||||
emissionSource: item.emissionSource,
|
||||
subSector: item.subSector,
|
||||
emissionScope: item.emissionScope,
|
||||
totalEmission: item.totalEmission,
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}, []);
|
||||
|
||||
let totalEmission = 0;
|
||||
for (let i = 0; i < reduceByEmissionSourceData.length; i++) {
|
||||
totalEmission += reduceByEmissionSourceData[i].totalEmission;
|
||||
}
|
||||
|
||||
const lastItem = {
|
||||
subSector: {
|
||||
tag: `${reduceByEmissionSourceData[0]?.subSector.tag} Toplamı`,
|
||||
},
|
||||
totalEmission: `${editNumbers(totalEmission)}`,
|
||||
};
|
||||
|
||||
return [...reduceByEmissionSourceData, lastItem];
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
mainDataTablesFilterByYear?.length > 0 &&
|
||||
constantEnergyData?.length > 0
|
||||
) {
|
||||
const newConstantEnergyData = mainDataTablesFilterByYear.filter(
|
||||
(data) => data.sector?.tag === "Sabit Enerji"
|
||||
);
|
||||
|
||||
const groupedArray = newConstantEnergyData.reduce((result, item) => {
|
||||
const subSectorId = item.subSector.id;
|
||||
if (result[subSectorId]) {
|
||||
result[subSectorId].push(item);
|
||||
} else {
|
||||
result[subSectorId] = [item];
|
||||
}
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
const groupedArrayValues = Object.values(groupedArray);
|
||||
const newData = groupedArrayValues.flatMap((group) =>
|
||||
calculateScopeData(group)
|
||||
);
|
||||
|
||||
setScopeOfConstantEnergyData([
|
||||
...newData,
|
||||
constantEnergyData[constantEnergyData.length - 1],
|
||||
]);
|
||||
}
|
||||
}, [constantEnergyData]);
|
||||
|
||||
useEffect(() => {
|
||||
const initialFilterSubSector = constantEnergyData
|
||||
.filter((data) => data.subSector.tag !== "Genel Toplam")
|
||||
.reduce((acc, data) => {
|
||||
return {
|
||||
...acc,
|
||||
[data.subSector.tag]: true,
|
||||
};
|
||||
}, {});
|
||||
|
||||
setFilterSubSector(initialFilterSubSector);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="graphics-container2">
|
||||
{isPDFDownloading && <PdfHeader areaName={areaName} year={year} />}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
marginTop: "20px",
|
||||
boxShadow: !isPDFDownloading
|
||||
? "rgba(2, 138, 74, 0.1) 0px 0px 19px 0px"
|
||||
: "",
|
||||
}}
|
||||
>
|
||||
<h1
|
||||
style={{
|
||||
fontSize: `${isPDFDownloading ? "45px" : ""}`,
|
||||
}}
|
||||
className="text-center p-2"
|
||||
>
|
||||
Sabit Enerji
|
||||
</h1>
|
||||
</div>
|
||||
<Row className="mx-0 mt-2 mb-50 justify-content-center">
|
||||
{!hideTables &&
|
||||
!(
|
||||
isPDFDownloading &&
|
||||
hideComponents["constant-energy-subSector-dataTable"]
|
||||
) && (
|
||||
<Col sm="9" md="9">
|
||||
{!isPDFDownloading && (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={
|
||||
!hideComponents["constant-energy-subSector-dataTable"]
|
||||
}
|
||||
onChange={() =>
|
||||
handleCheckboxChange(
|
||||
"constant-energy-subSector-dataTable"
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<DataTable
|
||||
title={
|
||||
<h5
|
||||
style={{
|
||||
textAlign: "end",
|
||||
fontWeight: "bold",
|
||||
fontSize: `${isPDFDownloading ? "30px" : ""}`,
|
||||
}}
|
||||
>
|
||||
Sabit Enerji Sektörü Sera Gazı Emisyonları
|
||||
</h5>
|
||||
}
|
||||
className="react-dataTable mt-1 border-black"
|
||||
columns={serverSideColumnsOfConstantEmergy}
|
||||
data={constantEnergyData}
|
||||
noDataComponent={
|
||||
<p className="p-2">
|
||||
{t("DataInput.report")}
|
||||
{t("Warnings.notFound")}
|
||||
</p>
|
||||
}
|
||||
customStyles={
|
||||
isPDFDownloading
|
||||
? {
|
||||
rows: {
|
||||
fontSize: "25px",
|
||||
},
|
||||
headCells: {
|
||||
style: {
|
||||
fontSize: "23px",
|
||||
},
|
||||
},
|
||||
}
|
||||
: ""
|
||||
}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
<Row className="mt-5 justify-content-center">
|
||||
{!(
|
||||
isPDFDownloading &&
|
||||
hideComponents["constant-energy-subSector-chart"]
|
||||
) && (
|
||||
<Col sm="9" md="9" className="mt-5">
|
||||
{!isPDFDownloading && (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={!hideComponents["constant-energy-subSector-chart"]}
|
||||
onChange={() =>
|
||||
handleCheckboxChange("constant-energy-subSector-chart")
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<VerticalBarChart
|
||||
data={constantEnergyData}
|
||||
filterSubSector={filterSubSector}
|
||||
colors={colors}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
{!isPDFDownloading && (
|
||||
<Col sm="1" md="1" className="mt-5">
|
||||
<Label>{t("Show")}</Label>
|
||||
{constantEnergyData
|
||||
.filter((data) => data.subSector.tag != "Genel Toplam")
|
||||
.map((data, index) => (
|
||||
<div className="form-check form-switch mb-2" key={index}>
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
id={data.subSector.tag}
|
||||
checked={
|
||||
filterSubSector?.[data.subSector.tag] === true
|
||||
? true
|
||||
: false
|
||||
}
|
||||
onChange={(e) => {
|
||||
setFilterSubSector({
|
||||
...filterSubSector,
|
||||
[data.subSector.tag]: e.target.checked,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<label
|
||||
className="form-check-label h6"
|
||||
htmlFor={data.subSector.tag}
|
||||
>
|
||||
{data.subSector.tag}
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<div id="graphics-container3">
|
||||
{isPDFDownloading && <PdfHeader areaName={areaName} year={year} />}
|
||||
<Row className="mt-2 justify-content-center">
|
||||
{!hideTables &&
|
||||
!(
|
||||
isPDFDownloading &&
|
||||
hideComponents["constant-energy-scope-dataTable"]
|
||||
) && (
|
||||
<Col sm="9" md="9">
|
||||
{!isPDFDownloading && (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={!hideComponents["constant-energy-scope-dataTable"]}
|
||||
onChange={() =>
|
||||
handleCheckboxChange("constant-energy-scope-dataTable")
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<DataTable
|
||||
title={
|
||||
<h5
|
||||
style={{
|
||||
textAlign: "end",
|
||||
fontWeight: "bold",
|
||||
fontSize: `${isPDFDownloading ? "30px" : ""}`,
|
||||
}}
|
||||
>
|
||||
Sabit Enerji SGE Kapsam Sınıflandırması
|
||||
</h5>
|
||||
}
|
||||
className="react-dataTable mt-1 border-black"
|
||||
columns={serverSideColumnsOfScopeOfConstantEmergy}
|
||||
data={scopeOfConstantEnergyData}
|
||||
noDataComponent={
|
||||
<p className="p-2">
|
||||
{t("DataInput.report")}
|
||||
{t("Warnings.notFound")}
|
||||
</p>
|
||||
}
|
||||
customStyles={
|
||||
isPDFDownloading
|
||||
? {
|
||||
rows: {
|
||||
fontSize: "25px",
|
||||
},
|
||||
headCells: {
|
||||
style: {
|
||||
fontSize: "23px",
|
||||
},
|
||||
},
|
||||
}
|
||||
: ""
|
||||
}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConstantEnergyGraphics;
|
||||
@@ -0,0 +1,710 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Col, Label, Row } from "reactstrap";
|
||||
import DataTable from "react-data-table-component";
|
||||
import { editNumbers } from "../edit-numbers";
|
||||
import { DoughnutChart, VerticalBarChart } from "../graphics";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import {
|
||||
DirectionsBus,
|
||||
DirectionsBusFilled,
|
||||
DirectionsCar,
|
||||
LocalAirport,
|
||||
QuestionMark,
|
||||
} from "@mui/icons-material";
|
||||
import PdfHeader from "../pdf-header";
|
||||
|
||||
function findIconByName(tag) {
|
||||
const icons = {
|
||||
"Özel ve Ticari Ulaşım Araçları": (
|
||||
<DirectionsCar style={{ fontSize: 50 }} />
|
||||
),
|
||||
"Toplu Taşıma - Belediye ve Halk Otobüsleri": (
|
||||
<DirectionsBusFilled style={{ fontSize: 50 }} />
|
||||
),
|
||||
"Belediye Filo Araçları": <DirectionsBus style={{ fontSize: 50 }} />,
|
||||
Havalimanı: <LocalAirport style={{ fontSize: 50 }} />,
|
||||
};
|
||||
|
||||
return icons[tag] || <QuestionMark style={{ fontSize: 50 }} />;
|
||||
}
|
||||
|
||||
const CustomChart = ({ data }) => {
|
||||
data = data.filter((item) => item.activitySubUnit.tag != "Genel Toplam");
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p className="text-center" style={{ fontSize: "25px" }}>
|
||||
{data[0].subSector.tag} Sera Gazı Emisyonları
|
||||
</p>
|
||||
{data.map((item) => (
|
||||
<div key={item.totalEmission} style={{ marginBottom: "15px" }}>
|
||||
<div style={{ display: "flex", alignItems: "center" }}>
|
||||
<div
|
||||
style={{
|
||||
marginRight: "10px",
|
||||
width: "50px",
|
||||
height: "auto",
|
||||
objectFit: "cover",
|
||||
}}
|
||||
>
|
||||
{findIconByName(item.activitySubUnit.tag)}
|
||||
</div>
|
||||
<div style={{ width: "100%" }}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "end",
|
||||
fontSize: "18px",
|
||||
}}
|
||||
>
|
||||
<span>{item.percentage} %</span>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "30px",
|
||||
backgroundColor: "#f0f0f0",
|
||||
marginRight: "10px",
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: `${item.percentage}%`,
|
||||
height: "100%",
|
||||
backgroundColor: "#555",
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "end",
|
||||
color: "#808080",
|
||||
fontWeight: "bold",
|
||||
fontSize: "18px",
|
||||
}}
|
||||
>
|
||||
<span>{item.activitySubUnit.tag}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const TransportGraphics = ({
|
||||
transportData,
|
||||
transportSubSectorData,
|
||||
isPDFDownloading,
|
||||
hideTables,
|
||||
colors,
|
||||
hideComponents,
|
||||
handleCheckboxChange,
|
||||
areaName,
|
||||
year,
|
||||
}) => {
|
||||
const veri = [
|
||||
{
|
||||
tag: "veri1",
|
||||
image: "./avatar.jpg",
|
||||
totalEmission: 555.55,
|
||||
},
|
||||
{
|
||||
tag: "veri2",
|
||||
image: "./Secapsoft.png",
|
||||
totalEmission: 66.66,
|
||||
},
|
||||
];
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [filterSubSector, setFilterSubSector] = useState({});
|
||||
const [separatedTransportSubSectorData, setSeparatedTransportSubSectorData] =
|
||||
useState({});
|
||||
const [separatedEmissionSourceData, setSeparatedEmissionSourceData] =
|
||||
useState({});
|
||||
|
||||
const serverSideColumnsOfTransport = [
|
||||
{
|
||||
name: t("EmissionSources.subSector"),
|
||||
selector: (row) => row.subSector,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight:
|
||||
row?.subSector?.tag === "Genel Toplam" ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{row.subSector?.tag || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: `Sera Gazı Miktarı (${t("DataInput.total")} tCO₂e)`,
|
||||
selector: (row) => row.totalEmission,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight:
|
||||
row?.subSector?.tag === "Genel Toplam" ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{editNumbers(row.totalEmission) || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: `${t("Oransal Dağılım")} %`,
|
||||
selector: (row) => row.percentage,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight:
|
||||
row?.subSector?.tag === "Genel Toplam" ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{row.percentage + "%" || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const serverSideColumnsOfSubSectorOfTransport = [
|
||||
{
|
||||
name: t("EmissionSources.subUnit"),
|
||||
selector: (row) => row.activitySubUnit,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight:
|
||||
row?.activitySubUnit?.tag === "Genel Toplam" ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{row.activitySubUnit?.tag || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: `Sera Gazı Miktarı (${t("DataInput.total")} tCO₂e)`,
|
||||
selector: (row) => row.totalEmission,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight:
|
||||
row?.activitySubUnit?.tag === "Genel Toplam" ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{editNumbers(row.totalEmission) || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: `${t("Oransal Dağılım")} %`,
|
||||
selector: (row) => row.percentage,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight:
|
||||
row?.activitySubUnit?.tag === "Genel Toplam" ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{row.percentage + "%" || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const serverSideColumnsOfEmissionSourceOfSubSectorOfTransport = [
|
||||
{
|
||||
name: t("EmissionSources.emissionSource"),
|
||||
selector: (row) => row.emissionSource,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight:
|
||||
row?.activitySubUnit?.tag === "Genel Toplam" ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{row.emissionSource?.tag || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: `Sera Gazı Miktarı (${t("DataInput.total")} tCO₂e)`,
|
||||
selector: (row) => row.totalEmission,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight:
|
||||
row?.activitySubUnit?.tag === "Genel Toplam" ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{editNumbers(row.totalEmission) || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const calculateTotalEmission = (filteredData) => {
|
||||
if (!filteredData || filteredData.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const reduceBySubUnitData = filteredData
|
||||
.filter((data) => data.activitySubUnit != null)
|
||||
.reduce((data, item) => {
|
||||
const existingItem = data.find(
|
||||
(dataItem) => dataItem.activitySubUnit.id === item.activitySubUnit.id
|
||||
);
|
||||
if (existingItem) {
|
||||
existingItem.totalEmission += item.totalEmission;
|
||||
} else {
|
||||
data.push({
|
||||
activitySubUnit: item.activitySubUnit,
|
||||
emissionSource: item.emissionSource,
|
||||
subSector: item.subSector,
|
||||
emissionScope: item.emissionScope,
|
||||
totalEmission: item.totalEmission,
|
||||
});
|
||||
}
|
||||
return data;
|
||||
}, []);
|
||||
|
||||
let totalEmission = 0;
|
||||
for (let i = 0; i < reduceBySubUnitData.length; i++) {
|
||||
totalEmission += reduceBySubUnitData[i].totalEmission;
|
||||
}
|
||||
|
||||
for (let i = 0; i < reduceBySubUnitData?.length; i++) {
|
||||
const percentage = (
|
||||
(reduceBySubUnitData[i].totalEmission / totalEmission) *
|
||||
100
|
||||
).toFixed(2);
|
||||
reduceBySubUnitData[i].percentage = percentage;
|
||||
}
|
||||
|
||||
const lastItem = {
|
||||
activitySubUnit: { tag: `Genel Toplam` },
|
||||
emissionSource: { tag: `Genel Toplam` },
|
||||
totalEmission: `${editNumbers(totalEmission)}`,
|
||||
percentage: "100,00",
|
||||
};
|
||||
|
||||
return [...reduceBySubUnitData, lastItem];
|
||||
};
|
||||
|
||||
const calculateTotalEmissionOfEmissionSource = (filteredData) => {
|
||||
if (!filteredData || filteredData.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const reduceByEmissionSourceData = filteredData.reduce((data, item) => {
|
||||
const existingItem = data.find(
|
||||
(dataItem) => dataItem.emissionSource.id === item.emissionSource.id
|
||||
);
|
||||
if (existingItem) {
|
||||
existingItem.totalEmission += item.totalEmission;
|
||||
} else {
|
||||
data.push({
|
||||
activitySubUnit: item.activitySubUnit,
|
||||
emissionSource: item.emissionSource,
|
||||
subSector: item.subSector,
|
||||
emissionScope: item.emissionScope,
|
||||
totalEmission: item.totalEmission,
|
||||
});
|
||||
}
|
||||
return data;
|
||||
}, []);
|
||||
|
||||
let totalEmission = 0;
|
||||
for (let i = 0; i < reduceByEmissionSourceData.length; i++) {
|
||||
totalEmission += reduceByEmissionSourceData[i].totalEmission;
|
||||
}
|
||||
|
||||
for (let i = 0; i < reduceByEmissionSourceData?.length; i++) {
|
||||
const percentage = (
|
||||
(reduceByEmissionSourceData[i].totalEmission / totalEmission) *
|
||||
100
|
||||
).toFixed(2);
|
||||
reduceByEmissionSourceData[i].percentage = percentage;
|
||||
}
|
||||
|
||||
const lastItem = {
|
||||
activitySubUnit: { tag: `Genel Toplam` },
|
||||
emissionSource: { tag: `Genel Toplam` },
|
||||
totalEmission: `${editNumbers(totalEmission)}`,
|
||||
percentage: "100,00",
|
||||
};
|
||||
|
||||
return [...reduceByEmissionSourceData, lastItem];
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (transportSubSectorData?.length > 0) {
|
||||
const groupedArray = transportSubSectorData
|
||||
.filter((data) => data.activitySubUnit != null)
|
||||
.reduce((result, item) => {
|
||||
const subSectorId = item.subSector.id;
|
||||
if (result[subSectorId]) {
|
||||
result[subSectorId].push(item);
|
||||
} else {
|
||||
result[subSectorId] = [item];
|
||||
}
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
const groupedArrayValues = Object.values(groupedArray);
|
||||
const newData = groupedArrayValues.map((group) =>
|
||||
calculateTotalEmission(group)
|
||||
);
|
||||
const newDataOfEmissionSource = groupedArrayValues.map((group) =>
|
||||
calculateTotalEmissionOfEmissionSource(group)
|
||||
);
|
||||
setSeparatedTransportSubSectorData(newData);
|
||||
setSeparatedEmissionSourceData(newDataOfEmissionSource);
|
||||
}
|
||||
}, [transportSubSectorData]);
|
||||
|
||||
useEffect(() => {
|
||||
const initialFilterSubSector = transportData
|
||||
.filter((data) => data.subSector.tag !== "Genel Toplam")
|
||||
.reduce((acc, data) => {
|
||||
return {
|
||||
...acc,
|
||||
[data.subSector.tag]: true,
|
||||
};
|
||||
}, {});
|
||||
|
||||
setFilterSubSector(initialFilterSubSector);
|
||||
}, []);
|
||||
|
||||
const customStyles = {
|
||||
rows: {
|
||||
fontSize: "25px",
|
||||
},
|
||||
headCells: {
|
||||
style: {
|
||||
fontSize: "23px",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="graphics-container4">
|
||||
{isPDFDownloading && <PdfHeader areaName={areaName} year={year} />}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
marginTop: "20px",
|
||||
boxShadow: !isPDFDownloading
|
||||
? "rgba(2, 138, 74, 0.1) 0px 0px 19px 0px"
|
||||
: "",
|
||||
}}
|
||||
>
|
||||
<h1
|
||||
style={{
|
||||
fontSize: `${isPDFDownloading ? "45px" : ""}`,
|
||||
}}
|
||||
className="text-center p-2"
|
||||
>
|
||||
Ulaşım
|
||||
</h1>
|
||||
</div>
|
||||
<Row className="mx-0 mt-5 mb-50 justify-content-center">
|
||||
{!hideTables &&
|
||||
!(
|
||||
isPDFDownloading &&
|
||||
hideComponents["transport-subSectors-dataTable"]
|
||||
) && (
|
||||
<Col sm="9" md="9">
|
||||
{!isPDFDownloading && (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={!hideComponents["transport-subSectors-dataTable"]}
|
||||
onChange={() =>
|
||||
handleCheckboxChange("transport-subSectors-dataTable")
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<DataTable
|
||||
title={
|
||||
<h5
|
||||
style={{
|
||||
textAlign: "end",
|
||||
fontWeight: "bold",
|
||||
fontSize: `${isPDFDownloading ? "30px" : ""}`,
|
||||
}}
|
||||
>
|
||||
Ulaşım Sektörü Sera Gazı Emisyonları
|
||||
</h5>
|
||||
}
|
||||
className="react-dataTable mt-1 border-black"
|
||||
columns={serverSideColumnsOfTransport}
|
||||
data={transportData}
|
||||
noDataComponent={
|
||||
<p className="p-2">
|
||||
{t("DataInput.report")}
|
||||
{t("Warnings.notFound")}
|
||||
</p>
|
||||
}
|
||||
customStyles={isPDFDownloading ? customStyles : ""}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
<Row className="mt-5 justify-content-center">
|
||||
{!(
|
||||
isPDFDownloading && hideComponents["transport-subSectors-chart"]
|
||||
) && (
|
||||
<Col sm="9" md="7" className="mt-5">
|
||||
{!isPDFDownloading && (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={!hideComponents["transport-subSectors-chart"]}
|
||||
onChange={() =>
|
||||
handleCheckboxChange("transport-subSectors-chart")
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<VerticalBarChart
|
||||
data={transportData}
|
||||
filterSubSector={filterSubSector}
|
||||
colors={colors}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
{!isPDFDownloading && (
|
||||
<Col sm="3" md="1" className="mt-5">
|
||||
<Label>{t("Show")}</Label>
|
||||
{transportData
|
||||
.filter((data) => data.subSector.tag != "Genel Toplam")
|
||||
.map((data, index) => (
|
||||
<div className="form-check form-switch mb-2" key={index}>
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
id={data.subSector.tag}
|
||||
checked={
|
||||
filterSubSector?.[data.subSector.tag] === true
|
||||
? true
|
||||
: false
|
||||
}
|
||||
onChange={(e) => {
|
||||
setFilterSubSector({
|
||||
...filterSubSector,
|
||||
[data.subSector.tag]: e.target.checked,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<label
|
||||
className="form-check-label h6"
|
||||
htmlFor={data.subSector.tag}
|
||||
>
|
||||
{data.subSector.tag}
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<div id="graphics-container5">
|
||||
{isPDFDownloading && <PdfHeader areaName={areaName} year={year} />}
|
||||
{separatedTransportSubSectorData?.length > 0 && (
|
||||
<h1
|
||||
style={{
|
||||
fontSize: `${isPDFDownloading ? "30px" : ""}`,
|
||||
fontWeight: "bold",
|
||||
}}
|
||||
className="mt-5 text-center"
|
||||
>
|
||||
Alt Sektörlere Göre Sera Gazı Salınımları
|
||||
</h1>
|
||||
)}
|
||||
{separatedTransportSubSectorData?.length > 0 &&
|
||||
separatedTransportSubSectorData.map((group, index) => (
|
||||
<div key={uuidv4()}>
|
||||
<Row className="mx-0 mt-5 mb-50 justify-content-center">
|
||||
{!hideTables &&
|
||||
!(
|
||||
isPDFDownloading &&
|
||||
hideComponents[`${index}-transport-subSector-dataTable`]
|
||||
) && (
|
||||
<Col sm="9" md="9">
|
||||
{!isPDFDownloading && (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={
|
||||
!hideComponents[
|
||||
`${index}-transport-subSector-dataTable`
|
||||
]
|
||||
}
|
||||
onChange={() =>
|
||||
handleCheckboxChange(
|
||||
`${index}-transport-subSector-dataTable`
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<DataTable
|
||||
title={
|
||||
<h5
|
||||
style={{
|
||||
textAlign: "end",
|
||||
fontWeight: "bold",
|
||||
fontSize: `${isPDFDownloading ? "30px" : ""}`,
|
||||
}}
|
||||
>
|
||||
{group[0].subSector.tag} Sera Gazı Emisyonları
|
||||
</h5>
|
||||
}
|
||||
className="react-dataTable mt-1 border-black"
|
||||
columns={serverSideColumnsOfSubSectorOfTransport}
|
||||
data={group}
|
||||
noDataComponent={
|
||||
<p className="p-2">
|
||||
{t("DataInput.report")}
|
||||
{t("Warnings.notFound")}
|
||||
</p>
|
||||
}
|
||||
customStyles={isPDFDownloading ? customStyles : ""}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
<Row className="justify-content-center">
|
||||
{!(
|
||||
isPDFDownloading &&
|
||||
hideComponents[`${index}-transport-subSector-chart`]
|
||||
) && (
|
||||
<Col sm="7" md="7" className="mb-5 mt-3">
|
||||
{!isPDFDownloading && (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={
|
||||
!hideComponents[`${index}-transport-subSector-chart`]
|
||||
}
|
||||
onChange={() =>
|
||||
handleCheckboxChange(
|
||||
`${index}-transport-subSector-chart`
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<CustomChart data={group} />
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div id="graphics-container6">
|
||||
{isPDFDownloading && <PdfHeader areaName={areaName} year={year} />}
|
||||
{separatedEmissionSourceData?.length > 0 &&
|
||||
separatedEmissionSourceData.map((group, index) => (
|
||||
<React.Fragment key={uuidv4()}>
|
||||
<Row className="mx-0 mt-1 mb-50 justify-content-center">
|
||||
{!hideTables &&
|
||||
!(
|
||||
isPDFDownloading &&
|
||||
hideComponents[
|
||||
`${index}-transport-emission-source-dataTable`
|
||||
]
|
||||
) && (
|
||||
<Col sm="9" md="9" className="mt-2">
|
||||
{!isPDFDownloading && (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={
|
||||
!hideComponents[
|
||||
`${index}-transport-emission-source-dataTable`
|
||||
]
|
||||
}
|
||||
onChange={() =>
|
||||
handleCheckboxChange(
|
||||
`${index}-transport-emission-source-dataTable`
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<DataTable
|
||||
title={
|
||||
<h5
|
||||
style={{
|
||||
textAlign: "end",
|
||||
fontWeight: "bold",
|
||||
fontSize: `${isPDFDownloading ? "30px" : ""}`,
|
||||
}}
|
||||
>
|
||||
{group[0].subSector.tag} Yakıt Bazlı Sera Gazı
|
||||
Emisyon Miktarları
|
||||
</h5>
|
||||
}
|
||||
className="react-dataTable mt-1 border-black"
|
||||
columns={
|
||||
serverSideColumnsOfEmissionSourceOfSubSectorOfTransport
|
||||
}
|
||||
data={group}
|
||||
noDataComponent={
|
||||
<p className="p-2">
|
||||
{t("DataInput.report")}
|
||||
{t("Warnings.notFound")}
|
||||
</p>
|
||||
}
|
||||
customStyles={isPDFDownloading ? customStyles : ""}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
<Row className="mt-3 justify-content-center">
|
||||
{!(
|
||||
isPDFDownloading &&
|
||||
hideComponents[`${index}-transport-emission-source-chart`]
|
||||
) && (
|
||||
<div style={{ width: "30%" }}>
|
||||
{!isPDFDownloading && (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={
|
||||
!hideComponents[
|
||||
`${index}-transport-emission-source-chart`
|
||||
]
|
||||
}
|
||||
onChange={() =>
|
||||
handleCheckboxChange(
|
||||
`${index}-transport-emission-source-chart`
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<DoughnutChart data={group} colors={colors} />
|
||||
</div>
|
||||
)}
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default TransportGraphics;
|
||||
218
sge-frontend/src/components/subSector-graphics/WasteGraphics.js
Normal file
218
sge-frontend/src/components/subSector-graphics/WasteGraphics.js
Normal file
@@ -0,0 +1,218 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Col, Label, Row } from "reactstrap";
|
||||
import DataTable from "react-data-table-component";
|
||||
import { editNumbers } from "../edit-numbers";
|
||||
import { VerticalBarChart } from "../graphics";
|
||||
import PdfHeader from "../pdf-header";
|
||||
|
||||
const WasteGraphics = ({
|
||||
wasteData,
|
||||
isPDFDownloading,
|
||||
hideTables,
|
||||
colors,
|
||||
hideComponents,
|
||||
handleCheckboxChange,
|
||||
areaName,
|
||||
year,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [filterSubSector, setFilterSubSector] = useState({});
|
||||
|
||||
const serverSideColumnsOfWaste = [
|
||||
{
|
||||
name: t("EmissionSources.subSector"),
|
||||
selector: (row) => row.subSector,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight:
|
||||
row?.subSector?.tag === "Genel Toplam" ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{row.subSector?.tag || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: `Sera Gazı Miktarı (${t("DataInput.total")} tCO₂e)`,
|
||||
selector: (row) => row.totalEmission,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight:
|
||||
row?.subSector?.tag === "Genel Toplam" ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{editNumbers(row.totalEmission) || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: `${t("Oransal Dağılım")} %`,
|
||||
selector: (row) => row.percentage,
|
||||
sortable: false,
|
||||
cell: (row) => (
|
||||
<span
|
||||
style={{
|
||||
fontWeight:
|
||||
row?.subSector?.tag === "Genel Toplam" ? "bold" : "initial",
|
||||
}}
|
||||
>
|
||||
{row.percentage + "%" || "-"}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
const initialFilterSubSector = wasteData
|
||||
.filter((data) => data.subSector.tag !== "Genel Toplam")
|
||||
.reduce((acc, data) => {
|
||||
return {
|
||||
...acc,
|
||||
[data.subSector.tag]: true,
|
||||
};
|
||||
}, {});
|
||||
|
||||
setFilterSubSector(initialFilterSubSector);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div id="graphics-container-waste">
|
||||
{isPDFDownloading && <PdfHeader areaName={areaName} year={year} />}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
marginTop: "20px",
|
||||
boxShadow: !isPDFDownloading
|
||||
? "rgba(2, 138, 74, 0.1) 0px 0px 19px 0px"
|
||||
: "",
|
||||
}}
|
||||
>
|
||||
<h1
|
||||
style={{
|
||||
fontSize: `${isPDFDownloading ? "45px" : ""}`,
|
||||
}}
|
||||
className="text-center p-2"
|
||||
>
|
||||
Atık
|
||||
</h1>
|
||||
</div>
|
||||
<Row className="mx-0 mt-5 mb-50 justify-content-center">
|
||||
{!hideTables &&
|
||||
!(
|
||||
isPDFDownloading && hideComponents["waste-subSector-dataTable"]
|
||||
) && (
|
||||
<Col sm="9" md="9">
|
||||
{!isPDFDownloading && (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={!hideComponents["waste-subSector-dataTable"]}
|
||||
onChange={() =>
|
||||
handleCheckboxChange("waste-subSector-dataTable")
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<DataTable
|
||||
title={
|
||||
wasteData != undefined && (
|
||||
<h5
|
||||
style={{
|
||||
textAlign: "end",
|
||||
fontWeight: "bold",
|
||||
fontSize: `${isPDFDownloading ? "30px" : ""}`,
|
||||
}}
|
||||
>
|
||||
Atık Sektörü Sera Gazı Emisyonları
|
||||
</h5>
|
||||
)
|
||||
}
|
||||
className="react-dataTable mt-1 border-black"
|
||||
columns={serverSideColumnsOfWaste}
|
||||
data={wasteData}
|
||||
noDataComponent={
|
||||
<p className="p-2">
|
||||
{t("DataInput.report")}
|
||||
{t("Warnings.notFound")}
|
||||
</p>
|
||||
}
|
||||
customStyles={
|
||||
isPDFDownloading
|
||||
? {
|
||||
rows: {
|
||||
fontSize: "25px",
|
||||
},
|
||||
headCells: {
|
||||
style: {
|
||||
fontSize: "23px",
|
||||
},
|
||||
},
|
||||
}
|
||||
: ""
|
||||
}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
<Row className="mt-5 justify-content-center">
|
||||
{!(isPDFDownloading && hideComponents["waste-subSector-chart"]) && (
|
||||
<Col sm="9" md="7" className="mt-5">
|
||||
{!isPDFDownloading && (
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={!hideComponents["waste-subSector-chart"]}
|
||||
onChange={() => handleCheckboxChange("waste-subSector-chart")}
|
||||
/>
|
||||
)}
|
||||
<VerticalBarChart
|
||||
data={wasteData}
|
||||
filterSubSector={filterSubSector}
|
||||
colors={colors}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
{!isPDFDownloading && (
|
||||
<Col sm="3" md="1" className="mt-5">
|
||||
<Label>{t("Filter")}</Label>
|
||||
{wasteData
|
||||
.filter((data) => data.subSector.tag != "Genel Toplam")
|
||||
.map((data, index) => (
|
||||
<div className="form-check form-switch mb-2" key={index}>
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
id={data.subSector.tag}
|
||||
checked={
|
||||
filterSubSector?.[data.subSector.tag] === true
|
||||
? true
|
||||
: false
|
||||
}
|
||||
onChange={(e) => {
|
||||
setFilterSubSector({
|
||||
...filterSubSector,
|
||||
[data.subSector.tag]: e.target.checked,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<label
|
||||
className="form-check-label h6"
|
||||
htmlFor={data.subSector.tag}
|
||||
>
|
||||
{data.subSector.tag}
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WasteGraphics;
|
||||
90
sge-frontend/src/components/token-timer/index.js
Normal file
90
sge-frontend/src/components/token-timer/index.js
Normal file
@@ -0,0 +1,90 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { default as SweetAlert } from "sweetalert2";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { handleLogout } from "@store/actions/auth";
|
||||
import { newAccessToken } from "@store/actions/accessToken";
|
||||
import { useSnackbar } from "notistack";
|
||||
|
||||
const Swal = withReactContent(SweetAlert);
|
||||
|
||||
const TokenTimer = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
|
||||
const [time, setTime] = useState(() => {
|
||||
const storedTime = localStorage.getItem("timer");
|
||||
return storedTime ? parseInt(storedTime) : 1800; // 30 dakika = 1800
|
||||
});
|
||||
|
||||
const lastActivity = parseInt(localStorage.getItem("lastActivity")); // user's lastActivity timer
|
||||
const lastActivitySeconds = Math.floor((Date.now() - lastActivity) / 1000);
|
||||
|
||||
useEffect(() => {
|
||||
let interval = null;
|
||||
|
||||
interval = setInterval(() => {
|
||||
setTime((prevTime) => {
|
||||
const updatedTime = prevTime - 1;
|
||||
localStorage.setItem("timer", updatedTime.toString());
|
||||
return updatedTime;
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
if (lastActivitySeconds === 800) {
|
||||
openModal();
|
||||
}
|
||||
|
||||
if (lastActivitySeconds === 895) {
|
||||
logout();
|
||||
}
|
||||
|
||||
if (time === 60 && lastActivitySeconds < 800) {
|
||||
handleReset();
|
||||
}
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [time]);
|
||||
|
||||
const openModal = () => {
|
||||
return Swal.fire({
|
||||
title: t("Timer.expire"),
|
||||
//text: `${formatTime(time)}`, //get timer dynamically
|
||||
icon: "warning",
|
||||
showCancelButton: true,
|
||||
confirmButtonText: t("Timer.continue"),
|
||||
cancelButtonText: t("Auth.logout"),
|
||||
customClass: {
|
||||
confirmButton: "btn btn-primary",
|
||||
cancelButton: "btn btn-danger ml-1",
|
||||
},
|
||||
buttonsStyling: false,
|
||||
}).then(function (result) {
|
||||
if (result.value !== null && result.value === true) {
|
||||
handleReset();
|
||||
} else if (result?.dismiss === "cancel") {
|
||||
logout();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
dispatch(handleLogout());
|
||||
enqueueSnackbar(t("Auth.logoutMessage"), {
|
||||
variant: "info",
|
||||
preventDuplicate: true,
|
||||
});
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
dispatch(newAccessToken());
|
||||
setTime(1800); // 30 dakika = 1800
|
||||
localStorage.setItem("timer", "1800");
|
||||
};
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default TokenTimer;
|
||||
Reference in New Issue
Block a user