50 lines
1.6 KiB
TypeScript
50 lines
1.6 KiB
TypeScript
"use client";
|
|
|
|
import { useQuery } from "@tanstack/react-query";
|
|
import { ColumnDef } from "@tanstack/react-table";
|
|
import { Plus } from "lucide-react";
|
|
import { useAuth } from "@/components/auth";
|
|
import { DataTable } from "@/components/data-table";
|
|
import { apiGet } from "@/lib/api";
|
|
|
|
export function ResourcePage<T>({
|
|
title,
|
|
subtitle,
|
|
path,
|
|
columns
|
|
}: {
|
|
title: string;
|
|
subtitle: string;
|
|
path: string;
|
|
columns: ColumnDef<T>[];
|
|
}) {
|
|
const { token } = useAuth();
|
|
const query = useQuery({
|
|
queryKey: [path, token],
|
|
queryFn: () => apiGet<T[]>(path, token ?? ""),
|
|
enabled: Boolean(token)
|
|
});
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<header className="flex flex-col justify-between gap-4 sm:flex-row sm:items-center">
|
|
<div>
|
|
<h1 className="text-3xl font-semibold text-text">{title}</h1>
|
|
<p className="mt-2 text-text-light">{subtitle}</p>
|
|
</div>
|
|
<button type="button" className="inline-flex h-12 items-center justify-center gap-2 rounded-lg bg-primary px-5 font-semibold text-white shadow-soft">
|
|
<Plus className="h-5 w-5" />
|
|
Neu
|
|
</button>
|
|
</header>
|
|
{query.isLoading ? (
|
|
<div className="rounded-lg border border-border bg-surface p-8 text-text-light shadow-soft">Daten werden geladen.</div>
|
|
) : query.isError ? (
|
|
<div className="rounded-lg border border-danger/30 bg-surface p-8 text-danger shadow-soft">Daten konnten nicht geladen werden.</div>
|
|
) : (
|
|
<DataTable data={query.data ?? []} columns={columns} />
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|