/** * Readability Analysis Component * * Displays comprehensive readability analysis including readability metrics, * content statistics, sentence/paragraph analysis, and target audience information. */ import React from 'react'; import { Box, Typography, Paper, Grid, IconButton, Tooltip } from '@mui/material'; import { MenuBook } from '@mui/icons-material'; interface ReadabilityAnalysisProps { detailedAnalysis?: { readability_analysis?: { metrics: Record; avg_sentence_length: number; avg_paragraph_length: number; readability_score: number; target_audience: string; recommendations: string[]; }; content_quality?: { word_count: number; unique_words: number; vocabulary_diversity: number; transition_words_used: number; content_depth_score: number; flow_score: number; recommendations: string[]; }; content_structure?: { total_sections: number; total_paragraphs: number; total_sentences: number; has_introduction: boolean; has_conclusion: boolean; has_call_to_action: boolean; structure_score: number; recommendations: string[]; }; }; visualizationData?: { content_stats: { word_count: number; sections: number; paragraphs: number; }; }; } const cardStyles = { p: 3, backgroundColor: '#ffffff', border: '1px solid #e2e8f0', borderRadius: 2, boxShadow: '0 12px 30px rgba(15,23,42,0.08)', color: '#0f172a', minHeight: '100%' } as const; const sectionTitleSx = { fontWeight: 700, letterSpacing: 0.2, color: '#0f172a', mb: 2 } as const; const statRowSx = { display: 'flex', justifyContent: 'space-between', alignItems: 'center', py: 0.5 } as const; const statLabelSx = { color: '#475569', fontWeight: 500 } as const; const statValueSx = { color: '#0f172a', fontWeight: 700 } as const; const metricRowSx = { display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '0.65rem 0.85rem', borderRadius: 12, backgroundColor: '#f1f5f9', cursor: 'help', transition: 'transform 0.2s ease, box-shadow 0.2s ease', '&:hover': { transform: 'translateY(-2px)', boxShadow: '0 10px 20px rgba(15,23,42,0.08)' } } as const; export const ReadabilityAnalysis: React.FC = ({ detailedAnalysis, visualizationData }) => { const readabilityMetrics = detailedAnalysis?.readability_analysis?.metrics ?? {}; const getMetricDetails = (metric: string, value: number) => { const tooltips: Record = { flesch_reading_ease: { description: 'Measures how easy text is to read (0-100 scale).', interpretation: value >= 80 ? 'Very Easy' : value >= 60 ? 'Standard' : 'Challenging' }, flesch_kincaid_grade: { description: 'U.S. grade level required to understand the text.', interpretation: value <= 8 ? 'Easy' : value <= 12 ? 'Moderate' : 'Advanced' }, gunning_fog: { description: 'Years of formal education needed for comprehension.', interpretation: value <= 12 ? 'Easy' : value <= 16 ? 'Moderate' : 'Advanced' }, smog_index: { description: 'Estimates the years of education needed to understand the text.', interpretation: value <= 8 ? 'Easy' : value <= 12 ? 'Moderate' : 'Advanced' }, automated_readability: { description: 'Automated readability score based on characters per word.', interpretation: value <= 8 ? 'Easy' : value <= 12 ? 'Moderate' : 'Advanced' }, coleman_liau: { description: 'Readability based on characters per word and sentence length.', interpretation: value <= 8 ? 'Easy' : value <= 12 ? 'Moderate' : 'Advanced' } }; return ( tooltips[metric] || { description: 'Readability metric', interpretation: 'No interpretation available' } ); }; const renderStatRow = (label: React.ReactNode, value: React.ReactNode) => ( {label} {value} ); return ( Readability Analysis Readability Metrics Readability Analysis Measures how easy your content is to read and understand. Flesch Reading Ease: 90-100 (Very Easy), 80-89 (Easy), 70-79 (Fairly Easy), 60-69 (Standard) Sentence Length: 15-20 words is optimal Syllables per Word: 1.5-1.7 keeps content approachable } arrow > {Object.keys(readabilityMetrics).length > 0 ? ( Object.entries(readabilityMetrics).map(([metric, value]) => { const { description, interpretation } = getMetricDetails(metric, value); const label = metric.replace('_', ' ').replace(/\b\w/g, (l) => l.toUpperCase()); return ( {label} {description} Interpretation: {interpretation} } arrow placement="top" > {metric.replace('_', ' ')} {value.toFixed(1)} ); }) ) : ( No readability metrics available. This may indicate an issue with the content analysis. )} Content Statistics {renderStatRow('Word Count', detailedAnalysis?.content_quality?.word_count || visualizationData?.content_stats.word_count || 'N/A')} {renderStatRow('Sections', detailedAnalysis?.content_structure?.total_sections || visualizationData?.content_stats.sections || 'N/A')} {renderStatRow('Paragraphs', detailedAnalysis?.content_structure?.total_paragraphs || visualizationData?.content_stats.paragraphs || 'N/A')} {renderStatRow('Sentences', detailedAnalysis?.content_structure?.total_sentences || 'N/A')} {renderStatRow('Unique Words', detailedAnalysis?.content_quality?.unique_words || 'N/A')} {renderStatRow( 'Vocabulary Diversity', detailedAnalysis?.content_quality?.vocabulary_diversity !== undefined ? `${(detailedAnalysis.content_quality.vocabulary_diversity * 100).toFixed(1)}%` : 'N/A' )} Sentence & Paragraph Analysis {renderStatRow( 'Average Sentence Length', detailedAnalysis?.readability_analysis?.avg_sentence_length !== undefined ? `${detailedAnalysis.readability_analysis.avg_sentence_length.toFixed(1)} words` : 'N/A' )} {renderStatRow( 'Average Paragraph Length', detailedAnalysis?.readability_analysis?.avg_paragraph_length !== undefined ? `${detailedAnalysis.readability_analysis.avg_paragraph_length.toFixed(1)} words` : 'N/A' )} {renderStatRow( 'Transition Words Used', detailedAnalysis?.content_quality?.transition_words_used || 'N/A' )} Target Audience {renderStatRow('Reading Level', detailedAnalysis?.readability_analysis?.target_audience || 'N/A')} {renderStatRow('Content Depth Score', detailedAnalysis?.content_quality?.content_depth_score || 'N/A')} {renderStatRow('Flow Score', detailedAnalysis?.content_quality?.flow_score || 'N/A')} ); };