ui: refresh proposals list page

This commit is contained in:
Marco Allegretti 2026-01-29 18:13:32 +01:00
parent 5937a0fc54
commit 307a482b56

View file

@ -5,33 +5,48 @@ import { API_BASE as apiBase } from '../lib/api';
---
<Layout title="All Proposals">
<section class="proposals-page">
<div class="header-row">
<section class="ui-page">
<div class="ui-container">
<div class="hero ui-card ui-card-glass">
<div class="hero-top">
<div>
<h1>All Proposals</h1>
<p class="subtitle">Browse proposals across all communities</p>
<h1 class="hero-title">All Proposals</h1>
<p class="hero-subtitle">Browse proposals across all communities</p>
</div>
</div>
</div>
<div class="filters">
<input type="text" id="search-input" placeholder="Search proposals..." />
<select id="status-filter">
<option value="">All Statuses</option>
<div class="toolbar ui-card">
<div class="toolbar-grid">
<div>
<label class="toolbar-label" for="search-input">Search</label>
<input type="text" id="search-input" class="ui-input" placeholder="Search proposals…" />
</div>
<div>
<label class="toolbar-label" for="status-filter">Status</label>
<select id="status-filter" class="ui-select">
<option value="">All statuses</option>
<option value="draft">Draft</option>
<option value="discussion">Discussion</option>
<option value="voting">Voting</option>
<option value="closed">Closed</option>
</select>
<select id="sort-filter">
<option value="newest">Newest First</option>
<option value="oldest">Oldest First</option>
<option value="most-votes">Most Votes</option>
<option value="most-comments">Most Comments</option>
</div>
<div>
<label class="toolbar-label" for="sort-filter">Sort</label>
<select id="sort-filter" class="ui-select">
<option value="newest">Newest first</option>
<option value="oldest">Oldest first</option>
<option value="most-votes">Most votes</option>
<option value="most-comments">Most comments</option>
</select>
</div>
</div>
</div>
<div id="proposals-list" class="list">
<p class="loading">Loading proposals...</p>
<div class="state-card ui-card"><p class="loading">Loading proposals...</p></div>
</div>
</div>
</section>
</Layout>
@ -57,12 +72,12 @@ import { API_BASE as apiBase } from '../lib/api';
if (!container) return;
if (proposals.length === 0) {
container.innerHTML = '<div class="empty"><p>No proposals found.</p></div>';
container.innerHTML = '<div class="state-card ui-card"><p class="empty">No proposals found.</p></div>';
return;
}
container.innerHTML = proposals.map(p => `
<a href="/proposals/${p.id}" class="proposal-card">
<a href="/proposals/${p.id}" class="proposal-card ui-card">
<div class="proposal-header">
<h3>${p.title}</h3>
<span class="ui-pill status-${p.status}">${p.status}</span>
@ -126,43 +141,60 @@ import { API_BASE as apiBase } from '../lib/api';
</script>
<style>
.proposals-page {
padding: 2rem 0;
.hero {
padding: 1.25rem;
margin-bottom: 1rem;
}
.header-row {
.hero-top {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 2rem;
justify-content: space-between;
gap: 1rem;
flex-wrap: wrap;
}
h1 {
font-size: 2.5rem;
margin-bottom: 0.5rem;
.hero-title {
margin: 0;
font-size: 2.125rem;
letter-spacing: -0.02em;
}
.subtitle {
.hero-subtitle {
margin: 0.25rem 0 0;
color: var(--color-text-muted);
}
.filters {
display: flex;
gap: 1rem;
margin-bottom: 1.5rem;
.toolbar {
padding: 1rem;
margin-bottom: 1rem;
}
.filters input, .filters select {
border-radius: var(--radius-md);
.toolbar-grid {
display: grid;
grid-template-columns: 1.5fr 1fr 1fr;
gap: 0.75rem;
align-items: end;
}
.filters input {
flex: 1;
max-width: 300px;
.toolbar-label {
display: block;
font-size: 0.75rem;
letter-spacing: 0.02em;
text-transform: uppercase;
color: var(--color-text-muted);
margin-bottom: 0.35rem;
}
.filters select {
min-width: 150px;
@media (max-width: 768px) {
.toolbar-grid {
grid-template-columns: 1fr;
}
}
.state-card {
padding: 2.25rem 1.5rem;
text-align: center;
}
.list {
@ -172,19 +204,17 @@ import { API_BASE as apiBase } from '../lib/api';
.proposal-card {
display: block;
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-lg);
padding: 1.5rem;
padding: 1.1rem;
color: var(--color-text);
box-shadow: var(--shadow-sm);
transition: transform var(--motion-fast) var(--easing-standard), box-shadow var(--motion-fast) var(--easing-standard), border-color var(--motion-fast) var(--easing-standard);
text-decoration: none;
transition: transform var(--motion-fast) var(--easing-standard), box-shadow var(--motion-fast) var(--easing-standard), border-color var(--motion-fast) var(--easing-standard), background var(--motion-fast) var(--easing-standard);
}
.proposal-card:hover {
border-color: var(--color-border-hover);
transform: translateY(-1px);
transform: translateY(-2px);
box-shadow: var(--shadow-md);
background: rgba(255, 255, 255, 0.03);
}
.proposal-header {
@ -192,10 +222,13 @@ import { API_BASE as apiBase } from '../lib/api';
justify-content: space-between;
align-items: center;
margin-bottom: 0.25rem;
gap: 0.75rem;
}
.proposal-card h3 {
font-size: 1.25rem;
letter-spacing: -0.01em;
margin: 0;
}
.status-draft { background: var(--color-neutral-muted); color: var(--color-on-primary); }
@ -230,10 +263,4 @@ import { API_BASE as apiBase } from '../lib/api';
font-size: 0.75rem;
color: var(--color-text-muted);
}
.loading, .empty, .error {
text-align: center;
padding: 3rem;
color: var(--color-text-muted);
}
</style>