kyd-shared-badge 0.3.16 → 0.3.17

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kyd-shared-badge",
3
- "version": "0.3.16",
3
+ "version": "0.3.17",
4
4
  "private": false,
5
5
  "main": "./src/index.ts",
6
6
  "module": "./src/index.ts",
@@ -155,6 +155,12 @@ const SharedBadgeDisplay = ({ badgeData, chatProps }: { badgeData: PublicBadgeDa
155
155
  isPublic={true}
156
156
  badgeImageUrl={badgeData.badgeImageUrl || ''}
157
157
  summary={report_summary}
158
+ enterpriseMatch={(() => {
159
+ const em = assessmentResult?.enterprise_match;
160
+ if (!em) return null;
161
+ const role = em.role || {};
162
+ return { score: typeof em.score === 'number' ? em.score : undefined, description: em.description, roleName: role.name };
163
+ })()}
158
164
  countries={(assessmentResult?.screening_sources?.ip_risk_analysis?.raw_data?.countries) || []}
159
165
  />
160
166
  </Reveal>
@@ -4,6 +4,7 @@ import Image from 'next/image';
4
4
  import { formatLocalDate } from '../utils/date';
5
5
  import countriesLib from 'i18n-iso-countries';
6
6
  import enLocale from 'i18n-iso-countries/langs/en.json';
7
+ import { FiInfo } from 'react-icons/fi';
7
8
 
8
9
  // Register English locale once at module import time
9
10
  countriesLib.registerLocale(enLocale);
@@ -36,10 +37,11 @@ interface ReportHeaderProps {
36
37
  isPublic: boolean;
37
38
  badgeImageUrl: string;
38
39
  summary?: string;
40
+ enterpriseMatch?: { score?: number; description?: string; roleName?: string } | null;
39
41
  countries?: string[];
40
42
  }
41
43
 
42
- const ReportHeader = ({ badgeId, developerName, updatedAt, score = 0, badgeImageUrl, summary, countries = [] }: ReportHeaderProps) => {
44
+ const ReportHeader = ({ badgeId, developerName, updatedAt, score = 0, badgeImageUrl, summary, enterpriseMatch, countries = [] }: ReportHeaderProps) => {
43
45
  // Use the dynamic image if available, otherwise fall back to the score-based one.
44
46
  const finalBadgeImageUrl = badgeImageUrl || getBadgeImageUrl(score || 0);
45
47
  const tint = hexToRgba(pickTint(score || 0), 0.06);
@@ -59,7 +61,7 @@ const ReportHeader = ({ badgeId, developerName, updatedAt, score = 0, badgeImage
59
61
  {/* Left Half: Badge Image with robust centered overlay */}
60
62
  <div className="w-full md:w-1/3 flex items-center justify-center self-stretch">
61
63
  <div className="relative w-full max-w-xs select-none">
62
- <Image src={finalBadgeImageUrl} alt="KYD Badge" width={400} height={400} unoptimized className='w-full h-auto pointer-events-none p-10'/>
64
+ <Image src={finalBadgeImageUrl} alt="KYD Badge" width={400} height={400} priority className='w-full h-auto pointer-events-none p-10'/>
63
65
  {/* Centered overlay slightly lower on Y axis, responsive and readable */}
64
66
  <div className="pointer-events-none absolute left-1/2 top-[66%] -translate-x-1/2 -translate-y-1/2">
65
67
  <div className="font-extrabold text-black text-3xl " >
@@ -96,7 +98,32 @@ const ReportHeader = ({ badgeId, developerName, updatedAt, score = 0, badgeImage
96
98
  })()
97
99
  )}
98
100
  </div>
99
- {summary && (
101
+ {(enterpriseMatch?.description || enterpriseMatch?.score !== undefined) ? (
102
+ <div className={'hidden md:block text-sm space-y-2 pt-4'} style={{ borderTop: '1px solid var(--icon-button-secondary)' }}>
103
+ <div className="flex items-center justify-between">
104
+ <div className="flex items-center gap-2">
105
+ <p className={'font-semibold'} style={{ color: 'var(--text-secondary)' }}>Role Match{enterpriseMatch?.roleName ? ` — ${enterpriseMatch.roleName}` : ''}</p>
106
+ <span className={'relative inline-flex items-center group'} style={{ color: 'var(--text-secondary)' }}>
107
+ <FiInfo size={16} />
108
+ <div className="hidden group-hover:block absolute z-30 left-1/2 -translate-x-1/2 top-full mt-2 w-80">
109
+ <div style={{ background: 'var(--content-card-background)', border: '1px solid var(--icon-button-secondary)', color: 'var(--text-main)', padding: 10, borderRadius: 6 }}>
110
+ <div style={{ fontWeight: 600 }}>AI-generated</div>
111
+ <div style={{ marginTop: 6, fontSize: 12, color: 'var(--text-secondary)' }}>Role match score and description are AI-generated.</div>
112
+ </div>
113
+ </div>
114
+ </span>
115
+ </div>
116
+ {typeof enterpriseMatch?.score === 'number' && (
117
+ <span className="px-2 py-1 rounded text-xs font-semibold" style={{ background: 'var(--content-card-background)', border: '1px solid var(--icon-button-secondary)', color: 'var(--text-main)' }}>
118
+ {Math.round(enterpriseMatch.score)}%
119
+ </span>
120
+ )}
121
+ </div>
122
+ {enterpriseMatch?.description && (
123
+ <p className={'text-sm'} style={{ color: 'var(--text-main)' }}>{enterpriseMatch.description}</p>
124
+ )}
125
+ </div>
126
+ ) : summary && (
100
127
  <div className={'hidden md:block text-sm space-y-2 pt-4'} style={{ borderTop: '1px solid var(--icon-button-secondary)' }}>
101
128
  <div>
102
129
  <p className={'font-semibold'} style={{ color: 'var(--text-secondary)' }}>Summary:</p>
package/src/types.ts CHANGED
@@ -154,6 +154,15 @@ export interface FBIWantedMatch {
154
154
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
155
155
  raw_result: any;
156
156
  }
157
+ export interface EnterpriseMatch {
158
+ role: {
159
+ name: string;
160
+ description: string;
161
+ };
162
+ score: number;
163
+ description: string;
164
+ }
165
+
157
166
 
158
167
  export interface AssessmentResult {
159
168
  final_percent: number;
@@ -225,8 +234,8 @@ export interface AssessmentResult {
225
234
  skills_matrix?: SkillsMatrix;
226
235
  skills_all?: SkillsAll;
227
236
  graph_insights?: GraphInsightsPayload;
237
+ enterprise_match?: EnterpriseMatch;
228
238
  }
229
-
230
239
  export interface ClientMetadata {
231
240
  ipAddress: string;
232
241
  userAgent: string;