Skip to content

Commit

Permalink
Refactored components, abstracted enums, uniform title for device hel…
Browse files Browse the repository at this point in the history
…per and more.
  • Loading branch information
fwaalkens committed Oct 16, 2023
1 parent 24b8023 commit 78c03f2
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 170 deletions.
188 changes: 87 additions & 101 deletions src/app/Marine2/components/boxes/Charger/Charger.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { ChargerInstanceId, useCharger } from "@victronenergy/mfd-modules"
import { observer } from "mobx-react-lite"
import InverterChargerIcon from "../../../images/icons/inverter-charger.svg"
import { useEffect, useState } from "react"
import { observer } from "mobx-react"
import classNames from "classnames"
import { translate } from "react-i18nify"
import { ChargerInstanceId, useCharger } from "@victronenergy/mfd-modules"
import { CHARGER_MODE } from "../../../utils/constants"
import { formatStateForTranslation } from "../../../utils/format"
import { CURRENT_LIMIT_STEP } from "../../../utils/constants/generic"
import Button from "../../ui/Button"
import GeneratorIcon from "../../../images/icons/generator.svg"
import classnames from "classnames"
import InverterChargerIcon from "../../../images/icons/inverter-charger.svg"
import ValueBar from "../../ui/ValueBar"
import Box from "../../ui/Box"
import { applyStyles, defaultBoxStyles } from "../../../utils/media"
import { useEffect, useState } from "react"
import classNames from "classnames"
import RadioButton from "../../ui/RadioButton"
import DeviceSettingModal from "../../ui/DeviceSettingModal/DeviceSettingModal"
import ValueOverview from "../../ui/ValueOverview"
Expand All @@ -23,21 +22,18 @@ import {
currentStepIncrementFor,
isCurrentStepDividable,
} from "../../../utils/helpers/current-limit-adjuster"
import { CURRENT_LIMIT_STEP } from "../../../utils/constants/generic"
import { ISize } from "@m2Types/generic/size"
import { titleFor } from "../../../utils/helpers/devices/title-for"
import { translatedStateFor } from "../../../utils/helpers/devices/translated-state-for"
import { formatModeFor } from "../../../utils/formatters/devices/charger/format-mode-for"

const Charger = ({ instanceId, componentMode = "compact", compactBoxSize }: Props) => {
const chargerModeFormatter = (value: number) => {
switch (value) {
case CHARGER_MODE.OFF:
return translate("common.off")
case CHARGER_MODE.ON:
return translate("common.on")
default:
return translate("common.emptyBar")
}
}
interface Props {
instanceId: ChargerInstanceId
componentMode?: ComponentMode
compactBoxSize?: ISize
}

const Charger = ({ instanceId, componentMode = "compact", compactBoxSize }: Props) => {
let {
nrOfOutputs = 3,
productName,
Expand All @@ -52,11 +48,11 @@ const Charger = ({ instanceId, componentMode = "compact", compactBoxSize }: Prop
// When a topic is invalid, it returns undefined -> no value means topic is not supported
const chargerSupportsMode = mode !== undefined
const chargerSupportsInputLimit = currentLimit !== undefined
const chargerMode = chargerModeFormatter(Number(mode))
const chargerMode = formatModeFor(mode)
const currentValue = !!current && (!!current[0] || current[0] === 0) ? current[0] : undefined
const subTitle = !!state || state === 0 ? translate(formatStateForTranslation(Number(state))) : undefined

const productNameShort = customName || (productName && productName.split(" ")[0])
const title = titleFor(customName, productName)
const subTitle = translatedStateFor(state)

const [boxSize, setBoxSize] = useState<ISize>({ width: 0, height: 0 })
const activeStyles = applyStyles(boxSize, defaultBoxStyles)
Expand Down Expand Up @@ -117,7 +113,7 @@ const Charger = ({ instanceId, componentMode = "compact", compactBoxSize }: Prop
/* todo: fix types for svg */
/* @ts-ignore */
Icon={InverterChargerIcon}
title={productNameShort}
title={title}
subtitle={subTitle}
value={currentValue}
unit="A"
Expand All @@ -129,94 +125,84 @@ const Charger = ({ instanceId, componentMode = "compact", compactBoxSize }: Prop
return (
<Box
icon={
<GeneratorIcon
/* todo: fix types for svg */
/* @ts-ignore */
className="w-7"
></GeneratorIcon>
/* todo: fix types for svg */
/* @ts-ignore */
<GeneratorIcon className="w-7" />
}
title={productNameShort}
title={title}
getBoxSizeCallback={setBoxSize}
>
<div className="w-full h-full flex flex-col justify-between">
<div className={classNames("text-victron-darkGray dark:text-white", activeStyles?.mainValue)}>
{subTitle}
</div>
<div className={classNames("text-victron-darkGray dark:text-white", activeStyles?.mainValue)}>{subTitle}</div>
<div className="w-full h-full min-h-0 shrink flex flex-col justify-end mt-2">
<div className={classnames("", activeStyles?.secondaryValue)}>
<ValueBar values={current.slice(0, nrOfOutputs).map((v) => ({ value: v, unit: "A" }))} />
</div>
<div className="flex mt-3">
{chargerSupportsInputLimit && (
<Button className="w-full mr-4" size="md" onClick={() => setIsLimitModalOpen(!isLimitModalOpen)}>
{!!currentLimit ? formatValue(Number(currentLimit)) + "A" : 0 + "A"}
</Button>
)}
{chargerSupportsMode && (
<Button className="w-full" size="md" onClick={() => setIsModeModalOpen(!isModeModalOpen)}>
{chargerMode}
</Button>
)}
<div className={classNames("", activeStyles?.secondaryValue)}>
<div className={classNames("", activeStyles?.secondaryValue)}>
<ValueBar values={current.slice(0, nrOfOutputs).map((v) => ({ value: v, unit: "A" }))} />
</div>
<div className="flex mt-3">
{chargerSupportsInputLimit && (
<Button className="w-full mr-4" size="md" onClick={() => setIsLimitModalOpen(!isLimitModalOpen)}>
{!!currentLimit ? formatValue(Number(currentLimit)) + "A" : 0 + "A"}
</Button>
)}
{chargerSupportsMode && (
<Button className="w-full" size="md" onClick={() => setIsModeModalOpen(!isModeModalOpen)}>
{chargerMode}
</Button>
)}
</div>
</div>
{/* TODO refactor modal to seperate file like inverter/charger. */}
{chargerSupportsMode && (
<DeviceSettingModal
title={title}
subtitle={translate("common.mode")}
open={isModeModalOpen}
onClose={closeModeModal}
onSet={submitMode}
>
{/* TODO Refactor to list-item or label component, too much duplicate code. */}
<div className="divide-y divide-victron-darkGray-200 text-base">
<label
className="w-full flex justify-between items-center pb-4"
onClick={() => setModeForSubmission(CHARGER_MODE.ON)}
>
<span>{translate("common.on")}</span>
<RadioButton
onChange={() => setModeForSubmission(CHARGER_MODE.ON)}
selected={modeForSubmission === CHARGER_MODE.ON}
responsive={false}
/>
</label>
<label
className="w-full flex justify-between items-center pt-4"
onClick={() => setModeForSubmission(CHARGER_MODE.OFF)}
>
<span>{translate("common.off")}</span>
<RadioButton
onChange={() => setModeForSubmission(CHARGER_MODE.OFF)}
selected={modeForSubmission === CHARGER_MODE.OFF}
responsive={false}
/>
</label>
</div>
</DeviceSettingModal>
)}
{chargerSupportsInputLimit && (
<DeviceSettingModal
title={title}
subtitle={translate("common.inputCurrentLimit")}
open={isLimitModalOpen}
onClose={closeLimitModal}
onSet={submitLimit}
>
<LimitAdjuster decreaseLimit={decreaseLimit} increaseLimit={increaseLimit} value={limitForSubmission} />
</DeviceSettingModal>
)}
</div>
{chargerSupportsMode && (
<DeviceSettingModal
title={productNameShort}
subtitle={translate("common.mode")}
open={isModeModalOpen}
onClose={closeModeModal}
onSet={submitMode}
>
{/* TODO Refactor to list-item or label component, too much duplicate code. */}
<div className="divide-y divide-victron-darkGray-200 text-base">
<label
className="w-full flex justify-between items-center pb-4"
onClick={() => setModeForSubmission(CHARGER_MODE.ON)}
>
<span>{translate("common.on")}</span>
<RadioButton
onChange={() => setModeForSubmission(CHARGER_MODE.ON)}
selected={modeForSubmission === CHARGER_MODE.ON}
responsive={false}
/>
</label>
<label
className="w-full flex justify-between items-center pt-4"
onClick={() => setModeForSubmission(CHARGER_MODE.OFF)}
>
<span>{translate("common.off")}</span>
<RadioButton
onChange={() => setModeForSubmission(CHARGER_MODE.OFF)}
selected={modeForSubmission === CHARGER_MODE.OFF}
responsive={false}
/>
</label>
</div>
</DeviceSettingModal>
)}
{chargerSupportsInputLimit && (
<DeviceSettingModal
title={productNameShort}
subtitle={translate("common.inputCurrentLimit")}
open={isLimitModalOpen}
onClose={closeLimitModal}
onSet={submitLimit}
>
<LimitAdjuster decreaseLimit={decreaseLimit} increaseLimit={increaseLimit} value={limitForSubmission} />
</DeviceSettingModal>
)}
</div>
</Box>
)
}

interface Props {
instanceId: ChargerInstanceId
componentMode?: ComponentMode
compactBoxSize?: {
width: number
height: number
}
}

export default observer(Charger)
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
useGeneratorRelay,
useInverters,
useVebus,
VebusInverters,
VebusInverters
} from "@victronenergy/mfd-modules"
import Charger from "../Charger"
import Inverter from "../Inverter"
Expand All @@ -32,7 +32,7 @@ import { ComponentMode } from "@m2Types/generic/component-mode"

const DevicesOverview = ({ componentMode = "full", pageSelectorPropsSetter }: Props) => {
const { inverters } = useInverters()
const { instanceId, vebusInverters } = useVebus()
const { instanceId: vebusInstanceId, vebusInverters } = useVebus()
const { chargers } = useChargers()
const generatorFp = useGeneratorFp()
const generatorRelay = useGeneratorRelay()
Expand All @@ -42,7 +42,7 @@ const DevicesOverview = ({ componentMode = "full", pageSelectorPropsSetter }: Pr
chargers,
inverters,
vebusInverters,
instanceId,
vebusInstanceId,
generatorFp,
generatorRelay,
compactBoxSize,
Expand Down Expand Up @@ -90,11 +90,11 @@ const DevicesOverview = ({ componentMode = "full", pageSelectorPropsSetter }: Pr
)
}

const getAvailableDeviceBoxes = function (
const getAvailableDeviceBoxes = function(
chargers: ChargerInstanceId[],
inverters: InverterInstanceId[],
vebusInverters: VebusInverters,
instanceId: InstanceId,
vebusInstanceId: InstanceId,
generatorFp: GeneratorFpProvider,
generatorRelay: GeneratorRelayProvider,
compactBoxSize: { width: number; height: number },
Expand Down Expand Up @@ -138,8 +138,10 @@ const getAvailableDeviceBoxes = function (
})
}

if (!!instanceId) {
devices.push(<InverterCharger key={instanceId} componentMode={componentMode} compactBoxSize={compactBoxSize} />)
if (!!vebusInstanceId && !vebusInverters.includes(vebusInstanceId)) {
devices.push(
<InverterCharger key={vebusInstanceId} componentMode={componentMode} compactBoxSize={compactBoxSize} />
)
}

if (!!generatorFp.phases)
Expand Down
Loading

0 comments on commit 78c03f2

Please sign in to comment.