Make the datacenter creation modal mobile friendly

This commit is contained in:
2025-08-19 00:08:42 +03:00
parent 2257ec79f6
commit 47959fb35f

View File

@@ -428,6 +428,23 @@ const DataCenterManagement = () => {
setSelectedSector(row.sector?.id); setSelectedSector(row.sector?.id);
setSelectedSubSector(row.subSector?.id); setSelectedSubSector(row.subSector?.id);
// If there are existing emission sources, fetch consumption units for each
if (
row.dataCenterEmissionSources &&
row.dataCenterEmissionSources.length > 0
) {
row.dataCenterEmissionSources.forEach((dces) => {
if (dces.emissionSource && dces.emissionSource.id) {
dispatch(
getConsuptionUnits({
id: dces.emissionSource.id,
sector: row.sector?.id,
})
);
}
});
}
// Only set map position if we have both address and valid coordinates // Only set map position if we have both address and valid coordinates
setMapPosition( setMapPosition(
row.address && row.latitude && row.longitude row.address && row.latitude && row.longitude
@@ -1029,189 +1046,232 @@ const DataCenterManagement = () => {
<Col sm="12"> <Col sm="12">
<FormGroup> <FormGroup>
<Label>Emission Sources & Consumption Units</Label> <Label>Emission Sources & Consumption Units</Label>
<div className="border p-3 rounded bg-light"> <div className="border rounded p-3 bg-light">
<small className="text-muted mb-2 d-block"> <div className="d-flex justify-content-between align-items-center mb-3">
Configure emission sources for this data center. At least <small className="text-muted">
one emission source with consumption unit is required. Configure emission sources for this data center. At
</small> least one emission source with consumption unit is
required.
</small>
<Button
color="primary"
size="sm"
onClick={() => {
setSelectedDataCenter({
...selectedDataCenter,
dataCenterEmissionSources: [
...selectedDataCenter.dataCenterEmissionSources,
{
emissionSourceId: null,
consuptionUnitId: null,
isDefault: false,
},
],
});
}}
disabled={!selectedDataCenter.subSectorId}
className="d-none d-sm-flex"
>
<Plus size={14} className="me-1" />
Add Source
</Button>
</div>
{selectedDataCenter.dataCenterEmissionSources.map( {selectedDataCenter.dataCenterEmissionSources.map(
(source, index) => ( (source, index) => (
<Row key={index} className="mb-2 align-items-end"> <div
<Col sm="5"> key={index}
<Label className="border rounded p-3 mb-3 bg-white"
for={`emissionSource-${index}`} >
className="form-label" <Row className="g-3">
> <Col xs="12" md="6">
Emission Source * <Label
</Label> for={`emissionSource-${index}`}
<Select className="form-label fw-bold"
id={`emissionSource-${index}`} >
placeholder="Select emission source..." Emission Source *
options={emissionSourcesOptions} </Label>
value={emissionSourcesOptions?.find( <Select
(option) => id={`emissionSource-${index}`}
option.value === source.emissionSourceId placeholder="Select emission source..."
)} options={emissionSourcesOptions}
onChange={(option) => { value={emissionSourcesOptions?.find(
const updatedSources = [ (option) =>
...selectedDataCenter.dataCenterEmissionSources, option.value === source.emissionSourceId
]; )}
updatedSources[index] = { onChange={(option) => {
...updatedSources[index],
emissionSourceId: option?.value,
consuptionUnitId: null, // Reset consumption unit when emission source changes
};
setSelectedDataCenter({
...selectedDataCenter,
dataCenterEmissionSources: updatedSources,
});
// Fetch consumption units for the selected emission source
if (option?.value) {
dispatch(
getConsuptionUnits({
id: option.value,
sector: selectedDataCenter?.sectorId,
})
);
}
}}
isClearable
filterOption={customFilterForSelect}
isDisabled={!selectedDataCenter.subSectorId}
styles={{
placeholder: (provided) => ({
...provided,
color: "#6e6b7b",
}),
}}
menuPlacement="top"
/>
</Col>
<Col sm="4">
<Label
for={`consuptionUnit-${index}`}
className="form-label"
>
Consumption Unit *
</Label>
<Select
id={`consuptionUnit-${index}`}
placeholder="Select consumption unit..."
options={consuptionUnitsOptions}
value={consuptionUnitsOptions?.find(
(option) =>
option.value === source.consuptionUnitId
)}
onChange={(option) => {
const updatedSources = [
...selectedDataCenter.dataCenterEmissionSources,
];
updatedSources[index] = {
...updatedSources[index],
consuptionUnitId: option?.value,
};
setSelectedDataCenter({
...selectedDataCenter,
dataCenterEmissionSources: updatedSources,
});
}}
isClearable
filterOption={customFilterForSelect}
isDisabled={!source.emissionSourceId}
styles={{
placeholder: (provided) => ({
...provided,
color: "#6e6b7b",
}),
}}
menuPlacement="top"
/>
</Col>
<Col sm="3">
<Label className="form-label d-block">
Actions
</Label>
<div className="d-flex gap-2">
<Button
color={
source.isDefault
? "primary"
: "outline-secondary"
}
size="sm"
onClick={() => {
const updatedSources = [ const updatedSources = [
...selectedDataCenter.dataCenterEmissionSources, ...selectedDataCenter.dataCenterEmissionSources,
]; ];
// First, set all sources to not default updatedSources[index] = {
updatedSources.forEach( ...updatedSources[index],
(s) => (s.isDefault = false) emissionSourceId: option?.value,
); consuptionUnitId: null, // Reset consumption unit when emission source changes
// Then set the selected one as default };
updatedSources[index].isDefault = true;
setSelectedDataCenter({ setSelectedDataCenter({
...selectedDataCenter, ...selectedDataCenter,
dataCenterEmissionSources: updatedSources, dataCenterEmissionSources: updatedSources,
}); });
}} // Fetch consumption units for the selected emission source
title="Set as default emission source" if (option?.value) {
> dispatch(
{source.isDefault ? "★ Default" : "☆ Default"} getConsuptionUnits({
</Button> id: option.value,
<Button sector: selectedDataCenter?.sectorId,
color="outline-danger" })
size="sm"
onClick={() => {
const updatedSources =
selectedDataCenter.dataCenterEmissionSources.filter(
(_, i) => i !== index
); );
// If we're removing the default source and there are other sources, make the first one default
if (
source.isDefault &&
updatedSources.length > 0
) {
updatedSources[0].isDefault = true;
} }
}}
isClearable
filterOption={customFilterForSelect}
isDisabled={!selectedDataCenter.subSectorId}
styles={{
placeholder: (provided) => ({
...provided,
color: "#6e6b7b",
}),
}}
menuPlacement="auto"
/>
</Col>
<Col xs="12" md="6">
<Label
for={`consuptionUnit-${index}`}
className="form-label fw-bold"
>
Consumption Unit *
</Label>
<Select
id={`consuptionUnit-${index}`}
placeholder="Select consumption unit..."
options={consuptionUnitsOptions}
value={consuptionUnitsOptions?.find(
(option) =>
option.value === source.consuptionUnitId
)}
onChange={(option) => {
const updatedSources = [
...selectedDataCenter.dataCenterEmissionSources,
];
updatedSources[index] = {
...updatedSources[index],
consuptionUnitId: option?.value,
};
setSelectedDataCenter({ setSelectedDataCenter({
...selectedDataCenter, ...selectedDataCenter,
dataCenterEmissionSources: updatedSources, dataCenterEmissionSources: updatedSources,
}); });
}} }}
disabled={ isClearable
selectedDataCenter.dataCenterEmissionSources filterOption={customFilterForSelect}
.length === 1 isDisabled={!source.emissionSourceId}
} styles={{
title="Remove emission source" placeholder: (provided) => ({
> ...provided,
<Trash size={14} /> color: "#6e6b7b",
</Button> }),
</div> }}
</Col> menuPlacement="auto"
</Row> />
</Col>
</Row>
<Row className="mt-3">
<Col xs="12">
<div className="d-flex flex-column flex-sm-row gap-2 justify-content-between align-items-start align-items-sm-center">
<div className="d-flex gap-2 flex-wrap">
<Button
color={
source.isDefault
? "primary"
: "outline-secondary"
}
size="sm"
onClick={() => {
const updatedSources = [
...selectedDataCenter.dataCenterEmissionSources,
];
// First, set all sources to not default
updatedSources.forEach(
(s) => (s.isDefault = false)
);
// Then set the selected one as default
updatedSources[index].isDefault = true;
setSelectedDataCenter({
...selectedDataCenter,
dataCenterEmissionSources:
updatedSources,
});
}}
title="Set as default emission source"
>
{source.isDefault
? "★ Default"
: "☆ Set Default"}
</Button>
{source.isDefault && (
<span className="badge bg-success align-self-center">
Default Source
</span>
)}
</div>
<Button
color="outline-danger"
size="sm"
onClick={() => {
const updatedSources =
selectedDataCenter.dataCenterEmissionSources.filter(
(_, i) => i !== index
);
// If we're removing the default source and there are other sources, make the first one default
if (
source.isDefault &&
updatedSources.length > 0
) {
updatedSources[0].isDefault = true;
}
setSelectedDataCenter({
...selectedDataCenter,
dataCenterEmissionSources: updatedSources,
});
}}
disabled={
selectedDataCenter.dataCenterEmissionSources
.length === 1
}
title="Remove emission source"
>
<Trash size={14} className="me-1" />
Remove
</Button>
</div>
</Col>
</Row>
</div>
) )
)} )}
<Button <div className="text-center mt-3">
color="primary" <Button
size="sm" color="primary"
onClick={() => { size="sm"
setSelectedDataCenter({ onClick={() => {
...selectedDataCenter, setSelectedDataCenter({
dataCenterEmissionSources: [ ...selectedDataCenter,
...selectedDataCenter.dataCenterEmissionSources, dataCenterEmissionSources: [
{ ...selectedDataCenter.dataCenterEmissionSources,
emissionSourceId: null, {
consuptionUnitId: null, emissionSourceId: null,
isDefault: false, consuptionUnitId: null,
}, isDefault: false,
], },
}); ],
}} });
disabled={!selectedDataCenter.subSectorId} }}
> disabled={!selectedDataCenter.subSectorId}
<Plus size={14} className="me-1" /> className="w-100 d-sm-none"
Add Emission Source >
</Button> <Plus size={14} className="me-1" />
Add Another Emission Source
</Button>
</div>
</div> </div>
</FormGroup> </FormGroup>
</Col> </Col>