|
97 | 97 | <!-- Left sidebar --> |
98 | 98 | <aside class="sidebar" :class="{ 'sidebar--collapsed': !sidebarOpen }"> |
99 | 99 | <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 --> |
101 | 101 | <template v-if="azureConnected"> |
102 | 102 | <div |
103 | 103 | v-for="cat in scoreCategories" |
104 | 104 | :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)" |
107 | 115 | > |
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">{{ |
120 | 120 | cat.subtitle |
121 | 121 | }}</span> |
122 | 122 | </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> |
149 | 126 | </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) --> |
163 | 150 | <div |
164 | | - v-if=" |
165 | | - maturityScores[cat.key] && |
166 | | - !collapsedSections['score_' + cat.key] |
167 | | - " |
| 151 | + v-if="maturityScores[cat.key]" |
168 | 152 | class="assessment-summary" |
| 153 | + @click.stop |
169 | 154 | > |
170 | 155 | <div |
171 | 156 | v-for="sc in maturityScores[cat.key]" |
@@ -2583,6 +2568,13 @@ function maturityOverall(level) { |
2583 | 2568 | ); |
2584 | 2569 | } |
2585 | 2570 |
|
| 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 | +
|
2586 | 2578 | function starsText(score) { |
2587 | 2579 | if (score < 0) return "☆☆☆☆☆"; |
2588 | 2580 | const full = Math.min(score, 5); |
@@ -3729,19 +3721,8 @@ function buildWowTable(headerCells, dataRows) { |
3729 | 3721 | .map((_, c) => { |
3730 | 3722 | const raw = row[c] ?? ""; |
3731 | 3723 | 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>`; |
3745 | 3726 | }) |
3746 | 3727 | .join(""); |
3747 | 3728 | return `<tr>${cells}</tr>`; |
@@ -4556,6 +4537,99 @@ async function send() { |
4556 | 4537 | color: #005a9e; |
4557 | 4538 | box-shadow: 0 1px 2px rgba(0, 120, 212, 0.08); |
4558 | 4539 | } |
| 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 | +
|
4559 | 4633 | .sidebar-subgroup { |
4560 | 4634 | border-top: 1px solid #edebe9; |
4561 | 4635 | } |
|
0 commit comments