From 46e8ba031251da82fdb426ce862f6cfe6bcaa7d9 Mon Sep 17 00:00:00 2001 From: Lucas Santana Date: Fri, 7 Feb 2025 10:20:48 -0300 Subject: [PATCH] =?UTF-8?q?fix:=20corrige=20fluxo=20de=20reda=C3=A7=C3=B5e?= =?UTF-8?q?s=20e=20visualiza=C3=A7=C3=A3o=20p=C3=B3s-an=C3=A1lise=20-=20Co?= =?UTF-8?q?rrige=20carregamento=20do=20conte=C3=BAdo=20ap=C3=B3s=20envio?= =?UTF-8?q?=20-=20Adiciona=20salvamento=20autom=C3=A1tico=20antes=20da=20a?= =?UTF-8?q?n=C3=A1lise=20-=20Melhora=20UX=20com=20feedback=20visual=20e=20?= =?UTF-8?q?badges?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 17 ++ .../essays/EssayAnalysis.tsx | 269 ++++++++++-------- .../student-dashboard/essays/EssayPage.tsx | 59 +++- 3 files changed, 210 insertions(+), 135 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d516ea..714a75e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -277,3 +277,20 @@ e este projeto adere ao [Semantic Versioning](https://semver.org/lang/pt-BR/). - Implementada transformação dos dados para o formato esperado - Adicionado tratamento para valores nulos - Melhorada tipagem dos dados retornados + +### Modificado +- Melhorado o fluxo de redações: + - Corrigido carregamento do conteúdo da redação após envio para análise + - Adicionado salvamento automático do conteúdo antes de enviar para análise + - Melhorada visualização do status 'analisada' com badge verde + - Adicionado botão "Ver Análise" para redações analisadas + - Ajustado Editor para modo somente leitura após envio + - Melhorada contagem de palavras em todos os estados da redação + +### Técnico +- Refatorado componente `EssayPage`: + - Adicionada lógica de salvamento antes do envio para análise + - Melhorada query do Supabase para incluir conteúdo explicitamente + - Implementado feedback visual durante operações de salvamento + - Otimizado carregamento inicial da redação + - Adicionado tratamento de estados para diferentes status da redação diff --git a/src/pages/student-dashboard/essays/EssayAnalysis.tsx b/src/pages/student-dashboard/essays/EssayAnalysis.tsx index 8641b64..240bdb2 100644 --- a/src/pages/student-dashboard/essays/EssayAnalysis.tsx +++ b/src/pages/student-dashboard/essays/EssayAnalysis.tsx @@ -3,8 +3,9 @@ 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, Loader2 } from 'lucide-react'; import { Progress } from '@/components/ui/progress'; +import { cn } from '@/lib/utils'; interface EssayAnalysis { id: string; @@ -123,155 +124,177 @@ export function EssayAnalysis() { } } - if (loading) return
Carregando...
; - if (!essay || !analysis) return
Análise não encontrada
; + if (loading) { + return ( +
+
+
+
+
+ {[1, 2, 3].map((i) => ( +
+ ))} +
+
+
+ ); + } + + if (!essay || !analysis) { + return ( +
+
+
Análise não encontrada
+ +
+
+ ); + } return (
-
- -
-

{essay.title}

-

- {essay.essay_type.title} • {essay.essay_genre.title} -

+ {/* Cabeçalho */} +
+
+ +
+

{essay.title}

+

+ {essay.essay_type.title} • {essay.essay_genre.title} +

+
-
- {/* Pontuação Geral */} - - - Pontuação Geral - - -
-
- {analysis.overall_score} + {/* Conteúdo Principal */} +
+ {/* Cartão de Pontuação */} + + +
+
+ {analysis.overall_score} + /100
-
/100
+
Pontuação Geral
- {/* Pontos Fortes */} - - - - - Pontos Fortes - - - -
    - {analysis.strengths.map((strength, index) => ( -
  • {strength}
  • - ))} -
-
-
+ {/* Grid de Métricas */} +
+ {/* Pontos Fortes */} + + + + + Pontos Fortes + + + +
    + {analysis.strengths.map((strength, index) => ( +
  • +
    + {strength} +
  • + ))} +
+
+
- {/* Pontos a Melhorar */} - - - - - Pontos a Melhorar - - - -
    - {analysis.improvements.map((improvement, index) => ( -
  • {improvement}
  • + {/* Pontos a Melhorar */} + + + + + Pontos a Melhorar + + + +
      + {analysis.improvements.map((improvement, index) => ( +
    • +
      + {improvement} +
    • + ))} +
    +
    +
    + + {/* Critérios de Avaliação */} + + + Critérios de Avaliação + + + {[ + { label: 'Adequação ao Gênero', value: analysis.criteria_scores.adequacy, color: 'bg-blue-500' }, + { label: 'Coerência', value: analysis.criteria_scores.coherence, color: 'bg-green-500' }, + { label: 'Coesão', value: analysis.criteria_scores.cohesion, color: 'bg-purple-500' }, + { label: 'Vocabulário', value: analysis.criteria_scores.vocabulary, color: 'bg-orange-500' }, + { label: 'Gramática', value: analysis.criteria_scores.grammar, color: 'bg-pink-500' } + ].map((criterion) => ( +
    +
    + {criterion.label} + {criterion.value}% +
    +
    +
    +
    +
    ))} -
-
-
+ + +
{/* Feedback Detalhado */} - + Feedback Detalhado - -
-

Estrutura

-

{analysis.feedback.structure}

+ +
+

Estrutura

+

{analysis.feedback.structure}

-
-

Conteúdo

-

{analysis.feedback.content}

+
+

Conteúdo

+

{analysis.feedback.content}

-
-

Linguagem

-

{analysis.feedback.language}

-
- - - - {/* Critérios de Avaliação */} - - - Critérios de Avaliação - - -
-
- Adequação ao Gênero - {analysis.criteria_scores.adequacy}% -
- -
-
-
- Coerência - {analysis.criteria_scores.coherence}% -
- -
-
-
- Coesão - {analysis.criteria_scores.cohesion}% -
- -
-
-
- Vocabulário - {analysis.criteria_scores.vocabulary}% -
- -
-
-
- Gramática - {analysis.criteria_scores.grammar}% -
- +
+

Linguagem

+

{analysis.feedback.language}

{/* Sugestões */} - + - Sugestões para Melhoria + Sugestões para Melhoria -

+

{analysis.suggestions}

@@ -279,4 +302,4 @@ export function EssayAnalysis() {
); -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/pages/student-dashboard/essays/EssayPage.tsx b/src/pages/student-dashboard/essays/EssayPage.tsx index b35fb18..5f7482d 100644 --- a/src/pages/student-dashboard/essays/EssayPage.tsx +++ b/src/pages/student-dashboard/essays/EssayPage.tsx @@ -5,7 +5,7 @@ import { Button } from '@/components/ui/button'; import { Card, CardContent } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; -import { ArrowLeft, Save, Send, Trash2 } from 'lucide-react'; +import { ArrowLeft, Save, Send, Trash2, BarChart3 } from 'lucide-react'; import { Badge } from '@/components/ui/badge'; import { AlertDialog, @@ -77,13 +77,20 @@ export function EssayPage() { .select(` *, essay_type:essay_types(*), - essay_genre:essay_genres(*) + essay_genre:essay_genres(*), + content `) .eq('id', id) .single(); if (error) throw error; setEssay(data); + + // Atualizar contagem de palavras + if (data?.content) { + const words = data.content.trim().split(/\s+/).length; + setWordCount(words); + } } catch (error) { console.error('Erro ao carregar redação:', error); } finally { @@ -114,13 +121,19 @@ export function EssayPage() { async function submitForAnalysis() { if (!essay) return; try { - // Primeiro atualiza o status - const { error: updateError } = await supabase + setSaving(true); + + // Primeiro salvar o conteúdo atual + const { error: saveError } = await supabase .from('student_essays') - .update({ status: 'submitted' }) + .update({ + title: essay.title, + content: essay.content, + status: 'submitted' + }) .eq('id', essay.id); - if (updateError) throw updateError; + if (saveError) throw saveError; // Chama a Edge Function para análise const { error: analysisError } = await supabase.functions.invoke('analyze-essay', { @@ -138,6 +151,8 @@ export function EssayPage() { navigate(`/aluno/redacoes/${essay.id}/analise`); } catch (error) { console.error('Erro ao enviar para análise:', error); + } finally { + setSaving(false); } } @@ -217,9 +232,9 @@ export function EssayPage() { - + @@ -278,16 +293,36 @@ export function EssayPage() { )} + + {essay.status === 'analyzed' && ( + + )}
setEssay({ ...essay, content: newContent })} - placeholder="Escreva sua redação aqui..." + content={essay.content || ''} + onChange={(newContent) => essay.status === 'draft' ? setEssay({ ...essay, content: newContent }) : null} + placeholder={essay.status === 'draft' ? "Escreva sua redação aqui..." : ""} readOnly={essay.status !== 'draft'} + className={cn( + "min-h-[400px]", + essay.status !== 'draft' && "bg-gray-50" + )} />
{wordCount} palavras - {!isWithinWordLimit && ( + {essay.status === 'draft' && !isWithinWordLimit && ( {' '}(mínimo: {essay.essay_genre.requirements.min_words}, máximo: {essay.essay_genre.requirements.max_words})