diff --git a/CHANGELOG.md b/CHANGELOG.md index f4c183d..4c11b73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -197,6 +197,15 @@ e este projeto adere ao [Semantic Versioning](https://semver.org/lang/pt-BR/). - Atualizada a função `analyze-essay` para salvar as notas e justificativas das competências - Adicionada restrição para garantir que os valores das competências estejam entre 0 e 200 +### Modificado +- Melhorado o layout da página de análise de redações: + - Separação clara entre critérios gerais e competências do ENEM + - Nova seção dedicada às competências do ENEM com layout aprimorado + - Barras de progresso mais visíveis para as competências + - Adicionadas descrições detalhadas para cada competência + - Cards coloridos para justificativas das competências + - Melhorias visuais nos critérios gerais de avaliação + ## [1.5.0] - 2024-03-19 ### Modificado diff --git a/src/components/dashboard/WritingMetricsChart.tsx b/src/components/dashboard/WritingMetricsChart.tsx index 446ac83..c383767 100644 --- a/src/components/dashboard/WritingMetricsChart.tsx +++ b/src/components/dashboard/WritingMetricsChart.tsx @@ -17,7 +17,11 @@ interface TimeFilterOption { months: number | null; } -const METRICS_CONFIG: MetricConfig[] = [ +interface MetricNames { + [key: string]: string; +} + +const WRITING_METRICS: MetricConfig[] = [ { key: 'score', name: 'Nota Geral', color: '#6366f1' }, { key: 'adequacy', name: 'Adequação', color: '#f43f5e' }, { key: 'coherence', name: 'Coerência', color: '#0ea5e9' }, @@ -26,6 +30,14 @@ const METRICS_CONFIG: MetricConfig[] = [ { key: 'grammar', name: 'Gramática', color: '#f59e0b' } ]; +const ENEM_METRICS: MetricConfig[] = [ + { key: 'language_domain', name: 'Domínio da Língua', color: '#f43f5e' }, + { key: 'proposal_comprehension', name: 'Compreensão da Proposta', color: '#0ea5e9' }, + { key: 'argument_selection', name: 'Seleção de Argumentos', color: '#10b981' }, + { key: 'linguistic_mechanisms', name: 'Mecanismos Linguísticos', color: '#8b5cf6' }, + { key: 'intervention_proposal', name: 'Proposta de Intervenção', color: '#f59e0b' } +]; + const TIME_FILTERS: TimeFilterOption[] = [ { value: '3m', label: '3 meses', months: 3 }, { value: '6m', label: '6 meses', months: 6 }, @@ -39,13 +51,28 @@ interface WritingMetricsChartProps { } export function WritingMetricsChart({ data = [], className = '' }: WritingMetricsChartProps) { - const [visibleMetrics, setVisibleMetrics] = React.useState>( - new Set(METRICS_CONFIG.map(metric => metric.key)) + const [visibleWritingMetrics, setVisibleWritingMetrics] = React.useState>( + new Set(WRITING_METRICS.map(metric => metric.key)) + ); + const [visibleEnemMetrics, setVisibleEnemMetrics] = React.useState>( + new Set(ENEM_METRICS.map(metric => metric.key)) ); const [timeFilter, setTimeFilter] = React.useState('12m'); - const toggleMetric = (metricKey: string) => { - setVisibleMetrics(prev => { + const toggleWritingMetric = (metricKey: string) => { + setVisibleWritingMetrics(prev => { + const newSet = new Set(prev); + if (newSet.has(metricKey)) { + newSet.delete(metricKey); + } else { + newSet.add(metricKey); + } + return newSet; + }); + }; + + const toggleEnemMetric = (metricKey: string) => { + setVisibleEnemMetrics(prev => { const newSet = new Set(prev); if (newSet.has(metricKey)) { newSet.delete(metricKey); @@ -76,13 +103,13 @@ export function WritingMetricsChart({ data = [], className = '' }: WritingMetric const filteredData = React.useMemo(() => filterDataByTime(data), [data, timeFilter]); - return ( -
+ const renderChart = (title: string, description: string, metrics: MetricConfig[], visibleMetrics: Set, toggleMetric: (key: string) => void) => ( +
-

Evolução da Escrita por Semana

-

Acompanhe seu progresso na escrita ao longo do tempo

+

{title}

+

{description}

{/* Filtro de Período */} @@ -106,7 +133,7 @@ export function WritingMetricsChart({ data = [], className = '' }: WritingMetric
@@ -115,7 +142,7 @@ export function WritingMetricsChart({ data = [], className = '' }: WritingMetric {/* Pill Buttons */}
- {METRICS_CONFIG.map(metric => ( + {metrics.map(metric => (
); + + return ( +
+ {renderChart( + "Evolução da Escrita por Semana", + "Acompanhe seu progresso na escrita ao longo do tempo", + WRITING_METRICS, + visibleWritingMetrics, + toggleWritingMetric + )} + {renderChart( + "Evolução das Competências do ENEM", + "Acompanhe seu progresso nas competências do ENEM ao longo do tempo", + ENEM_METRICS, + visibleEnemMetrics, + toggleEnemMetric + )} +
+ ); } \ No newline at end of file diff --git a/src/pages/student-dashboard/StudentDashboardPage.tsx b/src/pages/student-dashboard/StudentDashboardPage.tsx index c40a245..25874d6 100644 --- a/src/pages/student-dashboard/StudentDashboardPage.tsx +++ b/src/pages/student-dashboard/StudentDashboardPage.tsx @@ -67,6 +67,16 @@ interface EssayAnalysis { content_feedback: string; language_feedback: string; }>; + language_domain_value: number; + language_domain_justification: string; + proposal_comprehension_value: number; + proposal_comprehension_justification: string; + argument_selection_value: number; + argument_selection_justification: string; + linguistic_mechanisms_value: number; + linguistic_mechanisms_justification: string; + intervention_proposal_value: number; + intervention_proposal_justification: string; } interface ProcessedEssayAnalysis { @@ -86,6 +96,28 @@ interface ProcessedEssayAnalysis { content_feedback: string; language_feedback: string; }; + competencies: { + language_domain: { + value: number; + justification: string; + }; + proposal_comprehension: { + value: number; + justification: string; + }; + argument_selection: { + value: number; + justification: string; + }; + linguistic_mechanisms: { + value: number; + justification: string; + }; + intervention_proposal: { + value: number; + justification: string; + }; + }; } export function StudentDashboardPage() { @@ -170,6 +202,11 @@ export function StudentDashboardPage() { cohesion: 0, vocabulary: 0, grammar: 0, + language_domain: 0, + proposal_comprehension: 0, + argument_selection: 0, + linguistic_mechanisms: 0, + intervention_proposal: 0, minutesWriting: 0 }; } @@ -181,6 +218,11 @@ export function StudentDashboardPage() { acc[week].cohesion += analysis.scores.cohesion; acc[week].vocabulary += analysis.scores.vocabulary; acc[week].grammar += analysis.scores.grammar; + acc[week].language_domain += analysis.competencies.language_domain.value; + acc[week].proposal_comprehension += analysis.competencies.proposal_comprehension.value; + acc[week].argument_selection += analysis.competencies.argument_selection.value; + acc[week].linguistic_mechanisms += analysis.competencies.linguistic_mechanisms.value; + acc[week].intervention_proposal += analysis.competencies.intervention_proposal.value; acc[week].minutesWriting += 30; // Tempo médio estimado por redação return acc; @@ -195,6 +237,11 @@ export function StudentDashboardPage() { cohesion: Math.round(data.cohesion / data.count), vocabulary: Math.round(data.vocabulary / data.count), grammar: Math.round(data.grammar / data.count), + language_domain: Math.round(data.language_domain / data.count), + proposal_comprehension: Math.round(data.proposal_comprehension / data.count), + argument_selection: Math.round(data.argument_selection / data.count), + linguistic_mechanisms: Math.round(data.linguistic_mechanisms / data.count), + intervention_proposal: Math.round(data.intervention_proposal / data.count), minutesWriting: data.minutesWriting })) .sort((a, b) => a.week.localeCompare(b.week)); @@ -342,7 +389,17 @@ export function StudentDashboardPage() { structure_feedback, content_feedback, language_feedback - ) + ), + language_domain_value, + language_domain_justification, + proposal_comprehension_value, + proposal_comprehension_justification, + argument_selection_value, + argument_selection_justification, + linguistic_mechanisms_value, + linguistic_mechanisms_justification, + intervention_proposal_value, + intervention_proposal_justification ) `) .eq('student_id', session.user.id) @@ -373,6 +430,28 @@ export function StudentDashboardPage() { structure_feedback: analysis.essay_analysis_feedback?.[0]?.structure_feedback || '', content_feedback: analysis.essay_analysis_feedback?.[0]?.content_feedback || '', language_feedback: analysis.essay_analysis_feedback?.[0]?.language_feedback || '' + }, + competencies: { + language_domain: { + value: analysis.language_domain_value || 0, + justification: analysis.language_domain_justification || '' + }, + proposal_comprehension: { + value: analysis.proposal_comprehension_value || 0, + justification: analysis.proposal_comprehension_justification || '' + }, + argument_selection: { + value: analysis.argument_selection_value || 0, + justification: analysis.argument_selection_justification || '' + }, + linguistic_mechanisms: { + value: analysis.linguistic_mechanisms_value || 0, + justification: analysis.linguistic_mechanisms_justification || '' + }, + intervention_proposal: { + value: analysis.intervention_proposal_value || 0, + justification: analysis.intervention_proposal_justification || '' + } } }; }) @@ -389,14 +468,24 @@ export function StudentDashboardPage() { coherence: acc.coherence + (analysis.scores?.coherence || 0), cohesion: acc.cohesion + (analysis.scores?.cohesion || 0), vocabulary: acc.vocabulary + (analysis.scores?.vocabulary || 0), - grammar: acc.grammar + (analysis.scores?.grammar || 0) + grammar: acc.grammar + (analysis.scores?.grammar || 0), + language_domain: acc.language_domain + (analysis.competencies?.language_domain?.value || 0), + proposal_comprehension: acc.proposal_comprehension + (analysis.competencies?.proposal_comprehension?.value || 0), + argument_selection: acc.argument_selection + (analysis.competencies?.argument_selection?.value || 0), + linguistic_mechanisms: acc.linguistic_mechanisms + (analysis.competencies?.linguistic_mechanisms?.value || 0), + intervention_proposal: acc.intervention_proposal + (analysis.competencies?.intervention_proposal?.value || 0) }), { score: 0, adequacy: 0, coherence: 0, cohesion: 0, vocabulary: 0, - grammar: 0 + grammar: 0, + language_domain: 0, + proposal_comprehension: 0, + argument_selection: 0, + linguistic_mechanisms: 0, + intervention_proposal: 0 }); console.log('Soma das métricas:', metricsSum); @@ -412,7 +501,12 @@ export function StudentDashboardPage() { averageCoherence: Math.round(metricsSum.coherence / totalAnalyses), averageCohesion: Math.round(metricsSum.cohesion / totalAnalyses), averageVocabulary: Math.round(metricsSum.vocabulary / totalAnalyses), - averageGrammar: Math.round(metricsSum.grammar / totalAnalyses) + averageGrammar: Math.round(metricsSum.grammar / totalAnalyses), + averageLanguageDomain: Math.round(metricsSum.language_domain / totalAnalyses), + averageProposalComprehension: Math.round(metricsSum.proposal_comprehension / totalAnalyses), + averageArgumentSelection: Math.round(metricsSum.argument_selection / totalAnalyses), + averageLinguisticMechanisms: Math.round(metricsSum.linguistic_mechanisms / totalAnalyses), + averageInterventionProposal: Math.round(metricsSum.intervention_proposal / totalAnalyses) }; console.log('Métricas de escrita calculadas:', writingMetrics); @@ -543,72 +637,6 @@ export function StudentDashboardPage() { {/* Gráfico de Evolução da Escrita */}
- - {/* Histórias Recentes */} -
-
-

Histórias Recentes

- -
- - {recentStories.length === 0 ? ( -
- -

- Nenhuma história ainda -

-

- Comece sua jornada criando sua primeira história! -

- -
- ) : ( -
- {recentStories.map((story) => ( -
navigate(`/aluno/historias/${story.id}`)} - > - {story.cover && ( -
- {story.title} -
- )} -
-

{story.title}

-
- {new Date(story.created_at).toLocaleDateString()} - - {story.status === 'published' ? 'Publicada' : 'Rascunho'} - -
-
-
- ))} -
- )} -
); } \ No newline at end of file diff --git a/src/pages/student-dashboard/essays/EssayAnalysis.tsx b/src/pages/student-dashboard/essays/EssayAnalysis.tsx index 1a1a44c..3cf97e8 100644 --- a/src/pages/student-dashboard/essays/EssayAnalysis.tsx +++ b/src/pages/student-dashboard/essays/EssayAnalysis.tsx @@ -3,7 +3,7 @@ import { useParams, useNavigate } from 'react-router-dom'; import { supabase } from '@/lib/supabase'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { ArrowLeft, CheckCircle2, XCircle } from 'lucide-react'; +import { ArrowLeft, CheckCircle2, XCircle, BookOpen, Brain, MessageSquare, Puzzle, Target } from 'lucide-react'; import { Progress } from '@/components/ui/progress'; interface EssayAnalysis { @@ -25,6 +25,28 @@ interface EssayAnalysis { vocabulary: number; grammar: number; }; + competencies: { + language_domain: { + value: number; + justification: string; + }; + proposal_comprehension: { + value: number; + justification: string; + }; + argument_selection: { + value: number; + justification: string; + }; + linguistic_mechanisms: { + value: number; + justification: string; + }; + intervention_proposal: { + value: number; + justification: string; + }; + }; created_at: string; } @@ -64,6 +86,16 @@ interface EssayAnalysisData { vocabulary: number; grammar: number; }>; + language_domain_value: number; + language_domain_justification: string; + proposal_comprehension_value: number; + proposal_comprehension_justification: string; + argument_selection_value: number; + argument_selection_justification: string; + linguistic_mechanisms_value: number; + linguistic_mechanisms_justification: string; + intervention_proposal_value: number; + intervention_proposal_justification: string; } export function EssayAnalysis() { @@ -117,7 +149,17 @@ export function EssayAnalysis() { cohesion, vocabulary, grammar - ) + ), + language_domain_value, + language_domain_justification, + proposal_comprehension_value, + proposal_comprehension_justification, + argument_selection_value, + argument_selection_justification, + linguistic_mechanisms_value, + linguistic_mechanisms_justification, + intervention_proposal_value, + intervention_proposal_justification `) .eq('essay_id', id) .order('created_at', { ascending: false }) @@ -143,6 +185,28 @@ export function EssayAnalysis() { cohesion: analysisData.scores[0]?.cohesion || 0, vocabulary: analysisData.scores[0]?.vocabulary || 0, grammar: analysisData.scores[0]?.grammar || 0 + }, + competencies: { + language_domain: { + value: analysisData.language_domain_value || 0, + justification: analysisData.language_domain_justification || '' + }, + proposal_comprehension: { + value: analysisData.proposal_comprehension_value || 0, + justification: analysisData.proposal_comprehension_justification || '' + }, + argument_selection: { + value: analysisData.argument_selection_value || 0, + justification: analysisData.argument_selection_justification || '' + }, + linguistic_mechanisms: { + value: analysisData.linguistic_mechanisms_value || 0, + justification: analysisData.linguistic_mechanisms_justification || '' + }, + intervention_proposal: { + value: analysisData.intervention_proposal_value || 0, + justification: analysisData.intervention_proposal_justification || '' + } } }; @@ -305,6 +369,107 @@ export function EssayAnalysis() {
+ + {/* Nova seção de Competências do ENEM */} +
+

Competências do ENEM

+
+ {/* Competência 1 */} +
+
+ +
+

Competência 1: Domínio da Língua

+

Demonstrar domínio da modalidade escrita formal da Língua Portuguesa

+
+
+ {analysis.competencies.language_domain.value} + /200 +
+
+ +

+ {analysis.competencies.language_domain.justification} +

+
+ + {/* Competência 2 */} +
+
+ +
+

Competência 2: Compreensão da Proposta

+

Compreender a proposta de redação e aplicar conceitos das várias áreas de conhecimento

+
+
+ {analysis.competencies.proposal_comprehension.value} + /200 +
+
+ +

+ {analysis.competencies.proposal_comprehension.justification} +

+
+ + {/* Competência 3 */} +
+
+ +
+

Competência 3: Seleção de Argumentos

+

Selecionar, relacionar, organizar e interpretar informações, fatos, opiniões e argumentos

+
+
+ {analysis.competencies.argument_selection.value} + /200 +
+
+ +

+ {analysis.competencies.argument_selection.justification} +

+
+ + {/* Competência 4 */} +
+
+ +
+

Competência 4: Mecanismos Linguísticos

+

Demonstrar conhecimento dos mecanismos linguísticos necessários para a construção da argumentação

+
+
+ {analysis.competencies.linguistic_mechanisms.value} + /200 +
+
+ +

+ {analysis.competencies.linguistic_mechanisms.justification} +

+
+ + {/* Competência 5 */} +
+
+ +
+

Competência 5: Proposta de Intervenção

+

Elaborar proposta de intervenção para o problema abordado

+
+
+ {analysis.competencies.intervention_proposal.value} + /200 +
+
+ +

+ {analysis.competencies.intervention_proposal.justification} +

+
+
+
); } \ No newline at end of file diff --git a/src/types/metrics.ts b/src/types/metrics.ts index aa7effa..864d88b 100644 --- a/src/types/metrics.ts +++ b/src/types/metrics.ts @@ -21,6 +21,11 @@ export interface WritingMetrics { averageCohesion: number; averageVocabulary: number; averageGrammar: number; + averageLanguageDomain: number; + averageProposalComprehension: number; + averageArgumentSelection: number; + averageLinguisticMechanisms: number; + averageInterventionProposal: number; } export interface WeeklyReadingMetrics { @@ -43,6 +48,11 @@ export interface WeeklyWritingMetrics { cohesion: number; vocabulary: number; grammar: number; + language_domain: number; + proposal_comprehension: number; + argument_selection: number; + linguistic_mechanisms: number; + intervention_proposal: number; minutesWriting: number; }