Hey there! ๐
Remember, you only tip once โ your picks automatically count towards all squads you're part of.
is_admin = true in the profiles table. Set this in Supabase directly.| Status | Player sees? | Player tips? | Admin tips? | Add matches? | Bulk import? | Edit venue/time? |
|---|---|---|---|---|---|---|
| Future | No | No | No | Yes | Yes | Yes |
| Next | No | No | Yes | Yes | Yes | Yes |
| Current (no tips) | Yes | Yes | Yes | Yes | Yes | Yes |
| Current (has tips) | Yes | Yes | Yes | No | No | Venue/time only |
| Locked | Yes (read-only) | No | No | No | No | Venue/time only |
| Results applied | Yes (with scores) | No | No | No | No | Venue/time only |
round, home_team, away_team, venue, kickoff_time
Separators: Tab (paste from Excel) and comma (.csv) are auto-detected. Header row is auto-skipped.
Preview: โ
exact match, ๐ก fuzzy match (click dropdown to confirm), ๐ด not found (add via Teams/Venues tab first), โ ๏ธ parse error.
Duplicates: If a match already exists in the round, a Skip/Replace toggle appears. Skip = leave as-is, Replace = update venue and kickoff time only.
Apply: If any ๐ก, โ ๏ธ round warnings, or duplicates exist, a confirmation dialog lists all non-green items before writing. Nothing saves without your click.
current via the Rounds sub-tab dropdown, or in Supabase: UPDATE rounds SET status = 'current' WHERE id = '<round_id>';points_earned, margin_score, bonus_earned).| Outcome | Points | Margin score |
|---|---|---|
| Correct winner | 4 pts | |predicted margin - actual margin| |
| Correct winner, null margin | 4 pts | actual margin (penalty for not entering) |
| Correct draw prediction | 4 pts | 0 |
| Wrong winner | 0 pts | predicted margin + actual margin |
| Wrong winner, null margin | 0 pts | 2 ร actual margin |
| No tip submitted | 0 pts | No score calculated |
| Outcome | Points | Bonus | Margin score |
|---|---|---|---|
| Correct result (right side wins/draws) | 2 pts | โ | |predicted diff - actual diff| |
| Exact scoreline match | 2 pts | +1 bonus | 0 |
| Wrong result | 0 pts | โ | |predicted diff - actual diff| |
| No tip submitted | 0 pts | โ | No score calculated |
| Preset | What it shows | Filter |
|---|---|---|
| ๐ค Player Lookup | All squads, tips, results, and points for a user | Username (autocomplete) |
| ๐ Round Overview | All rounds with match counts, tip counts, status | Competition |
| ๐ฏ Tips for a Round | Every tip submitted for a specific round | Competition + Round |
| ๐๏ธ Match Results | Final scores for all matches in a round | Competition + Round |
| ๐ฅ Squad Members | All members of a squad with status | Squad |
| Table | Key columns | Notes |
|---|---|---|
| sports | id, name, slug, icon, input_mode, allow_draw | Top-level. input_mode: winner-margin or exact-score |
| competitions | id, sport_id, name, season, timezone, is_active | FK to sports. Timezone used for match time display |
| rounds | id, competition_id, round_number, label, status | Status: future, next, current, locked |
| matches | id, round_id, competition_id, home_team, away_team, match_time, venue, sort_order | match_time stored as UTC. Text team/venue names |
| teams | id, name, short_name, sport_id, competition_id, home_venue | Linked to sport. Optional competition_id for name conflicts |
| venues | id, name, city | Global โ no sport link. Unique on name + city |
| predictions | id, user_id, match_uuid, competition_id, round_uuid, winner, margin, home_score, away_score, points_earned, margin_score, bonus_earned | One row per user per match |
| results | id, match_uuid, home_score, away_score, home_team, away_team, sport, season, round, is_test | One row per match. Unique on match_uuid. is_test flags seeded test data |
| squads | id, name, code, owner_id, competition_id | 6-letter code for joining. FK to competitions |
| squad_members | squad_id, user_id | Junction table. Composite PK on (squad_id, user_id) |
| profiles | id, username, theme, is_admin | Set is_admin = true in Supabase for admin access |
| messages | id, user_id, username, message, email, read | User-to-admin. Max 50 chars |
| notifications | id, user_id, type, message, read | Bell notifications (squad requests, etc) |
| favourites | id, user_id, target_id | Player favourites list |
| admin_logs | id, actor, action, target_type, target_id, detail, metadata | Audit trail. Auto-populated by admin_log() |
| Problem | Cause | Fix |
|---|---|---|
| Round select empty in Results | No rounds created for that comp | Go to Matches โ Rounds and add rounds first |
| Match error on Apply โ no unique constraint | DB constraint missing | ALTER TABLE matches ADD CONSTRAINT matches_round_home_away_unique UNIQUE (round_id, home_team, away_team); |
| Results not saving | Missing constraint or RLS | ALTER TABLE results ADD CONSTRAINT results_match_uuid_unique UNIQUE (match_uuid); + add admin RLS policies |
| Points not calculating | User tipped after results applied | Re-run Apply All after all users have tipped |
| Contact Admin failing | RLS missing on messages table | Add insert policy for authenticated, select/update for admins |
| Squad shows wrong comp | competition_id is null | UPDATE squads SET competition_id = '...' WHERE sport_legacy = '...'; |
| Bulk Import button disabled | Round has tips or results | Bulk import only works on rounds with no tips and no results |
| Bulk Import ๐ด on a team that exists | Team name doesn't match exactly | Use the dropdown to pick the correct team, or check spelling in Teams tab |
| Auto-lock not firing | Match times not set, or timezone mismatch | Check times are entered in the comp's timezone. Auto-lock fires on any page load after kickoff |
| Testing โ keep tipping open | Auto-lock fires when kickoff passes | Leave match times blank during testing. Lock manually via Results tab when ready |
window.devTests.runAll()