From 7e93a5960952566e454b8d2f4faf8fbc88a9b4fc Mon Sep 17 00:00:00 2001 From: Lucas Santana Date: Tue, 4 Feb 2025 16:04:57 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20aprimora=20m=C3=A9tricas=20do=20dashboa?= =?UTF-8?q?rd=20do=20aluno=20-=20Calcula=20m=C3=A9tricas=20usando=20todas?= =?UTF-8?q?=20as=20hist=C3=B3rias=20e=20grava=C3=A7=C3=B5es=20-=20Adiciona?= =?UTF-8?q?=20novas=20m=C3=A9tricas=20detalhadas=20-=20Implementa=20toolti?= =?UTF-8?q?ps=20explicativos=20-=20Separa=20consultas=20de=20m=C3=A9tricas?= =?UTF-8?q?=20e=20exibi=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 15 ++ .../StudentDashboardPage.tsx | 214 +++++++++++++++++- 2 files changed, 217 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc931a8..79c8442 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -201,3 +201,18 @@ e este projeto adere ao [Semantic Versioning](https://semver.org/lang/pt-BR/). - Adicionada tipagem forte para dados de idioma - Implementada validação robusta de códigos de idioma - Melhorada a estrutura de componentes para suportar dados dinâmicos + +## [1.5.0] - 2024-03-19 + +### Modificado +- Aprimoramento no cálculo de métricas do dashboard do aluno: + - Métricas agora são calculadas considerando todas as histórias e gravações do aluno + - Adicionadas novas métricas detalhadas: pronúncia, precisão, compreensão, velocidade, pausas e erros + - Melhorias na interface com tooltips explicativos para cada métrica + - Separação entre dados para métricas (todas as histórias) e exibição (6 mais recentes) + +### Técnico +- Refatoração da busca de dados no StudentDashboardPage: + - Separação entre consulta de métricas e consulta de exibição + - Otimização no cálculo de médias das métricas + - Melhoria na organização do código com comentários explicativos diff --git a/src/pages/student-dashboard/StudentDashboardPage.tsx b/src/pages/student-dashboard/StudentDashboardPage.tsx index 0a09d0b..65a84fe 100644 --- a/src/pages/student-dashboard/StudentDashboardPage.tsx +++ b/src/pages/student-dashboard/StudentDashboardPage.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Plus, BookOpen, Clock, TrendingUp, Award } from 'lucide-react'; +import { Plus, BookOpen, Clock, TrendingUp, Award, Mic, Target, Brain, Gauge, Pause, XCircle, HelpCircle } from 'lucide-react'; import { useNavigate } from 'react-router-dom'; import { supabase } from '../../lib/supabase'; import type { Story, Student } from '../../types/database'; @@ -9,6 +9,12 @@ interface DashboardMetrics { averageReadingFluency: number; totalReadingTime: number; currentLevel: number; + averagePronunciation: number; + averageAccuracy: number; + averageComprehension: number; + averageWordsPerMinute: number; + averagePauses: number; + averageErrors: number; } export function StudentDashboardPage() { @@ -18,7 +24,13 @@ export function StudentDashboardPage() { totalStories: 0, averageReadingFluency: 0, totalReadingTime: 0, - currentLevel: 1 + currentLevel: 1, + averagePronunciation: 0, + averageAccuracy: 0, + averageComprehension: 0, + averageWordsPerMinute: 0, + averagePauses: 0, + averageErrors: 0 }); const [loading, setLoading] = React.useState(true); const [error, setError] = React.useState(null); @@ -44,8 +56,16 @@ export function StudentDashboardPage() { if (studentError) throw studentError; setStudent(studentData); - // Buscar histórias do aluno - const { data: storiesData, error: storiesError } = await supabase + // Buscar todas as histórias do aluno para cálculo de métricas + const { data: allStoriesData, error: allStoriesError } = await supabase + .from('stories') + .select('id') + .eq('student_id', session.user.id); + + if (allStoriesError) throw allStoriesError; + + // Buscar histórias recentes para exibição + const { data: recentStoriesData, error: storiesError } = await supabase .from('stories') .select('*') .eq('student_id', session.user.id) @@ -54,15 +74,52 @@ export function StudentDashboardPage() { if (storiesError) throw storiesError; - // Calcular métricas (exemplo simplificado) - setMetrics({ - totalStories: storiesData?.length || 0, - averageReadingFluency: 85, - totalReadingTime: 120, - currentLevel: 3 - }); + // Buscar todas as gravações completadas do aluno + const { data: recordings, error: recordingsError } = await supabase + .from('story_recordings') + .select('*') + .eq('status', 'completed') + .in('story_id', allStoriesData.map(story => story.id)); - // Buscar histórias recentes com a capa definida + if (recordingsError) throw recordingsError; + + // Calcular métricas baseadas nas gravações + if (recordings && recordings.length > 0) { + const totalRecordings = recordings.length; + const metricsSum = recordings.reduce((acc, recording) => ({ + fluency: acc.fluency + recording.fluency_score, + pronunciation: acc.pronunciation + recording.pronunciation_score, + accuracy: acc.accuracy + recording.accuracy_score, + comprehension: acc.comprehension + recording.comprehension_score, + wordsPerMinute: acc.wordsPerMinute + recording.words_per_minute, + pauses: acc.pauses + recording.pause_count, + errors: acc.errors + recording.error_count + }), { + fluency: 0, + pronunciation: 0, + accuracy: 0, + comprehension: 0, + wordsPerMinute: 0, + pauses: 0, + errors: 0 + }); + + // Calcular médias + setMetrics({ + totalStories: allStoriesData.length, // Usando o total de histórias + averageReadingFluency: Math.round(metricsSum.fluency / totalRecordings), + totalReadingTime: recordings.length * 2, // Exemplo: 2 minutos por gravação + currentLevel: Math.ceil(metricsSum.fluency / (totalRecordings * 20)), // Exemplo: nível baseado na fluência + averagePronunciation: Math.round(metricsSum.pronunciation / totalRecordings), + averageAccuracy: Math.round(metricsSum.accuracy / totalRecordings), + averageComprehension: Math.round(metricsSum.comprehension / totalRecordings), + averageWordsPerMinute: Math.round(metricsSum.wordsPerMinute / totalRecordings), + averagePauses: Math.round(metricsSum.pauses / totalRecordings), + averageErrors: Math.round(metricsSum.errors / totalRecordings) + }); + } + + // Buscar histórias recentes com a capa definida (mantendo o limite de 6 para exibição) const { data, error } = await supabase .from('stories') .select(` @@ -228,6 +285,139 @@ export function StudentDashboardPage() { + {/* Métricas de Leitura */} +
+
+

Métricas Detalhadas de Leitura

+
+
+
+
+
+
+
+ +
+
+
+

Pronúncia Média

+
+ +
+
+

{metrics.averagePronunciation}%

+
+
+
+ +
+
+
+ +
+
+
+

Precisão na Leitura

+
+ +
+
+

{metrics.averageAccuracy}%

+
+
+
+ +
+
+
+ +
+
+
+

Compreensão do Texto

+
+ +
+
+

{metrics.averageComprehension}%

+
+
+
+ +
+
+
+ +
+
+
+

Velocidade de Leitura

+
+ +
+
+

{metrics.averageWordsPerMinute} WPM

+
+
+
+ +
+
+
+ +
+
+
+

Pausas na Leitura

+
+ +
+
+

{metrics.averagePauses}

+
+
+
+ +
+
+
+ +
+
+
+

Erros de Leitura

+
+ +
+
+

{metrics.averageErrors}

+
+
+
+
+
+ {/* Histórias Recentes */}