Initial commit - WhyRating Engine (Google Reviews Scraper)
This commit is contained in:
213
web/components/taxonomy/ProfilesSection.tsx
Normal file
213
web/components/taxonomy/ProfilesSection.tsx
Normal file
@@ -0,0 +1,213 @@
|
||||
'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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user