"use client"; import * as React from "react"; import { AnimatePresence, motion } from "framer-motion"; import { api, type Job } from "@/lib/api"; import { useToast } from "@/components/toast"; import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; export type JobsSnapshot = { jobs: Job[]; counts: Record; pending: number; }; const PILL: Record = { imported: "text-ok border-ok/40 bg-ok/10", failed: "text-err border-err/40 bg-err/10", downloading: "text-warn border-warn/40 bg-warn/10", searching: "text-warn border-warn/40 bg-warn/10", queued: "text-warn border-warn/40 bg-warn/10", }; export function Requests({ snap, refresh }: { snap: JobsSnapshot | null; refresh: () => void }) { const toast = useToast(); if (!snap) return null; const { jobs, counts, pending } = snap; const active = (counts.queued ?? 0) + (counts.searching ?? 0) + (counts.downloading ?? 0); const done = counts.imported ?? 0; const failed = counts.failed ?? 0; const total = active + done; const stats: [string, number, string][] = [ ["In flight", active, "text-accent"], ["Imported", done, "text-ok"], ["Failed", failed, "text-err"], ["Waiting", pending, ""], ]; return ( <>
{stats.map(([label, n, colour]) => ( {n} {label} ))}
{active > 0 && total > 0 && ( )} {jobs.length === 0 ? (
Nothing requested yet.
) : ( {jobs.map((j) => (
{j.cover && ( /* eslint-disable-next-line @next/next/no-img-element */ (e.currentTarget.style.visibility = "hidden")} /> )}
{j.title}
{[j.artist, j.album, j.detail].filter(Boolean).join(" ยท ")}
{j.state === "failed" && ( )} {(j.state === "searching" || j.state === "downloading") && ( )} {j.state}
))}
)} ); }