214 lines
7.0 KiB
TypeScript
214 lines
7.0 KiB
TypeScript
'use client';
|
|
|
|
import { Check, X, Minus } from 'lucide-react';
|
|
import { taxonomy } from '@/lib/taxonomy/data';
|
|
|
|
const PROFILE_COLORS: Record<string, { bg: string; border: string; text: string; badge: string }> = {
|
|
lite: {
|
|
bg: 'bg-green-500/10',
|
|
border: 'border-green-500/30',
|
|
text: 'text-green-400',
|
|
badge: 'bg-green-500',
|
|
},
|
|
core: {
|
|
bg: 'bg-blue-500/10',
|
|
border: 'border-blue-500/30',
|
|
text: 'text-blue-400',
|
|
badge: 'bg-blue-500',
|
|
},
|
|
standard: {
|
|
bg: 'bg-purple-500/10',
|
|
border: 'border-purple-500/30',
|
|
text: 'text-purple-400',
|
|
badge: 'bg-purple-500',
|
|
},
|
|
full: {
|
|
bg: 'bg-amber-500/10',
|
|
border: 'border-amber-500/30',
|
|
text: 'text-amber-400',
|
|
badge: 'bg-amber-500',
|
|
},
|
|
};
|
|
|
|
const COMPLEXITY_COLORS: Record<string, string> = {
|
|
Minimal: 'text-green-400',
|
|
Low: 'text-blue-400',
|
|
Medium: 'text-purple-400',
|
|
High: 'text-amber-400',
|
|
};
|
|
|
|
const ALL_FIELDS = [
|
|
'primary_code',
|
|
'secondary_codes',
|
|
'valence',
|
|
'intensity',
|
|
'specificity',
|
|
'actionability',
|
|
'temporal',
|
|
'evidence',
|
|
'comparative',
|
|
'causal_chain',
|
|
'linked_spans',
|
|
'confidence',
|
|
'annotator_notes',
|
|
];
|
|
|
|
const FIELD_LABELS: Record<string, string> = {
|
|
primary_code: 'Primary Code',
|
|
secondary_codes: 'Secondary Codes',
|
|
valence: 'Valence',
|
|
intensity: 'Intensity',
|
|
specificity: 'Specificity',
|
|
actionability: 'Actionability',
|
|
temporal: 'Temporal',
|
|
evidence: 'Evidence',
|
|
comparative: 'Comparative',
|
|
causal_chain: 'Causal Chain',
|
|
linked_spans: 'Linked Spans',
|
|
confidence: 'Confidence',
|
|
annotator_notes: 'Annotator Notes',
|
|
};
|
|
|
|
export default function ProfilesSection() {
|
|
const profiles = Object.entries(taxonomy.profiles);
|
|
|
|
const getFieldStatus = (profile: typeof taxonomy.profiles.lite, field: string) => {
|
|
if (profile.required_fields.includes(field)) return 'required';
|
|
if (profile.optional_fields.includes(field)) return 'optional';
|
|
if (profile.forbidden_fields.includes(field)) return 'forbidden';
|
|
return 'forbidden';
|
|
};
|
|
|
|
return (
|
|
<div className="p-6 space-y-6">
|
|
{/* Header */}
|
|
<div>
|
|
<h2 className="text-xl font-bold text-gray-100">Implementation Profiles</h2>
|
|
<p className="text-gray-400 mt-1">
|
|
4 profiles for different implementation complexity levels
|
|
</p>
|
|
</div>
|
|
|
|
{/* Profile Cards */}
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-4 gap-4">
|
|
{profiles.map(([profileKey, profile]) => {
|
|
const colors = PROFILE_COLORS[profileKey];
|
|
|
|
return (
|
|
<div
|
|
key={profileKey}
|
|
className={`rounded-lg border ${colors.border} ${colors.bg} p-4`}
|
|
>
|
|
{/* Profile Header */}
|
|
<div className="flex items-center justify-between mb-2">
|
|
<h3 className={`font-semibold ${colors.text}`}>{profile.name}</h3>
|
|
<span className={`w-3 h-3 rounded-full ${colors.badge}`} />
|
|
</div>
|
|
|
|
{/* Stats */}
|
|
<div className="flex items-center gap-3 mb-3 text-sm">
|
|
<span className="text-gray-300">{profile.code_count} codes</span>
|
|
<span className="text-gray-600">|</span>
|
|
<span className={COMPLEXITY_COLORS[profile.complexity]}>
|
|
{profile.complexity}
|
|
</span>
|
|
</div>
|
|
|
|
<p className="text-sm text-gray-400 mb-4">{profile.use_case}</p>
|
|
|
|
{/* Code pattern */}
|
|
<div className="mb-4">
|
|
<span className="text-xs text-gray-500">Code Level:</span>
|
|
<span className="ml-2 font-mono text-sm text-gray-300">
|
|
{profile.code_type}
|
|
</span>
|
|
</div>
|
|
|
|
{/* Pattern */}
|
|
<div className="bg-gray-800/50 rounded p-2 mb-3">
|
|
<span className="text-xs text-gray-500">Pattern:</span>
|
|
<code className="block font-mono text-xs text-gray-300 mt-1">
|
|
{profile.primary_code_pattern}
|
|
</code>
|
|
</div>
|
|
|
|
{/* Secondary codes */}
|
|
<div className="text-xs text-gray-400">
|
|
{profile.secondary_codes_allowed ? (
|
|
<span>
|
|
Up to {profile.secondary_codes_max} secondary codes (tier{' '}
|
|
{profile.secondary_codes_tier})
|
|
</span>
|
|
) : (
|
|
<span className="text-gray-500">No secondary codes</span>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
|
|
{/* Field Comparison Table */}
|
|
<div className="mt-8">
|
|
<h3 className="text-lg font-semibold text-gray-200 mb-4">Field Requirements by Profile</h3>
|
|
<div className="overflow-x-auto">
|
|
<table className="w-full text-sm">
|
|
<thead>
|
|
<tr className="border-b border-gray-700">
|
|
<th className="text-left py-2 px-3 text-gray-400 font-medium">Field</th>
|
|
{profiles.map(([profileKey, profile]) => (
|
|
<th
|
|
key={profileKey}
|
|
className={`text-center py-2 px-3 ${PROFILE_COLORS[profileKey].text} font-medium`}
|
|
>
|
|
{profile.name}
|
|
</th>
|
|
))}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{ALL_FIELDS.map((field) => (
|
|
<tr key={field} className="border-b border-gray-800 hover:bg-gray-800/30">
|
|
<td className="py-2 px-3 text-gray-300">{FIELD_LABELS[field]}</td>
|
|
{profiles.map(([profileKey, profile]) => {
|
|
const status = getFieldStatus(profile, field);
|
|
return (
|
|
<td key={profileKey} className="py-2 px-3 text-center">
|
|
{status === 'required' && (
|
|
<Check className="w-4 h-4 text-green-400 mx-auto" />
|
|
)}
|
|
{status === 'optional' && (
|
|
<Minus className="w-4 h-4 text-yellow-400 mx-auto" />
|
|
)}
|
|
{status === 'forbidden' && (
|
|
<X className="w-4 h-4 text-gray-600 mx-auto" />
|
|
)}
|
|
</td>
|
|
);
|
|
})}
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{/* Legend */}
|
|
<div className="flex items-center gap-6 mt-4 text-xs text-gray-400">
|
|
<div className="flex items-center gap-2">
|
|
<Check className="w-4 h-4 text-green-400" />
|
|
<span>Required</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Minus className="w-4 h-4 text-yellow-400" />
|
|
<span>Optional</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<X className="w-4 h-4 text-gray-600" />
|
|
<span>Not used</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|