Commit 4: Kategorien-API (CRUD + Reorder) und Favoriten-Toggle im Frontend

This commit is contained in:
2026-07-19 02:10:08 +02:00
parent f963f7eb4e
commit 129b4253b5
9 changed files with 261 additions and 19 deletions

View File

@@ -1,4 +1,5 @@
import { useEffect, useMemo, useRef, useState } from "react";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { SearchInput, StatusBadge, ResultsList } from "@launchpad/ui";
import { rankServices, type Service, type HealthStatus } from "@launchpad/shared";
import { useServices } from "./hooks/useServices.js";
@@ -60,6 +61,18 @@ function openService(service: Service) {
window.open(service.url, "_blank", "noopener,noreferrer");
}
async function toggleServiceFavorite(service: Service): Promise<Service> {
const res = await fetch(`/api/services/${service.id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ favorite: !service.favorite }),
});
if (!res.ok) {
throw new Error(`Favorit konnte nicht aktualisiert werden (HTTP ${res.status})`);
}
return res.json();
}
export default function App() {
const [theme, toggleTheme] = useTheme();
const [query, setQuery] = useState("");
@@ -67,6 +80,14 @@ export default function App() {
const { health, error: healthError } = useBackendHealth();
const { data: services, isLoading, isError } = useServices();
const inputRef = useRef<HTMLInputElement>(null);
const queryClient = useQueryClient();
const toggleFavorite = useMutation({
mutationFn: toggleServiceFavorite,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["services"] });
},
});
const results = useMemo(
() => rankServices(services ?? [], query),
@@ -157,6 +178,7 @@ export default function App() {
selectedIndex={selectedIndex}
onHover={setSelectedIndex}
onOpen={openService}
onToggleFavorite={(service) => toggleFavorite.mutate(service)}
emptyLabel={
(services?.length ?? 0) === 0
? "Noch keine Dienste angelegt. Füge welche über die API hinzu."