Compare commits

...

3 Commits

Author SHA1 Message Date
Lucas Santana
69dbb5fa48 fix: Corrigindo visualização de imagens das histórias
Some checks are pending
Docker Build and Push / build (push) Waiting to run
2025-02-04 15:25:05 -03:00
Lucas Santana
9e3f7a7c31 fix: Ajustando menu lateral do aluno 2025-02-04 10:11:08 -03:00
Lucas Santana
821b6ca9ec fix: Corrigindo responsividade 2025-02-04 10:01:49 -03:00
5 changed files with 81 additions and 35 deletions

View File

@ -181,3 +181,23 @@ e este projeto adere ao [Semantic Versioning](https://semver.org/lang/pt-BR/).
- Implementada validação de idioma antes da geração - Implementada validação de idioma antes da geração
- Atualizado payload da Edge Function para incluir `language_type` - Atualizado payload da Edge Function para incluir `language_type`
- Melhorada tipagem para suporte a múltiplos idiomas - Melhorada tipagem para suporte a múltiplos idiomas
## [1.4.0] - 2024-01-31
### Adicionado
- Integração completa com a tabela `languages` do banco de dados
- Suporte para ícones de bandeira nos seletores de idioma
- Instruções específicas por idioma na interface
- Hook `useLanguages` para gerenciamento centralizado de idiomas
### Modificado
- Removido `LANGUAGE_OPTIONS` hard coded do `StoryGenerator`
- Atualizado `CreateStoryPage` para usar `DEFAULT_LANGUAGE` do type
- Melhorada a validação de idiomas usando dados do banco
- Aprimorada a UX do seletor de idiomas com ícones e instruções
### Técnico
- Refatorado o sistema de idiomas para usar dados dinâmicos do banco
- 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

View File

@ -40,22 +40,6 @@ export function StudentDashboardLayout() {
<nav className="p-4 space-y-1"> <nav className="p-4 space-y-1">
<NavLink <NavLink
to="/aluno" to="/aluno"
end
onClick={handleNavigation}
className={({ isActive }) =>
`flex items-center gap-2 px-4 py-2 rounded-lg text-sm ${
isActive
? 'bg-purple-50 text-purple-700'
: 'text-gray-600 hover:bg-gray-50'
}`
}
>
<LayoutDashboard className="h-5 w-5" />
{!isCollapsed && <span>Início</span>}
</NavLink>
<NavLink
to="/aluno/historias"
onClick={handleNavigation} onClick={handleNavigation}
className={({ isActive }) => className={({ isActive }) =>
`flex items-center gap-2 px-4 py-2 rounded-lg text-sm ${ `flex items-center gap-2 px-4 py-2 rounded-lg text-sm ${
@ -69,6 +53,22 @@ export function StudentDashboardLayout() {
{!isCollapsed && <span>Minhas Histórias</span>} {!isCollapsed && <span>Minhas Histórias</span>}
</NavLink> </NavLink>
<NavLink
to="/aluno/painel"
end
onClick={handleNavigation}
className={({ isActive }) =>
`flex items-center gap-2 px-4 py-2 rounded-lg text-sm ${
isActive
? 'bg-purple-50 text-purple-700'
: 'text-gray-600 hover:bg-gray-50'
}`
}
>
<LayoutDashboard className="h-5 w-5" />
{!isCollapsed && <span>Painel</span>}
</NavLink>
{/* <NavLink {/* <NavLink
to="/aluno/conquistas" to="/aluno/conquistas"
onClick={handleNavigation} onClick={handleNavigation}

View File

@ -14,7 +14,6 @@ interface DashboardMetrics {
export function StudentDashboardPage() { export function StudentDashboardPage() {
const navigate = useNavigate(); const navigate = useNavigate();
const [student, setStudent] = React.useState<Student | null>(null); const [student, setStudent] = React.useState<Student | null>(null);
const [stories, setStories] = React.useState<Story[]>([]);
const [metrics, setMetrics] = React.useState<DashboardMetrics>({ const [metrics, setMetrics] = React.useState<DashboardMetrics>({
totalStories: 0, totalStories: 0,
averageReadingFluency: 0, averageReadingFluency: 0,
@ -54,18 +53,16 @@ export function StudentDashboardPage() {
.limit(6); .limit(6);
if (storiesError) throw storiesError; if (storiesError) throw storiesError;
setStories(storiesData || []);
// Calcular métricas // Calcular métricas (exemplo simplificado)
// Em produção: Implementar cálculos reais baseados nos dados
setMetrics({ setMetrics({
totalStories: storiesData?.length || 0, totalStories: storiesData?.length || 0,
averageReadingFluency: 85, // Exemplo averageReadingFluency: 85,
totalReadingTime: 120, // Exemplo: 120 minutos totalReadingTime: 120,
currentLevel: 3 // Exemplo currentLevel: 3
}); });
// Buscar histórias recentes com a primeira página como capa // Buscar histórias recentes com a capa definida
const { data, error } = await supabase const { data, error } = await supabase
.from('stories') .from('stories')
.select(` .select(`
@ -80,7 +77,26 @@ export function StudentDashboardPage() {
.limit(6); .limit(6);
if (error) throw error; if (error) throw error;
setRecentStories(data || []);
// Transformar os dados para definir a propriedade 'cover' de forma robusta
const mappedData = (data || []).map(story => {
let coverObj = null;
if (story.cover) {
coverObj = Array.isArray(story.cover) ? story.cover[0] : story.cover;
} else if (story.pages && story.pages.length > 0) {
coverObj = story.pages[0];
}
if (coverObj && typeof coverObj === 'object' && coverObj.image_url) {
return { ...story, cover: coverObj };
} else if (coverObj && typeof coverObj === 'string') {
return { ...story, cover: { image_url: coverObj } };
}
return { ...story, cover: null };
});
setRecentStories(mappedData);
} catch (err) { } catch (err) {
console.error('Erro ao carregar dashboard:', err); console.error('Erro ao carregar dashboard:', err);
@ -128,10 +144,10 @@ export function StudentDashboardPage() {
return ( return (
<div> <div>
{/* Cabeçalho */} {/* Cabeçalho */}
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6 mb-8"> <div className="bg-white rounded-xl shadow-sm border border-gray-200 p-4 sm:p-6 mb-8">
<div className="flex justify-between items-start"> <div className="flex flex-col sm:flex-row justify-between items-center sm:items-start gap-4 sm:gap-0">
<div className="flex items-center gap-4"> <div className="flex flex-col sm:flex-row items-center sm:items-center gap-4 text-center sm:text-left">
<div className="w-16 h-16 bg-purple-100 rounded-full flex items-center justify-center"> <div className="w-16 h-16 bg-purple-100 rounded-full flex items-center justify-center flex-shrink-0">
{student?.avatar_url ? ( {student?.avatar_url ? (
<img <img
src={student.avatar_url} src={student.avatar_url}
@ -145,18 +161,18 @@ export function StudentDashboardPage() {
)} )}
</div> </div>
<div> <div>
<h1 className="text-2xl font-bold text-gray-900">{student?.name}</h1> <h1 className="text-xl sm:text-2xl font-bold text-gray-900">{student?.name}</h1>
<p className="text-xs text-gray-500 truncate"> <p className="text-xs text-gray-500 truncate max-w-[250px] sm:max-w-none">
{student?.class?.name} - {student?.class?.grade} {student?.school?.name} {student?.class?.name} - {student?.class?.grade} {student?.school?.name}
</p> </p>
</div> </div>
</div> </div>
<button <button
onClick={() => navigate('/aluno/historias/nova')} onClick={() => navigate('/aluno/historias/nova')}
className="flex items-center gap-2 px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition" className="w-full sm:w-auto flex items-center justify-center gap-2 px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition"
> >
<Plus className="h-5 w-5" /> <Plus className="h-5 w-5" />
Nova História <span>Nova História</span>
</button> </button>
</div> </div>
</div> </div>

View File

@ -42,7 +42,7 @@ export function StudentStoriesPage() {
if (error) throw error; if (error) throw error;
// Aplicar ordenação // Aplicar ordenação
const sortedData = (data || []).sort((a, b) => { let sortedData = (data || []).sort((a, b) => {
switch (sortBy) { switch (sortBy) {
case 'oldest': case 'oldest':
return new Date(a.created_at).getTime() - new Date(b.created_at).getTime(); return new Date(a.created_at).getTime() - new Date(b.created_at).getTime();
@ -55,6 +55,12 @@ export function StudentStoriesPage() {
} }
}); });
// Adicionar a propriedade 'cover', usando a imagem da primeira página
sortedData = sortedData.map(story => ({
...story,
cover: story.pages && story.pages.length > 0 ? story.pages[0] : null
}));
setStories(sortedData); setStories(sortedData);
} catch (err) { } catch (err) {
console.error('Erro ao buscar histórias:', err); console.error('Erro ao buscar histórias:', err);

View File

@ -177,7 +177,7 @@ export const router = createBrowserRouter([
children: [ children: [
{ {
index: true, index: true,
element: <StudentDashboardPage />, element: <StudentStoriesPage />,
}, },
{ {
path: 'historias', path: 'historias',
@ -200,6 +200,10 @@ export const router = createBrowserRouter([
path: 'configuracoes', path: 'configuracoes',
element: <StudentSettingsPage />, element: <StudentSettingsPage />,
}, },
{
path: 'painel',
element: <StudentDashboardPage />,
},
{ {
path: 'conquistas', path: 'conquistas',
element: <AchievementsPage />, element: <AchievementsPage />,