diff --git a/app/admin/page.tsx b/app/admin/page.tsx deleted file mode 100644 index 2d28abd..0000000 --- a/app/admin/page.tsx +++ /dev/null @@ -1,483 +0,0 @@ -"use client" - -import { useState, useEffect, Suspense } from "react" -import { useSearchParams, useRouter } from "next/navigation" -import { motion, AnimatePresence } from "framer-motion" -import { Restaurant } from "@/app/types" - -function priceLabel(range: number) { - return "€".repeat(range) -} - -function AdminContent() { - const searchParams = useSearchParams() - const router = useRouter() - const preselectedId = searchParams.get("restaurant") - - const [restaurants, setRestaurants] = useState([]) - const [loading, setLoading] = useState(true) - const [activeTab, setActiveTab] = useState<"add-restaurant" | "add-visit" | "manage">( - preselectedId ? "add-visit" : "add-restaurant" - ) - const [feedback, setFeedback] = useState(null) - - // Add restaurant form - const [rForm, setRForm] = useState({ - name: "", - city: "", - country: "", - address: "", - lat: "", - lng: "", - cuisine: "", - price_range: "2", - }) - - // Add visit form - const [vForm, setVForm] = useState({ - restaurantId: preselectedId || "", - date: new Date().toISOString().slice(0, 10), - dishes: "", - rating: "8", - notes: "", - price_paid: "", - }) - - useEffect(() => { - fetch("/api/restaurants") - .then((r) => r.json()) - .then((data) => { - setRestaurants(data) - setLoading(false) - }) - .catch(() => setLoading(false)) - }, []) - - function showFeedback(msg: string) { - setFeedback(msg) - setTimeout(() => setFeedback(null), 3000) - } - - async function handleAddRestaurant(e: React.FormEvent) { - e.preventDefault() - const body = { - name: rForm.name, - city: rForm.city, - country: rForm.country, - address: rForm.address, - lat: parseFloat(rForm.lat), - lng: parseFloat(rForm.lng), - cuisine: rForm.cuisine.split(",").map((c) => c.trim()).filter(Boolean), - price_range: parseInt(rForm.price_range) as 1 | 2 | 3 | 4, - } - const res = await fetch("/api/restaurants", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(body), - }) - if (res.ok) { - const newR = await res.json() - setRestaurants((prev) => [...prev, newR]) - setRForm({ name: "", city: "", country: "", address: "", lat: "", lng: "", cuisine: "", price_range: "2" }) - showFeedback("Restaurant added!") - } else { - showFeedback("Error adding restaurant") - } - } - - async function handleAddVisit(e: React.FormEvent) { - e.preventDefault() - if (!vForm.restaurantId) return - - const body = { - date: new Date(vForm.date).toISOString(), - dishes: vForm.dishes.split("\n").map((d) => d.trim()).filter(Boolean), - rating: parseInt(vForm.rating), - notes: vForm.notes, - ...(vForm.price_paid ? { price_paid: parseFloat(vForm.price_paid) } : {}), - } - const res = await fetch(`/api/restaurants/${vForm.restaurantId}/visits`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(body), - }) - if (res.ok) { - setVForm((prev) => ({ ...prev, dishes: "", notes: "", price_paid: "" })) - showFeedback("Visit added!") - // Refresh - fetch("/api/restaurants") - .then((r) => r.json()) - .then(setRestaurants) - } else { - showFeedback("Error adding visit") - } - } - - async function handleDeleteVisit(restaurantId: string, visitId: string) { - if (!confirm("Delete this visit?")) return - const res = await fetch(`/api/restaurants/${restaurantId}/visits/${visitId}`, { - method: "DELETE", - }) - if (res.ok) { - setRestaurants((prev) => - prev.map((r) => - r.id === restaurantId - ? { ...r, visits: r.visits.filter((v) => v.id !== visitId) } - : r - ) - ) - showFeedback("Visit deleted") - } - } - - async function handleDeleteRestaurant(restaurantId: string) { - if (!confirm("Delete this restaurant and all its visits?")) return - const res = await fetch(`/api/restaurants/${restaurantId}`, { method: "DELETE" }) - if (res.ok) { - setRestaurants((prev) => prev.filter((r) => r.id !== restaurantId)) - showFeedback("Restaurant deleted") - } - } - - const inputClass = - "w-full bg-white/[0.04] border border-white/[0.08] rounded-xl px-4 py-3 text-sm text-[#f5f5f5] placeholder-white/25 outline-none focus:border-[#f59e0b]/40 focus:bg-white/[0.06] transition-all" - const labelClass = "block text-xs font-semibold uppercase tracking-wider text-white/40 mb-1.5" - - const tabs = [ - { id: "add-restaurant", label: "New Place" }, - { id: "add-visit", label: "Add Visit" }, - { id: "manage", label: "Manage" }, - ] as const - - return ( -
- {/* Header */} - -

admin

-

manage your food journal

-
- - {/* Feedback toast */} - - {feedback && ( - - {feedback} - - )} - - - {/* Tabs */} -
- {tabs.map((tab) => ( - - ))} -
- - {/* Add Restaurant */} - {activeTab === "add-restaurant" && ( - -
-
- - setRForm({ ...rForm, name: e.target.value })} - required - /> -
-
- - setRForm({ ...rForm, city: e.target.value })} - required - /> -
-
- - setRForm({ ...rForm, country: e.target.value })} - required - /> -
-
- - -
-
- -
- - setRForm({ ...rForm, address: e.target.value })} - required - /> -
- -
-
- - setRForm({ ...rForm, lat: e.target.value })} - required - /> -
-
- - setRForm({ ...rForm, lng: e.target.value })} - required - /> -
-
- -
- - setRForm({ ...rForm, cuisine: e.target.value })} - required - /> -
- - -
- )} - - {/* Add Visit */} - {activeTab === "add-visit" && ( - -
- - -
- -
-
- - setVForm({ ...vForm, date: e.target.value })} - required - /> -
-
- - setVForm({ ...vForm, rating: e.target.value })} - required - /> -
-
- -
- -