diff --git a/app/components/device/new/sensors-info.tsx b/app/components/device/new/sensors-info.tsx index 1c6b77ed..422f82ad 100644 --- a/app/components/device/new/sensors-info.tsx +++ b/app/components/device/new/sensors-info.tsx @@ -2,7 +2,15 @@ import { useState, useEffect } from 'react' import { useFormContext } from 'react-hook-form' import { z } from 'zod' import { CustomDeviceConfig } from './custom-device-config' -import { Card, CardContent } from '~/components/ui/card' +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from '~/components/ui/accordion' +import { Badge } from '~/components/ui/badge' +import { Checkbox } from '~/components/ui/checkbox' +import { Label } from '~/components/ui/label' import { cn } from '~/lib/utils' import { getSensorsForModel } from '~/utils/model-definitions' @@ -38,12 +46,8 @@ export function SensorSelectionStep() { : selectedDevice setSelectedDeviceModel(deviceModel) - if (deviceModel !== 'custom') { - const fetchedSensors = getSensorsForModel(deviceModel) - setSensors(fetchedSensors) - } else { - setSensors([]) - } + const fetchedSensors = getSensorsForModel(deviceModel) + setSensors(fetchedSensors) } }, [selectedDevice]) @@ -73,48 +77,50 @@ export function SensorSelectionStep() { const sensorGroups = groupSensorsByType(sensors) - const handleGroupToggle = (group: SensorGroup) => { - const isGroupSelected = group.sensors.every((sensor) => - selectedSensors.some( - (s) => s.title === sensor.title && s.sensorType === sensor.sensorType, - ), + const isSensorSelected = (sensor: Sensor) => + selectedSensors.some( + (s) => s.title === sensor.title && s.sensorType === sensor.sensorType, ) - const updatedSensors = isGroupSelected + const isGroupFullySelected = (group: SensorGroup) => + group.sensors.every((sensor) => isSensorSelected(sensor)) + + const isGroupPartiallySelected = (group: SensorGroup) => + group.sensors.some((sensor) => isSensorSelected(sensor)) && + !isGroupFullySelected(group) + + const getSelectedCountForGroup = (group: SensorGroup) => + group.sensors.filter((sensor) => isSensorSelected(sensor)).length + + const handleSensorToggle = (sensor: Sensor) => { + const isAlreadySelected = isSensorSelected(sensor) + + const updatedSensors = isAlreadySelected ? selectedSensors.filter( (s) => - !group.sensors.some( - (sensor) => - s.title === sensor.title && s.sensorType === sensor.sensorType, - ), + !(s.title === sensor.title && s.sensorType === sensor.sensorType), ) - : [ - ...selectedSensors, - ...group.sensors.filter( - (sensor) => - !selectedSensors.some( - (s) => - s.title === sensor.title && - s.sensorType === sensor.sensorType, - ), - ), - ] + : [...selectedSensors, sensor] setSelectedSensors(updatedSensors) setValue('selectedSensors', updatedSensors) } - const handleSensorToggle = (sensor: Sensor) => { - const isAlreadySelected = selectedSensors.some( - (s) => s.title === sensor.title && s.sensorType === sensor.sensorType, - ) + const handleGroupToggle = (group: SensorGroup) => { + const isFullySelected = isGroupFullySelected(group) - const updatedSensors = isAlreadySelected + const updatedSensors = isFullySelected ? selectedSensors.filter( (s) => - !(s.title === sensor.title && s.sensorType === sensor.sensorType), + !group.sensors.some( + (sensor) => + s.title === sensor.title && s.sensorType === sensor.sensorType, + ), ) - : [...selectedSensors, sensor] + : [ + ...selectedSensors, + ...group.sensors.filter((sensor) => !isSensorSelected(sensor)), + ] setSelectedSensors(updatedSensors) setValue('selectedSensors', updatedSensors) @@ -124,93 +130,154 @@ export function SensorSelectionStep() { return

Please select a device first.

} - if (selectedDevice === 'custom') { + if (selectedDevice === 'Custom') { return } + const isSenseBoxHomeV2 = selectedDeviceModel === 'senseBoxHomeV2' + return ( -
-
-
- {sensorGroups.map((group) => { - const isGroupSelected = group.sensors.every((sensor) => - selectedSensors.some( - (s) => - s.title === sensor.title && - s.sensorType === sensor.sensorType, - ), - ) - - return ( - handleGroupToggle(group) - : undefined - } - > - -

- {group.sensorType} -

- -
    - {group.sensors.map((sensor) => { - const isSelected = selectedSensors.some( - (s) => - s.title === sensor.title && - s.sensorType === sensor.sensorType, - ) - - return ( -
  • { - e.stopPropagation() - handleSensorToggle(sensor) - } - : undefined - } - > - {sensor.title} ({sensor.unit}) -
  • - ) - })} -
-
+
+ {/* Selected count summary */} +
+

+ {selectedSensors.length} sensor + {selectedSensors.length !== 1 ? 's' : ''} selected +

+ {selectedSensors.length > 0 && ( + + )} +
+ + + {sensorGroups.map((group) => { + const isFullySelected = isGroupFullySelected(group) + const isPartiallySelected = isGroupPartiallySelected(group) + const selectedCount = getSelectedCountForGroup(group) + + return ( + + +
+
{group.image && ( {`${group.sensorType} )} +
+

{group.sensorType}

+

+ {group.sensors.length} parameter + {group.sensors.length !== 1 ? 's' : ''} +

+
- - - ) - })} -
-
+ {selectedCount > 0 && ( + + {selectedCount} selected + + )} +
+ + +
+ {/* Select All option */} +
e.stopPropagation()} + > + handleGroupToggle(group)} + /> + +
+ + {/* Individual sensors - only show for non-senseBoxHomeV2 or always show */} + {!isSenseBoxHomeV2 && ( +
+ {group.sensors.map((sensor) => { + const isSelected = isSensorSelected(sensor) + const sensorId = `sensor-${group.sensorType}-${sensor.title}` + + return ( +
e.stopPropagation()} + > + handleSensorToggle(sensor)} + /> + +
+ ) + })} +
+ )} + + {/* For senseBoxHomeV2, just show the parameters as info */} + {isSenseBoxHomeV2 && ( +
+

Includes:

+ {group.sensors.map((sensor) => ( +

+ • {sensor.title} ({sensor.unit}) +

+ ))} +
+ )} +
+
+ + ) + })} +
) }