BikeControl (SwiftControl)
Use Zwift Click, Zwift Play, Shimano Di2, or any Bluetooth controller with MyWhoosh, Rouvy, Zwift, and more. Free to try on iOS, Android, Windows, and macOS.
Gestão do racha: presença, ranking, pagamentos e caixa.
Translation pending
Sports & fitnessTypeScript · PLpgSQLGitHub @paulohjunior3-debugOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Aplicação web para se divertir com meus amigos.
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Gestão completa de um racha de futebol semanal — presença, fila de suplentes, rateio automático, gols e assistências, ranking mensal com pódio, premiação e caixa transparente.Read the full README ↗
Gestão completa de um racha de futebol semanal — presença, fila de suplentes, rateio automático, gols e assistências, ranking mensal com pódio, premiação e caixa transparente.
Todo grupo que joga uma pelada semanal enfrenta o mesmo caos: confirmação de presença espalhada no WhatsApp, ninguém sabe se sobrou vaga ou virou suplente, alguém sempre esquece de pagar e o saldo do caixa vive incerto. O Resenha F.C resolve isso com um fluxo único: o jogador confirma presença pelo celular, o sistema controla automaticamente titulares/suplentes (2 goleiros + 15 linha), divide o valor da quadra em tempo real entre quem confirmou, registra gols/assistências e fecha um ranking mensal com pódio e premiação — tudo com controle de acesso por papel (administrador, moderador, jogador).
Construído como estudo de caso de uma aplicação multi-tenant de regras de negócio concorrentes (duas pessoas confirmando presença ao mesmo tempo não podem furar a fila) resolvidas no banco, não no frontend.
| Camada | Tecnologia |
|---|---|
| Framework | Next.js 16 (App Router, Server Actions, Server Components) |
| Linguagem | TypeScript (strict) |
| Estilo | Tailwind CSS v4 |
| Banco de dados | PostgreSQL (Supabase) |
| Autenticação | Supabase Auth + RLS |
| Regras de negócio | Funções Postgres SECURITY DEFINER (evitam condição de corrida na fila) |
| Deploy | Vercel + Supabase (free tier) |
| PWA | Web App Manifest + Service Worker |
flowchart LR
subgraph Cliente
A[PWA / Navegador]
end
subgraph Vercel
B[Next.js — Server Components & Actions]
P[proxy.ts — sessão & guarda de rotas por papel]
end
subgraph Supabase
C[(Postgres)]
D[Auth]
E[RPC SECURITY DEFINER\nfila · rateio · ranking]
end
A <--> B
B --> P
B -- RLS por papel --> C
B --> D
B -- confirmar/desistir/finalizar --> E
E --> C
A UI nunca decide sozinha se alguém vira titular ou suplente, nem recalcula o rateio — ela apenas chama funções de banco (confirmar_presenca, desistir_presenca, finalizar_lista, finalizar_ranking) que fazem a leitura e escrita de forma atômica. Isso elimina condição de corrida quando dois jogadores confirmam ao mesmo tempo, e mantém a regra de negócio em um único lugar, reutilizável por qualquer client futuro (app nativo, bot de WhatsApp etc.).
erDiagram
players ||--o| player_attributes : "tem"
players ||--o| profiles : "autentica como"
players ||--o{ match_players : "confirma em"
matches ||--o{ match_players : "lista de"
players ||--o{ ranking_results : "pontua em"
rankings ||--o{ ranking_results : "agrega"
players ||--o{ prizes : "premiado em"
rankings ||--o{ prizes : "gera"
matches ||--o{ cash_transactions : "gera lançamento"
players {
uuid id PK
text apelido
bool eh_goleiro
text classificacao "F..A"
}
matches {
uuid id PK
date data
numeric valor_total
text status "fechada|aberta|finalizada"
}
match_players {
uuid match_id FK
uuid player_id FK
int posicao_lista
text tipo_vaga "titular|suplente"
numeric valor_devido
bool pagou
int gols
int assistencias
}
rankings {
uuid id PK
text periodo "YYYY-MM"
bool finalizado
}
A especificação original deixava alguns pontos de negócio em aberto — decisões tomadas e o porquê:
[email protected], ver lib/auth/roles.ts). O jogador só digita nome/apelido e senha — nunca vê esse detalhe.recalcular_valores) e só é congelado quando a lista fecha — assim quem confirma cedo já vê o valor mais próximo do real.confirmar_presenca/desistir_presenca rodam com SECURITY DEFINER para serem atômicas: a checagem de vaga disponível e a escrita acontecem na mesma transação.lib/business/scoring.ts e classification.ts — ajustar o peso de um gol não exige tocar em nenhuma tela.proxy.ts em vez de middleware.ts. No Next.js 16 o arquivo de middleware foi renomeado para Proxy — a guarda de sessão e RBAC por rota vive em src/proxy.ts.proxy.ts obriga o jogador a criar sua própria senha em /trocar-senha antes de acessar qualquer outra tela.resenha-fc/
├─ src/
│ ├─ app/
│ │ ├─ login/ # autenticação (Server Action)
│ │ └─ (app)/ # rotas autenticadas
│ │ ├─ dashboard/
│ │ ├─ racha/ # fila, confirmação, gols/pagamentos
│ │ ├─ ranking/ # pódio e histórico
│ │ ├─ jogadores/[id]/ # perfil, habilidades, premiações
│ │ ├─ caixa/
│ │ └─ admin/usuarios/ # cadastro de jogadores/moderadores
│ ├─ components/{layout,pwa}/
│ ├─ lib/
│ │ ├─ supabase/{client,server,admin}.ts
│ │ ├─ business/{scoring,classification,racha}.ts
│ │ └─ auth/{roles,session}.ts
│ └─ proxy.ts # sessão + RBAC por rota
├─ supabase/migrations/ # schema, RLS e funções (SQL versionado)
├─ scripts/create-admin.mjs # bootstrap do primeiro administrador
└─ public/{manifest.json,sw.js,icons/}
npm install
cp .env.example .env.local # preencha com as chaves do seu projeto Supabase
npm run dev
supabase/migrations/ em ordem numérica no SQL Editor.Project URL, anon public key e service_role key (Project Settings > API) para .env.local.node --env-file=.env.local scripts/create-admin.mjs "Seu Nome" "seuapelido"
O comando imprime uma senha temporária de 6 dígitos — no primeiro login o app pede pra trocar por uma senha definitiva.http://localhost:3000 e faça login com o apelido e a senha temporária.