From 6d9e307318e2f5601a69bb0cc551b19a17b6e95f Mon Sep 17 00:00:00 2001 From: Tamas Gal Date: Thu, 16 Oct 2025 10:00:31 +0200 Subject: [PATCH] Fix formatting, add types --- feedmee/src/app/admin/page.tsx | 742 +++++++++++++++++---------------- 1 file changed, 390 insertions(+), 352 deletions(-) diff --git a/feedmee/src/app/admin/page.tsx b/feedmee/src/app/admin/page.tsx index 3532668..e593e36 100644 --- a/feedmee/src/app/admin/page.tsx +++ b/feedmee/src/app/admin/page.tsx @@ -1,18 +1,15 @@ "use client"; import { useEffect, useState } from "react"; -import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"; +import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { TopBar } from "@/components/ui/topbar"; import { RefreshCw } from "lucide-react"; import { useRouter } from "next/navigation"; - - const API_URL = ""; - type User = { id: number; username: string; @@ -31,11 +28,10 @@ type Order = { type FinalizedSummary = { pickup: string[]; kitchen: string[] }; - -type MenuItem = { - id: number; - category: string; - name: string +type MenuItem = { + id: number; + category: string; + name: string; }; export default function AdminPage() { @@ -55,40 +51,40 @@ export default function AdminPage() { const [lastSummary, setLastSummary] = useState(null); const auth = (): Record => { - const token = localStorage.getItem("token"); - return token ? { Authorization: `Bearer ${token}` } : {}; + const token = localStorage.getItem("token"); + return token ? { Authorization: `Bearer ${token}` } : {}; }; useEffect(() => { fetch(`${API_URL}/api/admin/finalize/time`, { headers: auth() }) - .then(r => r.json()) - .then(data => setFinalizeTime(data.time)); + .then((r) => r.json()) + .then((data) => setFinalizeTime(data.time)); }, []); useEffect(() => { const token = localStorage.getItem("token"); if (!token) { - router.push("/auth"); - return; + router.push("/auth"); + return; } fetch(`${API_URL}/api/me`, { - headers: { Authorization: `Bearer ${token}` } + headers: { Authorization: `Bearer ${token}` }, }) - .then(res => res.json()) - .then(data => { + .then((res) => res.json()) + .then((data) => { if (!data.role || data.role > 1) { - router.push("/landing"); + router.push("/landing"); } - }) - .catch(() => router.push("/auth")); + }) + .catch(() => router.push("/auth")); }, [router]); useEffect(() => { fetch(`${API_URL}/api/admin/users`, { headers: auth() }) - .then(r => r.ok ? r.json() : []) - .then(setUsers) - .catch(() => setUsers([])); + .then((r) => (r.ok ? r.json() : [])) + .then(setUsers) + .catch(() => setUsers([])); }, []); useEffect(() => { @@ -97,9 +93,9 @@ export default function AdminPage() { useEffect(() => { fetch(`${API_URL}/api/admin/menu`, { headers: auth() }) - .then((res) => res.json()) - .then((data: MenuItem[]) => setMenuItems(data || [])) - .catch(() => setMenuItems([])); + .then((res) => res.json()) + .then((data: MenuItem[]) => setMenuItems(data || [])) + .catch(() => setMenuItems([])); }, []); useEffect(() => { @@ -108,15 +104,17 @@ export default function AdminPage() { async function refreshOrders() { try { - const res = await fetch(`${API_URL}/api/admin/orders`, { headers: auth() }); - if (res.ok) { + const res = await fetch(`${API_URL}/api/admin/orders`, { + headers: auth(), + }); + if (res.ok) { const data: Order[] = await res.json(); setOrders(data || []); - } else { + } else { setOrders([]); - } + } } catch { - setOrders([]); + setOrders([]); } } @@ -128,9 +126,13 @@ export default function AdminPage() { async function addMenuItem() { await fetch(`${API_URL}/api/admin/menu`, { - method: "POST", - headers: { "Content-Type": "application/json", ...auth() }, - body: JSON.stringify({ action: "add", category: newCategory, name: newItem }), + method: "POST", + headers: { "Content-Type": "application/json", ...auth() }, + body: JSON.stringify({ + action: "add", + category: newCategory, + name: newItem, + }), }); setNewItem(""); await refreshMenu(); @@ -139,9 +141,13 @@ export default function AdminPage() { async function updateMenuItem() { if (!editingItem) return; await fetch(`${API_URL}/api/admin/menu`, { - method: "POST", - headers: { "Content-Type": "application/json", ...auth() }, - body: JSON.stringify({ action: "update", id: editingItem.id, name: editingItem.name }), + method: "POST", + headers: { "Content-Type": "application/json", ...auth() }, + body: JSON.stringify({ + action: "update", + id: editingItem.id, + name: editingItem.name, + }), }); setEditingItem(null); await refreshMenu(); @@ -149,47 +155,55 @@ export default function AdminPage() { async function deleteMenuItem(id: number) { await fetch(`${API_URL}/api/admin/menu`, { - method: "POST", - headers: { "Content-Type": "application/json", ...auth() }, - body: JSON.stringify({ action: "delete", id }), + method: "POST", + headers: { "Content-Type": "application/json", ...auth() }, + body: JSON.stringify({ action: "delete", id }), }); await refreshMenu(); } async function deleteUser(id: number) { if (!confirm("Biztos törlöd a felhasználót?")) return; - await fetch(`${API_URL}/api/admin/users/${id}`, { method: "DELETE", headers: auth() }); + await fetch(`${API_URL}/api/admin/users/${id}`, { + method: "DELETE", + headers: auth(), + }); setUsers((prev) => prev.filter((u) => u.id !== id)); } async function updateUser(id: number) { - const body: any = {}; + const body: { + username?: string; + password?: string; + role?: number; + } = {}; + if (newUsername) body.username = newUsername; if (newPassword) body.password = newPassword; if (newRole !== null) body.role = newRole; await fetch(`${API_URL}/api/admin/users/${id}`, { - method: "PUT", - headers: { "Content-Type": "application/json", ...auth() }, - body: JSON.stringify(body), + method: "PUT", + headers: { "Content-Type": "application/json", ...auth() }, + body: JSON.stringify(body), }); setUsers((prev) => - prev.map((u) => + prev.map((u) => u.id === id ? { ...u, username: body.username || u.username } : u - ) + ) ); setUsers((prev) => - prev.map((u) => - u.id === id - ? { - ...u, - username: body.username ?? u.username, - role: body.role ?? u.role, - } - : u - ) + prev.map((u) => + u.id === id + ? { + ...u, + username: body.username ?? u.username, + role: body.role ?? u.role, + } + : u + ) ); setEditing(null); @@ -200,17 +214,17 @@ export default function AdminPage() { function toggleSelect(id: number) { setSelectedOrders((prev) => - prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id] + prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id] ); } async function updateStatusSelected(status: string) { for (const id of selectedOrders) { - await fetch(`${API_URL}/api/admin/orders/${id}/status`, { + await fetch(`${API_URL}/api/admin/orders/${id}/status`, { method: "PUT", headers: { "Content-Type": "application/json", ...auth() }, body: JSON.stringify({ status }), - }); + }); } setSelectedOrders([]); @@ -219,14 +233,17 @@ export default function AdminPage() { async function deleteSelected() { await Promise.all( - selectedOrders.map(async (id) => { + selectedOrders.map(async (id) => { await fetch(`${API_URL}/api/admin/orders/${id}/status`, { - method: "PUT", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ status: "history" }), + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ status: "history" }), }); - await fetch(`${API_URL}/api/admin/orders/${id}`, { method: "DELETE", headers: auth() }); - }) + await fetch(`${API_URL}/api/admin/orders/${id}`, { + method: "DELETE", + headers: auth(), + }); + }) ); const res = await fetch(`${API_URL}/api/admin/orders`); setSelectedOrders([]); @@ -235,14 +252,16 @@ export default function AdminPage() { async function saveFinalizeTime() { await fetch(`${API_URL}/api/admin/finalize/time`, { - method: "POST", - headers: { "Content-Type": "application/json", ...auth() }, - body: JSON.stringify({ time: finalizeTime }), + method: "POST", + headers: { "Content-Type": "application/json", ...auth() }, + body: JSON.stringify({ time: finalizeTime }), }); } async function loadLastSummary() { - const res = await fetch(`${API_URL}/api/mod/finalize/last`, { headers: auth() }); + const res = await fetch(`${API_URL}/api/mod/finalize/last`, { + headers: auth(), + }); const data = await res.json(); if (data.status !== "none") setLastSummary(data); else setLastSummary(null); @@ -250,341 +269,360 @@ export default function AdminPage() { async function triggerFinalizeNow() { await fetch(`${API_URL}/api/admin/finalize/now`, { - method: "POST", - headers: auth(), + method: "POST", + headers: auth(), }); await loadLastSummary(); } return (
- -
+ +
-

+

Users -

+ -
+
- {users.length > 0 ? ( + {users.length > 0 ? ( users.map((u) => ( - - {editing === u.id ? ( -
- {/* Keep current username visible */} - - {u.username} (role: {u.role}) - + + {editing === u.id ? ( +
+ {/* Keep current username visible */} + + {u.username}{" "} + + (role: {u.role}) + + - {/* Inputs + buttons */} -
- setNewUsername(e.target.value)} - className="bg-white/70 text-black sm:w-40 border-white" - /> - setNewPassword(e.target.value)} - className="bg-white/70 text-black sm:w-40 border-white" - /> - setNewRole(Number(e.target.value))} - className="bg-white/70 text-black sm:w-20 border-white" - /> -
- - -
-
+ {/* Inputs + buttons */} +
+ setNewUsername(e.target.value)} + className="bg-white/70 text-black sm:w-40 border-white" + /> + setNewPassword(e.target.value)} + className="bg-white/70 text-black sm:w-40 border-white" + /> + setNewRole(Number(e.target.value))} + className="bg-white/70 text-black sm:w-20 border-white" + /> +
+ + +
- ) : ( - <> - - {u.username} (role: {u.role}) - -
- - -
- - )} - - - +
+ ) : ( + <> + + {u.username}{" "} + + (role: {u.role}) + + +
+ + +
+ + )} +
)) - ) : ( + ) : (

No registered users.

- )} -
+ )}
+
- {/* Orders panel */} -

+ {/* Orders panel */} +

Orders -

+ -
+
- {orders.length > 0 ? ( + {orders.length > 0 ? ( orders.map((o) => ( - toggleSelect(o.id)} className={`glass-panel p-3 cursor-pointer ${ - selectedOrders.includes(o.id) ? "ring-2 ring-orange-400" : "" + selectedOrders.includes(o.id) ? "ring-2 ring-orange-400" : "" }`} - > + > -
+
{o.username}:{" "} {o.soup && o.soup.trim() !== "" ? `${o.soup}, ` : ""} {o.main}, {o.side} - {o.status} + {o.status} -
- +
+ {new Date(o.created_at).toLocaleString()} - +
-
+ )) - ) : ( + ) : (

No orders to display.

- )} + )}
{/* Action buttons */}
- - - - + + + +
-
- - {/* Menu Management Panel */} -

- Menu Editor -

+
-
-
- {["soup", "main", "side"].map((cat) => ( -
-

- {cat === "soup" ? "Soups" : cat === "main" ? "Main courses" : "Sides"} -

+ {/* Menu Management Panel */} +

+ Menu Editor +

-
- {menuItems.filter((i) => i.category === cat).map((item) => ( - - {editingItem?.id === item.id ? ( -
- - setEditingItem({ ...editingItem, name: e.target.value }) - } - className="bg-white/70 text-black sm:w-40 border-white" - /> -
- - -
-
- ) : ( - <> - {item.name} -
- - -
- - )} -
- ))} -
+
+
+ {["soup", "main", "side"].map((cat) => ( +
+

+ {cat === "soup" + ? "Soups" + : cat === "main" + ? "Main courses" + : "Sides"} +

- {/* Add new item for this category */} -
- { - setNewItem(e.target.value); - setNewCategory(cat); - }} - className="bg-white/70 text-black sm:w-2/3 border-white" - /> - -
-
- ))} -
-
+ {editingItem?.id === item.id ? ( +
+ + setEditingItem({ + ...editingItem, + name: e.target.value, + }) + } + className="bg-white/70 text-black sm:w-40 border-white" + /> +
+ + +
+
+ ) : ( + <> + + {item.name} + +
+ + +
+ + )} + + ))} +
-

- Order Finalization -

- -
-
- setFinalizeTime(e.target.value)} - className="bg-white/70 text-black rounded px-2 py-1 border border-white w-full sm:w-40" + {/* Add new item for this category */} +
+ { + setNewItem(e.target.value); + setNewCategory(cat); + }} + className="bg-white/70 text-black sm:w-2/3 border-white" /> - +
+
+ ))} +
+
+ +

+ Order Finalization +

+ +
+
+ setFinalizeTime(e.target.value)} + className="bg-white/70 text-black rounded px-2 py-1 border border-white w-full sm:w-40" + /> + + +
+
+ + {/* Finalized Order Summary Panel */} +

+ Legutóbbi összesítés +

+ +
+ {lastSummary ? ( + <> +
+

+ Átvételi nézet +

+
    + {lastSummary.pickup.map((line, idx) => ( +
  • {line}
  • + ))} +
-
- - {/* Finalized Order Summary Panel */} -

- Legutóbbi összesítés -

- -
- {lastSummary ? ( - <> -
-

Átvételi nézet

-
    - {lastSummary.pickup.map((line, idx) => ( -
  • {line}
  • - ))} -
-
- -
-

Konyha nézet

-
    - {lastSummary.kitchen.map((line, idx) => ( -
  • {line}
  • - ))} -
-
- - ) : ( -

Nincs elérhető összesítés.

- )} -
- +
+

+ Konyha nézet +

+
    + {lastSummary.kitchen.map((line, idx) => ( +
  • {line}
  • + ))} +
+
+ + ) : ( +

Nincs elérhető összesítés.

+ )} +
); }