'use client'; import React from 'react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Progress } from '@/components/ui/progress'; import { Activity, FileText, Clock, TrendingUp, TrendingDown, Minus, Info, CheckCircle, AlertTriangle, XCircle } from 'lucide-react'; import { cn } from '@/lib/utils'; import { ActivityScore, ContentScore, TimelinessScore, TimeEntryAnalysis, AggregateAnalysis } from '@/lib/types/analytics'; interface ScoreCardProps { title: string; score: number; description?: string; trend?: 'up' | 'down' | 'neutral'; trendValue?: number; icon?: React.ReactNode; size?: 'sm' | 'md' | 'lg'; className?: string; } export function ScoreCard({ title, score, description, trend, trendValue, icon, size = 'md', className }: ScoreCardProps) { const percentage = Math.round(score * 100); const scoreColor = getScoreColor(score); const scoreLabel = getScoreLabel(score); const sizeClasses = { sm: 'p-4', md: 'p-6', lg: 'p-8', }; const titleSizeClasses = { sm: 'text-sm', md: 'text-base', lg: 'text-lg', }; const scoreSizeClasses = { sm: 'text-2xl', md: 'text-3xl', lg: 'text-4xl', }; return (
{icon} {title} {trend && (
{trend === 'up' && } {trend === 'down' && } {trend === 'neutral' && } {(trendValue !== undefined) && ( 0 ? "text-green-600" : trendValue < 0 ? "text-red-600" : "text-gray-600" )}> {trendValue > 0 ? '+' : ''}{trendValue}% )}
)}
{description && (

{description}

)}
{/* Score Display */}
{percentage}% {scoreLabel}
{getScoreIcon(score)} {scoreLabel}
{/* Progress Bar */}
Poor Average Excellent
); } interface ActivityScoreCardProps { title: string; score: ActivityScore; icon?: React.ReactNode; className?: string; } export function ActivityScoreCard({ title, score, icon, className }: ActivityScoreCardProps) { return ( {icon || } {title} {/* Overall Score */}
{Math.round(score.score * 100)}%
Activity Score
{/* Breakdown */}

Score Breakdown

Completeness
{Math.round(score.breakdown.completeness * 100)}%
Consistency
{Math.round(score.breakdown.consistency * 100)}%
Duration
{Math.round(score.breakdown.duration * 100)}%
Categorization
{Math.round(score.breakdown.categorization * 100)}%
{/* Positive Factors */} {score.factors.length > 0 && (

Positive Factors

{score.factors.map((factor: string, index: number) => ( {factor} ))}
)}
); } interface ContentScoreCardProps { title: string; score: ContentScore; icon?: React.ReactNode; className?: string; } export function ContentScoreCard({ title, score, icon, className }: ContentScoreCardProps) { return ( {icon || } {title} {/* Overall Score */}
{Math.round(score.score * 100)}%
Content Score
{/* Breakdown */}

Score Breakdown

Notes Quality
{Math.round(score.breakdown.notesQuality * 100)}%
Title Clarity
{Math.round(score.breakdown.titleClarity * 100)}%
Internal Notes
{Math.round(score.breakdown.internalNotes * 100)}%
Technical Detail
{Math.round(score.breakdown.technicalDetail * 100)}%
{/* Positive Factors */} {score.factors.length > 0 && (

Positive Factors

{score.factors.map((factor: string, index: number) => ( {factor} ))}
)}
); } interface TimelinessScoreCardProps { title: string; score: TimelinessScore; icon?: React.ReactNode; className?: string; } export function TimelinessScoreCard({ title, score, icon, className }: TimelinessScoreCardProps) { return ( {icon || } {title} {/* Overall Score */}
{Math.round(score.score * 100)}%
Timeliness Score
{/* Breakdown */}

Score Breakdown

Entry Delay
{Math.round(score.breakdown.entryDelay * 100)}%
Business Hours
{Math.round(score.breakdown.businessHours * 100)}%
Regularity
{Math.round(score.breakdown.regularity * 100)}%
Approval Time
{Math.round(score.breakdown.approvalTimeliness * 100)}%
{/* Positive Factors */} {score.factors.length > 0 && (

Positive Factors

{score.factors.map((factor: string, index: number) => ( {factor} ))}
)}
); } interface AggregateScoreCardProps { analysis: AggregateAnalysis; className?: string; } export function AggregateScoreCard({ analysis, className }: AggregateScoreCardProps) { return ( Overall Performance {/* Overall Score */}
{Math.round(analysis.scores.overall * 100)}%
Overall Score
{/* Individual Scores */}
{Math.round(analysis.scores.activity * 100)}%
Activity
{Math.round(analysis.scores.content * 100)}%
Content
{Math.round(analysis.scores.timeliness * 100)}%
Timeliness
{/* Summary Stats */}
Total Entries: {analysis.totalEntries}
Total Hours: {Number(analysis.totalHours).toFixed(1)}
Avg Hours/Entry: {Number(analysis.averageHoursPerEntry).toFixed(1)}
Date Range: {analysis.dateRange.latest.toLocaleDateString()}
); } // Helper functions function getScoreColor(score: number) { if (score >= 0.8) { return { text: 'text-green-600', badge: 'bg-green-100 text-green-800 border-green-200', progress: 'bg-green-500', }; } if (score >= 0.6) { return { text: 'text-yellow-600', badge: 'bg-yellow-100 text-yellow-800 border-yellow-200', progress: 'bg-yellow-500', }; } return { text: 'text-red-600', badge: 'bg-red-100 text-red-800 border-red-200', progress: 'bg-red-500', }; } function getScoreLabel(score: number) { if (score >= 0.8) return 'Excellent'; if (score >= 0.6) return 'Good'; if (score >= 0.4) return 'Average'; return 'Poor'; } function getScoreIcon(score: number) { if (score >= 0.8) { return ; } if (score >= 0.6) { return ; } return ; }