This commit is contained in:
2026-03-05 22:08:06 +02:00
parent 22b700e241
commit 8f96d7514f
24 changed files with 2303 additions and 488 deletions

View File

@@ -1,127 +0,0 @@
{{ define "body" }}
<section class="window config-window" aria-label="Room configuration">
<div class="title-bar">
<span>CreateRoom.exe</span>
<div class="title-bar-controls" aria-hidden="true">
<button type="button">_</button>
<button type="button"></button>
<button type="button">×</button>
</div>
</div>
<div class="window-content">
<p class="intro-copy">Configure your Scrum Poker room and share the invite link with your team.</p>
<form id="room-config-form" class="room-form" novalidate>
<div class="config-layout">
<section class="config-panel">
<div class="field-group">
<label for="room-name">Room name</label>
<input type="text" id="room-name" name="roomName" maxlength="40" value="{{ .DefaultRoomName }}" placeholder="Sprint 32 Planning" required>
</div>
<div class="field-row">
<div class="field-group">
<label for="username">Your username</label>
<input type="text" id="username" name="username" maxlength="32" value="{{ .DefaultUsername }}" placeholder="alice_dev" required>
</div>
<div class="field-group">
<label for="max-people">Max people</label>
<div class="number-input-wrap">
<input type="number" id="max-people" name="maxPeople" min="2" max="50" value="{{ .DefaultMaxPeople }}" required>
</div>
</div>
</div>
<div class="field-row">
<div class="field-group">
<label for="estimation-scale">Estimation scale</label>
<select id="estimation-scale" name="estimationScale">
<option value="fibonacci" {{ if eq .DefaultScale "fibonacci" }}selected{{ end }}>Fibonacci (0,1,2,3,5,8,13,21,?)</option>
<option value="tshirt" {{ if eq .DefaultScale "tshirt" }}selected{{ end }}>T-Shirt (XS,S,M,L,XL,?)</option>
<option value="powers-of-two" {{ if eq .DefaultScale "powers-of-two" }}selected{{ end }}>Powers of 2 (1,2,4,8,16,32,?)</option>
</select>
</div>
<div class="field-group">
<label for="reveal-mode">Reveal mode</label>
<select id="reveal-mode" name="revealMode">
<option value="manual" {{ if eq .DefaultRevealMode "manual" }}selected{{ end }}>Manual reveal by moderator</option>
<option value="all-voted" {{ if eq .DefaultRevealMode "all-voted" }}selected{{ end }}>Auto reveal when everyone voted</option>
</select>
</div>
</div>
<div class="field-row">
<div class="field-group">
<label for="voting-timeout">Voting timeout (seconds)</label>
<div class="number-input-wrap number-with-unit">
<input type="number" id="voting-timeout" name="votingTimeout" min="0" max="3600" value="{{ .DefaultVotingTime }}">
<span class="input-unit">sec</span>
</div>
</div>
<div class="field-group">
<label for="moderator">Moderator role</label>
<select id="moderator" name="moderatorRole">
<option value="creator" {{ if eq .DefaultModerator "creator" }}selected{{ end }}>Room creator is moderator</option>
<option value="none" {{ if eq .DefaultModerator "none" }}selected{{ end }}>No fixed moderator</option>
</select>
</div>
</div>
<fieldset class="window options-box">
<legend>Room options</legend>
<label class="option-item">
<input type="checkbox" id="allow-spectators" name="allowSpectators" {{ if .AllowSpectators }}checked{{ end }}>
<span>Allow spectators (non-voting viewers)</span>
</label>
<label class="option-item">
<input type="checkbox" id="anonymous-voting" name="anonymousVoting" {{ if .AnonymousVoting }}checked{{ end }}>
<span>Anonymous voting until reveal</span>
</label>
<label class="option-item">
<input type="checkbox" id="auto-reset" name="autoReset" {{ if .AutoResetCards }}checked{{ end }}>
<span>Auto-reset cards after each reveal</span>
</label>
</fieldset>
</section>
<aside class="window preview-window" aria-label="Room preview">
<div class="title-bar">
<span>Room Preview</span>
</div>
<div class="window-content preview-content">
<div class="preview-meta">
<span id="preview-scale">Scale: {{ .DefaultScale }}</span>
<span id="preview-max-people">Max: {{ .DefaultMaxPeople }}</span>
</div>
<div class="preview-board" id="preview-board">
<div class="preview-cards" id="preview-cards"></div>
</div>
<div class="card-editor">
<label for="custom-card">Add card</label>
<div class="card-editor-row">
<input type="text" id="custom-card" maxlength="8" placeholder="e.g. 34 or ?">
<button type="button" id="add-card" class="btn">Add</button>
</div>
</div>
</div>
</aside>
</div>
<div class="status-line" id="config-status" role="status" aria-live="polite">
{{ .DefaultStatus }}
</div>
<div class="actions-row">
<button type="reset" class="btn">Reset</button>
<button type="submit" class="btn btn-primary">Create Room</button>
</div>
</form>
</div>
</section>
{{ end }}

View File

@@ -1,10 +0,0 @@
{{ define "footer" }}
</main>
<footer class="taskbar" aria-hidden="true">
<div class="taskbar-start">Start</div>
<div class="taskbar-status">Scrum Poker Setup</div>
</footer>
<script src="/static/js/app.js"></script>
</body>
</html>
{{ end }}

View File

@@ -1,18 +0,0 @@
{{ define "header" }}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Retro Scrum Poker - Room Setup</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/static/css/styles.css">
</head>
<body>
<div class="top-bar">
<button class="btn" id="theme-toggle">Dark Mode</button>
</div>
<main id="desktop">
{{ end }}

View File

@@ -1,5 +1,144 @@
{{ define "index.html" }}
{{ template "header" . }}
{{ template "body" . }}
{{ template "footer" . }}
{{ end }}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Scrum Poker - Room Configuration</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/static/css/styles.css">
</head>
<body data-page="config">
<div class="top-bar">
<button class="btn" id="theme-toggle" type="button">Dark Mode</button>
</div>
<main id="desktop">
<section class="window config-window" aria-label="Room configuration">
<div class="title-bar">
<span>CreateRoom.exe</span>
<div class="title-bar-controls" aria-hidden="true">
<button type="button">_</button>
<button type="button"></button>
<button type="button">×</button>
</div>
</div>
<div class="window-content">
<p class="intro-copy">Configure your Scrum Poker room and share the invite link with your team.</p>
<form id="room-config-form" class="room-form" novalidate>
<div class="config-layout">
<section class="config-panel">
<div class="field-group">
<label for="room-name">Room name</label>
<input type="text" id="room-name" name="roomName" maxlength="80" value="{{ .DefaultRoomName }}" placeholder="Sprint 32 Planning" required>
</div>
<div class="field-row">
<div class="field-group">
<label for="username">Your username</label>
<input type="text" id="username" name="username" maxlength="32" value="{{ .DefaultUsername }}" placeholder="alice_dev" required>
</div>
<div class="field-group">
<label for="max-people">Max people</label>
<div class="number-input-wrap">
<input type="number" id="max-people" name="maxPeople" min="2" max="50" value="{{ .DefaultMaxPeople }}" required>
</div>
</div>
</div>
<div class="field-row">
<div class="field-group">
<label for="estimation-scale">Estimation scale</label>
<select id="estimation-scale" name="estimationScale">
<option value="fibonacci" {{ if eq .DefaultScale "fibonacci" }}selected{{ end }}>Fibonacci (0,1,2,3,5,8,13,21,?)</option>
<option value="tshirt" {{ if eq .DefaultScale "tshirt" }}selected{{ end }}>T-Shirt (XS,S,M,L,XL,?)</option>
<option value="powers-of-two" {{ if eq .DefaultScale "powers-of-two" }}selected{{ end }}>Powers of 2 (1,2,4,8,16,32,?)</option>
</select>
</div>
<div class="field-group">
<label for="reveal-mode">Reveal mode</label>
<select id="reveal-mode" name="revealMode">
<option value="manual" {{ if eq .DefaultRevealMode "manual" }}selected{{ end }}>Manual reveal by moderator</option>
<option value="all_voted" {{ if eq .DefaultRevealMode "all_voted" }}selected{{ end }}>Auto reveal when everyone voted</option>
</select>
</div>
</div>
<div class="field-row">
<div class="field-group">
<label for="voting-timeout">Voting timeout (seconds)</label>
<div class="number-input-wrap number-with-unit">
<input type="number" id="voting-timeout" name="votingTimeoutSec" min="0" max="3600" value="{{ .DefaultVotingTime }}">
<span class="input-unit">sec</span>
</div>
</div>
<div class="field-group">
<label for="room-password">Room password (optional)</label>
<input type="password" id="room-password" name="password" maxlength="64" placeholder="Optional password">
</div>
</div>
<fieldset class="window options-box">
<legend>Room options</legend>
<label class="option-item">
<input type="checkbox" id="allow-spectators" name="allowSpectators" {{ if .AllowSpectators }}checked{{ end }}>
<span>Allow spectators (non-voting viewers)</span>
</label>
<label class="option-item">
<input type="checkbox" id="anonymous-voting" name="anonymousVoting" {{ if .AnonymousVoting }}checked{{ end }}>
<span>Anonymous voting until reveal</span>
</label>
<label class="option-item">
<input type="checkbox" id="auto-reset" name="autoReset" {{ if .AutoResetCards }}checked{{ end }}>
<span>Auto-reset cards after each reveal</span>
</label>
</fieldset>
</section>
<aside class="window preview-window" aria-label="Room preview">
<div class="title-bar">
<span>Room Preview</span>
</div>
<div class="window-content preview-content">
<div class="preview-meta">
<span id="preview-scale">Scale: {{ .DefaultScale }}</span>
<span id="preview-max-people">Max: {{ .DefaultMaxPeople }}</span>
</div>
<div class="preview-board" id="preview-board">
<div class="preview-cards" id="preview-cards"></div>
</div>
<p class="hint-text">Drag cards to reorder. Hover a card to remove it.</p>
<div class="card-editor">
<label for="custom-card">Add card</label>
<div class="card-editor-row">
<input type="text" id="custom-card" maxlength="8" placeholder="e.g. 34 or ?">
<button type="button" id="add-card" class="btn">Add</button>
</div>
</div>
</div>
</aside>
</div>
<div class="status-line" id="config-status" role="status" aria-live="polite">{{ .DefaultStatus }}</div>
<div class="actions-row">
<button type="reset" class="btn">Reset</button>
<button type="submit" class="btn btn-primary">Create Room</button>
</div>
</form>
</div>
</section>
</main>
<script src="/static/js/config.js"></script>
</body>
</html>

102
src/templates/room.html Normal file
View File

@@ -0,0 +1,102 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Scrum Poker Room</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/static/css/styles.css">
</head>
<body data-page="room" data-room-id="{{ .RoomID }}">
<div class="top-bar">
<button class="btn" id="theme-toggle" type="button">Dark Mode</button>
</div>
<main id="desktop" class="room-desktop">
<section class="room-grid" aria-label="Scrum poker room board">
<article class="window room-main-window">
<div class="title-bar">
<span id="room-title">Room</span>
<div class="title-bar-controls" aria-hidden="true">
<button type="button">_</button>
<button type="button"></button>
<button type="button">×</button>
</div>
</div>
<div class="window-content">
<div class="room-meta">
<span id="reveal-mode-label">Reveal mode: manual</span>
<span id="round-state-label">Cards hidden</span>
</div>
<div class="voting-board" id="voting-board"></div>
</div>
</article>
<aside class="window participants-window">
<div class="title-bar">
<span>Participants</span>
</div>
<div class="window-content participants-content">
<ul id="participant-list" class="participant-list"></ul>
</div>
</aside>
<section class="window control-window">
<div class="title-bar">
<span>Controls</span>
</div>
<div class="window-content control-content">
<div class="links-block">
<label>Participant Link</label>
<input id="participant-link" type="text" readonly>
<label>Admin Link</label>
<input id="admin-link" type="text" readonly>
</div>
<div id="admin-controls" class="admin-controls hidden">
<button type="button" id="reveal-btn" class="btn">Reveal</button>
<button type="button" id="reset-btn" class="btn">Reset</button>
</div>
<p id="room-status" class="status-line">Connecting...</p>
</div>
</section>
</section>
<section id="join-panel" class="window join-window hidden" aria-label="Join room">
<div class="title-bar">
<span>JoinRoom.exe</span>
</div>
<div class="window-content">
<form id="join-form" class="room-form" novalidate>
<div class="field-group">
<label for="join-username">Username</label>
<input id="join-username" name="username" type="text" maxlength="32" required>
</div>
<div class="field-group">
<label for="join-role">Role</label>
<select id="join-role" name="role">
<option value="participant">Participant</option>
<option value="viewer">Viewer</option>
</select>
</div>
<div class="field-group">
<label for="join-password">Room password (if required)</label>
<input id="join-password" name="password" type="password" maxlength="64">
</div>
<div class="field-group">
<label for="join-admin-token">Admin token (optional)</label>
<input id="join-admin-token" name="adminToken" type="text" maxlength="64">
</div>
<div class="actions-row">
<button type="submit" class="btn btn-primary">Join Room</button>
</div>
<p id="join-error" class="status-line hidden"></p>
</form>
</div>
</section>
</main>
<script src="/static/js/room.js"></script>
</body>
</html>