Skip to content

Commit

Permalink
Merge pull request #305 from dataforgoodfr/feat/D4G-296-display-team-…
Browse files Browse the repository at this point in the history
…values-on-admin-game-console

Feat/d4g 296 display team values on admin game console
  • Loading branch information
Baboo7 authored Jul 18, 2023
2 parents 8236135 + d708e9b commit b5e42a3
Show file tree
Hide file tree
Showing 11 changed files with 292 additions and 80 deletions.
2 changes: 1 addition & 1 deletion packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
]
},
"devDependencies": {
"@sentry/vite-plugin": "^0.4.0",
"@sentry/vite-plugin": "^2.4.0",
"@types/lodash": "^4.14.182",
"@typescript-eslint/eslint-plugin": "^5.19.0",
"@vitejs/plugin-react": "^3.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { Box, useTheme } from "@mui/material";
import sumBy from "lodash/sumBy";
import React from "react";
import React, { ReactNode, useMemo } from "react";

import { Typography } from "../../../common/components/Typography";
import { useCurrentStep, usePlay } from "../../context/playContext";
import { Icon } from "../../../common/components/Icon";
import { computeTeamActionStats } from "../../utils/production";
import { TeamAction } from "../../../../utils/types";
import { t } from "../../../translations";
import { useTranslation } from "../../../translations";
import { HelpIconWrapper } from "./TeamActionsRecap.styles";
import { formatBudget, formatProductionGw } from "../../../../lib/formatter";
import { GameStepId } from "../../constants";

export { TeamActionsRecap };

Expand All @@ -19,12 +18,15 @@ function TeamActionsRecap({
teamActions = [],
helper,
showCredibility,
showProductionValue,
}: {
title?: string;
teamActions: TeamAction[];
helper?: React.ReactNode;
showCredibility?: boolean;
showProductionValue?: boolean;
}) {
const { t } = useTranslation(["common", "countries"]);
const currentStep = useCurrentStep();
const { productionActionById } = usePlay();

Expand All @@ -35,80 +37,152 @@ function TeamActionsRecap({
])
);

function budgetWording(stepId: GameStepId): string {
if (stepId === "production-3") {
return "Budget restant :";
const budgetI18n = useMemo(() => {
if (currentStep?.id === "production-3") {
return t("team-actions.recap.remaining-budget");
}
return "Budget conseillé restant :";
}
return t("team-actions.recap.recommended-remaining-budget");
}, [currentStep, t]);

const energyStats = Object.values(energyNameToEnergyStats);
const budgetRemaining =
(currentStep?.budgetAdvised || 0) - sumBy(energyStats, "cost");
const powerInstalledInGw = sumBy(energyStats, "powerNeedGw");

return (
<Box display="flex" flexDirection="column" gap={3}>
<Box
className="team-actions-recap"
display="flex"
flexDirection="column"
gap={3}
>
<Box display="flex" alignItems="center" gap={1}>
<Icon name="production" />
<Typography variant="h5">{title || currentStep?.title}</Typography>
{helper && <HelpIconWrapper>{helper}</HelpIconWrapper>}
</Box>

<Box style={{ gap: "4px" }} display="flex" flexDirection="column">
{currentStep?.budgetAdvised && (
<Box display="flex" alignItems="center">
<Box sx={{ width: 300 }} display="flex" alignItems="center" gap={1}>
<Icon name="budget" />
<Box
className="team-actions-recap__overview"
style={{ gap: "4px" }}
display="flex"
flexDirection="column"
>
<OverviewItem
title={
<>
<Icon name="power" />
<Typography>
{budgetWording(currentStep?.id || "initial-situation")}
{t("team-actions.recap.installed-power")} :
</Typography>
</Box>
<Typography>{formatBudget(budgetRemaining)} €/j</Typography>
</Box>
</>
}
value={
<>
<Typography>
{t("unit.power.giga", {
value: formatProductionGw(powerInstalledInGw),
})}
</Typography>
</>
}
/>
{currentStep?.budgetAdvised && (
<OverviewItem
title={
<>
<Icon name="budget" />
<Typography>{budgetI18n} :</Typography>
</>
}
value={
<>
<Typography>
{t("unit.budget-per-day.base", {
value: formatBudget(budgetRemaining),
symbol: t("countries:country.fr.currency.symbol"),
})}
</Typography>
</>
}
/>
)}
<Box display="flex" alignItems="center">
<Box sx={{ width: 300 }} display="flex" alignItems="center" gap={1}>
<Icon name="power" />
<Typography>Puissance installée :</Typography>
</Box>
<Typography>{formatProductionGw(powerInstalledInGw)} GW</Typography>
</Box>
</Box>

<Box style={{ gap: "4px" }} display="flex" flexDirection="column">
<Box
className="team-actions-recap__energy-list"
display="flex"
flexDirection="column"
gap={1}
>
{teamActions.map((teamAction) => (
<EnergyListItem
key={productionActionById[teamAction.actionId].name}
teamAction={teamAction}
showCredibility={showCredibility}
showProductionValue={showProductionValue}
/>
))}
</Box>
</Box>
);
}

function OverviewItem({
title,
value,
}: {
title: ReactNode;
value: ReactNode;
}) {
return (
<Box
className="overview-item"
display="flex"
alignItems="center"
justifyContent="space-between"
sx={{ width: "100%", maxWidth: 325 }}
>
<Box display="flex" alignItems="center" gap={1}>
{title}
</Box>
<Box display="flex" alignItems="center" gap={1}>
{value}
</Box>
</Box>
);
}

function EnergyListItem({
teamAction,
showCredibility,
showProductionValue,
}: {
teamAction?: TeamAction;
showCredibility?: boolean;
showProductionValue?: boolean;
}) {
const theme = useTheme();
const { t } = useTranslation(["common", "countries"]);
const { productionActionById } = usePlay();

if (!teamAction) {
return null;
}

const productionAction = productionActionById[teamAction.actionId];
const stats = computeTeamActionStats(teamAction, productionActionById);
const color = teamAction.isTouched ? theme.palette.secondary.main : "white";

return (
<Box display="flex" alignItems="center" color={color}>
<Box sx={{ width: 300 }} display="flex" alignItems="center" gap={1}>
<Box
className="energy-list-item"
display="flex"
alignItems="start"
gap={1}
color={color}
>
<Box display="flex" gap={1}>
<Icon name="team" />
{showCredibility && (
<div
Expand All @@ -122,20 +196,45 @@ function EnergyListItem({
{!stats.isCredible && <Icon name="warning" sx={{ fontSize: 22 }} />}
</div>
)}
</Box>

<Box display="flex" flexDirection="column" flexGrow={1}>
<Typography>
{t(
`production.energy.${
productionActionById[teamAction.actionId].name
}.name`
)}
:
{t(`production.energy.${productionAction.name}.name`)}
</Typography>
</Box>

<Typography>
{formatProductionGw(stats.powerNeedGw)} GW &amp;{" "}
{formatBudget(stats.cost)} €/j
</Typography>
{showProductionValue && (
<Typography>
{t(
`production.energy.${productionAction.name}.accordion.label-slider`
)}{" "}
:{" "}
{productionAction.unit === "percentage"
? t("unit.percentage", { value: teamAction.value })
: t("unit.area.base", { value: teamAction.value })}
</Typography>
)}

<Box display="grid" gridTemplateColumns="1fr 1fr" maxWidth={300}>
<Box display="flex" alignItems="center" gap={1}>
<Icon name="power" />
<Typography as="span">
{t("unit.power.giga", {
value: formatProductionGw(stats.powerNeedGw),
})}
</Typography>
</Box>
<Box display="flex" alignItems="center" gap={1}>
<Icon name="budget" />
<Typography as="span">
{t("unit.budget-per-day.base", {
value: formatBudget(stats.cost),
symbol: t("countries:country.fr.currency.symbol"),
})}
</Typography>
</Box>
</Box>
</Box>
</Box>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ import { STEPS } from "../constants";
import { Dialog } from "../../common/components/Dialog";
import { useTranslation } from "../../translations/useTranslation";

export { GameConsoleView };
export { GameConsolePage };

// TODO: protect page using user role.
function GameConsoleView() {
function GameConsolePage() {
const [selectedScreen, setSelectedScreen] = useState<string>("Teams");
return (
<>
Expand Down
28 changes: 17 additions & 11 deletions packages/client/src/modules/play/GameConsole/TeamConsoleContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,22 @@ function TeamConsoleContent({ team }: { team: ITeam }) {
<PlayerComponent key={player.user.id} player={player} />
))}
</Box>
<Box display="flex" flexDirection="column">
<Box display="flex" flexDirection="column" gap={2}>
{isProductionStep && (
<PlayBox>
<TeamActionsRecap
title="Actions Production"
teamActions={teamActionsAtCurrentStep}
showCredibility
/>
</PlayBox>
<Box>
<PlayBox>
<TeamActionsRecap
title="Actions Production"
teamActions={teamActionsAtCurrentStep}
showCredibility
showProductionValue
/>
</PlayBox>
</Box>
)}
<PlayerChart team={team} />
<Box>
<PlayerChart team={team} />
</Box>
</Box>
</Box>
</PlayBox>
Expand Down Expand Up @@ -214,12 +219,13 @@ function PlayerConsumption({ player }: { player: Player }) {
{formatCarbonFootprint(currentPersona.carbonFootprint)} kgCO2/j
</Typography>
</Box>
<Box display="flex" alignItems="center">
<Box display="flex" alignItems="top">
<Icon name="action-points" />
<Typography ml={1} width={150}>
<Typography ml={1} width={150} sx={{ flexShrink: 0 }}>
Point d'actions :
</Typography>
<Rating
sx={{ flexWrap: "wrap" }}
emptyIcon={
<Icon
name="star"
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/modules/play/GameConsole/index.tsx
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { GameConsoleView } from "./GameConsoleView";
export { GameConsolePage } from "./GameConsolePage";
4 changes: 2 additions & 2 deletions packages/client/src/modules/play/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GameConsoleView } from "./GameConsole";
import { GameConsolePage } from "./GameConsole";
import { MyGames } from "./MyGames";
import { PlayerPersona } from "./PlayerPersona";
import { PlayLayout } from "./PlayLayout";
Expand All @@ -7,7 +7,7 @@ import { Stats } from "./Stats";

export * from "./constants";
export {
GameConsoleView,
GameConsolePage,
MyGames,
PlayerPersona,
PlayLayout,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ function TeamActionOptionHeader({
};

return (
<Box display="flex" gap={1}>
<Box display="flex" alignItems="center" gap={1}>
<Icon name="information" onClick={handleOnOpenHelpCard} />
<Typography>
{t(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
Teachers,
} from "../../../administration";
import {
GameConsoleView,
GameConsolePage,
MyGames,
PlayerPersona,
PlayLayout,
Expand Down Expand Up @@ -69,8 +69,8 @@ function AuthenticatedApp() {
path="games/:id/console"
element={<RouteGuard guard={gameConsoleGuard} />}
>
<Route path="" element={<GameConsoleView />} />
<Route path="*" element={<GameConsoleView />} />
<Route path="" element={<GameConsolePage />} />
<Route path="*" element={<GameConsolePage />} />
</Route>
<Route path="" element={<Navigate to="my-games" />} />
<Route path="*" element={<Navigate to="my-games" />} />
Expand Down
Loading

0 comments on commit b5e42a3

Please sign in to comment.