import type { DownloadBoardPlanItem } from "@umt/contracts";
import { Check, X } from "lucide-react";
import { Link } from "react-router";
import { toast } from "sonner";
import { useDecideApproval, useIsAdminSession } from "~/api/agent.ts";
import { useCancelPlan, usePlanWhy } from "~/api/downloads.ts";
import { ConfirmDialog } from "~/components/console/confirm-dialog.tsx";
import { DetailSection } from "~/components/console/detail-sheet.tsx";
import { JsonView } from "~/components/console/json-view.tsx";
import { KvList } from "~/components/console/kv-list.tsx";
import { consolePath } from "~/components/console/nav.ts";
import { StatusBadge } from "~/components/console/status-badge.tsx";
import { TechInfo } from "~/components/console/tech-info.tsx";
import { Button } from "~/components/ui/button.tsx";
import { errorMessage } from "~/lib/api.ts";
import { reasonCode } from "~/lib/reasons.ts";
import { formatBytes, formatDateTime } from "~/lib/utils.ts";
import { PLAN_WAIT, PURPOSE_LABEL, planWaitHint, whyText } from "./plan-format.ts";
// DL-3:还没提交到下载器的下载(等批准 / 等磁盘空间 / 等开启自动化 / 准备提交)在下载面板里的状态、操作与详情;
// 已提交的下载在详情里显示「为什么下这个」。
export function PlanWaitBadge({ p, hint = false }: { p: DownloadBoardPlanItem; hint?: boolean }) {
const w = PLAN_WAIT[p.wait];
const h = hint ? planWaitHint(p) : null;
return (
{w.label}
{h ? {h} : null}
);
}
/** 批准 / 取消:等批准的走审批(拒绝后服务端取消这次下载);其余直接取消。都要确认 */
export function PlanActions({ p, size = "sm" }: { p: DownloadBoardPlanItem; size?: "sm" | "xs" }) {
const decide = useDecideApproval();
const cancel = useCancelPlan();
const admin = useIsAdminSession();
const approval = p.approval;
const stop = (e: { stopPropagation: () => void }) => e.stopPropagation();
const decideApproval = (status: "approved" | "rejected") =>
decide
.mutateAsync({
id: approval?.id ?? "",
status,
payloadHash: approval?.payloadHash ?? "",
...(status === "rejected" ? { reason: "在下载面板取消" } : {}),
})
.then(
() => toast.success(status === "approved" ? "已批准,开始提交下载" : "已取消这次下载"),
(err) => {
toast.error(errorMessage(err));
throw err;
},
);
return (
// biome-ignore lint/a11y/noStaticElementInteractions: 只拦截行点击
{approval ? (
批准
}
title={`批准下载「${p.name}」?`}
description={`${p.sizeBytes !== null ? `${formatBytes(p.sizeBytes, 1)},` : ""}批准后立即提交到下载器。`}
confirmLabel="批准"
onConfirm={() => decideApproval("approved")}
/>
) : null}
取消
}
title={`取消下载「${p.name}」?`}
description={
approval ? "不批准这次下载,智能体会收到结果。" : "释放为它预留的空间和额度,收录版本之后会重新找资源。"
}
confirmLabel="取消下载"
cancelLabel="返回"
destructive
onConfirm={() =>
approval
? decideApproval("rejected")
: cancel.mutateAsync(p.id).then(
() => toast.success("已取消这次下载"),
(err) => {
toast.error(errorMessage(err));
throw err;
},
)
}
/>
);
}
/** 「为什么下这个」:来源 · 目的,下一行选中理由要点;原始评估进技术信息 */
export function WhySection({
planId,
extraTech,
}: {
planId: string;
extraTech?: { label: string; value: string | null }[];
}) {
const why = usePlanWhy(planId);
if (why.isPending || !why.data) return null;
const t = whyText(why.data);
return (
{t.head}
{t.points ? {t.points}
: null}
({ ...x, wide: true })),
]}
>
);
}
/** 还没提交的下载的详情(抽屉内容) */
export function PlanDetail({ p }: { p: DownloadBoardPlanItem }) {
const hint = planWaitHint(p);
return (
{PLAN_WAIT[p.wait].label}
{p.wait === "approval" ? (
这次下载要你批准后才提交,铃铛里也有提醒。
) : hint ? (
{hint}。
) : null}
{p.media.title}
{p.media.year ? ` (${p.media.year})` : ""}
) : null,
},
{ label: "大小", value: p.sizeBytes === null ? "未知" : formatBytes(p.sizeBytes, 2) },
{ label: "用途", value: PURPOSE_LABEL[p.purpose] },
{ label: "加入时间", value: formatDateTime(p.createdAt) },
]}
/>
);
}