feat: A lot of changes
This commit is contained in:
+127
-37
@@ -6,47 +6,137 @@
|
||||
<title>Announcement Manager</title>
|
||||
<style>
|
||||
* {{ box-sizing: border-box; margin: 0; padding: 0; }}
|
||||
body {{ font-family: system-ui, sans-serif; background: #f5f5f5; padding: 2rem; color: #333; }}
|
||||
h1 {{ margin-bottom: 1.5rem; }}
|
||||
h2 {{ margin: 1.5rem 0 0.75rem; }}
|
||||
form {{ background: #fff; padding: 1rem; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,.1); }}
|
||||
.form-row {{ display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: end; }}
|
||||
label {{ display: flex; flex-direction: column; font-size: 0.85rem; gap: 0.25rem; }}
|
||||
input, textarea {{ padding: 0.4rem 0.6rem; border: 1px solid #ccc; border-radius: 4px; font-size: 0.95rem; }}
|
||||
textarea {{ min-width: 220px; resize: vertical; }}
|
||||
button {{ padding: 0.4rem 1rem; background: #2563eb; color: #fff; border: none; border-radius: 4px; cursor: pointer; font-size: 0.95rem; }}
|
||||
button:hover {{ background: #1d4ed8; }}
|
||||
button.danger {{ background: #dc2626; }}
|
||||
button.danger:hover {{ background: #b91c1c; }}
|
||||
table {{ width: 100%; border-collapse: collapse; background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,.1); }}
|
||||
th, td {{ padding: 0.6rem 0.75rem; text-align: left; border-bottom: 1px solid #eee; }}
|
||||
th {{ background: #f9fafb; font-weight: 600; }}
|
||||
.empty {{ padding: 2rem; text-align: center; color: #888; }}
|
||||
body {{ font-family: system-ui, -apple-system, sans-serif; background: #f1f5f9; color: #1e293b; min-height: 100vh; }}
|
||||
|
||||
.header {{ background: #fff; border-bottom: 1px solid #e2e8f0; padding: 1rem 2rem; display: flex; align-items: center; justify-content: space-between; position: sticky; top: 0; z-index: 10; }}
|
||||
.header h1 {{ font-size: 1.25rem; font-weight: 600; }}
|
||||
.header-actions {{ display: flex; gap: 0.75rem; align-items: center; }}
|
||||
.header-actions .count {{ font-size: 0.85rem; color: #64748b; }}
|
||||
|
||||
.main {{ padding: 2rem; max-width: 1400px; margin: 0 auto; }}
|
||||
|
||||
.toolbar {{ display: flex; gap: 0.75rem; align-items: center; flex-wrap: wrap; margin-bottom: 1.25rem; padding: 1rem 1.25rem; background: #fff; border-radius: 10px; box-shadow: 0 1px 3px rgba(0,0,0,.06); border: 1px solid #e2e8f0; }}
|
||||
.toolbar form {{ display: flex; gap: 0.5rem; align-items: center; }}
|
||||
.toolbar input[type=date] {{ padding: 0.45rem 0.7rem; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 0.9rem; }}
|
||||
.toolbar .clear {{ font-size: 0.85rem; color: #64748b; text-decoration: none; }}
|
||||
.toolbar .clear:hover {{ color: #1e293b; text-decoration: underline; }}
|
||||
|
||||
.btn {{ padding: 0.45rem 1rem; border: none; border-radius: 6px; cursor: pointer; font-size: 0.9rem; font-weight: 500; display: inline-flex; align-items: center; gap: 0.35rem; text-decoration: none; }}
|
||||
.btn-primary {{ background: #2563eb; color: #fff; }}
|
||||
.btn-primary:hover {{ background: #1d4ed8; }}
|
||||
.btn-ghost {{ background: transparent; color: #64748b; border: 1px solid #e2e8f0; }}
|
||||
.btn-ghost:hover {{ background: #f8fafc; color: #1e293b; }}
|
||||
.btn-danger {{ background: #ef4444; color: #fff; }}
|
||||
.btn-danger:hover {{ background: #dc2626; }}
|
||||
.btn-sm {{ padding: 0.3rem 0.65rem; font-size: 0.8rem; }}
|
||||
|
||||
.table-wrap {{ background: #fff; border-radius: 10px; border: 1px solid #e2e8f0; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,.06); }}
|
||||
table {{ width: 100%; border-collapse: collapse; }}
|
||||
th {{ padding: 0.85rem 1rem; text-align: left; font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: #64748b; background: #f8fafc; border-bottom: 1px solid #e2e8f0; }}
|
||||
td {{ padding: 0.85rem 1rem; border-bottom: 1px solid #f1f5f9; font-size: 0.9rem; vertical-align: middle; }}
|
||||
tr:last-child td {{ border-bottom: none; }}
|
||||
tr:hover td {{ background: #f8fafc; }}
|
||||
.cell-id {{ color: #94a3b8; font-size: 0.8rem; font-family: monospace; vertical-align: top; }}
|
||||
.cell-text {{ max-width: 400px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }}
|
||||
.cell-date {{ font-size: 0.85rem; color: #64748b; white-space: nowrap; font-variant-numeric: tabular-nums; }}
|
||||
.cell-actions {{ white-space: nowrap; }}
|
||||
|
||||
.flag {{ display: inline-block; padding: 0.2rem 0.55rem; border-radius: 999px; background: #dbeafe; color: #1e40af; font-size: 0.75rem; font-weight: 500; white-space: nowrap; }}
|
||||
.empty {{ padding: 3rem 1rem; text-align: center; color: #94a3b8; font-size: 0.95rem; }}
|
||||
|
||||
.pagination {{ display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 1rem; padding: 1rem 1.25rem; background: #fff; border-top: 1px solid #e2e8f0; }}
|
||||
.pagination-info {{ font-size: 0.9rem; color: #64748b; padding: 0.25rem 0; }}
|
||||
.pagination-pages {{ display: flex; gap: 0.4rem; align-items: center; }}
|
||||
.page-btn {{ display: inline-flex; align-items: center; justify-content: center; min-width: 2.5rem; height: 2.5rem; padding: 0 0.75rem; border-radius: 8px; font-size: 0.9rem; font-weight: 500; text-decoration: none; color: #475569; background: #f8fafc; border: 1px solid #e2e8f0; }}
|
||||
.page-btn:hover {{ background: #f1f5f9; border-color: #cbd5e1; }}
|
||||
.page-btn.active {{ background: #2563eb; color: #fff; font-weight: 600; border-color: #2563eb; }}
|
||||
.page-btn.disabled {{ color: #cbd5e1; cursor: default; background: #f8fafc; border-color: #f1f5f9; }}
|
||||
.page-btn.dots {{ color: #94a3b8; border: none; min-width: auto; padding: 0 0.3rem; background: transparent; }}
|
||||
|
||||
dialog {{ margin: auto; border: none; border-radius: 12px; padding: 0; box-shadow: 0 20px 60px rgba(0,0,0,.2); max-width: 520px; width: 90vw; }}
|
||||
dialog::backdrop {{ background: rgba(0,0,0,.4); }}
|
||||
dialog form {{ display: flex; flex-direction: column; }}
|
||||
.dialog-header {{ padding: 1.25rem 1.5rem; border-bottom: 1px solid #e2e8f0; font-size: 1.1rem; font-weight: 600; }}
|
||||
.dialog-body {{ padding: 1.25rem 1.5rem; display: flex; flex-direction: column; gap: 1rem; }}
|
||||
.dialog-body label {{ display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.85rem; font-weight: 500; }}
|
||||
.dialog-body input, .dialog-body textarea {{ padding: 0.5rem 0.65rem; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 0.9rem; font-family: inherit; }}
|
||||
.dialog-body textarea {{ min-height: 80px; resize: vertical; }}
|
||||
.dialog-footer {{ padding: 1rem 1.5rem; border-top: 1px solid #e2e8f0; display: flex; justify-content: flex-end; gap: 0.5rem; }}
|
||||
.flag-checkboxes {{ display: flex; gap: 0.75rem; flex-wrap: wrap; }}
|
||||
.flag-checkboxes label {{ display: flex; flex-direction: row; align-items: center; gap: 0.3rem; font-size: 0.85rem; font-weight: 400; cursor: pointer; }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Announcement Manager</h1>
|
||||
|
||||
<h2>Create Announcement</h2>
|
||||
<form action="/api/announcements" method="POST">
|
||||
<div class="form-row">
|
||||
<label>Author
|
||||
<input name="author" placeholder="e.g. School office" required>
|
||||
</label>
|
||||
<label>Text
|
||||
<textarea name="text_content" placeholder="Announcement text…" required></textarea>
|
||||
</label>
|
||||
<label>Start date
|
||||
<input type="date" name="start_date" required>
|
||||
</label>
|
||||
<label>End date
|
||||
<input type="date" name="end_date" required>
|
||||
</label>
|
||||
<button type="submit">Create</button>
|
||||
<header class="header">
|
||||
<h1>Announcement Manager</h1>
|
||||
<div class="header-actions">
|
||||
<span class="count">{total_count} total</span>
|
||||
<button class="btn btn-primary" onclick="document.getElementById('create-dialog').showModal()">+ New</button>
|
||||
</div>
|
||||
</form>
|
||||
</header>
|
||||
|
||||
<h2>Existing Announcements</h2>
|
||||
{rows}
|
||||
<div class="main">
|
||||
<div class="toolbar">
|
||||
<form action="/" method="GET">
|
||||
<input type="date" name="filter_date" value="{filter_date}">
|
||||
<button class="btn btn-ghost btn-sm" type="submit">Filter</button>
|
||||
</form>
|
||||
<a class="clear" href="/">Clear</a>
|
||||
</div>
|
||||
|
||||
<div class="table-wrap">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Author</th>
|
||||
<th>Text</th>
|
||||
<th>Start</th>
|
||||
<th>End</th>
|
||||
<th>Flags</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows}
|
||||
</tbody>
|
||||
</table>
|
||||
{pagination}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<dialog id="create-dialog">
|
||||
<form action="/api/announcements" method="POST">
|
||||
<div class="dialog-header">New Announcement</div>
|
||||
<div class="dialog-body">
|
||||
<label>
|
||||
Author
|
||||
<input name="author" placeholder="e.g. School office" required>
|
||||
</label>
|
||||
<label>
|
||||
Text
|
||||
<textarea name="text_content" placeholder="Announcement text…" required></textarea>
|
||||
</label>
|
||||
<label>
|
||||
Start date
|
||||
<input type="date" name="start_date" required>
|
||||
</label>
|
||||
<label>
|
||||
End date
|
||||
<input type="date" name="end_date" required>
|
||||
</label>
|
||||
<label style="gap:0.5rem">
|
||||
Flags
|
||||
<div class="flag-checkboxes">
|
||||
{flags_checkboxes}
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<button class="btn btn-ghost" type="button" onclick="this.closest('dialog').close()">Cancel</button>
|
||||
<button class="btn btn-primary" type="submit">Create</button>
|
||||
</div>
|
||||
</form>
|
||||
</dialog>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user