feat(ui): circular match-score ring in job workspace #24
@@ -10,7 +10,6 @@ import {
|
||||
DialogTitle,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
LinearProgress,
|
||||
MenuItem,
|
||||
Select,
|
||||
Tab,
|
||||
@@ -1229,27 +1228,35 @@ function MatchScoreCard({ score, loading }: { score: MatchScore | null; loading:
|
||||
|
||||
return (
|
||||
<Box sx={{ p: 1.75, mb: 2, borderRadius: 3, border: "1px solid", borderColor: "divider", backgroundColor: "background.default" }}>
|
||||
<Box sx={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 1, flexWrap: "wrap", mb: 1 }}>
|
||||
<Box sx={{ display: "flex", alignItems: "baseline", gap: 1 }}>
|
||||
<Typography variant="h4" sx={{ fontWeight: 800, fontVariantNumeric: "tabular-nums" }}>{score.hasEnoughSignal ? `${score.score}%` : "—"}</Typography>
|
||||
<Typography variant="overline">{t("matchScoreTitle")}</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", gap: 1, flexWrap: "wrap", alignItems: "center" }}>
|
||||
<Chip size="small" color={color === "inherit" ? "default" : color} label={bandLabel} />
|
||||
<Chip size="small" variant="outlined" label={t("matchScoreKeywordsCovered", { matched: score.matchedCount, total: score.totalKeywords })} />
|
||||
<Box sx={{ display: "flex", gap: 2.5, alignItems: "center", flexWrap: "wrap", mb: 1.5 }}>
|
||||
{score.hasEnoughSignal ? (
|
||||
<Box sx={{ position: "relative", width: 92, height: 92, flexShrink: 0 }}>
|
||||
<CircularProgress variant="determinate" value={100} size={92} thickness={4} sx={{ color: "divider", position: "absolute" }} />
|
||||
<CircularProgress
|
||||
variant="determinate"
|
||||
value={score.score}
|
||||
size={92}
|
||||
thickness={4}
|
||||
color={color === "inherit" ? "primary" : color}
|
||||
sx={{ position: "absolute", "& .MuiCircularProgress-circle": { strokeLinecap: "round" } }}
|
||||
/>
|
||||
<Box sx={{ position: "absolute", inset: 0, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center" }}>
|
||||
<Typography variant="h6" sx={{ fontWeight: 800, fontVariantNumeric: "tabular-nums", lineHeight: 1 }}>{score.score}%</Typography>
|
||||
<Typography variant="caption" sx={{ color: "text.secondary" }}>{t("matchScoreTitle")}</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
) : (
|
||||
<Typography variant="h4" sx={{ fontWeight: 800 }}>—</Typography>
|
||||
)}
|
||||
<Box sx={{ flex: 1, minWidth: 200 }}>
|
||||
{!score.hasEnoughSignal ? <Typography variant="body2" sx={{ color: "text.secondary", mb: 1 }}>{t("matchScoreNoSignal")}</Typography> : null}
|
||||
<Box sx={{ display: "flex", gap: 1, flexWrap: "wrap", alignItems: "center" }}>
|
||||
<Chip size="small" color={color === "inherit" ? "default" : color} label={bandLabel} />
|
||||
<Chip size="small" variant="outlined" label={t("matchScoreKeywordsCovered", { matched: score.matchedCount, total: score.totalKeywords })} />
|
||||
</Box>
|
||||
<Typography variant="caption" sx={{ color: "text.secondary", display: "block", mt: 1 }}>{t("matchScoreDeterministicHint")}</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
{score.hasEnoughSignal ? (
|
||||
<LinearProgress
|
||||
variant="determinate"
|
||||
value={score.score}
|
||||
color={color === "inherit" ? "primary" : color}
|
||||
sx={{ height: 8, borderRadius: 4, mb: 1.5 }}
|
||||
/>
|
||||
) : (
|
||||
<Typography variant="body2" sx={{ color: "text.secondary", mb: 1 }}>{t("matchScoreNoSignal")}</Typography>
|
||||
)}
|
||||
<Typography variant="caption" sx={{ color: "text.secondary", display: "block", mb: 1 }}>{t("matchScoreDeterministicHint")}</Typography>
|
||||
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "1fr 1fr" }, gap: 1.5 }}>
|
||||
<Box>
|
||||
<Typography variant="overline">{t("matchScoreMatched")}</Typography>
|
||||
|
||||
Reference in New Issue
Block a user