mirror of
https://github.com/lucasrcsantana/story-generator.git
synced 2025-12-17 05:47:52 +00:00
feat: adiciona página de conquistas do aluno
- Cria componente AchievementsPage para exibir conquistas do aluno - Implementa componentes Card e Badge para UI - Adiciona mock inicial de conquistas para demonstração - Corrige caminhos de importação relativos
This commit is contained in:
parent
5573274ad4
commit
f70585e9c1
41
src/components/student/StudentDashboardNavbar.tsx
Normal file
41
src/components/student/StudentDashboardNavbar.tsx
Normal file
@ -0,0 +1,41 @@
|
||||
import React from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
|
||||
export function StudentDashboardNavbar() {
|
||||
const location = useLocation();
|
||||
|
||||
return (
|
||||
<nav className="bg-white border-b border-gray-200">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="flex items-center justify-between h-16">
|
||||
<div className="flex items-center gap-8">
|
||||
<Link
|
||||
to="/aluno"
|
||||
className={`text-gray-900 hover:text-purple-600 ${
|
||||
location.pathname === '/aluno' ? 'text-purple-600' : ''
|
||||
}`}
|
||||
>
|
||||
Dashboard
|
||||
</Link>
|
||||
<Link
|
||||
to="/aluno/historias"
|
||||
className={`text-gray-900 hover:text-purple-600 ${
|
||||
location.pathname.includes('/aluno/historias') ? 'text-purple-600' : ''
|
||||
}`}
|
||||
>
|
||||
Histórias
|
||||
</Link>
|
||||
<Link
|
||||
to="/aluno/configuracoes"
|
||||
className={`text-gray-900 hover:text-purple-600 ${
|
||||
location.pathname === '/aluno/configuracoes' ? 'text-purple-600' : ''
|
||||
}`}
|
||||
>
|
||||
Configurações
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
34
src/components/ui/badge.tsx
Normal file
34
src/components/ui/badge.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import React from 'react';
|
||||
|
||||
interface BadgeProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
variant?: 'default' | 'success' | 'warning' | 'error' | 'secondary';
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const variantStyles = {
|
||||
default: 'bg-primary text-primary-foreground',
|
||||
success: 'bg-green-100 text-green-800',
|
||||
warning: 'bg-yellow-100 text-yellow-800',
|
||||
error: 'bg-red-100 text-red-800',
|
||||
secondary: 'bg-gray-100 text-gray-800'
|
||||
};
|
||||
|
||||
export function Badge({
|
||||
variant = 'default',
|
||||
className = '',
|
||||
children,
|
||||
...props
|
||||
}: BadgeProps): JSX.Element {
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium
|
||||
${variantStyles[variant]}
|
||||
${className}
|
||||
`}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
16
src/components/ui/card.tsx
Normal file
16
src/components/ui/card.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
|
||||
interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function Card({ className = '', children, ...props }: CardProps): JSX.Element {
|
||||
return (
|
||||
<div
|
||||
className={`bg-white rounded-lg shadow-sm border border-gray-200 ${className}`}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
14
src/layouts/student/StudentDashboardLayout.tsx
Normal file
14
src/layouts/student/StudentDashboardLayout.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import { StudentDashboardNavbar } from '@/components/student/StudentDashboardNavbar';
|
||||
import React from 'react';
|
||||
|
||||
export function StudentDashboardLayout() {
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50">
|
||||
<StudentDashboardNavbar />
|
||||
<main className="container mx-auto px-4 py-8">
|
||||
<Outlet />
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
86
src/pages/student-dashboard/AchievementsPage.tsx
Normal file
86
src/pages/student-dashboard/AchievementsPage.tsx
Normal file
@ -0,0 +1,86 @@
|
||||
import React from 'react';
|
||||
import { Card } from '../../components/ui/card';
|
||||
import { Badge } from '../../components/ui/badge';
|
||||
|
||||
interface Achievement {
|
||||
id: string;
|
||||
titulo: string;
|
||||
descricao: string;
|
||||
icone: string;
|
||||
conquistado: boolean;
|
||||
dataConquista?: string;
|
||||
progresso?: number;
|
||||
}
|
||||
|
||||
const conquistas: Achievement[] = [
|
||||
{
|
||||
id: '1',
|
||||
titulo: 'Primeira História',
|
||||
descricao: 'Completou sua primeira história',
|
||||
icone: '📚',
|
||||
conquistado: true,
|
||||
dataConquista: '2024-03-15',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
titulo: 'Leitor Dedicado',
|
||||
descricao: 'Leu histórias por 5 dias seguidos',
|
||||
icone: '🌟',
|
||||
conquistado: false,
|
||||
progresso: 3,
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
titulo: 'Explorador de Mundos',
|
||||
descricao: 'Leu histórias de 5 categorias diferentes',
|
||||
icone: '🌍',
|
||||
conquistado: false,
|
||||
progresso: 2,
|
||||
},
|
||||
];
|
||||
|
||||
export function AchievementsPage(): JSX.Element {
|
||||
return (
|
||||
<div className="container mx-auto p-6">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-3xl font-bold text-primary mb-2">Minhas Conquistas</h1>
|
||||
<p className="text-gray-600">
|
||||
Continue lendo e completando atividades para desbloquear mais conquistas!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{conquistas.map((conquista) => (
|
||||
<Card key={conquista.id} className={`p-6 ${!conquista.conquistado ? 'opacity-75' : ''}`}>
|
||||
<div className="flex items-start justify-between mb-4">
|
||||
<span className="text-4xl">{conquista.icone}</span>
|
||||
{conquista.conquistado ? (
|
||||
<Badge variant="success">Conquistado!</Badge>
|
||||
) : (
|
||||
<Badge variant="secondary">Em progresso</Badge>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<h3 className="text-xl font-semibold mb-2">{conquista.titulo}</h3>
|
||||
<p className="text-gray-600 mb-4">{conquista.descricao}</p>
|
||||
|
||||
{conquista.progresso !== undefined && (
|
||||
<div className="w-full bg-gray-200 rounded-full h-2.5">
|
||||
<div
|
||||
className="bg-primary h-2.5 rounded-full transition-all"
|
||||
style={{ width: `${(conquista.progresso / 5) * 100}%` }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{conquista.dataConquista && (
|
||||
<p className="text-sm text-gray-500 mt-4">
|
||||
Conquistado em: {new Date(conquista.dataConquista).toLocaleDateString('pt-BR')}
|
||||
</p>
|
||||
)}
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -17,10 +17,13 @@ import { SettingsPage } from './pages/dashboard/settings/SettingsPage';
|
||||
import { StudentDashboardPage } from './pages/student-dashboard/StudentDashboardPage';
|
||||
import { StudentDashboardLayout } from './pages/student-dashboard/StudentDashboardLayout';
|
||||
import { StudentStoriesPage } from './pages/student-dashboard/StudentStoriesPage';
|
||||
import { StudentSettingsPage } from './pages/student-dashboard/StudentSettingsPage';
|
||||
import { CreateStoryPage } from './pages/student-dashboard/CreateStoryPage';
|
||||
import { StoryPage } from './pages/student-dashboard/StoryPage';
|
||||
import { ProtectedRoute } from './components/auth/ProtectedRoute';
|
||||
import { UserManagementPage } from './pages/admin/UserManagementPage';
|
||||
import { AchievementsPage } from './pages/student-dashboard/AchievementsPage';
|
||||
import { StudentClassPage } from './pages/student-dashboard/StudentClassPage';
|
||||
|
||||
export const router = createBrowserRouter([
|
||||
{
|
||||
@ -155,6 +158,18 @@ export const router = createBrowserRouter([
|
||||
element: <StoryPage />,
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'configuracoes',
|
||||
element: <StudentSettingsPage />,
|
||||
},
|
||||
{
|
||||
path: 'conquistas',
|
||||
element: <AchievementsPage />,
|
||||
},
|
||||
{
|
||||
path: 'turmas/:classId',
|
||||
element: <StudentClassPage />,
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@ -19,6 +19,7 @@ import { StoryPage } from '../pages/story/StoryPage';
|
||||
import { StudentSettingsPage } from '../pages/student-dashboard/StudentSettingsPage';
|
||||
import { StudentDashboardLayout } from '../pages/student-dashboard/StudentDashboardLayout';
|
||||
import { StudentDashboard, StudentClassPage } from '../pages/student-dashboard';
|
||||
import { AchievementsPage } from '../pages/student-dashboard/AchievementsPage';
|
||||
import React from 'react';
|
||||
|
||||
export const router = createBrowserRouter([
|
||||
@ -35,7 +36,7 @@ export const router = createBrowserRouter([
|
||||
element: <StoryPage demo={true} />
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
path: 'login',
|
||||
children: [
|
||||
{
|
||||
path: 'school',
|
||||
@ -52,7 +53,7 @@ export const router = createBrowserRouter([
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/register',
|
||||
path: 'register',
|
||||
children: [
|
||||
{
|
||||
path: 'school',
|
||||
@ -70,7 +71,7 @@ export const router = createBrowserRouter([
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/dashboard',
|
||||
path: 'dashboard',
|
||||
element: <DashboardLayout />,
|
||||
children: [
|
||||
{
|
||||
@ -119,17 +120,15 @@ export const router = createBrowserRouter([
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/auth/callback',
|
||||
path: 'auth/callback',
|
||||
element: <AuthCallback />
|
||||
},
|
||||
{
|
||||
path: '/story/:storyId',
|
||||
path: 'story/:storyId',
|
||||
element: <StoryPage />
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/aluno',
|
||||
path: 'aluno',
|
||||
element: <StudentDashboardLayout />,
|
||||
children: [
|
||||
{
|
||||
@ -138,12 +137,22 @@ export const router = createBrowserRouter([
|
||||
},
|
||||
{
|
||||
path: 'configuracoes',
|
||||
element: <StudentSettingsPage />
|
||||
element: <StudentSettingsPage />,
|
||||
},
|
||||
{
|
||||
path: 'conquistas',
|
||||
element: <AchievementsPage />,
|
||||
},
|
||||
{
|
||||
path: 'historias/:id',
|
||||
element: <StoryPage />,
|
||||
},
|
||||
{
|
||||
path: 'turmas/:classId',
|
||||
element: <StudentClassPage />
|
||||
element: <StudentClassPage />,
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
}
|
||||
]);
|
||||
Loading…
Reference in New Issue
Block a user