mirror of
https://github.com/lucasrcsantana/story-generator.git
synced 2025-12-19 14:57:51 +00:00
Compare commits
No commits in common. "13536790fe7ea3a84a95d9de7a2298634eae0a0c" and "d35565dee4db62cefc0092cf23a5f0bd7aaa4a5d" have entirely different histories.
13536790fe
...
d35565dee4
@ -1,248 +0,0 @@
|
|||||||
# 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
|
|
||||||
@ -1,246 +0,0 @@
|
|||||||
# 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
|
|
||||||
@ -1,177 +0,0 @@
|
|||||||
# 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
|
|
||||||
@ -85,9 +85,9 @@ export function ExerciseSuggestions({ storyId, storyText, readingMetrics }: Exer
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-8">
|
<div className="mt-8">
|
||||||
<h2 className="text-2xl font-bold text-gray-900 mb-4 ">
|
<h3 className="text-xl font-bold text-gray-900 mb-4">
|
||||||
Exercícios Sugeridos
|
Exercícios Sugeridos
|
||||||
</h2>
|
</h3>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
{generateExercises().map((exercise) => (
|
{generateExercises().map((exercise) => (
|
||||||
<button
|
<button
|
||||||
|
|||||||
@ -394,7 +394,7 @@ export function StoryPage() {
|
|||||||
const { session } = useSession();
|
const { session } = useSession();
|
||||||
const { isUpperCase, toggleUppercase, isLoading } = useUppercasePreference(session?.user?.id);
|
const { isUpperCase, toggleUppercase, isLoading } = useUppercasePreference(session?.user?.id);
|
||||||
const { isHighlighted: isSyllablesEnabled, toggleHighlight: toggleSyllables } = useSyllables();
|
const { isHighlighted: isSyllablesEnabled, toggleHighlight: toggleSyllables } = useSyllables();
|
||||||
const [fontSize, setFontSize] = useState(24);
|
const [fontSize, setFontSize] = useState(18);
|
||||||
const [readingSpeed, setReadingSpeed] = useState(60); // 60 palavras por minuto
|
const [readingSpeed, setReadingSpeed] = useState(60); // 60 palavras por minuto
|
||||||
const [letterSpacing, setLetterSpacing] = useState(0);
|
const [letterSpacing, setLetterSpacing] = useState(0);
|
||||||
const [wordSpacing, setWordSpacing] = useState(0);
|
const [wordSpacing, setWordSpacing] = useState(0);
|
||||||
@ -854,13 +854,8 @@ export function StoryPage() {
|
|||||||
<h1 className="text-2xl font-bold text-gray-900">{story?.title}</h1>
|
<h1 className="text-2xl font-bold text-gray-900">{story?.title}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Container responsivo */}
|
{/* 3. Texto da História */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-10 gap-6 border-b border-gray-200 pb-6">
|
<div className="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
|
<div
|
||||||
className="prose max-w-none overflow-hidden"
|
className="prose max-w-none overflow-hidden"
|
||||||
style={{
|
style={{
|
||||||
@ -874,9 +869,36 @@ export function StoryPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 5. Imagem da História - Coluna Direita (60% em desktop) */}
|
{/* 4. Controles de Navegação */}
|
||||||
|
<div className="border-b border-gray-200 pb-6">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<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"
|
||||||
|
>
|
||||||
|
<ArrowLeft className="h-5 w-5" />
|
||||||
|
Página Anterior
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<span className="text-sm text-gray-500">
|
||||||
|
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"
|
||||||
|
>
|
||||||
|
Próxima Página
|
||||||
|
<ArrowRight className="h-5 w-5" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 5. Imagem da História - Agora com controle de visibilidade */}
|
||||||
{!focusMode.isActive && (
|
{!focusMode.isActive && (
|
||||||
<div className="col-span-1 md:col-span-6">
|
<div className="border-b border-gray-200 pb-6">
|
||||||
{story?.content?.pages?.[currentPage]?.image ? (
|
{story?.content?.pages?.[currentPage]?.image ? (
|
||||||
<ImageWithLoading
|
<ImageWithLoading
|
||||||
src={story.content.pages[currentPage].image}
|
src={story.content.pages[currentPage].image}
|
||||||
@ -890,38 +912,6 @@ export function StoryPage() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 4. Controles de Navegação */}
|
|
||||||
<div className="border-b border-gray-200 pb-6">
|
|
||||||
<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="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" />
|
|
||||||
<span className="hidden sm:inline">Página Anterior</span>
|
|
||||||
<span className="sm:hidden">Anterior</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<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="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"
|
|
||||||
>
|
|
||||||
<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>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{/* 6. Controle de Gravação */}
|
{/* 6. Controle de Gravação */}
|
||||||
{/*
|
{/*
|
||||||
@ -933,24 +923,7 @@ export function StoryPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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 */}
|
{/* Dashboard de métricas */}
|
||||||
{loadingRecordings ? (
|
{loadingRecordings ? (
|
||||||
@ -958,7 +931,7 @@ export function StoryPage() {
|
|||||||
<div className="h-48 bg-gray-100 rounded-lg mb-6" />
|
<div className="h-48 bg-gray-100 rounded-lg mb-6" />
|
||||||
</div>
|
</div>
|
||||||
) : recordings.length > 0 ? (
|
) : recordings.length > 0 ? (
|
||||||
<div className="space-y-8 pt-8">
|
<div className="space-y-8">
|
||||||
<h2 className="text-2xl font-bold text-gray-900">Dashboard de Leitura</h2>
|
<h2 className="text-2xl font-bold text-gray-900">Dashboard de Leitura</h2>
|
||||||
<StoryMetrics
|
<StoryMetrics
|
||||||
data={formatMetricsData(getLatestRecording())}
|
data={formatMetricsData(getLatestRecording())}
|
||||||
@ -1041,7 +1014,22 @@ export function StoryPage() {
|
|||||||
</Dialog.Root>
|
</Dialog.Root>
|
||||||
</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
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user