Compare commits

...

6 Commits

Author SHA1 Message Date
Lucas Santana
13536790fe fix: Ajustando páigna de leitura
Some checks failed
Docker Build and Push / build (push) Has been cancelled
2025-01-29 14:37:18 -03:00
Lucas Santana
9f7ea648fe fix: Ajustando visualização da página de leitura de história 2025-01-29 14:22:35 -03:00
Lucas Santana
e81dc5bedf fix: Ajustando visualização da página de leitura de história 2025-01-29 14:18:16 -03:00
Lucas Santana
4790d9788b fix: Ajustando páigna de leitura 2025-01-29 14:15:59 -03:00
Lucas Santana
d949587c44 fix: Ajustando visualização da história 2025-01-29 11:34:43 -03:00
Lucas Santana
bc2f120700 docs: Adicionando documentação no projeto 2025-01-27 17:44:00 -03:00
5 changed files with 737 additions and 54 deletions

248
docs/arquitetura.md Normal file
View File

@ -0,0 +1,248 @@
# Arquitetura do Sistema
## Visão Geral
A plataforma é construída usando uma arquitetura moderna e escalável, focada em proporcionar uma experiência educacional interativa e segura para crianças.
## Stack Tecnológica
### Frontend
- Next.js 14 (App Router)
- TypeScript
- Tailwind CSS
- Framer Motion
- React Query
### Backend
- Node.js
- Supabase
- Redis Upstash (cache)
- Supabase Storage (mídia)
## Estrutura de Diretórios
```
src/
├── app/ # Rotas e páginas
├── components/ # Componentes React
│ ├── ui/ # Componentes base
│ ├── forms/ # Formulários
│ └── exercises/ # Componentes de exercícios
├── features/ # Features do sistema
├── layouts/ # Layouts do sistema
├── constants/ # Constantes do sistema
├── lib/ # Utilitários e configurações
├── hooks/ # Hooks personalizados
├── services/ # Serviços externos
└── types/ # Definições de tipos
```
## Componentes Principais
### 1. Sistema de Autenticação
```typescript
interface AuthConfig {
providers: {
google: boolean;
email: boolean;
};
session: {
maxAge: number;
updateAge: number;
};
security: {
jwtSecret: string;
cookiePrefix: string;
};
}
```
### 2. Gerenciamento de Estado
```typescript
interface AppState {
user: UserState;
exercises: ExerciseState;
progress: ProgressState;
settings: SettingsState;
}
```
## Segurança
### 1. Autenticação
- JWT tokens
- Refresh tokens
- Sessões seguras
- Rate limiting
### 2. Dados
- Criptografia em trânsito
- Backup automático
- Sanitização de inputs
- Logs de auditoria
## Performance
### 1. Otimizações
- Lazy loading
- Code splitting
- Caching estratégico
- Compressão de assets
### 2. Monitoramento
- Métricas de tempo real
- Alertas automáticos
- Análise de performance
- Debug em produção
## Integração Contínua
### 1. Pipeline
```yaml
steps:
- name: Lint
run: yarn lint
- name: Type Check
run: yarn tsc
- name: Test
run: yarn test
- name: Build
run: yarn build
- name: Deploy
if: branch = main
run: yarn deploy
```
### 2. Qualidade de Código
- ESLint
- Prettier
- Jest
- Cypress
## Escalabilidade
### 1. Infraestrutura
- Containers Docker
- Load balancing
- Auto-scaling
- CDN global
### 2. Database
- Sharding
- Replicação
- Índices otimizados
- Migrations automáticas
## APIs e Integrações
### 1. REST APIs
```typescript
interface APIEndpoints {
auth: {
login: string;
register: string;
refresh: string;
};
exercises: {
list: string;
submit: string;
progress: string;
};
content: {
stories: string;
media: string;
exercises: string;
};
}
```
### 2. WebSockets
- Chat em tempo real
- Notificações
- Multiplayer
- Status online
## Acessibilidade e SEO
### 1. Acessibilidade
- WCAG 2.1
- ARIA labels
- Keyboard navigation
- Screen readers
### 2. SEO
- Meta tags
- Sitemap
- Robots.txt
- Schema.org
## Ambiente de Desenvolvimento
### 1. Setup
```bash
# Instalação
yarn install
# Desenvolvimento
yarn dev
# Testes
yarn test
# Build
yarn build
```
### 2. Ferramentas
- VSCode
- Docker
- Postman
- Git
## Monitoramento e Logs
### 1. Métricas
```typescript
interface SystemMetrics {
performance: {
responseTime: number;
errorRate: number;
userCount: number;
};
resources: {
cpuUsage: number;
memoryUsage: number;
diskSpace: number;
};
}
```
### 2. Logs
- Error tracking
- User actions
- Performance
- Security events
## Próximos Passos
1. **Microserviços**
- Auth service
- Content service
- Analytics service
- Notification service
2. **Machine Learning**
- Recomendações
- Análise de progresso
- Detecção de padrões
- Personalização
3. **Mobile**
- PWA
- App nativo
- Offline mode
- Push notifications

246
docs/desenvolvimento.md Normal file
View File

@ -0,0 +1,246 @@
# Fluxo de Desenvolvimento
## Padrões de Código
### 1. Nomenclatura
- Diretórios em kebab-case: `components/form-wizard`
- Componentes em PascalCase: `StoryCard.tsx`
- Utilitários em camelCase: `formatText.ts`
- Variáveis em camelCase: `userScore`
### 2. TypeScript
- Preferir interfaces sobre types
- Usar const com asserção `as const`
- Retornos explícitos em funções
- Imports relativos
## Estrutura de Commits
### 1. Prefixos
- `fix:` Correções de bugs
- `feat:` Novos recursos
- `perf:` Melhorias de performance
- `docs:` Documentação
- `style:` Formatação
- `refactor:` Refatoração
- `test:` Testes
- `chore:` Manutenção
### 2. Formato
```
<tipo>: <descrição>
[corpo]
[rodapé]
```
## Fluxo de Branches
### 1. Principais
- `main`: Produção
- `develop`: Desenvolvimento
- `staging`: Homologação
### 2. Features
```bash
# Nova feature
git checkout -b feature/nome-da-feature
# Commit das mudanças
git commit -m "feat: adiciona novo componente"
# Push para remote
git push origin feature/nome-da-feature
```
## Code Review
### 1. Checklist
- Código limpo e legível
- Testes adequados
- Documentação atualizada
- Performance otimizada
- Segurança verificada
### 2. Pull Request
```markdown
## Descrição
Breve descrição das mudanças
## Mudanças
- [ ] Item 1
- [ ] Item 2
## Screenshots
[Se aplicável]
## Testes
- [ ] Unitários
- [ ] Integração
- [ ] E2E
```
## Testes
### 1. Unitários
```typescript
describe('StoryComponent', () => {
it('deve renderizar corretamente', () => {
const { getByText } = render(<Story />);
expect(getByText('Título')).toBeInTheDocument();
});
});
```
### 2. Integração
```typescript
describe('ExerciseFlow', () => {
it('deve completar exercício', async () => {
const result = await completeExercise({
type: 'word-formation',
answer: 'casa'
});
expect(result.success).toBe(true);
});
});
```
## Documentação
### 1. Código
```typescript
/**
* Componente de exercício de formação de palavras
* @param {WordFormationProps} props - Propriedades do componente
* @returns {JSX.Element} Componente renderizado
*/
export const WordFormation: React.FC<WordFormationProps> = ({
word,
syllables,
onComplete
}) => {
// ...
};
```
### 2. README
- Setup do projeto
- Comandos disponíveis
- Estrutura de arquivos
- Contribuição
- Licença
## Segurança
### 1. Checklist
- Validação de inputs
- Sanitização de dados
- Proteção contra XSS
- Autenticação segura
### 2. Revisão
```typescript
// ❌ Inseguro
const query = `SELECT * FROM users WHERE id = ${id}`;
// ✅ Seguro
const query = 'SELECT * FROM users WHERE id = $1';
const values = [id];
```
## Performance
### 1. Frontend
- Lazy loading
- Memoização
- Bundle splitting
- Image optimization
### 2. Backend
- Caching
- Query optimization
- Connection pooling
- Rate limiting
## Deploy
### 1. Staging
```bash
# Build
yarn build
# Testes
yarn test
# Deploy staging
yarn deploy:staging
```
### 2. Produção
```bash
# Merge para main
git checkout main
git merge develop
# Deploy produção
yarn deploy:prod
```
## Monitoramento
### 1. Métricas
- Tempo de resposta
- Taxa de erro
- Uso de recursos
- Satisfação do usuário
### 2. Logs
```typescript
logger.info('Exercício completado', {
userId: user.id,
exerciseId: exercise.id,
score: result.score,
timeSpent: result.time
});
```
## Manutenção
### 1. Dependências
```bash
# Atualizar deps
yarn upgrade-interactive --latest
# Auditar segurança
yarn audit
# Limpar cache
yarn cache clean
```
### 2. Backup
- Database dumps
- Logs históricos
- Configurações
- Assets
## Contribuição
### 1. Setup
```bash
# Clone
git clone https://github.com/org/repo.git
# Install
yarn install
# Dev
yarn dev
```
### 2. Guidelines
- Código limpo
- Testes completos
- Documentação clara
- Pull requests concisos

177
docs/exercicios.md Normal file
View File

@ -0,0 +1,177 @@
# Sistema de Exercícios
## Visão Geral
O sistema de exercícios oferece diferentes tipos de atividades para reforçar o aprendizado da leitura e compreensão textual.
## Tipos de Exercícios
### 1. Formação de Palavras
```typescript
interface WordFormationExercise {
word: string;
syllables: string[];
hints?: string[];
difficulty: 'easy' | 'medium' | 'hard';
}
```
### 2. Completar Sentenças
```typescript
interface SentenceCompletionExercise {
sentence: string;
options: string[];
correctAnswer: string;
context: string;
}
```
### 3. Prática de Pronúncia
```typescript
interface PronunciationExercise {
word: string;
phonemes: string[];
audioUrl?: string;
examples: string[];
}
```
## Fluxo de Exercícios
### 1. Seleção
- Baseada no nível do aluno
- Progressão gradual
- Adaptação por desempenho
- Variedade de tipos
### 2. Execução
- Instruções claras
- Feedback imediato
- Dicas contextuais
- Suporte visual
### 3. Avaliação
- Pontuação automática
- Feedback detalhado
- Sugestões de melhoria
- Registro de progresso
## Componentes Principais
### 1. ExercisePlayer
- Controle de fluxo
- Timer integrado
- Sistema de pontuação
- Feedback visual
### 2. ExerciseFactory
- Criação dinâmica
- Validação de respostas
- Adaptação de dificuldade
- Geração de feedback
## Integração com Banco de Dados
### 1. Tabelas Relacionadas
```sql
-- Exercícios
create table exercises (
id uuid primary key,
type text,
difficulty text,
content jsonb,
created_at timestamptz
);
-- Progresso
create table exercise_progress (
student_id uuid,
exercise_id uuid,
score numeric,
completed_at timestamptz
);
```
### 2. Métricas Armazenadas
- Tempo de conclusão
- Taxa de acerto
- Tentativas realizadas
- Padrões de erro
## Acessibilidade
### 1. Visual
- Alto contraste
- Fontes ajustáveis
- Ícones intuitivos
- Animações suaves
### 2. Auditiva
- Instruções em áudio
- Feedback sonoro
- Controle de volume
- Legendas
### 3. Motora
- Controles simplificados
- Atalhos de teclado
- Tempo ajustável
- Pausas automáticas
## Gamificação
### 1. Sistema de Pontos
- Pontuação base
- Bônus por velocidade
- Combos de acertos
- Conquistas especiais
### 2. Progressão
- Níveis de dificuldade
- Desbloqueio gradual
- Medalhas e troféus
- Rankings opcionais
### 3. Recompensas
- Novos conteúdos
- Personalização
- Badges especiais
- Poder de escolha
## Monitoramento
### 1. Métricas Coletadas
```typescript
interface ExerciseMetrics {
timeSpent: number;
correctAnswers: number;
totalAttempts: number;
hintsUsed: number;
score: number;
}
```
### 2. Análise de Desempenho
- Padrões de erro
- Tempo de resposta
- Uso de dicas
- Evolução temporal
## Próximas Melhorias
1. **Novos Tipos**
- Exercícios de ritmo
- Compreensão auditiva
- Produção textual
- Jogos educativos
2. **Personalização**
- Temas customizados
- Níveis adaptativos
- Conteúdo dinâmico
- Preferências salvas
3. **Interatividade**
- Multiplayer
- Desafios em grupo
- Compartilhamento
- Competições

View File

@ -85,9 +85,9 @@ export function ExerciseSuggestions({ storyId, storyText, readingMetrics }: Exer
return (
<div className="mt-8">
<h3 className="text-xl font-bold text-gray-900 mb-4">
<h2 className="text-2xl font-bold text-gray-900 mb-4 ">
Exercícios Sugeridos
</h3>
</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{generateExercises().map((exercise) => (
<button

View File

@ -394,7 +394,7 @@ export function StoryPage() {
const { session } = useSession();
const { isUpperCase, toggleUppercase, isLoading } = useUppercasePreference(session?.user?.id);
const { isHighlighted: isSyllablesEnabled, toggleHighlight: toggleSyllables } = useSyllables();
const [fontSize, setFontSize] = useState(18);
const [fontSize, setFontSize] = useState(24);
const [readingSpeed, setReadingSpeed] = useState(60); // 60 palavras por minuto
const [letterSpacing, setLetterSpacing] = useState(0);
const [wordSpacing, setWordSpacing] = useState(0);
@ -854,64 +854,74 @@ export function StoryPage() {
<h1 className="text-2xl font-bold text-gray-900">{story?.title}</h1>
</div>
{/* 3. Texto da História */}
<div className="border-b border-gray-200 pb-6">
<div
className="prose max-w-none overflow-hidden"
style={{
fontSize: `${fontSize}px`,
letterSpacing: `${letterSpacing}px`,
wordSpacing: `${wordSpacing}px`,
lineHeight: lineHeight
}}
>
{renderHighlightedText(story?.content?.pages?.[currentPage]?.text || '')}
{/* Container responsivo */}
<div className="grid grid-cols-1 md:grid-cols-10 gap-6 border-b border-gray-200 pb-6">
{/* 3. Texto da História - Coluna que expande quando não há imagem */}
<div className={cn(
"col-span-1",
focusMode.isActive ? "md:col-span-10" : "md:col-span-4"
)}>
<div
className="prose max-w-none overflow-hidden"
style={{
fontSize: `${fontSize}px`,
letterSpacing: `${letterSpacing}px`,
wordSpacing: `${wordSpacing}px`,
lineHeight: lineHeight
}}
>
{renderHighlightedText(story?.content?.pages?.[currentPage]?.text || '')}
</div>
</div>
{/* 5. Imagem da História - Coluna Direita (60% em desktop) */}
{!focusMode.isActive && (
<div className="col-span-1 md:col-span-6">
{story?.content?.pages?.[currentPage]?.image ? (
<ImageWithLoading
src={story.content.pages[currentPage].image}
alt={`Ilustração da página ${currentPage + 1}`}
className="w-full rounded-lg"
/>
) : (
<div className="aspect-video bg-gray-100 rounded-lg flex items-center justify-center">
<p className="text-gray-500">Sem imagem para esta página</p>
</div>
)}
</div>
)}
</div>
{/* 4. Controles de Navegação */}
<div className="border-b border-gray-200 pb-6">
<div className="flex justify-between items-center">
<div className="flex flex-col sm:flex-row justify-between items-center gap-4 sm:gap-2">
<button
onClick={() => setCurrentPage(prev => prev - 1)}
disabled={currentPage === 0}
className="flex items-center gap-2 px-4 py-2 text-gray-600 hover:text-gray-900 disabled:opacity-50 disabled:cursor-not-allowed"
className="w-full sm:w-auto flex items-center justify-center gap-2 px-4 py-2 text-purple-600 border border-purple-600 rounded-md hover:bg-purple-50 disabled:opacity-50 disabled:cursor-not-allowed"
>
<ArrowLeft className="h-5 w-5" />
Página Anterior
<span className="hidden sm:inline">Página Anterior</span>
<span className="sm:hidden">Anterior</span>
</button>
<span className="text-sm text-gray-500">
<span className="text-sm text-gray-500 order-first sm:order-none">
Página {currentPage + 1} de {story?.content?.pages?.length}
</span>
<button
onClick={() => setCurrentPage(prev => prev + 1)}
disabled={currentPage === (story?.content?.pages?.length ?? 0) - 1}
className="flex items-center gap-2 px-4 py-2 text-gray-600 hover:text-gray-900 disabled:opacity-50 disabled:cursor-not-allowed"
className="w-full sm:w-auto flex items-center justify-center gap-2 px-4 py-2 bg-purple-600 text-white rounded-md hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed"
>
Próxima Página
<span className="hidden sm:inline">Próxima Página</span>
<span className="sm:hidden">Próxima</span>
<ArrowRight className="h-5 w-5" />
</button>
</div>
</div>
{/* 5. Imagem da História - Agora com controle de visibilidade */}
{!focusMode.isActive && (
<div className="border-b border-gray-200 pb-6">
{story?.content?.pages?.[currentPage]?.image ? (
<ImageWithLoading
src={story.content.pages[currentPage].image}
alt={`Ilustração da página ${currentPage + 1}`}
className="w-full rounded-lg"
/>
) : (
<div className="aspect-video bg-gray-100 rounded-lg flex items-center justify-center">
<p className="text-gray-500">Sem imagem para esta página</p>
</div>
)}
</div>
)}
{/* 6. Controle de Gravação */}
{/*
@ -923,7 +933,24 @@ export function StoryPage() {
</div>
</div>
*/}
</div>
{/* Depois do StoryMetrics */}
{recordings.length > 0 && (
<ExerciseSuggestions
storyId={story.id}
storyText={story.content.pages[currentPage].text}
readingMetrics={{
difficultWords: getLatestRecording().improvements
.filter(imp => imp.includes('palavra'))
.map(imp => imp.match(/palavra "([^"]+)"/)?.[1])
.filter(Boolean) as string[],
errorCount: getLatestRecording().error_count,
pauseCount: getLatestRecording().pause_count,
fluencyScore: getLatestRecording().fluency_score
}}
/>
)}
{/* Dashboard de métricas */}
{loadingRecordings ? (
@ -931,7 +958,7 @@ export function StoryPage() {
<div className="h-48 bg-gray-100 rounded-lg mb-6" />
</div>
) : recordings.length > 0 ? (
<div className="space-y-8">
<div className="space-y-8 pt-8">
<h2 className="text-2xl font-bold text-gray-900">Dashboard de Leitura</h2>
<StoryMetrics
data={formatMetricsData(getLatestRecording())}
@ -1014,22 +1041,7 @@ export function StoryPage() {
</Dialog.Root>
</div>
{/* Depois do StoryMetrics */}
{recordings.length > 0 && (
<ExerciseSuggestions
storyId={story.id}
storyText={story.content.pages[currentPage].text}
readingMetrics={{
difficultWords: getLatestRecording().improvements
.filter(imp => imp.includes('palavra'))
.map(imp => imp.match(/palavra "([^"]+)"/)?.[1])
.filter(Boolean) as string[],
errorCount: getLatestRecording().error_count,
pauseCount: getLatestRecording().pause_count,
fluencyScore: getLatestRecording().fluency_score
}}
/>
)}
</div>
);
}