From fc8d8ab8d0da95ec79056f59e14a150df6fcea89 Mon Sep 17 00:00:00 2001 From: Karan Jayachandra Date: Sun, 30 Aug 2026 22:43:21 +0200 Subject: Moved to svelte --- src/lib/components/AdminPanel.svelte | 33 ++++++++++++++++++++ src/lib/components/CourtList.svelte | 14 +++++++++ src/lib/components/GameCard.svelte | 17 +++++++++++ src/lib/components/GameCard.test.js | 32 +++++++++++++++++++ src/lib/components/GamesSection.svelte | 11 +++++++ src/lib/components/GuestList.svelte | 14 +++++++++ src/lib/components/ProposeConfirmControls.svelte | 8 +++++ src/lib/components/RegularList.svelte | 14 +++++++++ src/lib/components/SkillFactorSelect.svelte | 13 ++++++++ src/lib/components/TeamDisplay.svelte | 7 +++++ src/lib/components/TimerControls.svelte | 39 ++++++++++++++++++++++++ src/lib/components/TimerControls.test.js | 35 +++++++++++++++++++++ src/lib/components/ToggleButton.svelte | 7 +++++ src/lib/components/ToggleButton.test.js | 31 +++++++++++++++++++ 14 files changed, 275 insertions(+) create mode 100644 src/lib/components/AdminPanel.svelte create mode 100644 src/lib/components/CourtList.svelte create mode 100644 src/lib/components/GameCard.svelte create mode 100644 src/lib/components/GameCard.test.js create mode 100644 src/lib/components/GamesSection.svelte create mode 100644 src/lib/components/GuestList.svelte create mode 100644 src/lib/components/ProposeConfirmControls.svelte create mode 100644 src/lib/components/RegularList.svelte create mode 100644 src/lib/components/SkillFactorSelect.svelte create mode 100644 src/lib/components/TeamDisplay.svelte create mode 100644 src/lib/components/TimerControls.svelte create mode 100644 src/lib/components/TimerControls.test.js create mode 100644 src/lib/components/ToggleButton.svelte create mode 100644 src/lib/components/ToggleButton.test.js (limited to 'src/lib/components') diff --git a/src/lib/components/AdminPanel.svelte b/src/lib/components/AdminPanel.svelte new file mode 100644 index 0000000..2442386 --- /dev/null +++ b/src/lib/components/AdminPanel.svelte @@ -0,0 +1,33 @@ + + +
+ + +
+ diff --git a/src/lib/components/CourtList.svelte b/src/lib/components/CourtList.svelte new file mode 100644 index 0000000..b307980 --- /dev/null +++ b/src/lib/components/CourtList.svelte @@ -0,0 +1,14 @@ + + +
+ {#each getCourts() as court (court.id)} + toggleCourt(court.id)} + /> + {/each} +
diff --git a/src/lib/components/GameCard.svelte b/src/lib/components/GameCard.svelte new file mode 100644 index 0000000..7bdacb6 --- /dev/null +++ b/src/lib/components/GameCard.svelte @@ -0,0 +1,17 @@ + + +
+
Court {game.id + 1}
+ {#if reserved} +
Reserved
+ {:else} + +
+ + {/if} +
diff --git a/src/lib/components/GameCard.test.js b/src/lib/components/GameCard.test.js new file mode 100644 index 0000000..076a409 --- /dev/null +++ b/src/lib/components/GameCard.test.js @@ -0,0 +1,32 @@ +// @vitest-environment jsdom +import { describe, it, expect } from "vitest"; +import { render, screen } from "@testing-library/svelte"; +import GameCard from "./GameCard.svelte"; +import { createCourt, createRegular } from "../logic/players.js"; +import { + addBlockedGames, + addActiveGames, +} from "../logic/matchmaking.js"; + +describe("GameCard", () => { + it("renders 'Reserved' for a RESERVED placeholder game", () => { + const [game] = addBlockedGames([createCourt(2, false)]); + render(GameCard, { game }); + expect(screen.getByText("Reserved")).toBeInTheDocument(); + expect(screen.getByText("Court 3")).toBeInTheDocument(); + }); + + it("renders both teams' player names for a real match", () => { + const players = [ + createRegular(0, true, 1, 0, "Alice", "A"), + createRegular(1, true, 1, 0, "Bob", "B"), + createRegular(2, true, 1, 0, "Carl", "C"), + createRegular(3, true, 1, 0, "Dana", "D"), + ]; + const [game] = addActiveGames([createCourt(0, true)], players); + render(GameCard, { game }); + expect(screen.queryByText("Reserved")).not.toBeInTheDocument(); + expect(screen.getByText("Alice")).toBeInTheDocument(); + expect(screen.getByText("Dana")).toBeInTheDocument(); + }); +}); diff --git a/src/lib/components/GamesSection.svelte b/src/lib/components/GamesSection.svelte new file mode 100644 index 0000000..a2f4f55 --- /dev/null +++ b/src/lib/components/GamesSection.svelte @@ -0,0 +1,11 @@ + + +

{getGameDescription()}

+
+ {#each getGames() as game (game.id)} + + {/each} +
diff --git a/src/lib/components/GuestList.svelte b/src/lib/components/GuestList.svelte new file mode 100644 index 0000000..2b597eb --- /dev/null +++ b/src/lib/components/GuestList.svelte @@ -0,0 +1,14 @@ + + +
+ {#each getGuests() as guest (guest.id)} + toggleGuest(guest.id)} + /> + {/each} +
diff --git a/src/lib/components/ProposeConfirmControls.svelte b/src/lib/components/ProposeConfirmControls.svelte new file mode 100644 index 0000000..692ad56 --- /dev/null +++ b/src/lib/components/ProposeConfirmControls.svelte @@ -0,0 +1,8 @@ + + +
+ + +
diff --git a/src/lib/components/RegularList.svelte b/src/lib/components/RegularList.svelte new file mode 100644 index 0000000..dd8fb7a --- /dev/null +++ b/src/lib/components/RegularList.svelte @@ -0,0 +1,14 @@ + + +
+ {#each getRegulars() as regular (regular.id)} + toggleRegular(regular.id)} + /> + {/each} +
diff --git a/src/lib/components/SkillFactorSelect.svelte b/src/lib/components/SkillFactorSelect.svelte new file mode 100644 index 0000000..bc882a7 --- /dev/null +++ b/src/lib/components/SkillFactorSelect.svelte @@ -0,0 +1,13 @@ + + + diff --git a/src/lib/components/TeamDisplay.svelte b/src/lib/components/TeamDisplay.svelte new file mode 100644 index 0000000..e175446 --- /dev/null +++ b/src/lib/components/TeamDisplay.svelte @@ -0,0 +1,7 @@ + + +{team.playerOne.firstName} {team.playerOne.lastName} +

+{team.playerTwo.firstName} {team.playerTwo.lastName} diff --git a/src/lib/components/TimerControls.svelte b/src/lib/components/TimerControls.svelte new file mode 100644 index 0000000..5983514 --- /dev/null +++ b/src/lib/components/TimerControls.svelte @@ -0,0 +1,39 @@ + + +
+ + + + + +
diff --git a/src/lib/components/TimerControls.test.js b/src/lib/components/TimerControls.test.js new file mode 100644 index 0000000..3176c17 --- /dev/null +++ b/src/lib/components/TimerControls.test.js @@ -0,0 +1,35 @@ +// @vitest-environment jsdom +import { describe, it, expect, afterEach } from "vitest"; +import { render, screen, fireEvent } from "@testing-library/svelte"; +import TimerControls from "./TimerControls.svelte"; +import { stopTimer } from "../stores/timer.svelte.js"; + +describe("TimerControls", () => { + afterEach(() => { + stopTimer(); + }); + + it("shows the resting display for the default minutes", () => { + render(TimerControls); + expect(screen.getByTitle("Time display")).toHaveValue("12:00"); + }); + + it("disables inc/dec while running, and re-enables on stop", async () => { + render(TimerControls); + const startBtn = screen.getByTitle("Timer start"); + const stopBtn = screen.getByTitle("Timer stop"); + const incBtn = screen.getByTitle("Timer increment"); + const decBtn = screen.getByTitle("Timer decrement"); + + expect(incBtn).not.toBeDisabled(); + expect(decBtn).not.toBeDisabled(); + + await fireEvent.click(startBtn); + expect(incBtn).toBeDisabled(); + expect(decBtn).toBeDisabled(); + + await fireEvent.click(stopBtn); + expect(incBtn).not.toBeDisabled(); + expect(decBtn).not.toBeDisabled(); + }); +}); diff --git a/src/lib/components/ToggleButton.svelte b/src/lib/components/ToggleButton.svelte new file mode 100644 index 0000000..138aa15 --- /dev/null +++ b/src/lib/components/ToggleButton.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ToggleButton.test.js b/src/lib/components/ToggleButton.test.js new file mode 100644 index 0000000..cfbb90d --- /dev/null +++ b/src/lib/components/ToggleButton.test.js @@ -0,0 +1,31 @@ +// @vitest-environment jsdom +import { describe, it, expect, vi } from "vitest"; +import { render, screen, fireEvent } from "@testing-library/svelte"; +import ToggleButton from "./ToggleButton.svelte"; + +describe("ToggleButton", () => { + it("renders the label", () => { + render(ToggleButton, { label: "Court 1", active: true, onclick: () => {} }); + expect(screen.getByText("Court 1")).toBeInTheDocument(); + }); + + it("shows the outline/secondary styling when inactive", () => { + render(ToggleButton, { label: "Court 1", active: false, onclick: () => {} }); + const button = screen.getByRole("button"); + expect(button).toHaveClass("outline", "secondary"); + }); + + it("has no outline/secondary styling when active", () => { + render(ToggleButton, { label: "Court 1", active: true, onclick: () => {} }); + const button = screen.getByRole("button"); + expect(button).not.toHaveClass("outline"); + expect(button).not.toHaveClass("secondary"); + }); + + it("calls onclick when clicked", async () => { + const onclick = vi.fn(); + render(ToggleButton, { label: "Court 1", active: true, onclick }); + await fireEvent.click(screen.getByRole("button")); + expect(onclick).toHaveBeenCalledOnce(); + }); +}); -- cgit v1.3.1