feat(ui): circular match-score ring in job workspace #24

Merged
cesnimda merged 1 commits from feature/ui-rework-match-score-ring into main 2026-07-12 02:05:18 +02:00
@@ -10,7 +10,6 @@ import {
DialogTitle, DialogTitle,
FormControl, FormControl,
InputLabel, InputLabel,
LinearProgress,
MenuItem, MenuItem,
Select, Select,
Tab, Tab,
@@ -1229,27 +1228,35 @@ function MatchScoreCard({ score, loading }: { score: MatchScore | null; loading:
return ( return (
<Box sx={{ p: 1.75, mb: 2, borderRadius: 3, border: "1px solid", borderColor: "divider", backgroundColor: "background.default" }}> <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", gap: 2.5, alignItems: "center", flexWrap: "wrap", mb: 1.5 }}>
<Box sx={{ display: "flex", alignItems: "baseline", gap: 1 }}> {score.hasEnoughSignal ? (
<Typography variant="h4" sx={{ fontWeight: 800, fontVariantNumeric: "tabular-nums" }}>{score.hasEnoughSignal ? `${score.score}%` : "—"}</Typography> <Box sx={{ position: "relative", width: 92, height: 92, flexShrink: 0 }}>
<Typography variant="overline">{t("matchScoreTitle")}</Typography> <CircularProgress variant="determinate" value={100} size={92} thickness={4} sx={{ color: "divider", position: "absolute" }} />
</Box> <CircularProgress
<Box sx={{ display: "flex", gap: 1, flexWrap: "wrap", alignItems: "center" }}> variant="determinate"
<Chip size="small" color={color === "inherit" ? "default" : color} label={bandLabel} /> value={score.score}
<Chip size="small" variant="outlined" label={t("matchScoreKeywordsCovered", { matched: score.matchedCount, total: score.totalKeywords })} /> 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>
</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 sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "1fr 1fr" }, gap: 1.5 }}>
<Box> <Box>
<Typography variant="overline">{t("matchScoreMatched")}</Typography> <Typography variant="overline">{t("matchScoreMatched")}</Typography>