import type { HTMLAttributes } from "react";
import type {
OrderStatus,
ReviewDecision,
StepStatus,
WorkflowStepName,
} from "@/lib/types/backend";
import {
ORDER_STATUS_META,
REVIEW_DECISION_META,
STEP_STATUS_META,
WORKFLOW_STEP_META,
type StatusMeta,
type StatusTone,
} from "@/lib/types/status";
type StatusBadgeVariant =
| "order"
| "reviewDecision"
| "stepStatus"
| "workflowStep";
type StatusBadgeBaseProps = HTMLAttributes;
type OrderStatusBadgeProps = StatusBadgeBaseProps & {
status: OrderStatus;
variant?: "order";
};
type ReviewDecisionBadgeProps = StatusBadgeBaseProps & {
status: ReviewDecision;
variant: "reviewDecision";
};
type StepStatusBadgeProps = StatusBadgeBaseProps & {
status: StepStatus;
variant: "stepStatus";
};
type WorkflowStepBadgeProps = StatusBadgeBaseProps & {
status: WorkflowStepName | null;
variant: "workflowStep";
};
export type StatusBadgeProps =
| OrderStatusBadgeProps
| ReviewDecisionBadgeProps
| StepStatusBadgeProps
| WorkflowStepBadgeProps;
const TONE_STYLES: Record = {
neutral:
"border-[rgba(76,69,60,0.14)] bg-[rgba(110,98,84,0.08)] text-[var(--ink-muted)]",
info: "border-[rgba(57,86,95,0.16)] bg-[rgba(57,86,95,0.1)] text-[#2e4d56]",
warning:
"border-[rgba(145,104,46,0.18)] bg-[rgba(202,164,97,0.14)] text-[#7a5323]",
success:
"border-[rgba(88,106,56,0.18)] bg-[rgba(110,127,82,0.14)] text-[#50633b]",
danger:
"border-[rgba(140,74,67,0.18)] bg-[rgba(140,74,67,0.12)] text-[#7f3f38]",
};
function joinClasses(...values: Array) {
return values.filter(Boolean).join(" ");
}
function getMetaFromRecord(
record: Record,
status: string,
variant: StatusBadgeVariant,
): StatusMeta {
const meta = record[status as T];
if (!meta) {
throw new Error(`Invalid status "${status}" for variant "${variant}".`);
}
return meta;
}
function resolveStatusMeta(props: StatusBadgeProps): StatusMeta {
switch (props.variant) {
case "reviewDecision":
return getMetaFromRecord(REVIEW_DECISION_META, props.status, props.variant);
case "stepStatus":
return getMetaFromRecord(STEP_STATUS_META, props.status, props.variant);
case "workflowStep":
if (props.status === null) {
return { label: "未开始", tone: "neutral" };
}
return getMetaFromRecord(WORKFLOW_STEP_META, props.status, props.variant);
case "order":
case undefined:
return getMetaFromRecord(ORDER_STATUS_META, props.status, "order");
}
}
export function StatusBadge({ className, ...props }: StatusBadgeProps) {
const meta = resolveStatusMeta(props);
return (
{meta.label}
);
}