Skip to content

Commit

Permalink
Refactored modals and options for inverter/charger and inverters.
Browse files Browse the repository at this point in the history
  • Loading branch information
fwaalkens committed Oct 20, 2023
1 parent 787058e commit b41aad6
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 105 deletions.
88 changes: 11 additions & 77 deletions src/app/Marine2/components/boxes/Inverter/Inverter.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
import { useEffect, useState } from "react"
import { useState } from "react"
import { observer } from "mobx-react-lite"
import { translate } from "react-i18nify"
import { ComponentMode } from "@m2Types/generic/component-mode"
import { ISize } from "@m2Types/generic/size"
import { InverterInstanceId, useAppStore, useInverter } from "@victronenergy/mfd-modules"
import InverterChargerIcon from "../../../images/icons/inverter-charger.svg"
import GeneratorIcon from "../../../images/icons/generator.svg"
import { INVERTER_MODE } from "../../../utils/constants"
import classNames from "classnames"
import ValueBar from "../../ui/ValueBar"
import Button from "../../ui/Button"
import DeviceSettingModal from "../../ui/DeviceSettingModal/DeviceSettingModal"
import RadioButton from "../../ui/RadioButton"
import Box from "../../ui/Box"
import { applyStyles, defaultBoxStyles } from "../../../utils/media"
import ValueOverview from "../../ui/ValueOverview"
import { formatModeFor } from "../../../utils/formatters/devices/inverter/format-mode-for"
import { translatedStateFor } from "../../../utils/helpers/devices/translated-state-for"
import { titleFor } from "../../../utils/helpers/devices/title-for"
import { Modal } from "./Modal/Modal"

interface Props {
instanceId: InverterInstanceId
Expand All @@ -28,12 +25,9 @@ interface Props {

const Inverter = ({ instanceId, isVebusInverter, componentMode = "compact", compactBoxSize }: Props) => {
const { locked } = useAppStore() // lock from theme settings

const source = isVebusInverter ? "vebus" : "inverter"
const { state, mode, voltage, current, power, productName, customName, updateMode } = useInverter(instanceId, source)

// Vebus inverters use mode 3 instead of 2 for ON.
const onMode = isVebusInverter ? INVERTER_MODE.VEBUS_ON : INVERTER_MODE.ON
const { state, mode, voltage, current, power, customName, productName } = useInverter(instanceId, source)

const title = titleFor(customName, productName)
const subTitle = translatedStateFor(state)
Expand All @@ -44,22 +38,7 @@ const Inverter = ({ instanceId, isVebusInverter, componentMode = "compact", comp
const [boxSize, setBoxSize] = useState<ISize>({ width: 0, height: 0 })
const activeStyles = applyStyles(boxSize, defaultBoxStyles)

const [isModeModalOpen, setIsModeModalOpen] = useState(false)
const [modeForSubmission, setModeForSubmission] = useState(Number(mode))

useEffect(() => {
setModeForSubmission(Number(mode))
}, [mode])

const closeModeModal = () => {
setIsModeModalOpen(false)
setModeForSubmission(Number(mode))
}

const submitMode = () => {
updateMode(modeForSubmission)
closeModeModal()
}
const [openModal, setOpenModal] = useState(false)

if (componentMode === "compact" && compactBoxSize) {
return (
Expand Down Expand Up @@ -98,62 +77,17 @@ const Inverter = ({ instanceId, isVebusInverter, componentMode = "compact", comp
]}
/>
</div>
<Button
disabled={locked}
className="w-full mt-3"
size="md"
onClick={() => setIsModeModalOpen(!isModeModalOpen)}
>
<Button disabled={locked} className="w-full mt-3" size="md" onClick={() => setOpenModal(!openModal)}>
{inverterMode}
</Button>
</div>
{/* TODO Refactor to seperate modal file. */}
<DeviceSettingModal
<Modal
instanceId={instanceId}
isVebusInverter={isVebusInverter}
title={title}
subtitle={translate("common.mode")}
open={isModeModalOpen}
onClose={closeModeModal}
onSet={submitMode}
>
{/* TODO Refactor to list item 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(onMode)}
>
<span>{translate("common.on")}</span>
<RadioButton
onChange={() => setModeForSubmission(onMode)}
selected={modeForSubmission === onMode}
responsive={false}
/>
</label>
<label
className="w-full flex justify-between items-center py-4 last:pb-0"
onClick={() => setModeForSubmission(INVERTER_MODE.OFF)}
>
<span>{translate("common.off")}</span>
<RadioButton
onChange={() => setModeForSubmission(INVERTER_MODE.OFF)}
selected={modeForSubmission === INVERTER_MODE.OFF}
responsive={false}
/>
</label>
{!isVebusInverter && (
<label
className="w-full flex justify-between items-center pt-4"
onClick={() => setModeForSubmission(INVERTER_MODE.ECO)}
>
<span>{translate("common.eco")}</span>
<RadioButton
onChange={() => setModeForSubmission(INVERTER_MODE.ECO)}
selected={modeForSubmission === INVERTER_MODE.ECO}
responsive={false}
/>
</label>
)}
</div>
</DeviceSettingModal>
open={openModal}
onClose={setOpenModal}
/>
</div>
</Box>
)
Expand Down
51 changes: 51 additions & 0 deletions src/app/Marine2/components/boxes/Inverter/Modal/Modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { FC, useEffect, useState } from "react"
import { observer } from "mobx-react"
import { translate } from "react-i18nify"
import { InverterInstanceId, useInverter } from "@victronenergy/mfd-modules"
import DeviceSettingModal from "../../../ui/DeviceSettingModal/DeviceSettingModal"
import { Options } from "./Options/Options"

interface Props {
instanceId: InverterInstanceId
isVebusInverter: boolean
title?: string
open: boolean
onClose: (arg: boolean) => void
}

export const Modal: FC<Props> = observer(({ instanceId, isVebusInverter, title, open, onClose }) => {
const source = isVebusInverter ? "vebus" : "inverter"

const { mode, updateMode } = useInverter(instanceId, source)
const [modeForSubmission, setModeForSubmission] = useState(Number(mode))

useEffect(() => {
setModeForSubmission(Number(mode))
}, [mode])

const closeModeModal = () => {
onClose(!open)
setModeForSubmission(Number(mode))
}

const submitMode = () => {
updateMode(modeForSubmission)
closeModeModal()
}

return (
<DeviceSettingModal
title={title}
subtitle={translate("common.mode")}
open={open}
onClose={closeModeModal}
onSet={submitMode}
>
<Options
mode={modeForSubmission}
onChange={setModeForSubmission}
isVebus={isVebusInverter}
/>
</DeviceSettingModal>
)
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { FC } from "react"
import { translate } from "react-i18nify"
import { inverterOptionsFor } from "../../../../../utils/helpers/devices/inverter-options-for"
import { OptionList } from "../../../../ui/OptionList/OptionList"
import { RadioOption } from "../../../../ui/OptionList/RadioOption/RadioOption"

interface Props {
mode: number
onChange: (arg: number) => void
isVebus: boolean
}

export const Options: FC<Props> = ({ mode, onChange, isVebus }) => {
const options = inverterOptionsFor(isVebus)

return (
<OptionList>
{options.map(({ key, value }) => (
<RadioOption key={key} mode={mode} onChange={onChange} value={value}>
{translate(key)}
</RadioOption>
))}
</OptionList>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const Modal: FC<Props> = observer(({ title, open, onClose }) => {
onClose={closeModeModal}
onSet={submitMode}
>
<Options modeForSubmission={modeForSubmission} onChange={setModeForSubmission} />
<Options mode={modeForSubmission} onChange={setModeForSubmission} />
</DeviceSettingModal>
)
})
Original file line number Diff line number Diff line change
@@ -1,33 +1,20 @@
import { FC } from "react"
import { translate } from "react-i18nify"
import { SYSTEM_MODE } from "app/Marine2/utils/constants"
import RadioButton from "../../../../ui/RadioButton"
import { OptionList } from "../../../../ui/OptionList/OptionList"
import { inverterChargerOptions } from "../../../../../utils/constants/mode-options"
import { RadioOption } from "../../../../ui/OptionList/RadioOption/RadioOption"

interface Props {
modeForSubmission: number
mode: number
onChange: (arg: number) => void
}

export const Options: FC<Props> = ({ modeForSubmission, onChange }) => {
const options = [
{ key: "common.on", value: SYSTEM_MODE.ON },
{ key: "common.off", value: SYSTEM_MODE.OFF },
{ key: "common.chargerOnly", value: SYSTEM_MODE.CHARGER_ONLY },
{ key: "common.inverterOnly", value: SYSTEM_MODE.INVERTER_ONLY },
]

return (
<div className="divide-y divide-victron-darkGray-200 text-base">
{options.map((option) => (
<label className="w-full flex justify-between items-center pb-4" onClick={() => onChange(option.value)}>
<span>{translate(option.key)}</span>
<RadioButton
onChange={() => onChange(option.value)}
selected={modeForSubmission === option.value}
responsive={false}
/>
</label>
))}
</div>
)
}
export const Options: FC<Props> = ({ mode, onChange }) => (
<OptionList>
{inverterChargerOptions.map(({ key, value }) => (
<RadioOption key={key} mode={mode} onChange={onChange} value={value}>
{translate(key)}
</RadioOption>
))}
</OptionList>
)
2 changes: 1 addition & 1 deletion src/app/Marine2/components/ui/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface Props {

const Frame: FC<Props> = ({ children, open = true, onClose, className }) => {
const classes = classnames(
"fixed inset-0 z-10 p-8 text-neutral-600 modal dark:text-white items-center justify-center",
"fixed inset-0 z-10 p-4 md:p-8 text-neutral-600 modal dark:text-white items-center justify-center",
`${open ? "flex" : "hidden"}` // control visibility via `open` attribute (or render conditionally)
)
return (
Expand Down
5 changes: 5 additions & 0 deletions src/app/Marine2/components/ui/OptionList/OptionList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { FC } from "react"

export const OptionList: FC = ({ children }) => (
<div className="divide-y divide-victron-darkGray-200 text-base">{children}</div>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { FC } from "react"
import RadioButton from "../../RadioButton"

interface Props {
mode: number
onChange: (arg: number) => void
key: string
value: number
}

export const RadioOption: FC<Props> = ({ mode, onChange, value, children }) => (
<label className="w-full flex justify-between items-center py-4 first:pt-0 last:pb-0" onClick={() => onChange(value)}>
<span>{children}</span>
<RadioButton onChange={() => onChange(value)} selected={mode === value} responsive={false} />
</label>
)
19 changes: 19 additions & 0 deletions src/app/Marine2/utils/constants/mode-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { INVERTER_MODE, SYSTEM_MODE } from "../constants"

export const inverterOptions = [
{ key: "common.on", value: INVERTER_MODE.ON },
{ key: "common.off", value: INVERTER_MODE.OFF },
{ key: "common.eco", value: INVERTER_MODE.ECO },
]

export const vebusInverOptions = [
{ key: "common.on", value: INVERTER_MODE.VEBUS_ON },
{ key: "common.off", value: INVERTER_MODE.OFF },
]

export const inverterChargerOptions = [
{ key: "common.on", value: SYSTEM_MODE.ON },
{ key: "common.off", value: SYSTEM_MODE.OFF },
{ key: "common.chargerOnly", value: SYSTEM_MODE.CHARGER_ONLY },
{ key: "common.inverterOnly", value: SYSTEM_MODE.INVERTER_ONLY },
]
3 changes: 3 additions & 0 deletions src/app/Marine2/utils/helpers/devices/inverter-options-for.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { inverterOptions, vebusInverOptions } from "../../constants/mode-options"

export const inverterOptionsFor = (isVebus: boolean) => (isVebus ? vebusInverOptions : inverterOptions)

0 comments on commit b41aad6

Please sign in to comment.