# TurmaCard

> Componentes / Cursos e matrícula · Estado: **Em andamento** — Implementado e utilizável, mas ainda sem a validação completa de acessibilidade.

Cartão de uma turma: cidade (ou "Online"), estado da turma, preço em parcelas, previsão, local, horário, modalidade, matrícula e inscrição, aviso de poucas vagas e o indicador de escolha. Dentro de um `TurmaCardGroup`, é um botão de opção de um grupo de rádio (E69). Recebe os dados de um `SisCourseDTO`.

- Função: Cursos e matrícula
- Também chamado de: turma, cartão de turma, oferta, escolha de turma
- Mora em: `app/components/molecules/TurmaCard.tsx`
- Página: [https://phorte-design-system.vercel.app/styleguide/peca/TurmaCard](https://phorte-design-system.vercel.app/styleguide/peca/TurmaCard)
- Ficha no Storybook: [components-complex-turmacard](https://main--69b4847d498a9bd8659db9ba.chromatic.com/?path=/docs/components-complex-turmacard--docs)
- Prévia ao vivo, sozinha: [https://phorte-design-system.vercel.app/previa/TurmaCard/0](https://phorte-design-system.vercel.app/previa/TurmaCard/0)
- Todas as peças: [https://phorte-design-system.vercel.app/llms.txt](https://phorte-design-system.vercel.app/llms.txt)

## Como usar no código

```tsx
import TurmaCard from '@/app/components/molecules/TurmaCard';

<TurmaCard turma={…}>…</TurmaCard>
```

O `…` marca as props obrigatórias — ver *Propriedades*.

## Uso

### Variantes na ficha

1. [Padrão](https://phorte-design-system.vercel.app/previa/TurmaCard/0)
2. [Selecionada](https://phorte-design-system.vercel.app/previa/TurmaCard/1)
3. [Em Destaque](https://phorte-design-system.vercel.app/previa/TurmaCard/2)
4. [Online](https://phorte-design-system.vercel.app/previa/TurmaCard/3)
5. [Escolha de turma](https://phorte-design-system.vercel.app/previa/TurmaCard/4)
6. [Últimas vagas](https://phorte-design-system.vercel.app/previa/TurmaCard/5)
7. [Esqueleto](https://phorte-design-system.vercel.app/previa/TurmaCard/6)

Na página de um curso, lado a lado, para a pessoa comparar as turmas e escolher uma — sempre dentro do `TurmaCardGroup`.

### Quando não usar

Para o curso em si, no catálogo, use o CourseCard. Para uma linha do tempo de datas, o TimelineItem.

### Faça

- Enquanto os dados chegam, mostre o `TurmaCardEsqueleto` (E157) — um por cartão esperado, dentro de um `EsqueletoGrupo rotulo="Carregando turmas"` —, e troque o grupo inteiro pelos cartões quando chegarem.
- Ponha os cartões num `TurmaCardGroup` com `value` e `onChange`: é ele que faz a escolha funcionar pelo teclado e pelo clique.
- Troque o `label` do grupo quando "Escolha a turma" não disser o bastante.
- Mande `vagasRestantes` do serviço: sem o dado, o aviso de poucas vagas não aparece (E69.3).

### Evite

- Um TurmaCard solto esperando que ele selecione: fora do grupo ele só mostra o estado (`isSelected`).
- Controle dentro do cartão: o cartão inteiro já é a opção.

### Anatomia

1. **Destaque** — Tag `aviso` "Destaque" no canto, quando a turma é destaque no site.
2. **Local** — Cidade e UF (ou "Online"), com ícone — o começo do nome da opção.
3. **Estado** — Badge (estado do objeto, E64): "Turma confirmada" (`success`, com visto), "Inscrições abertas" (`default`), "Em formação" (`warning`, com alerta) ou o estado cru (`outline`).
4. **Preço** — Parcelas em destaque ("12x R$ …") ou "Consulte valores" — no nome da opção, depois do local e da situação.
5. **Detalhes** — Uma lista de definição (`dl`): Previsão, Local, Horário, Modalidade, Matrícula e Inscrição — rótulo e valor ligados para quem ouve.
6. **Vagas** — "Últimas N vagas!" com 10 ou menos `vagasRestantes`.
7. **Indicador** — Rodapé com o desenho do Button (E127): `tonal` (verde claro) com o anel de seleção e "Escolher esta turma", ou `secondary` (verde cheio) com o visto e "Turma selecionada" — decorativo (`aria-hidden`): o estado vai em `aria-checked`.

### Estados

| Estado | O que muda |
| --- | --- |
| Carregando | O `TurmaCardEsqueleto` (E157): a mesma superfície e proporção, com as linhas e a imagem em esqueleto, decorativo (`aria-hidden`); o grupo diz "Carregando turmas" uma vez. Medido na ficha: a mesma largura e menos de 20% de diferença de altura. |
| Não escolhida | Borda `--border`; rodapé verde claro com o anel de seleção vazio (E127) — antes era cinza com um círculo fino, que parecia desabilitado. |
| Escolhida | Borda `--secondary`, sombra, rodapé em verde cheio com o visto (E127) — estado por cor **e** ícone e texto. |
| Foco | O anel de foco no cartão, só no teclado. |
| Poucas vagas | Com `vagasRestantes` de 1 a 10: "Últimas N vagas!" (ou "Última vaga!") em amarelo escuro. |
| Hover (no grupo) | Borda de controle e sombra maior. |

### Comportamento

| Situação | O que acontece |
| --- | --- |
| Clique num cartão do grupo | Chama `onChange` com o `sigId` — conferido no teste da ficha. |
| Vagas | Pelas vagas **livres** (`vagasRestantes`), e não pela capacidade: 9 livres de 10 dizem "Últimas 9 vagas!", 2 de 40 dizem "Últimas 2", sem o dado não diz nada — conferido no teste da ficha. |
| Sem cronograma | Usa as informações adicionais de data, se houver. |
| Sem data | "A definir". |
| Matrícula zero | Não mostra a linha de matrícula. |

### Relacionados

- [CourseCard](https://phorte-design-system.vercel.app/styleguide/md/CourseCard.md) — O curso, no catálogo.
- [FilterGroup](https://phorte-design-system.vercel.app/styleguide/md/FilterGroup.md) — O mesmo padrão de grupo de rádio, em pílulas.
- [TimelineItem](https://phorte-design-system.vercel.app/styleguide/md/TimelineItem.md) — Datas em linha do tempo.

## Especificação

### Propriedades

| Prop | Tipo | Padrão | Obrigatória | Descrição |
| --- | --- | --- | --- | --- |
| `turma` | `SisCourseDTO` | — | sim |  |
| `isSelected` | `boolean` | `false` | não | Fora de um `TurmaCardGroup`, só mostra o estado. Dentro, quem manda é o grupo. |

Aceita também: `Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect'>`.

### Tokens de cor

| Token | Valor | Usado como |
| --- | --- | --- |
| `--border` | #E5E5E5 | `border-border` |
| `--border-interactive` | #8C8C8C | `border-border-interactive` |
| `--card` | #FFFFFF | `bg-card` |
| `--foreground` | #1A1A1A | `text-ink` |
| `--muted-foreground` | #595959 | `text-muted-foreground` |
| `--primary` | #D42B2B | `text-primary` |
| `--secondary` | #0B8434 | `border-secondary` |
| `--warning-strong` | #945201 | `text-warning-strong` |

## Acessibilidade

### Teclado

| Tecla | Faz |
| --- | --- |
| Tab | Entra no grupo pela turma escolhida (ou pela primeira) e sai no próximo Tab — uma parada só. Conferido no teste da ficha. |
| → / ↓ / ← / ↑ | Vai à turma seguinte ou anterior e a escolhe, dando a volta — conferido no teste da ficha. |
| Home / End | Vai à primeira ou à última e a escolhe. |
| Espaço / Enter | Escolhe a turma em foco. |

### Leitor de tela

- O grupo é `role="radiogroup"` ("Escolha a turma"); cada cartão, `role="radio"` com `aria-checked` — conferido no teste da ficha. Até a E69 o cartão não recebia foco, e a faixa "Selecione…" não selecionava nada.
- O nome da opção é o conteúdo do cartão, na ordem de leitura — local, situação, preço, detalhes, vagas e o texto do indicador ("Escolher esta turma" ou "Turma selecionada"), como num rádio nativo com o `<label>` em volta. Era só o local e o preço, e o indicador ficava fora: quem usa comando de voz dizia o que via e nada respondia (SC 2.5.3, E140) — testado na ficha, e o axe da ficha roda com a regra `label-content-name-mismatch` ligada.

### O que sustenta o estado

Usa os padrões: estatico. Falta ouvir com leitor de tela: estatico.

## Status e recursos

| Tipo | Recurso | Status |
| --- | --- | --- |
| Código | `app/components/molecules/TurmaCard.tsx` | Disponível |
| Ficha | https://main--69b4847d498a9bd8659db9ba.chromatic.com/?path=/docs/components-complex-turmacard--docs | Disponível |
| Teste de acessibilidade | axe em `npm run test` | No gate de todo commit |
| Leitor de tela | Passada da E33 | Falta ouvir |
| Design | Figma | Desativado até a Fase 2 |

### Histórico

- `bf159c0` 2026-10-01 — E161b: os dois testes que o CI do PR #15 reprovou no Linux
- `251416b` 2026-10-01 — E159: Testimonials — o vídeo toca dentro do cartão, YouTube e Vimeo
- Histórico completo no GitHub: https://github.com/srbunnie/Pos-Phorte-Design-System/commits/main/app/components/molecules/TurmaCard.tsx
