Skip to content

Commit 6c1fef0

Browse files
committed
feat(chat): redesign maturity score cards for improved interactivity and visual clarity
1 parent 31fe479 commit 6c1fef0

1 file changed

Lines changed: 145 additions & 71 deletions

File tree

src/Dashboard/frontend/src/components/ChatView.vue

Lines changed: 145 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -97,75 +97,60 @@
9797
<!-- Left sidebar -->
9898
<aside class="sidebar" :class="{ 'sidebar--collapsed': !sidebarOpen }">
9999
<div class="sidebar-scroll">
100-
<!-- Score buttons (Crawl / Walk / Run) — single CTA per level -->
100+
<!-- Maturity score cards (Crawl / Walk / Run) — whole card is clickable -->
101101
<template v-if="azureConnected">
102102
<div
103103
v-for="cat in scoreCategories"
104104
:key="'score-' + cat.key"
105-
class="sidebar-category"
106-
:class="{ 'sidebar-category--border': cat.key !== 'crawl' }"
105+
class="maturity-card"
106+
:class="{
107+
'maturity-card--scored': maturityScores[cat.key],
108+
'maturity-card--disabled': streaming,
109+
}"
110+
role="button"
111+
tabindex="0"
112+
:title="cat.scorePrompt"
113+
@click="!streaming && sendQuestion(cat.scorePrompt)"
114+
@keydown.enter="!streaming && sendQuestion(cat.scorePrompt)"
107115
>
108-
<div
109-
class="sidebar-category-label"
110-
:class="{
111-
'sidebar-category-label--toggle': maturityScores[cat.key],
112-
}"
113-
@click="
114-
maturityScores[cat.key] && toggleSection('score_' + cat.key)
115-
"
116-
>
117-
<div class="sidebar-category-left">
118-
<span>{{ cat.label }}</span>
119-
<span v-if="cat.subtitle" class="sidebar-category-subtitle">{{
116+
<div class="maturity-card-header">
117+
<div class="maturity-card-title">
118+
<span class="maturity-card-label">{{ cat.label }}</span>
119+
<span v-if="cat.subtitle" class="maturity-card-subtitle">{{
120120
cat.subtitle
121121
}}</span>
122122
</div>
123-
<div class="sidebar-category-right">
124-
<span
125-
v-if="maturityScores[cat.key]"
126-
class="sidebar-stars"
127-
:style="{ color: starColor(maturityOverall(cat.key)) }"
128-
>{{ starsText(maturityOverall(cat.key)) }}</span
129-
>
130-
<svg
131-
v-if="maturityScores[cat.key]"
132-
class="collapse-chevron"
133-
:class="{
134-
'collapse-chevron--collapsed':
135-
collapsedSections['score_' + cat.key],
136-
}"
137-
viewBox="0 0 16 16"
138-
fill="none"
139-
>
140-
<path
141-
d="M4 6l4 4 4-4"
142-
stroke="currentColor"
143-
stroke-width="1.5"
144-
stroke-linecap="round"
145-
stroke-linejoin="round"
146-
/>
147-
</svg>
148-
</div>
123+
<span class="maturity-card-cta">
124+
{{ maturityScores[cat.key] ? "Re-score" : "Score" }}
125+
</span>
149126
</div>
150-
<button
151-
class="sidebar-question sidebar-question--score-cta"
152-
:disabled="streaming"
153-
:title="cat.scorePrompt"
154-
@click="sendQuestion(cat.scorePrompt)"
155-
>
156-
<span class="sidebar-question-label--score">{{
157-
maturityScores[cat.key]
158-
? "Rescore " + cat.label
159-
: "Score " + cat.label
160-
}}</span>
161-
</button>
162-
<!-- Score results (from LLM) — collapsible once scored -->
127+
<div class="maturity-card-body">
128+
<span
129+
class="maturity-card-stars"
130+
:style="{
131+
color: maturityScores[cat.key]
132+
? starColor(maturityOverall(cat.key))
133+
: '#c8c6c4',
134+
}"
135+
>{{
136+
maturityScores[cat.key]
137+
? starsText(maturityOverall(cat.key))
138+
: "☆☆☆☆☆"
139+
}}</span
140+
>
141+
<span class="maturity-card-score">
142+
{{
143+
maturityScores[cat.key]
144+
? maturityNumeric(cat.key) + " / 5"
145+
: "not scored"
146+
}}
147+
</span>
148+
</div>
149+
<!-- Per-dimension breakdown (only after scoring) -->
163150
<div
164-
v-if="
165-
maturityScores[cat.key] &&
166-
!collapsedSections['score_' + cat.key]
167-
"
151+
v-if="maturityScores[cat.key]"
168152
class="assessment-summary"
153+
@click.stop
169154
>
170155
<div
171156
v-for="sc in maturityScores[cat.key]"
@@ -2583,6 +2568,13 @@ function maturityOverall(level) {
25832568
);
25842569
}
25852570
2571+
function maturityNumeric(level) {
2572+
const scores = maturityScores[level];
2573+
if (!scores || scores.length === 0) return "0.0";
2574+
const avg = scores.reduce((sum, s) => sum + s.score, 0) / scores.length;
2575+
return avg.toFixed(1);
2576+
}
2577+
25862578
function starsText(score) {
25872579
if (score < 0) return "☆☆☆☆☆";
25882580
const full = Math.min(score, 5);
@@ -3729,19 +3721,8 @@ function buildWowTable(headerCells, dataRows) {
37293721
.map((_, c) => {
37303722
const raw = row[c] ?? "";
37313723
const isNum = numericColumns[c];
3732-
let inner = enhanceCell(raw);
3733-
let extra = "";
3734-
if (c === barColumn) {
3735-
const v = parseNumeric(raw);
3736-
if (v !== null) {
3737-
const pct = Math.min(
3738-
100,
3739-
Math.max(0, (Math.abs(v) / barColMax) * 100),
3740-
);
3741-
extra = `<span class="wt-bar"><i style="width:${pct.toFixed(1)}%"></i></span>`;
3742-
}
3743-
}
3744-
return `<td class="${isNum ? "wt-num" : ""}">${inner}${extra}</td>`;
3724+
const inner = enhanceCell(raw);
3725+
return `<td class="${isNum ? "wt-num" : ""}">${inner}</td>`;
37453726
})
37463727
.join("");
37473728
return `<tr>${cells}</tr>`;
@@ -4556,6 +4537,99 @@ async function send() {
45564537
color: #005a9e;
45574538
box-shadow: 0 1px 2px rgba(0, 120, 212, 0.08);
45584539
}
4540+
4541+
/* ── Maturity score cards (Crawl / Walk / Run) — clickable hero cards ── */
4542+
.maturity-card {
4543+
display: flex;
4544+
flex-direction: column;
4545+
gap: 6px;
4546+
margin: 8px 12px;
4547+
padding: 14px 14px 12px;
4548+
border: 1px solid #e1dfdd;
4549+
border-radius: 8px;
4550+
background: #fff;
4551+
cursor: pointer;
4552+
transition:
4553+
border-color 0.15s ease,
4554+
box-shadow 0.15s ease,
4555+
transform 0.1s ease;
4556+
user-select: none;
4557+
}
4558+
.maturity-card:hover:not(.maturity-card--disabled) {
4559+
border-color: #c8c6c4;
4560+
box-shadow: 0 2px 8px rgba(15, 23, 42, 0.08);
4561+
transform: translateY(-1px);
4562+
}
4563+
.maturity-card:focus-visible {
4564+
outline: 2px solid #c8c6c4;
4565+
outline-offset: 2px;
4566+
}
4567+
.maturity-card--disabled {
4568+
opacity: 0.55;
4569+
cursor: default;
4570+
}
4571+
.maturity-card--scored {
4572+
background: #fafbfc;
4573+
}
4574+
.maturity-card-header {
4575+
display: flex;
4576+
align-items: flex-start;
4577+
justify-content: space-between;
4578+
gap: 8px;
4579+
}
4580+
.maturity-card-title {
4581+
display: flex;
4582+
flex-direction: column;
4583+
gap: 2px;
4584+
min-width: 0;
4585+
}
4586+
.maturity-card-label {
4587+
font-size: 14px;
4588+
font-weight: 700;
4589+
color: #1f2328;
4590+
letter-spacing: 0.2px;
4591+
}
4592+
.maturity-card-subtitle {
4593+
font-size: 11px;
4594+
font-weight: 400;
4595+
color: #656d76;
4596+
}
4597+
.maturity-card-cta {
4598+
flex-shrink: 0;
4599+
font-size: 12px;
4600+
font-weight: 600;
4601+
color: #0078d4;
4602+
padding: 3px 10px;
4603+
border: 1px solid #0078d4;
4604+
border-radius: 12px;
4605+
background: transparent;
4606+
white-space: nowrap;
4607+
}
4608+
.maturity-card:hover:not(.maturity-card--disabled) .maturity-card-cta {
4609+
background: #0078d4;
4610+
color: #fff;
4611+
}
4612+
.maturity-card-body {
4613+
display: flex;
4614+
align-items: baseline;
4615+
justify-content: space-between;
4616+
gap: 10px;
4617+
margin-top: 2px;
4618+
}
4619+
.maturity-card-stars {
4620+
font-size: 22px;
4621+
letter-spacing: 3px;
4622+
line-height: 1;
4623+
}
4624+
.maturity-card-score {
4625+
font-size: 13px;
4626+
font-weight: 600;
4627+
color: #656d76;
4628+
}
4629+
.maturity-card--scored .maturity-card-score {
4630+
color: #1f2328;
4631+
}
4632+
45594633
.sidebar-subgroup {
45604634
border-top: 1px solid #edebe9;
45614635
}

0 commit comments

Comments
 (0)