From 745b24f8d73a2c7e7d5d9d5f650e14975ceb5f29 Mon Sep 17 00:00:00 2001 From: John Darragh Date: Wed, 25 Aug 2021 16:04:06 -0700 Subject: [PATCH] Add progress bar, shopping cart to sidebar --- .../RuleStrategy/RuleStrategy.js | 8 +- .../ProjectWizard/TdmCalculationWizard.js | 1 + .../WizardSidebar/EarnedPointsProgress.js | 217 ++++++++++++++++++ .../WizardSidebar/SidebarCart.js | 98 ++++++++ .../WizardSidebar/SidebarPointsPanel.js | 80 ++++--- .../WizardSidebar/SidebarProjectLevel.js | 6 +- .../WizardSidebar/WizardSidebar.js | 10 +- client/src/styles/Calculation.scss | 36 ++- 8 files changed, 409 insertions(+), 47 deletions(-) create mode 100644 client/src/components/ProjectWizard/WizardSidebar/EarnedPointsProgress.js create mode 100644 client/src/components/ProjectWizard/WizardSidebar/SidebarCart.js diff --git a/client/src/components/ProjectWizard/RuleStrategy/RuleStrategy.js b/client/src/components/ProjectWizard/RuleStrategy/RuleStrategy.js index bc5dbaab..9eadf7af 100644 --- a/client/src/components/ProjectWizard/RuleStrategy/RuleStrategy.js +++ b/client/src/components/ProjectWizard/RuleStrategy/RuleStrategy.js @@ -149,9 +149,11 @@ const RuleStrategy = ({ : null}
- {`${calcValue ? Math.round(calcValue * 100) / 100 : ""} ${ - calculationUnits || "" - }`} + {`${ + calcValue + ? Math.round(calcValue * 100) / 100 + " " + calculationUnits || "" + : "" + } `}
); diff --git a/client/src/components/ProjectWizard/TdmCalculationWizard.js b/client/src/components/ProjectWizard/TdmCalculationWizard.js index baa9b617..e7fc9a24 100644 --- a/client/src/components/ProjectWizard/TdmCalculationWizard.js +++ b/client/src/components/ProjectWizard/TdmCalculationWizard.js @@ -159,6 +159,7 @@ const TdmCalculationWizard = props => { rules={rules} onViewChange={onViewChange} resultRules={resultRules} + strategyRules={strategyRules} /> )} contentContainerRef={contentContainerRef} diff --git a/client/src/components/ProjectWizard/WizardSidebar/EarnedPointsProgress.js b/client/src/components/ProjectWizard/WizardSidebar/EarnedPointsProgress.js new file mode 100644 index 00000000..cc9c1dcf --- /dev/null +++ b/client/src/components/ProjectWizard/WizardSidebar/EarnedPointsProgress.js @@ -0,0 +1,217 @@ +import React, { useRef } from "react"; +import PropTypes from "prop-types"; +import { createUseStyles, useTheme } from "react-jss"; +import ToolTipIcon from "../../ToolTip/ToolTipIcon"; +import clsx from "clsx"; + +/* +See https://css-tricks.com/building-progress-ring-quickly/ + +for explanation of operation +*/ + +const DIAL_RADIUS = 95; +const STROKE_WIDTH = 15; + +const useStyles = createUseStyles({ + rotate: { + transform: "rotate(75deg)" + }, + progress: { + transition: "stroke-dashoffset 18s" + }, + tooltip: { + color: "rgb(30, 36, 63) !important", + padding: "15px", + minWidth: "200px", + maxWidth: "400px", + fontFamily: "Arial", + fontSize: 12, + lineHeight: "16px", + fontWeight: "bold", + boxShadow: "0px 0px 8px rgba(0, 46, 109, 0.2)", + borderRadius: 2, + "&.show": { + visibility: "visible !important", + opacity: "1 !important" + } + }, + lowOpacity: { + opacity: 0.4 + }, + noDisplay: { + display: "none !important" + } +}); + +const EarnedPointsProgress = props => { + const theme = useTheme(); + const classes = useStyles({ theme }); + const controlRef = useRef(null); + + const { rulesConfig } = props; + const radius = DIAL_RADIUS; + const stroke = STROKE_WIDTH; + + const target = rulesConfig.targetPointsRule.value || 0; + const earned = rulesConfig.earnedPointsRule.value || 0; + + const normalizedRadius = radius - stroke * 2; + const circumference = normalizedRadius * 2 * Math.PI; + const strokeDashoffset = Math.max( + 0, + circumference - (earned / target) * 0.85 * circumference + ); + + return ( +
0 + ? "tdm-calculation-progress" + : clsx("tdm-calculation-progress", classes.lowOpacity) + } + style={{ + display: "grid", + gridTemplateColumns: "1fr", + gridTemplateRows: "1fr", + justifyContent: "center" + }} + > +
+
{earned}
+
+ EARNED +
+
+
+
{target}
+
+ TARGET +
+
+
" + + rulesConfig.earnedPointsRule.description + + "

" + + rulesConfig.targetPointsRule.description + + "

" + } + data-iscapture="true" + data-html="true" + data-class={ + target > 0 + ? classes.tooltip + : clsx(classes.tooltip, classes.noDisplay) + } + style={{ + gridRow: 1, + gridColumn: 1, + zIndex: 10, + marginLeft: 170, + marginTop: 45 + }} + > + +
+ + + = 1 + ? theme.colorPrimary + : earned / target >= 0.01 + ? theme.colorEarnedPoints + : theme.colorDisabled + } + fill="transparent" + strokeWidth={stroke} + strokeDasharray={circumference + " " + circumference} + strokeLinecap="round" + style={{ + strokeDashoffset + }} + r={normalizedRadius} + cx={radius} + cy={radius} + /> + + +
+ ); +}; + +EarnedPointsProgress.propTypes = { + rulesConfig: PropTypes.object +}; + +export default EarnedPointsProgress; diff --git a/client/src/components/ProjectWizard/WizardSidebar/SidebarCart.js b/client/src/components/ProjectWizard/WizardSidebar/SidebarCart.js new file mode 100644 index 00000000..9bc61857 --- /dev/null +++ b/client/src/components/ProjectWizard/WizardSidebar/SidebarCart.js @@ -0,0 +1,98 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { createUseStyles } from "react-jss"; + +const useStyles = createUseStyles({ + noDisplay: { + display: "none !important" + } +}); + +const SidebarCart = props => { + const { strategyRules } = props; + const classes = useStyles(); + return ( +
+
+
+
+ TDM MEASURES SELECTED +
+
+ EARNED POINTS +
+
+
+ + {strategyRules + .filter(r => r.calcValue > 0) + .map(rule => ( +
+
+ {rule.name} +
+
+ + {Math.round(rule.calcValue * 100) / 100} + + +  pts + +
+
+ ))} +
+
+ ); +}; + +SidebarCart.propTypes = { + strategyRules: PropTypes.array +}; + +export default SidebarCart; diff --git a/client/src/components/ProjectWizard/WizardSidebar/SidebarPointsPanel.js b/client/src/components/ProjectWizard/WizardSidebar/SidebarPointsPanel.js index c2f1d5e4..b211f91f 100644 --- a/client/src/components/ProjectWizard/WizardSidebar/SidebarPointsPanel.js +++ b/client/src/components/ProjectWizard/WizardSidebar/SidebarPointsPanel.js @@ -1,46 +1,32 @@ -import React, { useEffect, useState } from "react"; +import React /*, { useEffect, useState } */ from "react"; import PropTypes from "prop-types"; -import SidebarPoints from "./SidebarPoints"; +// import SidebarPoints from "./SidebarPoints"; import SidebarProjectLevel from "./SidebarProjectLevel"; -import EarnedPointsMetContainer from "./EarnedPointsMetContainer"; +// import EarnedPointsMetContainer from "./EarnedPointsMetContainer"; +import EarnedPointsProgress from "./EarnedPointsProgress"; +import SidebarCart from "./SidebarCart"; +// import ToolTip from "../../ToolTip/ToolTip"; const SidebarPointsPanel = props => { - const { rules } = props; + const { rules, strategyRules } = props; let targetPointsRule = {}; let earnedPointsRule = {}; let projectLevelRule = {}; if (rules) { - targetPointsRule = rules.filter( - rule => rule.code === "TARGET_POINTS_PARK" - )[0]; - earnedPointsRule = rules.filter(rule => rule.code === "PTS_EARNED")[0]; - projectLevelRule = rules.filter(rule => rule.code === "PROJECT_LEVEL")[0]; + targetPointsRule = rules.find(rule => rule.code === "TARGET_POINTS_PARK"); + earnedPointsRule = rules.find(rule => rule.code === "PTS_EARNED"); + projectLevelRule = rules.find(rule => rule.code === "PROJECT_LEVEL"); } - const rulesConfig = { - target: { - value: rules[2].value - }, - earned: { - value: rules[3].value - } - }; + // const targetPoints = targetPointsRule ? targetPointsRule.value : null; + // const earnedPoints = earnedPointsRule ? earnedPointsRule.value : null; + const rulesConfig = { targetPointsRule, earnedPointsRule }; - const target = rulesConfig.target.value; - const earned = rulesConfig.earned.value; + // const [earnedPointsMet, setEarnedPointsMet] = useState(false); - const targetPointsTipText = rules[2].description; - const earnedPointsTipText = rules[3].description; - - const [earnedPointsMet, setEarnedPointsMet] = useState(false); - - useEffect(() => { - if (earned >= target && target > 0) { - setEarnedPointsMet(true); - } else { - setEarnedPointsMet(false); - } - }, [earned, target]); + // useEffect(() => { + // setEarnedPointsMet(earnedPoints >= targetPoints && targetPoints > 0); + // }, [earnedPoints, targetPoints]); return ( @@ -52,28 +38,48 @@ const SidebarPointsPanel = props => { rules={rules} /> -
-
+ {/*
*/} + {/*
+
*/} +
+ +
+ +
+
- {earnedPointsMet && } + + {/* {earnedPointsMet && } */} + {/* */} ); }; SidebarPointsPanel.propTypes = { - rules: PropTypes.array + rules: PropTypes.array, + strategyRules: PropTypes.array }; export default SidebarPointsPanel; diff --git a/client/src/components/ProjectWizard/WizardSidebar/SidebarProjectLevel.js b/client/src/components/ProjectWizard/WizardSidebar/SidebarProjectLevel.js index e65069da..5cde8570 100644 --- a/client/src/components/ProjectWizard/WizardSidebar/SidebarProjectLevel.js +++ b/client/src/components/ProjectWizard/WizardSidebar/SidebarProjectLevel.js @@ -7,7 +7,7 @@ import clsx from "clsx"; const useStyles = createUseStyles({ projectLevelHeader: { color: "white", - fontSize: 20, + fontSize: 18, fontFamily: "Oswald, Calibri", fontWeight: 500, textAlign: "center", @@ -15,10 +15,10 @@ const useStyles = createUseStyles({ }, projectLevelValue: { color: "white", - fontSize: 100, + fontSize: 80, fontFamily: "Oswald, Calibri", fontWeight: "bold", - marginBottom: 0, + marginBottom: "-12px", textAlign: "center", lineHeight: "1.1em" }, diff --git a/client/src/components/ProjectWizard/WizardSidebar/WizardSidebar.js b/client/src/components/ProjectWizard/WizardSidebar/WizardSidebar.js index 5d386908..685738bf 100644 --- a/client/src/components/ProjectWizard/WizardSidebar/WizardSidebar.js +++ b/client/src/components/ProjectWizard/WizardSidebar/WizardSidebar.js @@ -19,7 +19,7 @@ const useStyles = createUseStyles({ } }); -const WizardSidebar = ({ rules, onViewChange, resultRules }) => { +const WizardSidebar = ({ rules, onViewChange, resultRules, strategyRules }) => { const classes = useStyles(); return ( @@ -29,7 +29,10 @@ const WizardSidebar = ({ rules, onViewChange, resultRules }) => { Switch to Single Page View - +
)} @@ -39,7 +42,8 @@ const WizardSidebar = ({ rules, onViewChange, resultRules }) => { WizardSidebar.propTypes = { rules: PropTypes.any, onViewChange: PropTypes.any, - resultRules: PropTypes.any + resultRules: PropTypes.any, + strategyRules: PropTypes.array }; export default WizardSidebar; diff --git a/client/src/styles/Calculation.scss b/client/src/styles/Calculation.scss index 01725842..5a0b8686 100644 --- a/client/src/styles/Calculation.scss +++ b/client/src/styles/Calculation.scss @@ -100,13 +100,42 @@ display: flex; flex-direction: column; align-items: center; - flex-basis: 50%; + flex-basis: 25%; + flex-grow: 0; margin: 0; padding: 0.5em; background-color: transparent; color: $color-background; } +.tdm-calculation-progress { + flex-basis: 25%; + flex-grow: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin: 0; + padding: 0.5em; + background-color: transparent; + color: $color-background; +} + +.tdm-calculation-cart { + flex-basis: 50%; + display: flex; + flex-direction: column; + flex-shrink: 0; + align-items: stretch; + justify-content: flex-start; + background-color: #f7f9fa; + font-family: Oswald; + padding: 10px; + line-height: 1.5em; + color: $color-primary; + overflow-y: scroll; +} + .tdm-wizard-review-page { display: flex; flex-direction: column; @@ -119,4 +148,9 @@ .tdm-results-panel { top: 0; } + + // Hide the Shopping Cart on narrow devices + .tdm-calculation-cart { + display: none; + } }