kyd-shared-badge 0.1.2 → 0.1.4
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
|
@@ -30,9 +30,10 @@ interface ScoreCardProps {
|
|
|
30
30
|
descriptor?: string;
|
|
31
31
|
icon: IconType;
|
|
32
32
|
scoreType: 'number' | 'risk' | 'descriptor';
|
|
33
|
+
isRecruiter?: boolean;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
const ScoreCard = ({ title, score, description, descriptor, icon: Icon, scoreType }: ScoreCardProps) => {
|
|
36
|
+
const ScoreCard = ({ title, score, description, descriptor, icon: Icon, scoreType, isRecruiter = false }: ScoreCardProps) => {
|
|
36
37
|
const scoreColor = scoreType === 'descriptor' ? 'text-neutral-400' : getScoreColor(score);
|
|
37
38
|
let displayScore;
|
|
38
39
|
|
|
@@ -45,13 +46,20 @@ const ScoreCard = ({ title, score, description, descriptor, icon: Icon, scoreTyp
|
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
return (
|
|
48
|
-
<div
|
|
49
|
+
<div
|
|
50
|
+
className={
|
|
51
|
+
isRecruiter
|
|
52
|
+
? 'p-6 rounded-xl flex flex-col items-center justify-start text-center shadow h-full border'
|
|
53
|
+
: 'p-6 rounded-lg flex flex-col items-center justify-start text-center dark:bg-neutral-800/50 backdrop-blur-sm bg-white/70 shadow-lg border border-neutral-200 dark:border-neutral-700 h-full'
|
|
54
|
+
}
|
|
55
|
+
style={isRecruiter ? { backgroundColor: 'var(--content-card-background)', borderColor: 'var(--icon-button-secondary)' } : undefined}
|
|
56
|
+
>
|
|
49
57
|
<div className={`text-3xl mb-4 ${scoreColor}`}>
|
|
50
58
|
<Icon />
|
|
51
59
|
</div>
|
|
52
|
-
<h3 className={`font-semibold text-xl
|
|
60
|
+
<h3 className={`font-semibold text-xl ${scoreType === 'descriptor' ? 'text-neutral-400' : ''}`} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>{title}</h3>
|
|
53
61
|
<p className={`text-4xl font-bold ${scoreColor}`}>{displayScore}</p>
|
|
54
|
-
<p className=
|
|
62
|
+
<p className={isRecruiter ? 'text-sm mt-4' : 'text-sm text-neutral-600 dark:text-neutral-400 mt-4'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>{description}</p>
|
|
55
63
|
</div>
|
|
56
64
|
);
|
|
57
65
|
};
|
|
@@ -106,6 +114,7 @@ const SharedBadgeDisplay = ({ badgeData, type = 'individual' }: { badgeData: Pub
|
|
|
106
114
|
description={devTrustScore?.description || ''}
|
|
107
115
|
icon={FiThumbsUp}
|
|
108
116
|
scoreType='number'
|
|
117
|
+
isRecruiter={isRecruiter}
|
|
109
118
|
/>
|
|
110
119
|
<ScoreCard
|
|
111
120
|
title="KYD Risk™"
|
|
@@ -113,6 +122,7 @@ const SharedBadgeDisplay = ({ badgeData, type = 'individual' }: { badgeData: Pub
|
|
|
113
122
|
description={riskScore?.description || ''}
|
|
114
123
|
icon={FiShield}
|
|
115
124
|
scoreType='risk'
|
|
125
|
+
isRecruiter={isRecruiter}
|
|
116
126
|
/>
|
|
117
127
|
<ScoreCard
|
|
118
128
|
title={<span>KYD AI™ <span className="text-xs 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></span>}
|
|
@@ -121,6 +131,7 @@ const SharedBadgeDisplay = ({ badgeData, type = 'individual' }: { badgeData: Pub
|
|
|
121
131
|
descriptor={aiUsageScore?.descriptor}
|
|
122
132
|
icon={FiCpu}
|
|
123
133
|
scoreType='descriptor'
|
|
134
|
+
isRecruiter={isRecruiter}
|
|
124
135
|
/>
|
|
125
136
|
</div>
|
|
126
137
|
|
|
@@ -214,6 +225,7 @@ const SharedBadgeDisplay = ({ badgeData, type = 'individual' }: { badgeData: Pub
|
|
|
214
225
|
sources={[...(screening_sources.ofac_lists || []), ...(screening_sources.additional_watchlists || [])]}
|
|
215
226
|
searchedAt={updatedAt}
|
|
216
227
|
developerName={developerName || 'this developer'}
|
|
228
|
+
view={type}
|
|
217
229
|
/>
|
|
218
230
|
</div>
|
|
219
231
|
<div>
|
|
@@ -223,6 +235,7 @@ const SharedBadgeDisplay = ({ badgeData, type = 'individual' }: { badgeData: Pub
|
|
|
223
235
|
sources={screening_sources.risk_profile_domains || []}
|
|
224
236
|
searchedAt={updatedAt}
|
|
225
237
|
developerName={developerName || 'this developer'}
|
|
238
|
+
view={type}
|
|
226
239
|
/>
|
|
227
240
|
</div>
|
|
228
241
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import React, { useState } from 'react';
|
|
4
|
-
import { DomainCSVRow } from '../
|
|
4
|
+
import { DomainCSVRow } from '../types';
|
|
5
5
|
|
|
6
6
|
interface SanctionSource {
|
|
7
7
|
issuingEntity: string;
|
|
@@ -22,51 +22,54 @@ interface AppendixTableProps {
|
|
|
22
22
|
sources: string[] | DomainCSVRow[];
|
|
23
23
|
searchedAt: string;
|
|
24
24
|
developerName: string;
|
|
25
|
+
view?: 'recruiter' | 'individual';
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
const SanctionsRow = ({ source, searchedAt, developerName }: { source: SanctionSource, searchedAt: string, developerName: string }) => (
|
|
28
|
-
<tr className=
|
|
29
|
-
<td className=
|
|
28
|
+
const SanctionsRow = ({ source, searchedAt, developerName, isRecruiter }: { source: SanctionSource, searchedAt: string, developerName: string, isRecruiter: boolean }) => (
|
|
29
|
+
<tr className={isRecruiter ? 'transition-colors hover:bg-black/5' : 'hover:bg-neutral-50 dark:hover:bg-neutral-800/50 transition-colors'}>
|
|
30
|
+
<td className={isRecruiter ? 'px-4 py-4 whitespace-nowrap text-sm font-medium' : 'px-4 py-4 whitespace-nowrap text-sm font-medium text-neutral-800 dark:text-neutral-200'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>
|
|
30
31
|
{source.issuingEntity}
|
|
31
32
|
</td>
|
|
32
|
-
<td className=
|
|
33
|
+
<td className={isRecruiter ? 'px-4 py-4 whitespace-normal text-sm' : 'px-4 py-4 whitespace-normal text-sm text-neutral-600 dark:text-neutral-300'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
33
34
|
{source.listName}
|
|
34
35
|
</td>
|
|
35
|
-
<td className=
|
|
36
|
+
<td className={isRecruiter ? 'px-4 py-4 whitespace-nowrap text-sm' : 'px-4 py-4 whitespace-nowrap text-sm text-neutral-600 dark:text-neutral-300'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
36
37
|
{searchedAt}
|
|
37
38
|
</td>
|
|
38
|
-
<td className=
|
|
39
|
-
<span className=
|
|
39
|
+
<td className={isRecruiter ? 'px-4 py-4 whitespace-nowrap text-sm' : 'px-4 py-4 whitespace-nowrap text-sm text-neutral-600 dark:text-neutral-300'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
40
|
+
<span className={isRecruiter ? 'px-2 inline-flex text-xs leading-5 font-semibold rounded-full' : 'px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'} style={isRecruiter ? { backgroundColor: 'var(--icon-button-secondary)', color: 'var(--text-main)' } : undefined}>
|
|
40
41
|
Not Found
|
|
41
42
|
</span>
|
|
42
43
|
</td>
|
|
43
|
-
<td className=
|
|
44
|
-
No exact match for <strong>{developerName}</strong> (based on name and email) was found on this list.
|
|
44
|
+
<td className={isRecruiter ? 'px-4 py-4 text-sm whitespace-normal' : 'px-4 py-4 text-sm text-neutral-600 dark:text-neutral-300 whitespace-normal'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
45
|
+
No exact match for <strong style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>{developerName}</strong> (based on name and email) was found on this list.
|
|
45
46
|
</td>
|
|
46
47
|
</tr>
|
|
47
48
|
);
|
|
48
49
|
|
|
49
|
-
const DomainRow = ({ source, searchedAt, developerName }: { source: DomainSource, searchedAt: string, developerName: string }) => (
|
|
50
|
-
<tr className=
|
|
51
|
-
<td className=
|
|
52
|
-
<td className=
|
|
53
|
-
<td className=
|
|
54
|
-
<td className=
|
|
55
|
-
<td className=
|
|
56
|
-
<span className=
|
|
50
|
+
const DomainRow = ({ source, searchedAt, developerName, isRecruiter }: { source: DomainSource, searchedAt: string, developerName: string, isRecruiter: boolean }) => (
|
|
51
|
+
<tr className={isRecruiter ? 'transition-colors hover:bg-black/5' : 'hover:bg-neutral-50 dark:hover:bg-neutral-800/50 transition-colors'}>
|
|
52
|
+
<td className={isRecruiter ? 'px-4 py-4 whitespace-normal text-sm' : 'px-4 py-4 whitespace-normal text-sm text-neutral-600 dark:text-neutral-300'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>{source.country || 'N/A'}</td>
|
|
53
|
+
<td className={isRecruiter ? 'px-4 py-4 whitespace-normal text-sm' : 'px-4 py-4 whitespace-normal text-sm text-neutral-600 dark:text-neutral-300'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>{source.entityType || 'N/A'}</td>
|
|
54
|
+
<td className={isRecruiter ? 'px-4 py-4 whitespace-normal text-sm font-medium' : 'px-4 py-4 whitespace-normal text-sm font-medium text-neutral-800 dark:text-neutral-200'} style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>{source.entityName || source.url}</td>
|
|
55
|
+
<td className={isRecruiter ? 'px-4 py-4 whitespace-nowrap text-sm' : 'px-4 py-4 whitespace-nowrap text-sm text-neutral-600 dark:text-neutral-300'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>{searchedAt}</td>
|
|
56
|
+
<td className={isRecruiter ? 'px-4 py-4 whitespace-nowrap text-sm' : 'px-4 py-4 whitespace-nowrap text-sm text-neutral-600 dark:text-neutral-300'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
57
|
+
<span className={isRecruiter ? 'px-2 inline-flex text-xs leading-5 font-semibold rounded-full' : 'px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200'} style={isRecruiter ? { backgroundColor: 'var(--icon-button-secondary)', color: 'var(--text-main)' } : undefined}>
|
|
57
58
|
Not Found
|
|
58
59
|
</span>
|
|
59
60
|
</td>
|
|
60
|
-
<td className=
|
|
61
|
-
No profile matching <strong>{developerName}</strong> (based on name and email) was found at this domain.
|
|
61
|
+
<td className={isRecruiter ? 'px-4 py-4 text-sm whitespace-normal' : 'px-4 py-4 text-sm text-neutral-600 dark:text-neutral-300 whitespace-normal'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
62
|
+
No profile matching <strong style={isRecruiter ? { color: 'var(--text-main)' } : undefined}>{developerName}</strong> (based on name and email) was found at this domain.
|
|
62
63
|
</td>
|
|
63
64
|
</tr>
|
|
64
65
|
);
|
|
65
66
|
|
|
66
67
|
|
|
67
|
-
const AppendixTables: React.FC<AppendixTableProps> = ({ type, sources, searchedAt, developerName }) => {
|
|
68
|
+
const AppendixTables: React.FC<AppendixTableProps> = ({ type, sources, searchedAt, developerName, view = 'individual' }) => {
|
|
68
69
|
const [visibleCount, setVisibleCount] = useState(PAGE_SIZE);
|
|
69
70
|
|
|
71
|
+
const isRecruiter = view === 'recruiter';
|
|
72
|
+
|
|
70
73
|
const formattedDate = new Date(searchedAt).toLocaleString(undefined, {
|
|
71
74
|
year: 'numeric', month: 'short', day: 'numeric',
|
|
72
75
|
hour: 'numeric', minute: '2-digit',
|
|
@@ -100,35 +103,36 @@ const AppendixTables: React.FC<AppendixTableProps> = ({ type, sources, searchedA
|
|
|
100
103
|
|
|
101
104
|
return (
|
|
102
105
|
<div>
|
|
103
|
-
<div className=
|
|
104
|
-
<table className=
|
|
105
|
-
<thead className=
|
|
106
|
+
<div className={isRecruiter ? 'overflow-x-auto rounded-lg border' : 'overflow-x-auto rounded-lg border border-neutral-200 dark:border-neutral-700'} style={isRecruiter ? { borderColor: 'var(--icon-button-secondary)', backgroundColor: 'var(--content-card-background)' } : undefined}>
|
|
107
|
+
<table className={isRecruiter ? 'min-w-full' : 'min-w-full divide-y divide-neutral-200 dark:divide-neutral-700'}>
|
|
108
|
+
<thead className={isRecruiter ? '' : 'bg-neutral-50 dark:bg-neutral-800'}>
|
|
106
109
|
<tr>
|
|
107
110
|
{headers.map(header => (
|
|
108
|
-
<th key={header} scope="col" className=
|
|
111
|
+
<th key={header} scope="col" className={isRecruiter ? 'px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider' : 'px-4 py-3 text-left text-xs font-semibold text-neutral-500 dark:text-neutral-300 uppercase tracking-wider'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
109
112
|
{header}
|
|
110
113
|
</th>
|
|
111
114
|
))}
|
|
112
115
|
</tr>
|
|
113
116
|
</thead>
|
|
114
|
-
<tbody className=
|
|
117
|
+
<tbody className={isRecruiter ? '' : 'bg-white dark:bg-neutral-900 divide-y divide-neutral-200 dark:divide-neutral-700'}>
|
|
115
118
|
{visibleParsedSources.map((source, index) =>
|
|
116
119
|
type === 'sanctions'
|
|
117
|
-
? <SanctionsRow key={index} source={source as SanctionSource} searchedAt={formattedDate} developerName={developerName} />
|
|
118
|
-
: <DomainRow key={index} source={source as DomainSource} searchedAt={formattedDate} developerName={developerName} />
|
|
120
|
+
? <SanctionsRow key={index} source={source as SanctionSource} searchedAt={formattedDate} developerName={developerName} isRecruiter={isRecruiter} />
|
|
121
|
+
: <DomainRow key={index} source={source as DomainSource} searchedAt={formattedDate} developerName={developerName} isRecruiter={isRecruiter} />
|
|
119
122
|
)}
|
|
120
123
|
</tbody>
|
|
121
124
|
</table>
|
|
122
125
|
</div>
|
|
123
126
|
{parsedSources.length > PAGE_SIZE && (
|
|
124
|
-
<div className=
|
|
127
|
+
<div className={isRecruiter ? 'mt-4 flex items-center justify-between text-sm' : 'mt-4 flex items-center justify-between text-sm text-neutral-600 dark:text-neutral-400'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
125
128
|
<p>
|
|
126
129
|
Showing {Math.min(visibleCount, parsedSources.length)} of {parsedSources.length} entries
|
|
127
130
|
</p>
|
|
128
131
|
{visibleCount < parsedSources.length && (
|
|
129
132
|
<button
|
|
130
133
|
onClick={handleLoadMore}
|
|
131
|
-
className=
|
|
134
|
+
className={isRecruiter ? 'font-medium underline-offset-2 hover:underline' : 'font-medium text-blue-600 hover:text-blue-500 dark:text-blue-500 dark:hover:text-blue-400 transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 rounded-md'}
|
|
135
|
+
style={isRecruiter ? { color: 'var(--icon-accent)' } : undefined}
|
|
132
136
|
>
|
|
133
137
|
Load More
|
|
134
138
|
</button>
|
|
@@ -48,7 +48,7 @@ const ReportHeader = ({ badgeId, developerName, updatedAt, score = 0, isPublic,
|
|
|
48
48
|
KYD Self-Check™
|
|
49
49
|
</h1>
|
|
50
50
|
<p className={isRecruiter ? 'text-sm' : 'text-sm text-neutral-600 dark:text-neutral-400'} style={isRecruiter ? { color: 'var(--text-secondary)' } : undefined}>
|
|
51
|
-
{isPublic ? 'Public Report' : 'Private Report'}
|
|
51
|
+
{(isPublic && type === 'individual') ? 'Public Report' : 'Private Report'}
|
|
52
52
|
</p>
|
|
53
53
|
</div>
|
|
54
54
|
</div>
|