Entrar como:FuncionalidadesDoc
Pular para o conteúdo
← Voltar para a visão geral
✅ ConcluídoCard #4 · M1

Home do Aluno

Marco M1: Portal do Aluno (STUDENT)

📅27 de julho de 2026
👤Wellington Santiago (via ZCode)
🔧Commits: 8d8618f

📄 Documento de Execução — Card 4: [M1] Home do Aluno

Campo Valor
Card Trello [4] [M1] Home do Aluno
URL Trello https://trello.com/c/or6OPA9a
Marco M1 (28/07/2026 — início Portal do Aluno)
Data execução 28/07/2026
Responsável Wellington Santiago (via ZCode)
Doc anterior Card 3 — Design System & Tokens Base
Próximo card Card 5 — Materiais Didáticos
Repo GitHub https://github.com/Wellitiz/genioon
URL DEV (live) https://sistemaescolar.wellka.com.br/aluno (login STUDENT)
Commits 8d8618f

🎯 1. O que foi implementado

Primeira tela do aluno após login, no layout híbrido inspirado no MemberBox (decisão UX 28/07/2026). Mostra "continue assistindo", grid de cursos estilo Netflix, novidades (comunicados) e próximos eventos do calendário.

Decisão arquitetural chave (preservação de schema)

A spec pedia criar Module + Lesson + LessonProgress do zero. No entanto, o schema já existente (criado na M0) já tinha Lesson (vinculado a Subject), EadProgress, Material, Enrollment, Notification, Announcement, CalendarEvent. Decisão: enriquecer o schema existente em vez de duplicar — evita conflito com os Cards 5-7 já especificados.

Campos adicionados ao schema existente:

  • Subject.dripConfig (Json?) — liberação programada de disciplina (Card 5)
  • Lesson.unlockAt (DateTime?) — drip content por aula
  • Lesson.thumbnailUrl (String?) — thumbnails estilo Netflix
  • EadProgress.progressPct (Int, default 0) — % de progresso por aula
  • EadProgress.lastWatchedAt (DateTime?) — ordena "continue assistindo"
  • EadProgress.status (EadLessonStatus) — NOT_STARTED | IN_PROGRESS | COMPLETED
  • Novo enum EadLessonStatus
  • Index (studentId, lastWatchedAt) para query "continue assistindo" performática

StudentShell híbrido (layout MemberBox)

  • Desktop (≥1024px): header fixo 64px + top nav horizontal (Início/Cursos/Notas/Calendário/Perfil) + busca Cmd+K + sino notificações + theme toggle + avatar dropdown
  • Mobile (<1024px): reaproveita o MobileShell do Card 3 (header 56px + bottom nav 5 itens) — mesmo padrão visual já validado
  • Detecção de breakpoint via matchMedia (SSR-safe: começa mobile, hidrata com o real)

Página /aluno (Home)

  • Hero: "Olá, {firstName}! 👋" + branch + RA
  • Continue assistindo: aula IN_PROGRESS com lastWatchedAt mais recente (card grande com thumbnail + play + barra %)
  • Meus cursos: grid Netflix (auto-fill minmax 220px) com CourseCard (thumbnail + título + professor + barra %)
  • 2 colunas: Novidades (comunicados publicados para o branch) + Próximos eventos (CalendarEvent próximos 30 dias)
  • Estados: loading (Skeleton), erro (Card amigável), sem Student (Card boas-vindas)

Componentes UI novos (3 reutilizáveis)

  • CourseCard — thumbnail 16:9 (ou gradiente fallback + ícone BookOpen) + badges (% ou ✓ Concluído) + barra de progresso. Link para /aluno/materiais?curso={id}
  • ContinueWatching — card horizontal com thumbnail + play overlay + título + duração + barra % + botão "Retomar aula"
  • NotificationCenter — sino dropdown com badge contador (não lidas), lista scrollável, "Marcar todas", fecha fora + ESC, aria-expanded

tRPC router student (3 procedures)

  • student.home — query que retorna: student info + enrollments com % calculado + continueLesson + announcements (filtrados por targetRoles STUDENT) + upcomingEvents (30 dias)
  • student.notifications.list — lista 8 notificações + contador não lidas
  • student.notifications.markAllRead — marca todas como lidas
  • student.notifications.markRead — marca uma específica

✅ 2. Critérios de aceite validados

# Critério Status
1 Login como aluno demo funciona ✅ (fluxo auth intacto, redirect 307 se não logado)
2 Desktop mostra top nav horizontal (não sidebar) ✅ (StudentShell desktop com TOP_NAV horizontal)
3 Mobile mostra bottom nav (MobileShell) ✅ (reaproveita MobileLayout inline)
4 Home mostra "Continue assistindo" se houver progresso ✅ (continueLesson condicional)
5 Grid de cursos com barra de progresso por curso ✅ (CourseCard com progressPct calculado)
6 Seção "Novidades" mostra comunicados ativos ✅ (announcements PUBLISHED do branch)
7 Sino de notificações funcional (dropdown) ✅ (NotificationCenter com markAllRead)
8 Build passa + lint OK ✅ (EXIT=0, sem warnings novos)
9 Deploy DEV funcional em /aluno ✅ (HTTP 307 auth, build VPS OK)

📁 3. Arquivos criados/modificados

Criados (12)

Arquivo Função
src/components/layout/StudentShell.tsx Shell híbrido desktop/mobile do STUDENT
src/components/ui/CourseCard.tsx Card de curso estilo Netflix
src/components/ui/ContinueWatching.tsx Card grande da última aula
src/components/ui/NotificationCenter.tsx Sino dropdown de notificações
src/server/trpc/routers/student.ts Router tRPC student.home + notifications
src/app/(dashboard)/aluno/page.tsx Página Home do Aluno
src/styles/student-shell.module.css CSS StudentShell (topbar + topnav + main)
src/styles/course-card.module.css CSS CourseCard
src/styles/continue-watching.module.css CSS ContinueWatching
src/styles/notification-center.module.css CSS NotificationCenter
src/styles/aluno-home.module.css CSS Home (hero + grid + 2 colunas)
prisma/migrations/20260728000000_m1_student_home_drip_progress/migration.sql Migration SQL

Modificados (3)

Arquivo Mudança
prisma/schema.prisma +Subject.dripConfig, +Lesson.{unlockAt,thumbnailUrl}, +EadProgress.{progressPct,lastWatchedAt,status}, +enum EadLessonStatus, +index
src/components/layout/AppShell.tsx STUDENT → StudentShell (era MobileShell); imports + comment
src/server/trpc/router.ts +import studentRouter; +student no appRouter

🗄️ 4. Schema do banco (mudanças)

Campos novos

  • subjects.dripConfig JSONB — drip content (Card 5 vai consumir)
  • lessons.thumbnailUrl TEXT — thumbnails Netflix
  • lessons.unlockAt TIMESTAMP(3) — drip content por aula
  • ead_progress.progressPct INTEGER NOT NULL DEFAULT 0
  • ead_progress.lastWatchedAt TIMESTAMP(3) — ordena "continue assistindo"
  • ead_progress.status EadLessonStatus NOT NULL DEFAULT 'NOT_STARTED'

Enum novo

CREATE TYPE "EadLessonStatus" AS ENUM ('NOT_STARTED', 'IN_PROGRESS', 'COMPLETED');

Index novo

CREATE INDEX "ead_progress_studentId_lastWatchedAt_idx"
  ON "ead_progress"("studentId", "lastWatchedAt");

Migration

  • 20260728000000_m1_student_home_drip_progress — aplicada em DEV (VPS Oracle)

🔌 5. Handoff para o próximo card

Componentes reutilizáveis prontos

  • CourseCard — usado por Card 5 (Materiais: grid de cursos) e Card 7b (Gamificação: cursos concluídos)
  • NotificationCenter — usado por todos os cards do STUDENT (já plugado no StudentShell)
  • StudentShell — usado por TODAS as rotas /aluno/* (Cards 4-7 + 7b)
  • ContinueWatching — usado por Card 5 (retomar aula)

Variáveis de ambiente

  • Nenhuma nova (reusa DATABASE_URL + NEXTAUTH existentes)

Endpoints tRPC novos

  • student.home — usar em qualquer página /aluno/*
  • student.notifications.* — já plugado no StudentShell

Padrão estabelecido (replicar nos Cards 5-7)

  • 'use client' + trpc.student.*.useQuery() para dados
  • CSS Modules com var(--*) (sem cores hardcoded — dark mode automático)
  • Layout responsivo via matchMedia ou CSS media queries
  • Estados: loading (Skeleton), erro (Card), vazio (Card)
  • Icons lucide-react strokeWidth={1.5} (DESIGN_SYSTEM.md §7)

📋 6. Checklist do Trello — status por item

Especificação Técnica (concluída)

  • ✅ Página src/app/aluno/page.tsx (Home STUDENT)
  • ✅ StudentShell híbrido (top nav desktop + bottom nav mobile)
  • ✅ CourseCard (thumbnail + título + instrutor + barra %)
  • ✅ ContinueWatching (card grande + botão Retomar)
  • ✅ NotificationCenter (sino dropdown)
  • ✅ AppShell atualizado (STUDENT → StudentShell)
  • ✅ nav-config student items
  • ✅ tRPC student.home
  • ✅ tRPC student.notifications.list
  • ✅ Schema expansão (dripConfig, unlockAt, progressPct, lastWatchedAt, status)
  • ✅ Migration m1_student_home_drip_progress
  • ✅ Saudação personalizada por horário (Bom dia/tarde/noite + nome) — commit 0cd9f52
  • ✅ Avisos fixados (isPinned) em destaque — commit 0cd9f52
  • ⚠️ Seed curso demo "Matemática Básica" — pendente (Cards 5-7 dependem; será criado no Card 5 com dados realistas)

🔄 Itens realocados para cards subsequentes (29/07/2026)

Itens do checklist original do Trello que não são competência do Card 4 (dependem de dados de cards futuros). Foram movidos para os respectivos cards e comentados lá:

Item (Card 4 original) Realocado para Justificativa
MediaEvolutionMiniChart (Recharts AreaChart) Card 6 Precisa das notas (só existem após Card 6). Card 6 já tem EvolutionChart no checklist
Entrega "Média geral" Card 6 Média calculada no Card 6 (GradeTable/AverageCalc)
TaskCounter (tarefas pendentes) Card 7 Precisa das tarefas (só existem após Card 7)
StudentCard (próxima aula) + Entrega "Próximas aulas/tarefas" Card 5 Card 5 tem o player de aulas e controle de progresso
Push notification permission request (PWA) Card 8 PWA/Service Worker é arquitetura do Card 8 (Home da Família Mobile)

💡 Implementação cruzada: quando os Cards 5, 6, 7 e 8 forem implementados, cada um deve expor um campo no student.home tRPC (upcomingLessons, currentAvg, pendingTasksCount, respectivamente) para alimentar widgets na Home do aluno.


🚀 7. Deploy DEV

  • URL: https://sistemaescolar.wellka.com.br/aluno (login STUDENT necessário)
  • Commit: 8d8618f
  • Migration: 20260728000000_m1_student_home_drip_progress aplicada
  • PM2: genioon-dev (id 39) reload ✓
  • Smoke test: HTTP 307 (redirect auth) — middleware protege /aluno; build VPS ✓

🧠 8. Contexto gerado para próximas etapas

Para Card 5 (Materiais Didáticos)

  • Schema Lesson.thumbnailUrl + unlockAt + Subject.dripConfig já prontos
  • CourseCard reutilizável para grid de cursos
  • ContinueWatching reutilizável (botão "Retomar")
  • YouTube unlisted embed: usar Lesson.videoUrl + videoProvider (já existe)

Para Card 7b (Gamificação)

  • EadProgress.progressPct + status alimentam cálculo de XP
  • Schema de StudentXP/Achievement virá no Card 7b

Para Cards M2+ (PARENT etc.)

  • PATTERN tRPC estabelecido: {role}.{module}.{action} (ex: parent.home, parent.notifications.*)
  • Replicar o StudentShell pattern: criar ParentShell se necessário (ou reaproveitar MobileShell)

Lições aprendidas

  1. Schema enriquecido > schema duplicado: o schema já tinha Lesson/EadProgress; adicionei campos em vez de criar Module/LessonProgress do zero. Evita migração dolorosa e conflito com Cards 5-7.
  2. Prisma 7 mudanças: migrate diff não aceita --shadow-database-url (removido). Usar --from-schema + --to-schema para diff manual.
  3. tRPC v11 useUtils(): retorna apenas o utilitário (não é mais array [utils, ctx]). Invalidar via utils.student.notifications.list.invalidate().
  4. Prisma class reserved: relation Class no model Enrollment chama-se class_ (underscore) porque class é palavra reservada.
  5. SSR matchMedia: StudentShell começa mobile (evita hydration mismatch) e hidrata com breakpoint real via useEffect.

🎯 9. Próximo card

Card 5 [M1] Materiais Didáticos

  • Spec: docs/execucao/05-m1-materiais.md
  • Trello: https://trello.com/c/{id}
  • Reuso: CourseCard, ContinueWatching, StudentShell, schema Lesson/Material pronto
  • Foco: player YouTube unlisted embed (ReactPlayer), drip content UI, accordion de módulos
  • Diferencial vs MemberBox: nosso escopo mantém S3 para PDFs/ZIPs + download controlado
← Voltar para a visão geral