91 lines
4.5 KiB
TypeScript
91 lines
4.5 KiB
TypeScript
|
|
"use client";
|
||
|
|
/**
|
||
|
|
* TEE OFF ADMIN DASHBOARD v1.1
|
||
|
|
* ---------------------------------------------------------------------------
|
||
|
|
* PLASSERING: frontend/src/app/admin/page.tsx
|
||
|
|
* FUNKSJON: Monitorering av banestatus og administrasjon.
|
||
|
|
* ---------------------------------------------------------------------------
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { useState, useEffect } from 'react';
|
||
|
|
import { API_URL } from "@/config/constants";
|
||
|
|
|
||
|
|
export default function AdminDashboard() {
|
||
|
|
const [facilities, setFacilities] = useState([]);
|
||
|
|
const [loading, setLoading] = useState(true);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
fetch(`${API_URL}/facilities`)
|
||
|
|
.then(res => res.json())
|
||
|
|
.then(data => {
|
||
|
|
setFacilities(Array.isArray(data) ? data : []);
|
||
|
|
setLoading(false);
|
||
|
|
})
|
||
|
|
.catch(() => setLoading(false));
|
||
|
|
}, []);
|
||
|
|
|
||
|
|
if (loading) return <div className="p-20 text-center font-black animate-pulse">LASTER DASHBORD...</div>;
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="flex flex-col lg:flex-row min-h-screen bg-[#f1f7ed] font-sans">
|
||
|
|
{/* SIDEBAR (22%) */}
|
||
|
|
<aside className="lg:w-[22%] bg-[#11280f] text-white p-10 flex flex-col">
|
||
|
|
<h1 className="text-2xl font-black uppercase tracking-tighter mb-10">TeeOff Admin</h1>
|
||
|
|
<nav className="space-y-6 text-[10px] font-black uppercase tracking-[0.2em] text-[#7ca982] flex-grow">
|
||
|
|
<div className="text-white border-l-4 border-[#8bc34a] pl-4 py-1">Scraping Monitor</div>
|
||
|
|
<div className="hover:text-white cursor-pointer pl-4 py-1 transition-colors">Medlemskap</div>
|
||
|
|
<div className="hover:text-white cursor-pointer pl-4 py-1 transition-colors">Bildegalleri</div>
|
||
|
|
</nav>
|
||
|
|
<div className="mt-auto pt-10 border-t border-white/10">
|
||
|
|
<button onClick={() => window.location.href='/'} className="text-[10px] font-black uppercase tracking-widest text-red-400 hover:text-red-300">Logg ut</button>
|
||
|
|
</div>
|
||
|
|
</aside>
|
||
|
|
|
||
|
|
{/* HOVEDINNHOLD (78%) */}
|
||
|
|
<main className="lg:w-[78%] p-6 md:p-12">
|
||
|
|
<div className="bg-white rounded-[3rem] shadow-2xl p-10 md:p-16 border border-white">
|
||
|
|
<header className="flex justify-between items-center mb-12">
|
||
|
|
<div>
|
||
|
|
<h2 className="text-4xl font-black tracking-tighter text-[#11280f] mb-2">Scraping Monitor</h2>
|
||
|
|
<p className="text-xs font-bold text-gray-400 uppercase tracking-widest">Sjekker status på {facilities.length} anlegg</p>
|
||
|
|
</div>
|
||
|
|
<button className="bg-[#8bc34a] text-white px-8 py-4 rounded-2xl text-[10px] font-black uppercase tracking-widest shadow-xl hover:scale-105 transition-all">Kjør alle skrapere</button>
|
||
|
|
</header>
|
||
|
|
|
||
|
|
<div className="overflow-x-auto">
|
||
|
|
<table className="w-full text-left border-collapse">
|
||
|
|
<thead>
|
||
|
|
<tr className="text-[10px] font-black uppercase tracking-widest text-gray-300 border-b border-gray-50">
|
||
|
|
<th className="pb-6">Anlegg</th>
|
||
|
|
<th className="pb-6">Konfigurasjon</th>
|
||
|
|
<th className="pb-6">Siste Sjekk</th>
|
||
|
|
<th className="pb-6 text-right">Status</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody className="text-sm font-bold text-[#11280f]">
|
||
|
|
{facilities.map((f: any) => (
|
||
|
|
<tr key={f.id} className="border-b border-gray-50 group hover:bg-gray-50/50 transition-colors">
|
||
|
|
<td className="py-8">
|
||
|
|
<div className="font-black text-lg">{f.name}</div>
|
||
|
|
<div className="text-[10px] text-[#7ca982] uppercase tracking-widest">{f.city}</div>
|
||
|
|
</td>
|
||
|
|
<td className="py-8">
|
||
|
|
<div className="text-[11px] text-blue-600 truncate max-w-[200px] mb-1">{f.scrape_status_url}</div>
|
||
|
|
<div className="text-[10px] font-mono text-gray-300">{f.scrape_status_selector}</div>
|
||
|
|
</td>
|
||
|
|
<td className="py-8 text-gray-400 font-mono text-xs">
|
||
|
|
{f.status_updated_at ? new Date(f.status_updated_at).toLocaleDateString('nb-NO') : 'Aldri'}
|
||
|
|
</td>
|
||
|
|
<td className="py-8 text-right">
|
||
|
|
<button className="bg-gray-100 px-5 py-2.5 rounded-xl text-[9px] font-black uppercase tracking-widest hover:bg-[#11280f] hover:text-white transition-all">Rediger</button>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
))}
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</main>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|