89 lines
3.7 KiB
TypeScript
89 lines
3.7 KiB
TypeScript
import Link from "next/link";
|
|
import { listOrganizationsAdmin } from "@/lib/admin/organizations";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
type PageProps = {
|
|
searchParams: Promise<{ q?: string }>;
|
|
};
|
|
|
|
export default async function OrgsAdminPage({ searchParams }: PageProps) {
|
|
const sp = await searchParams;
|
|
const filters = { q: sp.q?.trim() || undefined };
|
|
const orgs = await listOrganizationsAdmin(filters);
|
|
const dateFmt = new Intl.DateTimeFormat("fr-FR", { day: "2-digit", month: "short", year: "2-digit" });
|
|
|
|
return (
|
|
<div className="mx-auto max-w-7xl">
|
|
<header className="mb-5 mt-2 flex items-end justify-between gap-3">
|
|
<div>
|
|
<h1 className="text-2xl font-semibold text-zinc-900">Organisations CE</h1>
|
|
<p className="mt-1 text-sm text-zinc-500">
|
|
{orgs.length} résultat{orgs.length > 1 ? "s" : ""}
|
|
</p>
|
|
</div>
|
|
<Link
|
|
href="/admin/organizations/new"
|
|
className="inline-flex items-center gap-1.5 rounded-md bg-zinc-900 px-3 py-1.5 text-sm font-semibold text-white hover:bg-zinc-800"
|
|
>
|
|
+ Nouvelle organisation
|
|
</Link>
|
|
</header>
|
|
|
|
<form className="mb-4 flex flex-wrap items-center gap-2 rounded-lg border border-zinc-200 bg-white p-3" method="get">
|
|
<input
|
|
type="text"
|
|
name="q"
|
|
defaultValue={filters.q ?? ""}
|
|
placeholder="Recherche nom, slug, description…"
|
|
className="flex-1 min-w-[220px] rounded-md border border-zinc-300 px-3 py-1.5 text-sm focus:border-zinc-900 focus:outline-none"
|
|
/>
|
|
<button type="submit" className="rounded-md bg-zinc-900 px-3 py-1.5 text-sm font-medium text-white hover:bg-zinc-800">
|
|
Filtrer
|
|
</button>
|
|
{filters.q ? (
|
|
<Link href="/admin/organizations" className="text-sm text-zinc-500 hover:text-zinc-900">
|
|
Réinit.
|
|
</Link>
|
|
) : null}
|
|
</form>
|
|
|
|
<div className="overflow-hidden rounded-lg border border-zinc-200 bg-white">
|
|
<table className="w-full text-sm">
|
|
<thead className="border-b border-zinc-200 bg-zinc-50 text-xs uppercase tracking-wider text-zinc-500">
|
|
<tr>
|
|
<th className="px-4 py-2 text-left font-semibold">Nom</th>
|
|
<th className="px-4 py-2 text-left font-semibold">Slug</th>
|
|
<th className="px-4 py-2 text-right font-semibold">Membres</th>
|
|
<th className="px-4 py-2 text-right font-semibold">Créée</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-zinc-100">
|
|
{orgs.length === 0 ? (
|
|
<tr>
|
|
<td colSpan={4} className="px-4 py-8 text-center text-sm text-zinc-500">
|
|
Aucune organisation.
|
|
</td>
|
|
</tr>
|
|
) : null}
|
|
{orgs.map((o) => (
|
|
<tr key={o.id} className="hover:bg-zinc-50">
|
|
<td className="px-4 py-2">
|
|
<Link href={`/admin/organizations/${o.id}`} className="font-medium text-zinc-900 hover:underline">
|
|
{o.name}
|
|
</Link>
|
|
{o.description ? (
|
|
<div className="text-[11px] text-zinc-500">{o.description.slice(0, 80)}{o.description.length > 80 ? "…" : ""}</div>
|
|
) : null}
|
|
</td>
|
|
<td className="px-4 py-2 text-zinc-700"><code>/{o.slug}</code></td>
|
|
<td className="px-4 py-2 text-right font-mono text-zinc-700">{o.membersCount}</td>
|
|
<td className="px-4 py-2 text-right text-[11px] text-zinc-500">{dateFmt.format(o.createdAt)}</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|