Filtered Orders Table
A page that reads URL query parameters for tab-based filtering with a clean data table.
from abstra.pages import register_function, get_query_params
from abstra.tables import select
@register_function
def get_orders(status: str):
where = {"status": status} if status and status != "all" else {}
orders = select("orders", where=where)
return [{"id": o["id"], "customer": o["customer"], "total": o["total_cents"]/100, "status": o["status"], "date": str(o["created_at"])} for o in orders]
@register_function
def __render__():
params = get_query_params()
current = params.get("status", "all")
tabs = [("all","All Orders"), ("pending","Pending"), ("completed","Completed"), ("cancelled","Cancelled")]
tab_html = "".join(
f'<a href="?status={val}" class="px-4 py-2 text-sm font-medium rounded-lg transition-colors '
f'{"bg-indigo-600 text-white shadow-sm" if current == val else "text-slate-500 hover:bg-slate-100"}">{label}</a>'
for val, label in tabs
)
return f"""
<script src="https://cdn.tailwindcss.com"></script>
<style>body {{ margin:0; font-family:'Inter',system-ui,sans-serif; background:#f8fafc; }}</style>
<div class="min-h-screen p-8 max-w-5xl mx-auto">
<div class="flex items-center justify-between mb-8">
<h1 class="text-2xl font-bold text-slate-800">Orders</h1>
<div class="flex gap-1 bg-slate-100 p-1 rounded-xl">{tab_html}</div>
</div>
<div class="bg-white rounded-2xl shadow-sm border border-slate-100 overflow-hidden">
<div id="table-content">
<div class="flex justify-center py-12"><div class="animate-spin w-6 h-6 border-2 border-indigo-600 border-t-transparent rounded-full"></div></div>
</div>
</div>
</div>
<script>
const fmt = n => new Intl.NumberFormat('pt-BR',{{style:'currency',currency:'BRL'}}).format(n);
const statusStyles = {{
pending: 'bg-amber-50 text-amber-700',
completed: 'bg-emerald-50 text-emerald-700',
cancelled: 'bg-rose-50 text-rose-700',
}};
async function load() {{
const orders = await get_orders("{current}");
const el = document.getElementById('table-content');
if (!orders.length) {{
el.innerHTML = '<div class="text-center py-16 text-slate-400"><p class="font-medium">No orders found</p><p class="text-sm mt-1">Try a different filter</p></div>';
return;
}}
el.innerHTML = `<table class="w-full text-sm">
<thead><tr class="text-left text-xs font-semibold text-slate-400 uppercase tracking-wider border-b border-slate-100">
<th class="px-6 py-3">Order</th><th class="px-6 py-3">Customer</th>
<th class="px-6 py-3">Date</th><th class="px-6 py-3 text-right">Total</th>
<th class="px-6 py-3">Status</th>
</tr></thead>
<tbody>${{orders.map(o => `<tr class="border-b border-slate-50 hover:bg-slate-50/50 transition-colors">
<td class="px-6 py-4 font-mono text-xs text-slate-500">#${{o.id.slice(0,8)}}</td>
<td class="px-6 py-4 font-medium text-slate-700">${{o.customer}}</td>
<td class="px-6 py-4 text-slate-400">${{o.date}}</td>
<td class="px-6 py-4 text-right font-mono tabular-nums">${{fmt(o.total)}}</td>
<td class="px-6 py-4"><span class="text-xs font-medium px-2.5 py-1 rounded-full ${{statusStyles[o.status] || 'bg-slate-50 text-slate-600'}}">${{o.status}}</span></td>
</tr>`).join('')}}</tbody>
</table>`;
}}
load();
</script>
"""
Key patterns: get_query_params() for server-side filter state, pill-style tab navigation, status badges, empty state, formatted currency.