first commit
This commit is contained in:
68
frontend/app/dashboards/page.tsx
Normal file
68
frontend/app/dashboards/page.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
"use client";
|
||||
|
||||
import Shell from "@/components/Shell";
|
||||
import { apiFetch, getCsrfFromCookie } from "@/lib/api";
|
||||
import Link from "next/link";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
type Dashboard = { id: number; name: string; is_shared: boolean };
|
||||
|
||||
export default function DashboardsPage() {
|
||||
const [items, setItems] = useState<Dashboard[]>([]);
|
||||
const [name, setName] = useState("Main");
|
||||
const [err, setErr] = useState<string | null>(null);
|
||||
|
||||
async function load() {
|
||||
setErr(null);
|
||||
try {
|
||||
const data = await apiFetch("/api/dashboards");
|
||||
setItems(data);
|
||||
} catch (e: any) {
|
||||
setErr(e.message || "error");
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => { load(); }, []);
|
||||
|
||||
async function create() {
|
||||
setErr(null);
|
||||
try {
|
||||
const csrf = getCsrfFromCookie();
|
||||
await apiFetch("/api/dashboards", {
|
||||
method: "POST",
|
||||
headers: { "X-CSRF-Token": csrf || "" },
|
||||
body: JSON.stringify({ name, is_shared: false })
|
||||
});
|
||||
await load();
|
||||
} catch (e: any) {
|
||||
setErr(e.message || "error");
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Shell>
|
||||
<div className="flex items-end justify-between gap-3">
|
||||
<div>
|
||||
<div className="text-2xl font-semibold">Dashboards</div>
|
||||
<div className="text-sm text-zinc-400">Twoje dashboardy</div>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<input className="px-3 py-2 rounded-lg bg-zinc-900 border border-zinc-700"
|
||||
value={name} onChange={e=>setName(e.target.value)} />
|
||||
<button onClick={create} className="px-3 py-2 rounded-lg bg-zinc-100 text-zinc-900">Create</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{err && <div className="mt-4 text-sm text-red-400">{err}</div>}
|
||||
|
||||
<div className="mt-6 grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-3">
|
||||
{items.map(d => (
|
||||
<Link key={d.id} href={`/dashboards/${d.id}`} className="block p-4 rounded-xl border border-zinc-800 bg-zinc-950 hover:bg-zinc-900">
|
||||
<div className="font-medium">{d.name}</div>
|
||||
<div className="text-xs text-zinc-400 mt-1">id: {d.id}</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</Shell>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user