volsu-contests/frontend/src/components/domain/problem-status-badge.tsx
2025-11-30 19:55:50 +03:00

82 lines
1.8 KiB
TypeScript

import { cn } from "@/lib/utils";
import { Check, Minus, X, Circle } from "lucide-react";
type ProblemStatus = "solved" | "partial" | "attempted" | "not_attempted";
interface ProblemStatusBadgeProps {
status: ProblemStatus;
score?: number;
maxScore?: number;
className?: string;
}
const statusConfig: Record<
ProblemStatus,
{
icon: typeof Check;
className: string;
bgClassName: string;
}
> = {
solved: {
icon: Check,
className: "text-success",
bgClassName: "bg-success/10",
},
partial: {
icon: Minus,
className: "text-warning",
bgClassName: "bg-warning/10",
},
attempted: {
icon: X,
className: "text-destructive",
bgClassName: "bg-destructive/10",
},
not_attempted: {
icon: Circle,
className: "text-muted-foreground",
bgClassName: "bg-muted",
},
};
export function ProblemStatusBadge({
status,
score,
maxScore,
className,
}: ProblemStatusBadgeProps) {
const config = statusConfig[status];
const Icon = config.icon;
return (
<div
className={cn(
"inline-flex items-center justify-center gap-1 rounded-full px-2 py-1 text-xs font-medium",
config.bgClassName,
config.className,
className
)}
>
<Icon className="h-3 w-3" />
{score !== undefined && maxScore !== undefined && status !== "not_attempted" && (
<span>
{score}/{maxScore}
</span>
)}
</div>
);
}
// Helper to determine status from score
export function getProblemStatus(
score: number | undefined,
maxScore: number,
hasAttempted: boolean
): ProblemStatus {
if (score === undefined || !hasAttempted) return "not_attempted";
if (score === maxScore) return "solved";
if (score > 0) return "partial";
return "attempted";
}