kyd-shared-badge 0.1.0 → 0.1.2
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 +2 -2
- package/src/SharedBadgeDisplay.tsx +41 -26
- package/src/components/ReportHeader.tsx +20 -11
package/package.json
CHANGED
|
@@ -56,7 +56,7 @@ const ScoreCard = ({ title, score, description, descriptor, icon: Icon, scoreTyp
|
|
|
56
56
|
);
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
-
const SharedBadgeDisplay = ({ badgeData }: { badgeData: PublicBadgeData }) => {
|
|
59
|
+
const SharedBadgeDisplay = ({ badgeData, type = 'individual' }: { badgeData: PublicBadgeData, type?: 'recruiter' | 'individual' }) => {
|
|
60
60
|
const { badgeId, developerName, assessmentResult, updatedAt, connectedPlatforms } = badgeData;
|
|
61
61
|
const { summary_scores, report_summary, developer_trust_explanation, key_skills, screening_sources, industry_considerations } = assessmentResult;
|
|
62
62
|
|
|
@@ -64,15 +64,22 @@ const SharedBadgeDisplay = ({ badgeData }: { badgeData: PublicBadgeData }) => {
|
|
|
64
64
|
const riskScore = summary_scores.risk_score;
|
|
65
65
|
const aiUsageScore = summary_scores.ai_usage;
|
|
66
66
|
|
|
67
|
+
const wrapperMaxWidth = type === 'recruiter' ? 'max-w-5xl' : 'max-w-6xl';
|
|
68
|
+
const isRecruiter = type === 'recruiter';
|
|
69
|
+
|
|
67
70
|
return (
|
|
68
|
-
<div className=
|
|
71
|
+
<div className={`${wrapperMaxWidth} mx-auto`}>
|
|
69
72
|
<div className="flex justify-end items-center mb-4">
|
|
70
73
|
<ShareButton
|
|
71
74
|
badgeId={badgeId}
|
|
72
75
|
shareTitle={`KYD Self-Check™ Report | ${badgeData.developerName}`}
|
|
73
76
|
shareText="Check out my KYD Self-Check™ from Know Your Developer™"
|
|
74
77
|
buttonText="Share"
|
|
75
|
-
className=
|
|
78
|
+
className={
|
|
79
|
+
isRecruiter
|
|
80
|
+
? 'flex items-center justify-center h-10 w-10 sm:w-auto sm:px-4 sm:py-2 text-white rounded-full sm:rounded-md transition-all duration-300 ease-in-out bg-[var(--icon-accent)] hover:bg-[var(--icon-accent-hover)]'
|
|
81
|
+
: 'flex items-center justify-center h-10 w-10 sm:w-auto sm:px-4 sm:py-2 bg-indigo-600 text-white rounded-full sm:rounded-md hover:bg-indigo-700 transition-all duration-300 ease-in-out'
|
|
82
|
+
}
|
|
76
83
|
/>
|
|
77
84
|
</div>
|
|
78
85
|
<ReportHeader
|
|
@@ -82,8 +89,16 @@ const SharedBadgeDisplay = ({ badgeData }: { badgeData: PublicBadgeData }) => {
|
|
|
82
89
|
score={summary_scores.kyd_self_check.score}
|
|
83
90
|
isPublic={true}
|
|
84
91
|
badgeImageUrl={badgeData.badgeImageUrl || ''}
|
|
92
|
+
type={type}
|
|
85
93
|
/>
|
|
86
|
-
<div
|
|
94
|
+
<div
|
|
95
|
+
className={
|
|
96
|
+
isRecruiter
|
|
97
|
+
? 'rounded-xl shadow-xl p-6 sm:p-8 mt-8 border'
|
|
98
|
+
: 'bg-white/80 dark:bg-neutral-900/80 backdrop-blur-sm rounded-lg shadow-xl p-6 sm:p-8 mt-8'
|
|
99
|
+
}
|
|
100
|
+
style={isRecruiter ? { backgroundColor: 'var(--content-card-background)', borderColor: 'var(--icon-button-secondary)' } : undefined}
|
|
101
|
+
>
|
|
87
102
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12">
|
|
88
103
|
<ScoreCard
|
|
89
104
|
title="KYD Technical™"
|
|
@@ -109,18 +124,18 @@ const SharedBadgeDisplay = ({ badgeData }: { badgeData: PublicBadgeData }) => {
|
|
|
109
124
|
/>
|
|
110
125
|
</div>
|
|
111
126
|
|
|
112
|
-
<div className=
|
|
127
|
+
<div className={isRecruiter ? 'space-y-12 divide-y' : 'space-y-12 divide-y divide-neutral-200/50 dark:divide-neutral-700/50'} style={isRecruiter ? { borderColor: 'var(--icon-button-secondary)' } : undefined}>
|
|
113
128
|
<div className="pt-8 first:pt-0">
|
|
114
|
-
<h3 className=
|
|
115
|
-
<div className=
|
|
129
|
+
<h3 className={isRecruiter ? 'text-2xl font-bold mb-4' : 'text-2xl font-bold text-neutral-900 dark:text-white mb-4'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>1. Summary Findings</h3>
|
|
130
|
+
<div className={isRecruiter ? 'prose prose-sm max-w-none' : 'prose prose-sm dark:prose-invert max-w-none text-neutral-600 dark:text-neutral-300'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
116
131
|
<p>{report_summary}</p>
|
|
117
132
|
</div>
|
|
118
133
|
{key_skills && key_skills.length > 0 && (
|
|
119
134
|
<div className="mt-6">
|
|
120
|
-
<h4 className=
|
|
135
|
+
<h4 className={isRecruiter ? 'text-lg font-semibold mb-3' : 'text-lg font-semibold text-neutral-900 dark:text-white mb-3'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>Key Skills Observed</h4>
|
|
121
136
|
<div className="flex flex-wrap gap-2">
|
|
122
137
|
{key_skills.map((skill: string, index: number) => (
|
|
123
|
-
<span key={index} className=
|
|
138
|
+
<span key={index} className={isRecruiter ? 'text-xs font-medium px-2.5 py-1 rounded-full' : 'bg-blue-100 text-blue-800 text-xs font-medium px-2.5 py-1 rounded-full dark:bg-blue-900 dark:text-blue-300'} style={isRecruiter ? { backgroundColor: 'var(--icon-button-secondary)', color: 'var(--text-main)' } : undefined}>
|
|
124
139
|
{skill}
|
|
125
140
|
</span>
|
|
126
141
|
))}
|
|
@@ -130,8 +145,8 @@ const SharedBadgeDisplay = ({ badgeData }: { badgeData: PublicBadgeData }) => {
|
|
|
130
145
|
</div>
|
|
131
146
|
|
|
132
147
|
<div className="pt-8">
|
|
133
|
-
<h3 className=
|
|
134
|
-
<div className=
|
|
148
|
+
<h3 className={isRecruiter ? 'text-xl font-bold mb-3' : 'text-xl font-bold text-neutral-900 dark:text-white mb-3'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>2. KYD Technical™ Signals</h3>
|
|
149
|
+
<div className={isRecruiter ? 'prose prose-sm max-w-none mb-6' : 'prose prose-sm dark:prose-invert max-w-none text-neutral-600 dark:text-neutral-300 mb-6'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
135
150
|
<p>{developer_trust_explanation}</p>
|
|
136
151
|
</div>
|
|
137
152
|
<ProviderInsights
|
|
@@ -142,16 +157,16 @@ const SharedBadgeDisplay = ({ badgeData }: { badgeData: PublicBadgeData }) => {
|
|
|
142
157
|
</div>
|
|
143
158
|
|
|
144
159
|
<div className="pt-8">
|
|
145
|
-
<h3 className=
|
|
160
|
+
<h3 className={isRecruiter ? 'text-xl font-bold mb-3' : 'text-xl font-bold text-neutral-900 dark:text-white mb-3'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>3. KYD Risk™ Signals</h3>
|
|
146
161
|
{badgeData.optOutScreening ? (
|
|
147
|
-
<div className=
|
|
162
|
+
<div className={isRecruiter ? 'mb-4 p-4 rounded-lg border' : 'mb-4 p-4 bg-yellow-100 dark:bg-yellow-900/30 border border-yellow-300 dark:border-yellow-700 rounded-lg'} style={isRecruiter ? { backgroundColor: 'var(--icon-button-secondary)', borderColor: 'var(--icon-button-secondary)' } : undefined}>
|
|
148
163
|
<div className="flex items-start">
|
|
149
164
|
<span className="h-5 w-5 text-yellow-500 dark:text-yellow-400 mr-3 mt-0.5 flex-shrink-0">
|
|
150
165
|
<FiAlertTriangle size={20} />
|
|
151
166
|
</span>
|
|
152
167
|
<div>
|
|
153
|
-
<h4 className=
|
|
154
|
-
<p className=
|
|
168
|
+
<h4 className={isRecruiter ? 'font-bold' : 'font-bold text-yellow-800 dark:text-yellow-200'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>User Opted Out of Screening</h4>
|
|
169
|
+
<p className={isRecruiter ? 'text-sm mt-1' : 'text-sm text-yellow-700 dark:text-yellow-300 mt-1'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
155
170
|
The user chose not to participate in the automated sanctions and risk screening process. The risk score reflects this decision and is for informational purposes only.
|
|
156
171
|
</p>
|
|
157
172
|
</div>
|
|
@@ -159,7 +174,7 @@ const SharedBadgeDisplay = ({ badgeData }: { badgeData: PublicBadgeData }) => {
|
|
|
159
174
|
</div>
|
|
160
175
|
) : (
|
|
161
176
|
<>
|
|
162
|
-
<div className=
|
|
177
|
+
<div className={isRecruiter ? 'prose prose-sm max-w-none space-y-4 mb-6' : 'prose prose-sm dark:prose-invert max-w-none text-neutral-600 dark:text-neutral-300 space-y-4 mb-6'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
163
178
|
<p>{riskScore?.description || ''}</p>
|
|
164
179
|
</div>
|
|
165
180
|
<IpRiskAnalysisDisplay ipRiskAnalysis={screening_sources?.ip_risk_analysis} />
|
|
@@ -168,8 +183,8 @@ const SharedBadgeDisplay = ({ badgeData }: { badgeData: PublicBadgeData }) => {
|
|
|
168
183
|
</div>
|
|
169
184
|
|
|
170
185
|
<div className="pt-8">
|
|
171
|
-
<h3 className=
|
|
172
|
-
<div className=
|
|
186
|
+
<h3 className={isRecruiter ? 'text-xl font-bold mb-3' : 'text-xl font-bold text-neutral-900 dark:text-white mb-3'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>4. KYD AI™ Signals <span className="text-sm font-semibold bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200 px-2 py-1 rounded-full align-middle">Beta</span></h3>
|
|
187
|
+
<div className={isRecruiter ? 'prose prose-sm max-w-none mb-6 space-y-4' : 'prose prose-sm dark:prose-invert max-w-none text-neutral-600 dark:text-neutral-300 mb-6 space-y-4'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
173
188
|
<p>{assessmentResult.ai_usage_summary?.explanation}</p>
|
|
174
189
|
{assessmentResult.ai_usage_summary?.key_findings && (
|
|
175
190
|
<ul className="list-disc list-inside">
|
|
@@ -182,18 +197,18 @@ const SharedBadgeDisplay = ({ badgeData }: { badgeData: PublicBadgeData }) => {
|
|
|
182
197
|
</div>
|
|
183
198
|
|
|
184
199
|
<div className="pt-8">
|
|
185
|
-
<h3 className=
|
|
186
|
-
<div className=
|
|
200
|
+
<h3 className={isRecruiter ? 'text-xl font-bold mb-3' : 'text-xl font-bold text-neutral-900 dark:text-white mb-3'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>5. Industry Considerations</h3>
|
|
201
|
+
<div className={isRecruiter ? 'prose prose-sm max-w-none' : 'prose prose-sm dark:prose-invert max-w-none text-neutral-600 dark:text-neutral-300'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
187
202
|
<p>{industry_considerations}</p>
|
|
188
203
|
</div>
|
|
189
204
|
</div>
|
|
190
205
|
|
|
191
206
|
{!badgeData.optOutScreening && screening_sources && (
|
|
192
207
|
<div className="pt-8">
|
|
193
|
-
<h3 className=
|
|
208
|
+
<h3 className={isRecruiter ? 'text-2xl font-bold mb-4' : 'text-2xl font-bold text-neutral-900 dark:text-white mb-4'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>6. Appendix: Data Sources</h3>
|
|
194
209
|
<div className="space-y-8">
|
|
195
210
|
<div>
|
|
196
|
-
<h4 className=
|
|
211
|
+
<h4 className={isRecruiter ? 'text-xl font-bold mb-4' : 'text-xl font-bold text-neutral-800 dark:text-white mb-4'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>Sanctions & Watchlists</h4>
|
|
197
212
|
<AppendixTables
|
|
198
213
|
type="sanctions"
|
|
199
214
|
sources={[...(screening_sources.ofac_lists || []), ...(screening_sources.additional_watchlists || [])]}
|
|
@@ -202,7 +217,7 @@ const SharedBadgeDisplay = ({ badgeData }: { badgeData: PublicBadgeData }) => {
|
|
|
202
217
|
/>
|
|
203
218
|
</div>
|
|
204
219
|
<div>
|
|
205
|
-
<h4 className=
|
|
220
|
+
<h4 className={isRecruiter ? 'text-xl font-bold mb-4' : 'text-xl font-bold text-neutral-800 dark:text-white mb-4'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>Country-specific Entity Affiliations</h4>
|
|
206
221
|
<AppendixTables
|
|
207
222
|
type="domains"
|
|
208
223
|
sources={screening_sources.risk_profile_domains || []}
|
|
@@ -214,7 +229,7 @@ const SharedBadgeDisplay = ({ badgeData }: { badgeData: PublicBadgeData }) => {
|
|
|
214
229
|
</div>
|
|
215
230
|
)}
|
|
216
231
|
|
|
217
|
-
<div className=
|
|
232
|
+
<div className={isRecruiter ? 'pt-8 text-sm text-center' : 'pt-8 text-sm text-neutral-500 dark:text-neutral-400 text-center'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
218
233
|
Report Completed: {new Date(updatedAt).toLocaleString(undefined, {
|
|
219
234
|
year: 'numeric',
|
|
220
235
|
month: 'long',
|
|
@@ -226,8 +241,8 @@ const SharedBadgeDisplay = ({ badgeData }: { badgeData: PublicBadgeData }) => {
|
|
|
226
241
|
</div>
|
|
227
242
|
</div>
|
|
228
243
|
</div>
|
|
229
|
-
<footer className=
|
|
230
|
-
<p className=
|
|
244
|
+
<footer className={isRecruiter ? 'mt-12 pt-6 border-t' : 'mt-12 pt-6 border-t border-neutral-200 dark:border-neutral-700'} style={isRecruiter ? { borderColor: 'var(--icon-button-secondary)' } : undefined}>
|
|
245
|
+
<p className={isRecruiter ? 'text-center text-xs max-w-4xl mx-auto' : 'text-center text-xs text-gray-500 dark:text-gray-400 max-w-4xl mx-auto'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
231
246
|
© 2025 Know Your Developer, LLC. All rights reserved. KYD Self-Check™, and associated marks are trademarks of Know Your Developer, LLC. This document is confidential, proprietary, and intended solely for the individual or entity to whom it is addressed. Unauthorized use, disclosure, copying, or distribution of this document or any of its contents is strictly prohibited and may be unlawful. Know Your Developer, LLC assumes no responsibility or liability for any errors or omissions contained herein. Report validity subject to the terms and conditions stated on the official Know Your Developer website located at https://knowyourdeveloper.ai.
|
|
232
247
|
</p>
|
|
233
248
|
</footer>
|
|
@@ -15,11 +15,13 @@ interface ReportHeaderProps {
|
|
|
15
15
|
score: number | undefined;
|
|
16
16
|
isPublic: boolean;
|
|
17
17
|
badgeImageUrl: string;
|
|
18
|
+
type?: 'recruiter' | 'individual';
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
const ReportHeader = ({ badgeId, developerName, updatedAt, score = 0, isPublic, badgeImageUrl }: ReportHeaderProps) => {
|
|
21
|
+
const ReportHeader = ({ badgeId, developerName, updatedAt, score = 0, isPublic, badgeImageUrl, type = 'individual' }: ReportHeaderProps) => {
|
|
21
22
|
// Use the dynamic image if available, otherwise fall back to the score-based one.
|
|
22
23
|
const finalBadgeImageUrl = badgeImageUrl || getBadgeImageUrl(score);
|
|
24
|
+
const isRecruiter = type === 'recruiter';
|
|
23
25
|
|
|
24
26
|
const formattedDate = updatedAt ? new Date(updatedAt).toLocaleString(undefined, {
|
|
25
27
|
year: 'numeric',
|
|
@@ -30,15 +32,22 @@ const ReportHeader = ({ badgeId, developerName, updatedAt, score = 0, isPublic,
|
|
|
30
32
|
}) : 'N/A';
|
|
31
33
|
|
|
32
34
|
return (
|
|
33
|
-
<div
|
|
35
|
+
<div
|
|
36
|
+
className={
|
|
37
|
+
isRecruiter
|
|
38
|
+
? 'mb-8 p-6 rounded-xl shadow-lg flex flex-col md:flex-row items-start md:items-center justify-between gap-6 border'
|
|
39
|
+
: 'mb-8 p-6 bg-white/80 dark:bg-neutral-900/80 backdrop-blur-sm rounded-lg shadow-lg flex flex-col md:flex-row items-start md:items-center justify-between gap-6'
|
|
40
|
+
}
|
|
41
|
+
style={isRecruiter ? { backgroundColor: 'var(--content-card-background)', borderColor: 'var(--icon-button-secondary)' } : undefined}
|
|
42
|
+
>
|
|
34
43
|
{/* Left Section */}
|
|
35
44
|
<div className="flex items-center text-left md:text-center">
|
|
36
45
|
<Image src={finalBadgeImageUrl} alt="KYD Badge" width={150} height={150} unoptimized />
|
|
37
46
|
<div className='flex flex-col'>
|
|
38
|
-
<h1 className=
|
|
47
|
+
<h1 className={isRecruiter ? 'font-bold text-lg' : 'font-bold text-lg text-neutral-900 dark:text-white'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>
|
|
39
48
|
KYD Self-Check™
|
|
40
49
|
</h1>
|
|
41
|
-
<p className=
|
|
50
|
+
<p className={isRecruiter ? 'text-sm' : 'text-sm text-neutral-600 dark:text-neutral-400'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
42
51
|
{isPublic ? 'Public Report' : 'Private Report'}
|
|
43
52
|
</p>
|
|
44
53
|
</div>
|
|
@@ -46,16 +55,16 @@ const ReportHeader = ({ badgeId, developerName, updatedAt, score = 0, isPublic,
|
|
|
46
55
|
|
|
47
56
|
{/* Middle Section */}
|
|
48
57
|
<div className="text-left md:text-center">
|
|
49
|
-
<p className=
|
|
50
|
-
<p className=
|
|
58
|
+
<p className={isRecruiter ? 'text-sm' : 'text-sm text-neutral-600 dark:text-neutral-400'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>Developer</p>
|
|
59
|
+
<p className={isRecruiter ? 'font-semibold text-2xl' : 'font-semibold text-neutral-900 dark:text-white text-2xl'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>{developerName || 'N/A'}</p>
|
|
51
60
|
</div>
|
|
52
61
|
|
|
53
62
|
{/* Right Section */}
|
|
54
|
-
<div className=
|
|
55
|
-
<p><span className=
|
|
56
|
-
<p><span className=
|
|
57
|
-
<p><span className=
|
|
58
|
-
<p><span className=
|
|
63
|
+
<div className={isRecruiter ? 'text-left text-sm space-y-1' : 'text-left text-sm text-neutral-600 dark:text-neutral-400 space-y-1'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
64
|
+
<p><span className={isRecruiter ? 'font-semibold' : 'font-semibold text-neutral-800 dark:text-neutral-200'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>Requested By:</span> {developerName || 'N/A'}</p>
|
|
65
|
+
<p><span className={isRecruiter ? 'font-semibold' : 'font-semibold text-neutral-800 dark:text-neutral-200'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>Organization:</span> Unaffiliated</p>
|
|
66
|
+
<p><span className={isRecruiter ? 'font-semibold' : 'font-semibold text-neutral-800 dark:text-neutral-200'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>Date Completed:</span> {formattedDate}</p>
|
|
67
|
+
<p><span className={isRecruiter ? 'font-semibold' : 'font-semibold text-neutral-800 dark:text-neutral-200'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>Report ID:</span> {badgeId}</p>
|
|
59
68
|
</div>
|
|
60
69
|
</div>
|
|
61
70
|
);
|