A per-event queue board for a repair cafe. Customers sign items in on a shared tablet; volunteers drag repairs through Queue, In progress and Done on a dashboard, then export the day's records as CSV. Zero npm dependencies: node:http plus JSON files on disk, no build step. Categories and house rules are set in config.json. Events are deleted 7 days after creation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
105 lines
3.3 KiB
HTML
105 lines
3.3 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Dashboard</title>
|
|
<link rel="stylesheet" href="/static/app.css">
|
|
</head>
|
|
<body class="dashboard">
|
|
|
|
<header class="board-header">
|
|
<h1 id="event-name"> </h1>
|
|
<span class="meta" id="expiry"></span>
|
|
<span class="spacer"></span>
|
|
<span class="meta" id="status-line"></span>
|
|
<a id="intake-link" href="">Sign-in form</a>
|
|
<a id="csv-link" href="">Download CSV</a>
|
|
</header>
|
|
|
|
<main class="board" id="board"></main>
|
|
|
|
<template id="column-template">
|
|
<section class="column">
|
|
<div class="column-header">
|
|
<h2></h2>
|
|
<span class="count"></span>
|
|
<label class="hint" style="font-weight:400">sort
|
|
<select class="sort">
|
|
<option value="time">time added</option>
|
|
<option value="category">item category</option>
|
|
</select>
|
|
</label>
|
|
</div>
|
|
<div class="cards"></div>
|
|
</section>
|
|
</template>
|
|
|
|
<!-- queue -> in progress -->
|
|
<dialog id="repairer-dialog">
|
|
<form method="dialog" class="dialog-body">
|
|
<h2>Who is repairing this?</h2>
|
|
<div class="field">
|
|
<label for="repairer-input">Volunteer name</label>
|
|
<input type="text" id="repairer-input" maxlength="80" autocomplete="off">
|
|
</div>
|
|
<div class="dialog-actions">
|
|
<button type="button" data-close="cancel">Cancel</button>
|
|
<button value="save" class="primary">Save</button>
|
|
</div>
|
|
</form>
|
|
</dialog>
|
|
|
|
<!-- in progress -> done -->
|
|
<dialog id="done-dialog">
|
|
<form method="dialog" class="dialog-body">
|
|
<h2>How did it go?</h2>
|
|
|
|
<div class="field">
|
|
<label>Result</label>
|
|
<label class="check"><input type="radio" name="outcome" value="fixed"> <span>Fixed</span></label>
|
|
<label class="check"><input type="radio" name="outcome" value="partially fixed"> <span>Partially fixed</span></label>
|
|
<label class="check"><input type="radio" name="outcome" value="not fixed"> <span>Not fixed</span></label>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<label for="tools-input">Tools / consumables used <span class="hint">— optional</span></label>
|
|
<input type="text" id="tools-input" maxlength="300" autocomplete="off">
|
|
</div>
|
|
|
|
<div class="field">
|
|
<label for="done-note">Notes <span class="hint">— optional</span></label>
|
|
<textarea id="done-note" maxlength="2000"></textarea>
|
|
</div>
|
|
|
|
<div class="dialog-actions">
|
|
<button type="button" data-close="cancel" class="left">Cancel</button>
|
|
<button type="button" data-close="skip">Skip for now</button>
|
|
<button value="save" class="primary">Save</button>
|
|
</div>
|
|
</form>
|
|
</dialog>
|
|
|
|
<!-- card detail -->
|
|
<dialog id="detail">
|
|
<div class="dialog-body">
|
|
<h2 id="detail-title"></h2>
|
|
<div id="detail-fields"></div>
|
|
|
|
<div class="detail-field">
|
|
<label>Notes</label>
|
|
<ul class="notes-list" id="notes-list"></ul>
|
|
<textarea id="new-note" placeholder="Add a note…" maxlength="2000" rows="2"></textarea>
|
|
<div style="margin-top:8px"><button type="button" class="small" id="add-note">Add note</button></div>
|
|
</div>
|
|
|
|
<div class="dialog-actions">
|
|
<button type="button" id="detail-close" class="primary">Close</button>
|
|
</div>
|
|
</div>
|
|
</dialog>
|
|
|
|
<script src="/static/dashboard.js"></script>
|
|
</body>
|
|
</html>
|