Skip to content

Commit

Permalink
feat(ui-thermal): minor user experience improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
hdinia committed Oct 10, 2023
1 parent 404db0e commit d6ed948
Show file tree
Hide file tree
Showing 9 changed files with 269 additions and 131 deletions.
2 changes: 1 addition & 1 deletion webapp/public/locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@
"study.modelization.map.districts.edit": "Edit districts",
"study.modelization.map.districts.delete.confirm": "Are you sure you want to delete '{{0}}' district?",
"study.modelization.load": "Load",
"study.modelization.thermal": "Thermal Clus.",
"study.modelization.thermal": "Thermal",
"study.modelization.hydro": "Hydro",
"study.modelization.hydro.correlation.viewMatrix": "View all correlations",
"study.modelization.hydro.correlation.coefficient": "Coeff. (%)",
Expand Down
2 changes: 1 addition & 1 deletion webapp/public/locales/fr/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@
"study.modelization.map.districts.edit": "Modifier un district",
"study.modelization.map.districts.delete.confirm": "Êtes-vous sûr de vouloir supprimer le district '{{0}}' ?",
"study.modelization.load": "Conso",
"study.modelization.thermal": "Clus. Thermiques",
"study.modelization.thermal": "Thermiques",
"study.modelization.hydro": "Hydro",
"study.modelization.hydro.correlation.viewMatrix": "Voir les correlations",
"study.modelization.hydro.correlation.coefficient": "Coeff. (%)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@ function ThermalForm() {
// Event handlers
////////////////////////////////////////////////////////////////

const handleSubmit =
(areaId: string, clusterId: string) =>
({ dirtyValues }: SubmitHandlerPlus<ThermalCluster>) => {
return updateThermalCluster(study.id, areaId, clusterId, dirtyValues);
};
const handleSubmit = ({ dirtyValues }: SubmitHandlerPlus<ThermalCluster>) => {
return updateThermalCluster(study.id, areaId, clusterId, dirtyValues);
};

////////////////////////////////////////////////////////////////
// JSX
Expand All @@ -55,7 +53,7 @@ function ThermalForm() {
return getThermalCluster(study.id, areaId, clusterId);
},
}}
onSubmit={handleSubmit(areaId, clusterId)}
onSubmit={handleSubmit}
autoSubmit
>
<Fields />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* eslint-disable camelcase */
import { useMemo } from "react";
import { MRT_ColumnDef } from "material-react-table";
import { Box, Chip, Stack } from "@mui/material";
import { useOutletContext } from "react-router-dom";
import { Box, Chip } from "@mui/material";
import { useLocation, useNavigate, useOutletContext } from "react-router-dom";
import { StudyMetadata } from "../../../../../../../common/types";
import {
ThermalClusterGroup,
Expand All @@ -11,6 +11,7 @@ import {
createThermalCluster,
deleteThermalClusters,
capacityAggregationFn,
CLUSTER_GROUP_OPTIONS,
} from "./utils";
import useAppSelector from "../../../../../../../redux/hooks/useAppSelector";
import { getCurrentAreaId } from "../../../../../../../redux/selectors";
Expand All @@ -20,18 +21,22 @@ import SimpleLoader from "../../../../../../common/loaders/SimpleLoader";

function Thermal() {
const { study } = useOutletContext<{ study: StudyMetadata }>();
const currentArea = useAppSelector(getCurrentAreaId);
const navigate = useNavigate();
const location = useLocation();
const currentAreaId = useAppSelector(getCurrentAreaId);
const groups = Object.values(ThermalClusterGroup);

const { data: clusters } = usePromise(
() => getThermalClusters(study.id, currentArea),
[study.id, currentArea]
const { data: clusters, isLoading } = usePromise(
() => getThermalClusters(study.id, currentAreaId),
[study.id, currentAreaId],
);

/**
* Calculates the installed and enabled capacity for each thermal cluster.
* @installedCapacity = unitCount * nominalCapacity.
* @enabledCapacity = unitCount * nominalCapacity if enabled is true else = 0.
* Calculate the installed and enabled capacity for each thermal cluster.
* - `installedCapacity` is calculated as the product of `unitCount` and `nominalCapacity`.
* - `enabledCapacity` is the product of `unitCount` and `nominalCapacity` if the cluster is enabled, otherwise it's 0.
* @function
* @returns {Array} - An array of cluster objects, each augmented with `installedCapacity` and `enabledCapacity`.
*/
const clustersWithCapacity = useMemo(
() =>
Expand All @@ -41,50 +46,92 @@ function Thermal() {
const enabledCapacity = enabled ? installedCapacity : 0;
return { ...cluster, installedCapacity, enabledCapacity };
}) || [],
[clusters]
[clusters],
);

const totalUnitCount = useMemo(
() => clusters?.reduce((acc, curr) => acc + curr.unitCount, 0),
[clusters]
);

const totalInstalledCapacity = useMemo(
() =>
clusters?.reduce(
(acc, curr) => acc + curr.unitCount * curr.nominalCapacity,
0
),
[clusters]
);
const { totalUnitCount, totalInstalledCapacity, totalEnabledCapacity } =
useMemo(() => {
if (!clusters) {
return {
totalUnitCount: 0,
totalInstalledCapacity: 0,
totalEnabledCapacity: 0,
};
}

const totalEnabledCapacity = useMemo(
() =>
clusters?.reduce(
(acc, curr) =>
acc + (curr.enabled ? curr.unitCount * curr.nominalCapacity : 0),
0
),
[clusters]
);
return clusters.reduce(
(acc, { unitCount, nominalCapacity, enabled }) => {
acc.totalUnitCount += unitCount;
acc.totalInstalledCapacity += unitCount * nominalCapacity;
acc.totalEnabledCapacity += enabled ? unitCount * nominalCapacity : 0;
return acc;
},
{
totalUnitCount: 0,
totalInstalledCapacity: 0,
totalEnabledCapacity: 0,
},
);
}, [clusters]);

const columns = useMemo<MRT_ColumnDef<ThermalCluster>[]>(
() => [
{
accessorKey: "name",
header: "Name",
size: 100,
Cell: ({ renderedCellValue, row }) => {
const clusterId = row.original.id;
return (
<Box
sx={{
cursor: "pointer",
"&:hover": {
color: "primary.main",
textDecoration: "underline",
},
}}
onClick={() => navigate(`${location.pathname}/${clusterId}`)}
>
{renderedCellValue}
</Box>
);
},
},
{
accessorKey: "group",
header: "Group",
size: 50,
filterVariant: "select",
filterSelectOptions: CLUSTER_GROUP_OPTIONS,
muiTableHeadCellProps: {
align: "left",
},
muiTableBodyCellProps: {
align: "left",
},
Footer: () => (
<Box sx={{ display: "flex", alignItems: "flex-start" }}>Total:</Box>
),
},
{
accessorKey: "enabled",
header: "Enabled",
size: 50,
filterVariant: "checkbox",
Cell: ({ cell }) => (
<Chip
label={cell.getValue<boolean>() ? "Yes" : "No"}
color={cell.getValue<boolean>() ? "success" : "error"}
size="small"
/>
),
},
{
accessorKey: "mustRun",
header: "Must Run",
size: 50,
filterVariant: "checkbox",
Cell: ({ cell }) => (
<Chip
label={cell.getValue<boolean>() ? "Yes" : "No"}
Expand All @@ -103,12 +150,7 @@ function Thermal() {
{cell.getValue<number>()}
</Box>
),
Footer: () => (
<Stack>
Total Units:
<Box color="warning.main">{totalUnitCount}</Box>
</Stack>
),
Footer: () => <Box color="warning.main">{totalUnitCount}</Box>,
},
{
accessorKey: "nominalCapacity",
Expand All @@ -119,7 +161,7 @@ function Thermal() {
},
{
accessorKey: "installedCapacity",
header: "Installed Capacity",
header: "Enabled / Installed",
size: 50,
aggregationFn: capacityAggregationFn,
AggregatedCell: ({ cell }) => (
Expand All @@ -129,17 +171,14 @@ function Thermal() {
),
Cell: ({ row }) => (
<>
{row.original.enabledCapacity ?? 0}/
{row.original.enabledCapacity ?? 0} /{" "}
{row.original.installedCapacity ?? 0} MW
</>
),
Footer: () => (
<Stack>
Total Installed:
<Box color="warning.main">
{totalEnabledCapacity}/{totalInstalledCapacity} MW
</Box>
</Stack>
<Box color="warning.main">
{totalEnabledCapacity} / {totalInstalledCapacity} MW
</Box>
),
},
{
Expand All @@ -149,29 +188,37 @@ function Thermal() {
Cell: ({ cell }) => <>{cell.getValue<number>().toFixed(2)} €/MWh</>,
},
],
[totalEnabledCapacity, totalInstalledCapacity, totalUnitCount]
[
location.pathname,
navigate,
totalEnabledCapacity,
totalInstalledCapacity,
totalUnitCount,
],
);

////////////////////////////////////////////////////////////////
// Event handlers
////////////////////////////////////////////////////////////////

const handleCreateRow = ({ name, group }: ThermalCluster) => {
return createThermalCluster(study.id, currentArea, {
name,
group,
});
const handleCreateRow = ({
id,
installedCapacity,
enabledCapacity,
...cluster
}: ThermalCluster) => {
return createThermalCluster(study.id, currentAreaId, cluster);
};

const handleDeleteSelection = (ids: string[]) => {
return deleteThermalClusters(study.id, currentArea, ids);
return deleteThermalClusters(study.id, currentAreaId, ids);
};

////////////////////////////////////////////////////////////////
// JSX
////////////////////////////////////////////////////////////////

if (!clusters) {
if (isLoading) {
return <SimpleLoader />;
}

Expand Down
Loading

0 comments on commit d6ed948

Please sign in to comment.