180 lines · 6.4 KB
import type { listAccountContainers } from "~/fns/containers";
import { Button } from "~/ui/Button";
import { ErrorBanner } from "~/ui/Callout";
import { Badge } from "~/ui/Badge";
import { EmptyState } from "~/ui/EmptyState";
import { Panel } from "~/ui/Panel";
import { RelativeTime } from "~/ui/RelativeTime";
import { cn } from "~/utils/cn";
import { TextLink } from "~/ui/TextLink";
import { ProgressTrack, quotaTone } from "~/ui/ProgressTrack";

type Overview = Awaited<ReturnType<typeof listAccountContainers>>;
type Session = Overview["sessions"][number];
type Usage = NonNullable<Overview["usage"]>;

const SECONDS_PER_MINUTE = 60;
const FULL_PERCENT = 100;
const STOP_LABELS: Record<string, string> = {
  idle: "slept after idling",
  cap: "hit the session cap",
  quota: "hit the monthly quota",
  exited: "exited",
  restarted: "restarted",
  failed: "failed to start",
  stopped: "stopped",
  "stopped by admin": "stopped by an admin",
};

function minutesLabel(minutes: number): string {
  return minutes < 1 ? "<1 min" : `${Math.round(minutes)} min`;
}

export function ContainerUsageBar({ usage }: { usage: Usage }) {
  const quota = usage.hardCapSeconds ?? usage.includedSeconds;
  const used = Math.round(usage.usedSeconds / SECONDS_PER_MINUTE);
  const percent = quota > 0 ? Math.min(FULL_PERCENT, (usage.usedSeconds / quota) * FULL_PERCENT) : 0;
  return (
    <div className="space-y-1.5 px-4 py-3">
      <div className="flex items-baseline justify-between text-sm">
        <span className="text-gray-200">Container minutes this month</span>