IKHSAN
EN Read in EnglishID

homeio

Publik

Fork dari doctor-io/homeio

Branch
main
Commit terakhir
958d74616 Oktober 2026

battery-popover.tsx

Buka raw
"use client";

import { PopoverShell } from "@/modules/system/components/status-bar/popover-shell";
import type { BatteryPopoverProps } from "@/modules/system/components/status-bar/types";
import { safePercent } from "@/modules/system/components/status-bar/utils";
import { BatteryCharging, BatteryFull } from "@/components/icons/platform-icons";

function formatCapacityRatio(value: number | null | undefined) {
  if (typeof value !== "number" || Number.isNaN(value)) return "--";
  return `${value.toFixed(1)}%`;
}

export function BatteryPopover({ battery, onClose }: BatteryPopoverProps) {
  const hasBattery = Boolean(battery?.hasBattery);
  const batteryPercent =
    typeof battery?.percent === "number" ? safePercent(battery.percent) : null;
  const isCharging = Boolean(battery?.isCharging);
  const acConnected = battery?.acConnected;
  const manufacturer = battery?.manufacturer ?? null;
  const cycleCount = battery?.cycleCount;
  const capacityRatio = formatCapacityRatio(
    battery?.designToMaxCapacityPercent,
  );
  const statusLabel = !hasBattery
    ? "No battery detected"
    : isCharging
      ? "Charging"
      : "On battery";

  return (
    <PopoverShell onClose={onClose} className="w-64">
      <div className="p-4">
        <div className="flex items-center gap-3 mb-4">
          <div className="size-10 rounded-xl bg-status-green/15 flex items-center justify-center">
            {isCharging ? (
              <BatteryCharging className="size-5 text-status-green" />
            ) : (
              <BatteryFull className="size-5 text-status-amber" />
            )}
          </div>
          <div>
            <p className="text-sm font-semibold text-foreground">
              Battery Status
            </p>
            <p className="text-xs text-muted-foreground">{statusLabel}</p>
          </div>
        </div>

        <div className="space-y-3">
          <div>
            <div className="flex items-center justify-between text-xs mb-1">
              <span className="text-muted-foreground">Charge Level</span>
              <span className="text-foreground font-medium">
                {batteryPercent === null ? "--" : `${batteryPercent}%`}
              </span>
            </div>
            <div className="h-2 rounded-[var(--radius)] bg-muted overflow-hidden">
              <div
                className={`h-full rounded-[var(--radius)] ${
                  batteryPercent === null
                    ? "bg-muted-foreground/40"
                    : batteryPercent < 20
                      ? "bg-status-red"
                      : batteryPercent < 50
                        ? "bg-status-amber"
                        : "bg-status-green"
                }`}
                style={{ width: `${batteryPercent ?? 0}%` }}
              />
            </div>
          </div>

          <div className="grid grid-cols-2 gap-3 pt-1">
            <div className="flex flex-col gap-0.5">
              <span className="text-xs text-muted-foreground uppercase tracking-wider">
                AC Power
              </span>
              <span className="text-sm font-medium text-foreground">
                {typeof acConnected === "boolean"
                  ? acConnected
                    ? "Connected"
                    : "Disconnected"
                  : "--"}
              </span>
            </div>
            <div className="flex flex-col gap-0.5">
              <span className="text-xs text-muted-foreground uppercase tracking-wider">
                Cycle Count
              </span>
              <span className="text-sm font-medium text-foreground">
                {typeof cycleCount === "number" ? cycleCount : "--"}
              </span>
            </div>
            <div className="flex flex-col gap-0.5">
              <span className="text-xs text-muted-foreground uppercase tracking-wider">
                Design / Max
              </span>
              <span className="text-sm font-medium text-foreground">
                {capacityRatio}
              </span>
            </div>
            <div className="flex flex-col gap-0.5">
              <span className="text-xs text-muted-foreground uppercase tracking-wider">
                Manufacturer
              </span>
              <span className="text-sm font-medium text-foreground">
                {manufacturer ?? "--"}
              </span>
            </div>
          </div>
        </div>
      </div>
    </PopoverShell>
  );
}
byte
4.477
baris
116
Jenis
tsx
Commit terakhir
16 Oktober 2026