kyd-shared-badge 0.3.29 → 0.3.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -24,6 +24,7 @@ import { BusinessRulesProvider } from './components/BusinessRulesContext';
|
|
|
24
24
|
import Reveal from './components/Reveal';
|
|
25
25
|
import { formatLocalDateTime } from './utils/date';
|
|
26
26
|
import ChatWidget from './chat/ChatWidget';
|
|
27
|
+
import UseCases from './components/UseCases';
|
|
27
28
|
type ChatWidgetProps = Partial<{
|
|
28
29
|
api: string;
|
|
29
30
|
title: string;
|
|
@@ -181,7 +182,7 @@ const SharedBadgeDisplay = ({ badgeData, chatProps, headless }: { badgeData: Pub
|
|
|
181
182
|
</Reveal>
|
|
182
183
|
{/* Coaching / Evidence under header when present */}
|
|
183
184
|
{(() => {
|
|
184
|
-
const em =
|
|
185
|
+
const em = assessmentResult.enterprise_match;
|
|
185
186
|
const coaching = em?.coaching;
|
|
186
187
|
if (!coaching || !(Array.isArray(coaching.items) && coaching.items.length)) return null;
|
|
187
188
|
return (
|
|
@@ -260,6 +261,11 @@ const SharedBadgeDisplay = ({ badgeData, chatProps, headless }: { badgeData: Pub
|
|
|
260
261
|
</Reveal>
|
|
261
262
|
</div>
|
|
262
263
|
|
|
264
|
+
{/* Enterprise Use Cases (directly under the three summary cards) */}
|
|
265
|
+
{assessmentResult?.enterprise_use_cases?.items && assessmentResult.enterprise_use_cases.items.length > 0 && (
|
|
266
|
+
<UseCases useCases={assessmentResult.enterprise_use_cases} headless={isHeadless} />
|
|
267
|
+
)}
|
|
268
|
+
|
|
263
269
|
{/* Technical Scores */}
|
|
264
270
|
<div className="mt-8" >
|
|
265
271
|
<div key={'Technical'} className='pt-8 space-y-8 kyd-avoid-break' style={{ borderColor: 'var(--icon-button-secondary)'}}>
|
|
@@ -37,7 +37,7 @@ export default function EnterpriseCoaching({
|
|
|
37
37
|
<div className={'text-sm font-semibold'} style={{ color: 'var(--text-main)' }}>
|
|
38
38
|
{roleName ? `Role Alignment — ${roleName}` : 'Role Alignment'}
|
|
39
39
|
</div>
|
|
40
|
-
<span className={'relative inline-flex items-center group'} style={{ color: 'var(--text-secondary)' }}>
|
|
40
|
+
{/* <span className={'relative inline-flex items-center group'} style={{ color: 'var(--text-secondary)' }}>
|
|
41
41
|
<FiInfo size={14} />
|
|
42
42
|
<div className="hidden group-hover:block absolute z-30 left-1/2 -translate-x-1/2 top-full mt-2 w-80">
|
|
43
43
|
<div style={{ background: 'var(--content-card-background)', border: '1px solid var(--icon-button-secondary)', color: 'var(--text-main)', padding: 10, borderRadius: 6 }}>
|
|
@@ -45,7 +45,7 @@ export default function EnterpriseCoaching({
|
|
|
45
45
|
<div style={{ marginTop: 6, fontSize: 12, color: 'var(--text-secondary)' }}>These items reflect alignment evidence and coaching opportunities based on the role requirements.</div>
|
|
46
46
|
</div>
|
|
47
47
|
</div>
|
|
48
|
-
</span>
|
|
48
|
+
</span> */}
|
|
49
49
|
</div>
|
|
50
50
|
</div>
|
|
51
51
|
<ul className={'space-y-3'}>
|
|
@@ -61,7 +61,7 @@ export default function EnterpriseCoaching({
|
|
|
61
61
|
<div className={'text-sm'}>{it.rationale}</div>
|
|
62
62
|
{it.action ? (
|
|
63
63
|
<div className={'text-sm'}>
|
|
64
|
-
<span className={'font-semibold'} style={{ color: 'var(--text-main)' }}>
|
|
64
|
+
<span className={'font-semibold'} style={{ color: 'var(--text-main)' }}>Coaching Opportunity:</span> {it.action}
|
|
65
65
|
</div>
|
|
66
66
|
) : null}
|
|
67
67
|
</div>
|
|
@@ -103,7 +103,7 @@ const ReportHeader = ({ badgeId, developerName, updatedAt, score = 0, badgeImage
|
|
|
103
103
|
<div className={'hidden md:block text-sm space-y-2 pt-4'} style={{ borderTop: '1px solid var(--icon-button-secondary)' }}>
|
|
104
104
|
<div className="flex items-center justify-between">
|
|
105
105
|
<div className="flex items-center gap-2">
|
|
106
|
-
<p className={'font-semibold'} style={{ color: 'var(--text-secondary)' }}>Role
|
|
106
|
+
<p className={'font-semibold'} style={{ color: 'var(--text-secondary)' }}>Role Alignment{enterpriseMatch?.roleName ? ` — ${enterpriseMatch.roleName}` : ''}</p>
|
|
107
107
|
<span className={'relative inline-flex items-center group'} style={{ color: 'var(--text-secondary)' }}>
|
|
108
108
|
<FiInfo size={16} />
|
|
109
109
|
<div className="hidden group-hover:block absolute z-30 left-1/2 -translate-x-1/2 top-full mt-2 w-80">
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import Reveal from './Reveal';
|
|
4
|
+
import { EnterpriseUseCases, UseCaseItem } from '../types';
|
|
5
|
+
|
|
6
|
+
export default function UseCases({ useCases, headless }: { useCases?: EnterpriseUseCases | null; headless?: boolean }) {
|
|
7
|
+
if (!useCases || !Array.isArray(useCases.items) || useCases.items.length === 0) return null;
|
|
8
|
+
|
|
9
|
+
const items: UseCaseItem[] = useCases.items.slice(0, 4);
|
|
10
|
+
const note = (useCases.note || '').trim();
|
|
11
|
+
|
|
12
|
+
// Fallback: derive a stable pseudo-random index (1-9) if backend hasn't set one
|
|
13
|
+
const fallbackIndex = (uc: UseCaseItem, idx: number) => {
|
|
14
|
+
if (typeof uc.image_index === 'number' && uc.image_index >= 1 && uc.image_index <= 9) return uc.image_index;
|
|
15
|
+
const seed = `${uc.title}|${uc.demonstrated_capability}|${idx}`;
|
|
16
|
+
let hash = 0;
|
|
17
|
+
for (let i = 0; i < seed.length; i++) {
|
|
18
|
+
hash = (hash * 31 + seed.charCodeAt(i)) >>> 0;
|
|
19
|
+
}
|
|
20
|
+
return (hash % 9) + 1;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Reveal headless={!!headless}>
|
|
25
|
+
<div className={'pt-8 kyd-avoid-break'}>
|
|
26
|
+
<h3 className={'text-2xl font-semibold mb-3'} style={{ color: 'var(--text-main)' }}>Potential Use Cases</h3>
|
|
27
|
+
<div className={'grid grid-cols-1 md:grid-cols-2 gap-4'}>
|
|
28
|
+
{items.map((uc, idx) => {
|
|
29
|
+
const imgIndex = fallbackIndex(uc, idx);
|
|
30
|
+
const imgSrc = `/badge/puzzle${imgIndex}.svg`;
|
|
31
|
+
return (
|
|
32
|
+
<div key={idx} className={'rounded-md p-5 border'} style={{ backgroundColor: 'var(--content-card-background)', borderColor: 'var(--icon-button-secondary)' }}>
|
|
33
|
+
<div className={'flex items-start gap-3'}>
|
|
34
|
+
<img src={imgSrc} alt={''} width={36} height={36} style={{ flexShrink: 0 }} />
|
|
35
|
+
<div className={'font-semibold'} style={{ color: 'var(--text-main)' }}>{uc.title}</div>
|
|
36
|
+
</div>
|
|
37
|
+
<div className={'font-semibold'} style={{ color: 'var(--text-main)' }}>{uc.title}</div>
|
|
38
|
+
{uc.potential_impact ? (
|
|
39
|
+
<div className={'text-sm mt-2'} style={{ color: 'var(--text-secondary)' }}>
|
|
40
|
+
<span className={'font-medium'} style={{ color: 'var(--text-main)' }}>Potential Impact: </span>
|
|
41
|
+
{uc.potential_impact}
|
|
42
|
+
</div>
|
|
43
|
+
) : null}
|
|
44
|
+
{uc.demonstrated_capability ? (
|
|
45
|
+
<div className={'text-sm mt-1'} style={{ color: 'var(--text-secondary)' }}>
|
|
46
|
+
<span className={'font-medium'} style={{ color: 'var(--text-main)' }}>Demonstrated Capability: </span>
|
|
47
|
+
{uc.demonstrated_capability}
|
|
48
|
+
</div>
|
|
49
|
+
) : null}
|
|
50
|
+
{uc.justification ? (
|
|
51
|
+
<div className={'text-sm mt-1'} style={{ color: 'var(--text-secondary)' }}>
|
|
52
|
+
<span className={'font-medium'} style={{ color: 'var(--text-main)' }}>Justification: </span>
|
|
53
|
+
{uc.justification}
|
|
54
|
+
</div>
|
|
55
|
+
) : null}
|
|
56
|
+
</div>
|
|
57
|
+
);})}
|
|
58
|
+
</div>
|
|
59
|
+
{note ? (
|
|
60
|
+
<div className={'text-xs mt-3'} style={{ color: 'var(--text-secondary)' }}>{note}</div>
|
|
61
|
+
) : null}
|
|
62
|
+
</div>
|
|
63
|
+
</Reveal>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
package/src/types.ts
CHANGED
|
@@ -176,6 +176,20 @@ export interface EnterpriseMatch {
|
|
|
176
176
|
coaching?: EnterpriseCoaching;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
+
export interface UseCaseItem {
|
|
180
|
+
title: string;
|
|
181
|
+
potential_impact: string;
|
|
182
|
+
demonstrated_capability: string;
|
|
183
|
+
justification: string;
|
|
184
|
+
// Optional deterministic image index (1-9) assigned by backend
|
|
185
|
+
image_index?: number;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export interface EnterpriseUseCases {
|
|
189
|
+
items: UseCaseItem[];
|
|
190
|
+
note?: string;
|
|
191
|
+
}
|
|
192
|
+
|
|
179
193
|
|
|
180
194
|
export interface AssessmentResult {
|
|
181
195
|
final_percent: number;
|
|
@@ -248,6 +262,7 @@ export interface AssessmentResult {
|
|
|
248
262
|
skills_all?: SkillsAll;
|
|
249
263
|
graph_insights?: GraphInsightsPayload;
|
|
250
264
|
enterprise_match?: EnterpriseMatch;
|
|
265
|
+
enterprise_use_cases?: EnterpriseUseCases;
|
|
251
266
|
}
|
|
252
267
|
export interface ClientMetadata {
|
|
253
268
|
ipAddress: string;
|