No description
  • Svelte 62.6%
  • TypeScript 36.6%
  • JavaScript 0.5%
  • CSS 0.1%
  • HTML 0.1%
  • Other 0.1%
Find a file
Jonatas Oliveira 1cd2103175
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci: o validador de HTML rodava sob Java 11 e não validava nada
As 18 verificações do `html-validity.spec.ts` falhavam em
`UnsupportedClassVersionError: class file version 61.0 ... only recognizes
up to 55.0` — 61 é Java 17, 55 é Java 11. O passo instalava
`default-jre-headless`, que no Ubuntu jammy é o 11, e o `vnu.jar` do
projeto foi compilado para o 17.

Passa a instalar `openjdk-17-jre-headless`. Verificado dentro da própria
imagem do Playwright: com o default, o vnu estoura; com o 17, devolve
`{"version":"26.8.6","messages":[]}`.

Vale registrar por que isso apareceu como falha e não como silêncio: o
teste recusa relatório vazio em vez de ler "nenhuma mensagem" como
"página válida". Sem essa guarda, as 18 verificações teriam ficado
verdes sem validar uma linha de HTML.
2026-08-20 19:57:43 +02:00
cypress test: add Cypress e2e structure + integration tests 2026-08-03 11:18:12 +02:00
src fix(register): tira o seletor "Tipo de conta" do cadastro 2026-08-20 14:04:26 +02:00
tests feat: telas da Wave 7 e correção de dois bugs no catálogo 2026-08-11 12:14:44 +02:00
.dockerignore build: replace Dockerfile with the corrected, already-deployed version 2026-08-03 11:18:12 +02:00
.gitignore fix(cart): traz as rotas do carrinho e de site-content, que estavam no repo do backend 2026-08-11 18:56:49 +02:00
.woodpecker.yml ci: o validador de HTML rodava sob Java 11 e não validava nada 2026-08-20 19:57:43 +02:00
app.json fix(deploy): replace deprecated CHECKS file with app.json healthchecks 2026-08-03 11:18:12 +02:00
Dockerfile build: replace Dockerfile with the corrected, already-deployed version 2026-08-03 11:18:12 +02:00
eslint.config.js chore(frontend): add ignores to ESLint config for build output 2026-08-03 11:18:12 +02:00
LICENSE Initial commit 2026-08-03 09:16:07 +00:00
package-lock.json feat: telas da Wave 7 e correção de dois bugs no catálogo 2026-08-11 12:14:44 +02:00
package.json feat: telas da Wave 7 e correção de dois bugs no catálogo 2026-08-11 12:14:44 +02:00
playwright.config.ts feat: implement Wave 7-8 core features (student dashboard, course player, quiz, certificates, bundle domain, code challenge, reviews, drip, prerequisites, email) 2026-08-03 11:18:11 +02:00
postcss.config.js feat: implement Wave 7-8 core features (student dashboard, course player, quiz, certificates, bundle domain, code challenge, reviews, drip, prerequisites, email) 2026-08-03 11:18:11 +02:00
Procfile build: replace Dockerfile with the corrected, already-deployed version 2026-08-03 11:18:12 +02:00
README.md feat: os tokens de design que 26 telas já usavam, e o README do front 2026-08-19 15:00:42 +02:00
svelte.config.js feat: implement Wave 7-8 core features (student dashboard, course player, quiz, certificates, bundle domain, code challenge, reviews, drip, prerequisites, email) 2026-08-03 11:18:11 +02:00
tailwind.config.ts feat: os tokens de design que 26 telas já usavam, e o README do front 2026-08-19 15:00:42 +02:00
tsconfig.json feat: implement Wave 7-8 core features (student dashboard, course player, quiz, certificates, bundle domain, code challenge, reviews, drip, prerequisites, email) 2026-08-03 11:18:11 +02:00
vite.config.ts fix: datetime.utcnow deprecation + lint fixes across backend 2026-08-03 11:18:12 +02:00
vitest.config.ts feat: implement Wave 7-8 core features (student dashboard, course player, quiz, certificates, bundle domain, code challenge, reviews, drip, prerequisites, email) 2026-08-03 11:18:11 +02:00

playfullms-front

Frontend SvelteKit 5 (runes) + Tailwind do PlayfulLMS.

Development

npm install
npm run dev          # http://localhost:5173

Requer o backend rodando em http://localhost:8000 (ver backend/README.md).

Script O que faz
npm run dev Dev server (Vite)
npm run build Build de produção (adapter-node)
npm run preview Serve o build
npm run check svelte-check + sync de tipos
npm run lint ESLint
npm test Unit tests (Vitest)
npm run test:e2e E2E (Playwright)
npm run test:cypress E2E (Cypress)

Autenticação

O login (src/routes/(auth)/login/+page.server.ts) posta em /api/v1/auth/login no backend e guarda o access_token em cookie httpOnly. Auth e papéis são do Keyrunes — o namespace usado é public, e o procedimento para criar o primeiro admin está em ../backend/README.md.

src/hooks.server.ts resolve o usuário a cada request via GET /auth/me e coloca o resultado em event.locals.user (SessionUser | null, tipado em src/app.d.ts). Visitante anônimo, token expirado e backend fora do ar são todos null — quem consome decide o que fazer.

Área Gate
src/routes/(admin)/ +layout.server.ts: exige ADMIN ou TEACHER; sem sessão redireciona para /login?redirect=…
src/routes/(app)/ Sem gate de layout — cada +page.server.ts checa o cookie
src/routes/(public)/ Aberto

Papéis vêm em maiúsculas (ADMIN / TEACHER / STUDENT), derivados no backend a partir do claim groups do Keyrunes.

Em dev com KEYRUNES_MOCK=true no backend, logar como admin@example.comADMIN e prof@example.comTEACHER (qualquer senha com 6+ caracteres).

Carrinho

$lib/stores/cart.svelte.ts guarda o estado do carrinho. Visitante anônimo fica em localStorage; ao logar, cartStore.merge() envia os itens para POST /cart/merge antes de navegar — sem isso, entrar no meio da compra perderia o carrinho.

cartStore.count é o número de linhas (não a soma das quantidades).

O badge do header não lê o store no servidor: o store é um singleton de módulo, e mutá-lo durante SSR vazaria o carrinho de um usuário na resposta de outro. hydrate() roda só no cliente (via $effect), e o header recebe cartCount como prop do layout para acertar o primeiro paint. A flag hydrated decide qual dos dois valores mostrar.

As chamadas passam pelos proxies em src/routes/api/v1/cart/*, que anexam o token do cookie — o código do navegador nunca vê o token.

Shell do site

SiteHeader e SiteFooter (em $lib/components/layout/) são montados pelos layouts de (public) e (app). O (admin) tem shell próprio.

Coisa Onde
Container 1170px max-w-site (definido em tailwind.config.ts)
Fontes Inter + Plus Jakarta Sans, carregadas em app.html com preconnect e display=swap
Ícones $lib/components/ui/Icon.svelte — 15 glifos SVG inline, sem webfont
404 +error.svelte na raiz e por grupo; o corpo vem de ErrorBody.svelte

Há quatro +error.svelte de propósito: uma URL que não casa com rota nenhuma não passa por layout de grupo, então a página raiz precisa trazer header e footer por conta própria. As variantes de grupo só renderizam o corpo.

(app)/+layout.server.ts faz o gate da área logada. Antes disso cada +page.server.ts checava o cookie sozinho — e quem esquecesse renderizava para visitante anônimo.

Fórum

Três telas em (app)/courses/[slug]/forum/: lista de tópicos, tópico com respostas ([topic_id]) e novo tópico (new). Tipos e o loader do curso ficam em $lib/server/forum.ts — SvelteKit só permite um conjunto fixo de exports em +page.server.ts.

O 403 da API vira uma página de erro que explica que falta matrícula, em vez de uma lista vazia.

Para decidir o que renderizar, compare locals.user.id (o users.id local), nunca locals.user.user_id (o subject do Keyrunes). Ids de autor vêm do banco; comparar com o subject não casa nunca — foi exatamente o bug que fazia o autor do tópico não ver o botão de aceitar solução.