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