refactor: Refatorando estilo da Essay Analysis

This commit is contained in:
Lucas Santana 2025-02-07 10:43:40 -03:00
parent ccbac66d28
commit 8b45fe72e7
2 changed files with 197 additions and 138 deletions

View File

@ -12,13 +12,13 @@ const Progress = React.forwardRef<
<ProgressPrimitive.Root
ref={ref}
className={cn(
"relative h-4 w-full overflow-hidden rounded-full bg-secondary",
"relative h-4 w-full overflow-hidden rounded-full bg-gray-200",
className
)}
{...props}
>
<ProgressPrimitive.Indicator
className="h-full w-full flex-1 bg-primary transition-all"
className="h-full w-full flex-1 bg-purple-600 transition-all"
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/>
</ProgressPrimitive.Root>

View File

@ -40,6 +40,32 @@ interface Essay {
};
}
interface EssayAnalysisData {
id: string;
essay_id: string;
overall_score: number;
suggestions: string;
created_at: string;
feedback: Array<{
structure_feedback: string;
content_feedback: string;
language_feedback: string;
}>;
strengths: Array<{
strength: string;
}>;
improvements: Array<{
improvement: string;
}>;
scores: Array<{
adequacy: number;
coherence: number;
cohesion: number;
vocabulary: number;
grammar: number;
}>;
}
export function EssayAnalysis() {
const navigate = useNavigate();
const { id } = useParams();
@ -70,16 +96,57 @@ export function EssayAnalysis() {
setEssay(essayData);
// Carregar análise
const { data: analysisData, error: analysisError } = await supabase
const { data, error: analysisError } = await supabase
.from('essay_analyses')
.select('*')
.select(`
*,
feedback:essay_analysis_feedback(
structure_feedback,
content_feedback,
language_feedback
),
strengths:essay_analysis_strengths(
strength
),
improvements:essay_analysis_improvements(
improvement
),
scores:essay_analysis_scores(
adequacy,
coherence,
cohesion,
vocabulary,
grammar
)
`)
.eq('essay_id', id)
.order('created_at', { ascending: false })
.limit(1)
.single();
if (analysisError) throw analysisError;
setAnalysis(analysisData);
// Transformar os dados para o formato esperado
const analysisData = data as EssayAnalysisData;
const analysis: EssayAnalysis = {
...analysisData,
feedback: {
structure: analysisData.feedback[0]?.structure_feedback || '',
content: analysisData.feedback[0]?.content_feedback || '',
language: analysisData.feedback[0]?.language_feedback || ''
},
strengths: analysisData.strengths?.map((s: { strength: string }) => s.strength) || [],
improvements: analysisData.improvements?.map((i: { improvement: string }) => i.improvement) || [],
criteria_scores: {
adequacy: analysisData.scores[0]?.adequacy || 0,
coherence: analysisData.scores[0]?.coherence || 0,
cohesion: analysisData.scores[0]?.cohesion || 0,
vocabulary: analysisData.scores[0]?.vocabulary || 0,
grammar: analysisData.scores[0]?.grammar || 0
}
};
setAnalysis(analysis);
} catch (error) {
console.error('Erro ao carregar dados:', error);
} finally {
@ -93,158 +160,150 @@ export function EssayAnalysis() {
return (
<div className="container mx-auto p-6">
<div className="flex items-center gap-4 mb-6">
<Button
variant="ghost"
<Button
variant="ghost"
onClick={() => navigate('/aluno/redacoes')}
className="text-purple-600 hover:text-purple-700"
className="flex items-center gap-2 text-gray-600 hover:text-gray-900"
trackingId="essay-analysis-back-to-list-button"
>
<ArrowLeft className="mr-2 h-4 w-4" />
Voltar para lista de redações
<ArrowLeft className="h-5 w-5" />
Voltar para redações
</Button>
<Button
variant="ghost"
onClick={() => navigate(`/aluno/redacoes/${id}`)}
className="text-gray-600 hover:text-gray-900"
trackingId="essay-analysis-back-to-essay-button"
>
<ArrowLeft className="mr-2 h-4 w-4" />
Voltar para redação
</Button>
<div>
<h1 className="text-3xl font-bold">{essay.title}</h1>
<p className="text-muted-foreground">
</div>
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6 space-y-6">
{/* Título e Tipo */}
<div className="border-b border-gray-200 pb-6">
<h1 className="text-2xl font-bold text-gray-900">{essay.title}</h1>
<p className="text-gray-500 mt-1">
{essay.essay_type.title} {essay.essay_genre.title}
</p>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{/* Pontuação Geral */}
<Card>
<CardHeader>
<CardTitle>Pontuação Geral</CardTitle>
</CardHeader>
<CardContent>
<div className="flex items-center justify-center">
<div className="text-6xl font-bold text-primary">
{analysis.overall_score}
{/* Grid de Cards */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{/* Pontuação Geral */}
<Card className="bg-purple-50 border-purple-100">
<CardContent className="pt-6">
<div className="flex items-center justify-center">
<div className="text-6xl font-bold text-purple-600">{analysis.overall_score}</div>
<div className="text-2xl text-purple-600 ml-2">/100</div>
</div>
<div className="text-2xl ml-1">/100</div>
</div>
</CardContent>
</Card>
<p className="text-center text-gray-600 mt-2">Pontuação Geral</p>
</CardContent>
</Card>
{/* Pontos Fortes */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<CheckCircle2 className="h-5 w-5 text-success" />
Pontos Fortes
</CardTitle>
</CardHeader>
<CardContent>
<ul className="list-disc list-inside space-y-2">
{analysis.strengths.map((strength, index) => (
<li key={index} className="text-success">{strength}</li>
))}
</ul>
</CardContent>
</Card>
{/* Pontos Fortes */}
<Card className="bg-green-50 border-green-100">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-green-600">
<CheckCircle2 className="h-5 w-5" />
Pontos Fortes
</CardTitle>
</CardHeader>
<CardContent>
<ul className="list-disc list-inside space-y-2">
{analysis.strengths.map((strength, index) => (
<li key={index} className="text-green-600">{strength}</li>
))}
</ul>
</CardContent>
</Card>
{/* Pontos a Melhorar */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<XCircle className="h-5 w-5 text-destructive" />
Pontos a Melhorar
</CardTitle>
</CardHeader>
<CardContent>
<ul className="list-disc list-inside space-y-2">
{analysis.improvements.map((improvement, index) => (
<li key={index} className="text-destructive">{improvement}</li>
))}
</ul>
</CardContent>
</Card>
{/* Pontos a Melhorar */}
<Card className="bg-orange-50 border-orange-100">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-orange-600">
<XCircle className="h-5 w-5" />
Pontos a Melhorar
</CardTitle>
</CardHeader>
<CardContent>
<ul className="list-disc list-inside space-y-2">
{analysis.improvements.map((improvement, index) => (
<li key={index} className="text-orange-600">{improvement}</li>
))}
</ul>
</CardContent>
</Card>
{/* Feedback Detalhado */}
<Card className="md:col-span-2">
<CardHeader>
<CardTitle>Feedback Detalhado</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div>
<h4 className="font-semibold mb-2">Estrutura</h4>
<p className="text-muted-foreground">{analysis.feedback.structure}</p>
</div>
<div>
<h4 className="font-semibold mb-2">Conteúdo</h4>
<p className="text-muted-foreground">{analysis.feedback.content}</p>
</div>
<div>
<h4 className="font-semibold mb-2">Linguagem</h4>
<p className="text-muted-foreground">{analysis.feedback.language}</p>
</div>
</CardContent>
</Card>
{/* Feedback Detalhado */}
<Card className="md:col-span-2 border-gray-200">
<CardHeader className="border-b border-gray-200">
<CardTitle>Feedback Detalhado</CardTitle>
</CardHeader>
<CardContent className="space-y-4 pt-4">
<div>
<h4 className="font-semibold mb-2 text-gray-900">Estrutura</h4>
<p className="text-gray-600">{analysis.feedback.structure}</p>
</div>
<div>
<h4 className="font-semibold mb-2 text-gray-900">Conteúdo</h4>
<p className="text-gray-600">{analysis.feedback.content}</p>
</div>
<div>
<h4 className="font-semibold mb-2 text-gray-900">Linguagem</h4>
<p className="text-gray-600">{analysis.feedback.language}</p>
</div>
</CardContent>
</Card>
{/* Critérios de Avaliação */}
<Card>
<CardHeader>
<CardTitle>Critérios de Avaliação</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div>
<div className="flex justify-between mb-1">
<span>Adequação ao Gênero</span>
<span>{analysis.criteria_scores.adequacy}%</span>
{/* Critérios de Avaliação */}
<Card className="border-gray-200">
<CardHeader className="border-b border-gray-200">
<CardTitle>Critérios de Avaliação</CardTitle>
</CardHeader>
<CardContent className="space-y-4 pt-4">
<div>
<div className="flex justify-between mb-1">
<span className="text-gray-600">Adequação ao Gênero</span>
<span className="font-medium">{analysis.criteria_scores.adequacy}%</span>
</div>
<Progress value={analysis.criteria_scores.adequacy} className="h-2" />
</div>
<Progress value={analysis.criteria_scores.adequacy} />
</div>
<div>
<div className="flex justify-between mb-1">
<span>Coerência</span>
<span>{analysis.criteria_scores.coherence}%</span>
<div>
<div className="flex justify-between mb-1">
<span className="text-gray-600">Coerência</span>
<span className="font-medium">{analysis.criteria_scores.coherence}%</span>
</div>
<Progress value={analysis.criteria_scores.coherence} className="h-2" />
</div>
<Progress value={analysis.criteria_scores.coherence} />
</div>
<div>
<div className="flex justify-between mb-1">
<span>Coesão</span>
<span>{analysis.criteria_scores.cohesion}%</span>
<div>
<div className="flex justify-between mb-1">
<span className="text-gray-600">Coesão</span>
<span className="font-medium">{analysis.criteria_scores.cohesion}%</span>
</div>
<Progress value={analysis.criteria_scores.cohesion} className="h-2" />
</div>
<Progress value={analysis.criteria_scores.cohesion} />
</div>
<div>
<div className="flex justify-between mb-1">
<span>Vocabulário</span>
<span>{analysis.criteria_scores.vocabulary}%</span>
<div>
<div className="flex justify-between mb-1">
<span className="text-gray-600">Vocabulário</span>
<span className="font-medium">{analysis.criteria_scores.vocabulary}%</span>
</div>
<Progress value={analysis.criteria_scores.vocabulary} className="h-2" />
</div>
<Progress value={analysis.criteria_scores.vocabulary} />
</div>
<div>
<div className="flex justify-between mb-1">
<span>Gramática</span>
<span>{analysis.criteria_scores.grammar}%</span>
<div>
<div className="flex justify-between mb-1">
<span className="text-gray-600">Gramática</span>
<span className="font-medium">{analysis.criteria_scores.grammar}%</span>
</div>
<Progress value={analysis.criteria_scores.grammar} className="h-2" />
</div>
<Progress value={analysis.criteria_scores.grammar} />
</div>
</CardContent>
</Card>
</CardContent>
</Card>
{/* Sugestões */}
<Card className="md:col-span-3">
<CardHeader>
<CardTitle>Sugestões para Melhoria</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground whitespace-pre-line">
{analysis.suggestions}
</p>
</CardContent>
</Card>
{/* Sugestões */}
<Card className="md:col-span-3 bg-blue-50 border-blue-100">
<CardHeader>
<CardTitle className="text-blue-600">Sugestões para Melhoria</CardTitle>
</CardHeader>
<CardContent>
<p className="text-gray-600 whitespace-pre-line">
{analysis.suggestions}
</p>
</CardContent>
</Card>
</div>
</div>
</div>
);