Spaces:
Running
Running
Static emotion timeline; fuzzy CV skill highlight
Browse files
frontend/src/components/insights.tsx
CHANGED
|
@@ -80,7 +80,7 @@ export function CameraPanel({ cam, nonverbal, self, dir }: { cam: CameraInfo; no
|
|
| 80 |
<XAxis dataKey="label" stroke="var(--color-muted)" fontSize={10} interval="preserveStartEnd" />
|
| 81 |
<YAxis stroke="var(--color-muted)" fontSize={11} tickFormatter={(v) => `${Math.round(v * 100)}%`} />
|
| 82 |
<Tooltip contentStyle={tip} formatter={(v: number, k: string) => [`${Math.round(v * 100)}%`, t(`emo_${k}` as "emo_happy")]} />
|
| 83 |
-
{EMO_ORDER.map((e) => <Area key={e} type="monotone" dataKey={e} stackId="1" stroke={EMO_COLOR[e]} fill={EMO_COLOR[e]} fillOpacity={0.75} />)}
|
| 84 |
</AreaChart>
|
| 85 |
</ResponsiveContainer>
|
| 86 |
</div>
|
|
@@ -181,7 +181,9 @@ export function SkillsPanel({ r, dir }: { r: Report; dir: string }) {
|
|
| 181 |
|
| 182 |
export function CvView({ cv, match, compact = false }: { cv: CvProfile; match?: SkillMatch | null; compact?: boolean }) {
|
| 183 |
const { t } = useI18n();
|
| 184 |
-
const
|
|
|
|
|
|
|
| 185 |
return (
|
| 186 |
<div className="space-y-5">
|
| 187 |
<div>
|
|
@@ -201,7 +203,7 @@ export function CvView({ cv, match, compact = false }: { cv: CvProfile; match?:
|
|
| 201 |
<p className="mb-2 text-sm font-medium text-muted">{t("cv_skills")}</p>
|
| 202 |
<ul className="flex flex-wrap gap-1.5" dir="ltr">
|
| 203 |
{cv.skills.map((s) => (
|
| 204 |
-
<li key={s} className={`rounded-lg border px-2 py-0.5 text-sm ${
|
| 205 |
))}
|
| 206 |
</ul>
|
| 207 |
</div>
|
|
|
|
| 80 |
<XAxis dataKey="label" stroke="var(--color-muted)" fontSize={10} interval="preserveStartEnd" />
|
| 81 |
<YAxis stroke="var(--color-muted)" fontSize={11} tickFormatter={(v) => `${Math.round(v * 100)}%`} />
|
| 82 |
<Tooltip contentStyle={tip} formatter={(v: number, k: string) => [`${Math.round(v * 100)}%`, t(`emo_${k}` as "emo_happy")]} />
|
| 83 |
+
{EMO_ORDER.map((e) => <Area key={e} type="monotone" dataKey={e} stackId="1" stroke={EMO_COLOR[e]} fill={EMO_COLOR[e]} fillOpacity={0.75} isAnimationActive={false} />)}
|
| 84 |
</AreaChart>
|
| 85 |
</ResponsiveContainer>
|
| 86 |
</div>
|
|
|
|
| 181 |
|
| 182 |
export function CvView({ cv, match, compact = false }: { cv: CvProfile; match?: SkillMatch | null; compact?: boolean }) {
|
| 183 |
const { t } = useI18n();
|
| 184 |
+
const norm = (x: string) => x.toLowerCase().replace(/^apache\s+/, "").replace(/[^a-z0-9+#]/g, "");
|
| 185 |
+
const want = (match?.matched ?? []).map(norm).filter(Boolean);
|
| 186 |
+
const isMatch = (skill: string) => { const k = norm(skill); return want.some((w) => w === k || (w.length > 2 && k.length > 2 && (k.includes(w) || w.includes(k)))); };
|
| 187 |
return (
|
| 188 |
<div className="space-y-5">
|
| 189 |
<div>
|
|
|
|
| 203 |
<p className="mb-2 text-sm font-medium text-muted">{t("cv_skills")}</p>
|
| 204 |
<ul className="flex flex-wrap gap-1.5" dir="ltr">
|
| 205 |
{cv.skills.map((s) => (
|
| 206 |
+
<li key={s} className={`rounded-lg border px-2 py-0.5 text-sm ${isMatch(s) ? "border-nile bg-nile-soft text-nile-deep" : "border-line text-ink"}`}>{s}</li>
|
| 207 |
))}
|
| 208 |
</ul>
|
| 209 |
</div>
|