feat: add boilerplate

This commit is contained in:
2026-10-26 21:56:23 +01:00
commit cc6675f7c6
29 changed files with 2231 additions and 0 deletions

94
app/templates/admin.html Normal file
View File

@@ -0,0 +1,94 @@
{% extends "base.html" %}
{% block title %}Admin · Guess the RAL{% endblock %}
{% block content %}
<section class="admin-grid">
<div class="pixel-panel">
<h1>WORKER</h1>
<p class="tiny">Playable jobs: {{ playable }} · queued/running: {{ queued }}</p>
<form class="stack" method="post" action="/admin/fetch">
<label>LINKEDIN JOB URL
<input name="url" required placeholder="https://www.linkedin.com/jobs/view/..." />
</label>
<button class="btn" type="submit">QUEUE FETCH</button>
</form>
<h2>TASKS</h2>
<table class="pixel-table">
<tr><th>ID</th><th>STATUS</th><th>URL</th><th>ERROR</th></tr>
{% for t in tasks %}
<tr>
<td>{{ t.id }}</td>
<td class="st-{{ t.status }}">{{ t.status }}</td>
<td class="clip">{{ t.url }}</td>
<td class="clip">{{ t.error[:120] }}</td>
</tr>
{% endfor %}
</table>
</div>
<div class="pixel-panel">
<h1>ADD JOB</h1>
<form class="stack" method="post" action="/admin/job">
<label>TITLE <input name="title" required /></label>
<label>COMPANY <input name="company" /></label>
<div class="grid-2">
<label>SUBJECT
<select name="subject">
<option>technology</option>
<option>financial</option>
<option>business</option>
<option>healthcare</option>
<option>legal</option>
<option>hr</option>
<option>design</option>
<option>other</option>
</select>
</label>
<label>WORK
<select name="work_type">
<option value="hybrid">hybrid</option>
<option value="remote">full remote</option>
<option value="onsite">in-place</option>
</select>
</label>
</div>
<label>LOCATION <input name="location" /></label>
<div class="grid-2">
<label>RAL EXACT <input name="ral_exact" /></label>
<label>RAL MIN <input name="ral_min" /></label>
</div>
<label>RAL MAX <input name="ral_max" /></label>
<label>EXTRA CLUES <input name="extra_info" /></label>
<label>DESCRIPTION <textarea name="description" rows="5"></textarea></label>
<button class="btn" type="submit">SAVE JOB</button>
</form>
</div>
</section>
<section class="pixel-panel">
<div class="row-between">
<h1>JOBS</h1>
<form method="post" action="/admin/logout"><button class="btn btn-ghost" type="submit">LOGOUT</button></form>
</div>
<table class="pixel-table">
<tr><th>ID</th><th>TITLE</th><th>COMPANY</th><th>RAL</th><th>TYPE</th><th>STATUS</th><th></th></tr>
{% for j in jobs %}
<tr>
<td>{{ j.id }}</td>
<td>{{ j.title }}</td>
<td>{{ j.company }}</td>
<td>{{ j.ral_exact or (j.ral_min and j.ral_max and (j.ral_min|string + '-' + j.ral_max|string)) or '?' }}</td>
<td>{{ j.work_type }}</td>
<td class="st-{{ j.status }}">{{ j.status }}</td>
<td>
<form method="post" action="/admin/job/{{ j.id }}/status">
<select name="status">
<option value="ready" {% if j.status=='ready' %}selected{% endif %}>ready</option>
<option value="needs_salary" {% if j.status=='needs_salary' %}selected{% endif %}>needs_salary</option>
<option value="hidden" {% if j.status=='hidden' %}selected{% endif %}>hidden</option>
</select>
<button class="btn btn-tiny" type="submit">SET</button>
</form>
</td>
</tr>
{% endfor %}
</table>
</section>
{% endblock %}

View File

@@ -0,0 +1,14 @@
{% extends "base.html" %}
{% block title %}Admin · Guess the RAL{% endblock %}
{% block content %}
<section class="hero pixel-panel">
<h1>ADMIN</h1>
{% if error %}<p class="alert">{{ error }}</p>{% endif %}
<form class="stack" method="post" action="/admin/login">
<label>PASSWORD
<input type="password" name="password" required />
</label>
<button class="btn" type="submit">ENTER</button>
</form>
</section>
{% endblock %}

22
app/templates/base.html Normal file
View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{% block title %}Guess the RAL{% endblock %}</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&family=VT323&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="/static/css/style.css" />
</head>
<body>
<div class="scanlines"></div>
<header class="topbar">
<a class="logo" href="/">GUESS THE RAL</a>
<nav><a href="/admin">ADMIN</a></nav>
</header>
<main>
{% block content %}{% endblock %}
</main>
{% block scripts %}{% endblock %}
</body>
</html>

28
app/templates/index.html Normal file
View File

@@ -0,0 +1,28 @@
{% extends "base.html" %}
{% block content %}
<section class="hero pixel-panel">
<div class="mascot-wrap">
{% include "mascot.html" %}
<p class="speech">Yo! I'm RALO. Read the job, hide the salary, guess the RAL. First one to the top of the board wins!</p>
</div>
{% if error %}<p class="alert">{{ error }}</p>{% endif %}
<form class="stack" method="post" action="/create">
<label>YOUR NAME
<input name="name" maxlength="24" required placeholder="PLAYER 1" />
</label>
<div class="grid-2">
<label>MAX PLAYERS (2-12)
<input type="number" name="max_players" min="2" max="12" value="8" />
</label>
<label>ROUNDS (4-32)
<input type="number" name="num_rounds" min="4" max="32" value="8" />
</label>
</div>
<label class="check"><input type="checkbox" name="extra_guesses" /> Extra clues from the posting</label>
<label class="check"><input type="checkbox" name="hide_company" /> Hide company name</label>
<label class="check"><input type="checkbox" name="hide_subject" /> Hide subject / industry</label>
<button class="btn" type="submit">HOST MATCH</button>
</form>
<p class="hint">Got an invite? Open the unique link from the host.</p>
</section>
{% endblock %}

16
app/templates/join.html Normal file
View File

@@ -0,0 +1,16 @@
{% extends "base.html" %}
{% block content %}
<section class="hero pixel-panel">
<div class="mascot-wrap">
{% include "mascot.html" %}
<p class="speech">Session {{ session.id[:8] }} is waiting. Drop your name and jump in!</p>
</div>
{% if error %}<p class="alert">{{ error }}</p>{% endif %}
<form class="stack" method="post" action="/join/{{ session.id }}">
<label>YOUR NAME
<input name="name" maxlength="24" required placeholder="PLAYER 2" />
</label>
<button class="btn" type="submit">JOIN MATCH</button>
</form>
</section>
{% endblock %}

View File

@@ -0,0 +1,4 @@
<div class="ralo" aria-hidden="true">
<div class="ralo-pixel"></div>
<div class="ralo-name">RALO</div>
</div>

37
app/templates/play.html Normal file
View File

@@ -0,0 +1,37 @@
{% extends "base.html" %}
{% block content %}
<section class="play-layout" data-session="{{ session.id }}" data-token="{{ player.token }}" data-host="{{ '1' if player.is_host else '0' }}" data-player="{{ player.id }}">
<aside class="pixel-panel board">
<h2>PLAYERS</h2>
<ol id="players"></ol>
<p class="tiny" id="invite"></p>
{% if player.is_host %}
<form class="stack host-settings" method="post" action="/play/{{ session.id }}/settings" id="host-form">
<h3>HOST SETTINGS</h3>
<label>PLAYERS
<input type="number" name="max_players" min="2" max="12" value="{{ session.max_players }}" />
</label>
<label>ROUNDS
<input type="number" name="num_rounds" min="4" max="32" value="{{ session.num_rounds }}" />
</label>
<label class="check"><input type="checkbox" name="extra_guesses" {% if session.extra_guesses %}checked{% endif %} /> Extra clues</label>
<label class="check"><input type="checkbox" name="hide_company" {% if session.hide_company %}checked{% endif %} /> Hide company</label>
<label class="check"><input type="checkbox" name="hide_subject" {% if session.hide_subject %}checked{% endif %} /> Hide subject</label>
<button class="btn btn-small" type="submit">SAVE</button>
</form>
<button class="btn" id="start-btn" type="button">START GAME</button>
<button class="btn btn-ghost" id="next-btn" type="button" hidden>NEXT ROUND</button>
{% endif %}
</aside>
<div class="pixel-panel stage">
<div class="mascot-wrap compact">
{% include "mascot.html" %}
<p class="speech" id="tip">Waiting in the lobby. The host will start the match.</p>
</div>
<div id="stage"></div>
</div>
</section>
{% endblock %}
{% block scripts %}
<script src="/static/js/play.js"></script>
{% endblock %}