feat: add architecture, api routes and components

This commit is contained in:
Atakan Doğan Özban
2026-07-06 02:27:06 +02:00
parent 91dbfa7d77
commit 2fe32edc3a
31 changed files with 2796 additions and 148 deletions
+118
View File
@@ -0,0 +1,118 @@
"use client";
import { useEffect, useState } from "react";
import Link from "next/link";
import { Location } from "@prisma/client";
export default function AdminDashboard() {
const [locations, setLocations] = useState<Location[]>([]);
const [loading, setLoading] = useState(true);
const fetchLocations = async () => {
try {
const res = await fetch("/api/admin/locations");
if (res.ok) {
const data = await res.json();
setLocations(data);
}
} catch (error) {
console.error("Failed to fetch locations", error);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchLocations();
}, []);
const handleDelete = async (id: string) => {
if (!confirm("Are you sure you want to delete this location?")) return;
try {
const res = await fetch(`/api/admin/locations/${id}`, {
method: "DELETE",
});
if (res.ok) {
fetchLocations();
} else {
alert("Failed to delete");
}
} catch (error) {
console.error(error);
}
};
if (loading) return <div className="text-white mt-4">Loading...</div>;
return (
<>
<div className="card shadow-sm border-0 mb-4 bg-dark text-white">
<div className="card-header bg-dark border-secondary d-flex justify-content-between align-items-center py-3">
<h5 className="mb-0 gsv-title">Manage Locations (Projects)</h5>
<Link href="/admin/new" className="btn btn-primary btn-sm">
+ Add New Project
</Link>
</div>
<div className="card-body p-0">
<div className="table-responsive">
<table className="table table-dark table-hover mb-0">
<thead>
<tr>
<th>Title</th>
<th>City</th>
<th>GPX Route</th>
<th>Visibility</th>
<th className="text-end">Actions</th>
</tr>
</thead>
<tbody>
{locations.map((loc) => (
<tr key={loc.id}>
<td>{loc.title}</td>
<td>{loc.city}</td>
<td>
{loc.gpxData ? (
<span className="badge bg-primary">Has Route</span>
) : (
<span className="badge bg-secondary">No Route</span>
)}
</td>
<td>
<span
className={`badge bg-${loc.visibility === "public" ? "success" : "secondary"
}`}
>
{loc.visibility}
</span>
</td>
<td className="text-end">
<Link
href={`/admin/edit/${loc.id}`}
className="btn btn-sm btn-outline-light me-2"
>
Edit
</Link>
<button
onClick={() => handleDelete(loc.id)}
className="btn btn-sm btn-outline-danger"
>
Delete
</button>
</td>
</tr>
))}
{locations.length === 0 && (
<tr>
<td colSpan={5} className="text-center py-4 text-muted">
No locations found. Start by adding one.
</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
</div>
</>
);
}