Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | 33x 470x 470x 470x 470x 63x 470x 470x 470x 470x 470x 63x | import { BiHide } from "react-icons/bi";
import { useStores } from "~/hooks/useStores";
import { HubDevice } from "~/types/HubDevice";
import { deviceToIconMap } from "~/utils/deviceToIconMap";
import { getFigure } from "~/utils/getFigure";
import { sanitizeName } from "~/utils/sanitizeName";
export const Device = ({
device,
controlDevice,
}: {
device: HubDevice;
controlDevice: (device: HubDevice) => void;
}) => {
const { archive } = useStores();
const deviceName = sanitizeName(device.name ?? "");
const deviceFigure = getFigure(deviceToIconMap(35), deviceName);
const handleToggle = (device: HubDevice) => {
controlDevice(device);
};
const handleArchive = (deviceId: number) => {
archive.add(deviceId);
};
const deviceId = `device-${device.connectedDeviceId}`;
const toggleId = `toggle-${device.connectedDeviceId}`;
const hideButtonId = `hide-${device.connectedDeviceId}`;
return (
<div
key={device.connectedDeviceId}
className="flex flex-col items-center justify-center text-base-content border-1 border-base-300 py-2 px-4 rounded-3xl"
aria-labelledby={deviceId}
>
<div className="flex justify-between w-[100%]">
<div className="flex gap-2 items-center justify-center">
<div
aria-hidden="true"
role="img"
aria-label={`${deviceName} device icon - ${
device.isActive ? "active" : "inactive"
}`}
>
{device.isActive
? deviceFigure.active
: deviceFigure.inactive}
</div>
<span id={deviceId} className="font-semibold min-w-max">
{deviceName}
</span>
</div>
<div
className="flex flex-row items-center justify-center gap-3 p-2"
role="group"
aria-label={`Controls for ${deviceName}`}
>
<button
id={hideButtonId}
onClick={() => handleArchive(device.connectedDeviceId)}
className="text-error hover:opacity-100 opacity-60 transition-opacity duration-200 cursor-pointer focus:outline-none focus:ring-2 focus:ring-error focus:ring-offset-2 rounded"
aria-label={`Hide ${deviceName} device`}
data-cy={`hide-${device.name}`}
type="button"
>
<BiHide size={22} aria-hidden="true" />
</button>
<div className="flex flex-col items-center gap-1">
<label htmlFor={toggleId} className="sr-only">
{device.isActive
? `Turn off ${deviceName}`
: `Turn on ${deviceName}`}
</label>
<input
id={toggleId}
type="checkbox"
checked={device.isActive}
onChange={() => handleToggle(device)}
className={`toggle ${
device.isActive
? "toggle-primary"
: "toggle-accent"
} cursor-pointer toggle-lg focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2`}
aria-describedby={`${toggleId}-status`}
/>
<span
id={`${toggleId}-status`}
className="sr-only"
aria-live="polite"
>
{deviceName} is currently{" "}
{device.isActive ? "on" : "off"}
</span>
</div>
</div>
</div>
</div>
);
};
|