mirror of
https://github.com/lucasrcsantana/story-generator.git
synced 2025-12-16 21:37:51 +00:00
refactor: Refatorando estilo da Essay Analysis
This commit is contained in:
parent
ccbac66d28
commit
8b45fe72e7
@ -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>
|
||||
|
||||
@ -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>
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user