From 1d5dea8ff1963273287c28bd33063bd8ef6387c5 Mon Sep 17 00:00:00 2001 From: Marc Wieland Date: Tue, 29 Apr 2025 13:16:54 +0200 Subject: [PATCH] Neue Teamuebersicht --- src/admin/AdminDashboard.tsx | 13 ++- src/admin/PlayerEdit.tsx | 82 +++++++++++++++---- src/admin/PlayerManagementPage.tsx | 101 +++++++++++++++++++++++ src/admin/TeamCreate.tsx | 83 ++++++++++++++++--- src/admin/TeamDetail.tsx | 123 ++++++++++++++++++++--------- src/main.tsx | 2 + 6 files changed, 338 insertions(+), 66 deletions(-) create mode 100644 src/admin/PlayerManagementPage.tsx diff --git a/src/admin/AdminDashboard.tsx b/src/admin/AdminDashboard.tsx index 58a97fb14..54c62cc3d 100644 --- a/src/admin/AdminDashboard.tsx +++ b/src/admin/AdminDashboard.tsx @@ -18,8 +18,8 @@ const AdminDashboard = () => { -
- {/* Jeder eingeloggt Benutzer darf News verwalten */} +
+ {/* Jeder Benutzer darf News verwalten */} @@ -49,6 +49,15 @@ const AdminDashboard = () => { + + + + + Spieler verwalten +

Alle Spieler sehen und bearbeiten

+
+
+
); diff --git a/src/admin/PlayerEdit.tsx b/src/admin/PlayerEdit.tsx index 74e2aa227..4d349f410 100644 --- a/src/admin/PlayerEdit.tsx +++ b/src/admin/PlayerEdit.tsx @@ -2,14 +2,21 @@ import { useEffect, useState } from "react"; import { useParams, useNavigate, Link } from "react-router-dom"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; -import { useToast } from "@/components/ui//use-toast"; +import { useToast } from "@/components/ui/use-toast"; +import { Label } from "@/components/ui/label"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; const apiBase = import.meta.env.VITE_API_URL; +type Team = { + id: number; + name: string; +}; + const PlayerEdit = () => { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); - const {toast} = useToast(); + const { toast } = useToast(); const [name, setName] = useState(""); const [nickname, setNickname] = useState(""); @@ -21,8 +28,12 @@ const PlayerEdit = () => { const [imageUrl, setImageUrl] = useState(null); const [uploading, setUploading] = useState(false); + const [teams, setTeams] = useState([]); + const [selectedTeamId, setSelectedTeamId] = useState(null); + useEffect(() => { fetchPlayer(); + fetchTeams(); }, [id]); const fetchPlayer = async () => { @@ -38,11 +49,24 @@ const PlayerEdit = () => { setFavoriteFood(data.favorite_food || ""); setStatus(data.status || "aktiv"); setImageUrl(data.image_url ? `${apiBase}${data.image_url}` : null); + if (data.team_ids && data.team_ids.length > 0) { + setSelectedTeamId(data.team_ids[0]); + } } catch (err) { console.error("Fehler beim Laden des Spielers:", err); } }; + const fetchTeams = async () => { + try { + const res = await fetch(`${apiBase}/api/teams`); + const data = await res.json(); + setTeams(data); + } catch (err) { + console.error("Fehler beim Laden der Teams:", err); + } + }; + const handleImageUpload = async (file: File) => { const formData = new FormData(); formData.append("image", file); @@ -67,6 +91,7 @@ const PlayerEdit = () => { const handleSave = async () => { try { + // Spieler speichern const res = await fetch(`${apiBase}/api/players/${id}`, { method: "PUT", headers: { "Content-Type": "application/json" }, @@ -78,26 +103,33 @@ const PlayerEdit = () => { birthdate, favorite_food: favoriteFood, status, - image_url: imageUrl?.replace(apiBase, ""), // Nur Pfad speichern + image_url: imageUrl?.replace(apiBase, ""), }), }); - - if (res.ok) { - toast({ - title: "Spieler gespeichert", - description: "Die Änderungen wurden erfolgreich übernommen.", + + if (!res.ok) throw new Error("Fehler beim Speichern"); + + // Teamzuordnung aktualisieren + if (selectedTeamId) { + await fetch(`${apiBase}/api/players/${id}/assign-team`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ team_id: selectedTeamId }), }); - setTimeout(() => { - navigate(-1); - }, 500); // Warte kurz, damit der Toast sichtbar bleibt - } else { - console.error("Fehler beim Speichern"); } + + toast({ + title: "Spieler gespeichert", + description: "Die Änderungen wurden erfolgreich übernommen.", + }); + + setTimeout(() => { + navigate(-1); + }, 500); } catch (err) { console.error("Fehler beim Speichern:", err); } }; - return (
@@ -130,6 +162,26 @@ const PlayerEdit = () => { onChange={(e) => setStatus(e.target.value)} /> + {/* Team Auswahl */} +
+ + +
+ {/* Bild-Upload */} { {/* Buttons */}
+ +
+ + + ))} +
+ )} + + ); +}; + +export default PlayerManagementPage; diff --git a/src/admin/TeamCreate.tsx b/src/admin/TeamCreate.tsx index fea5f598b..39883304a 100644 --- a/src/admin/TeamCreate.tsx +++ b/src/admin/TeamCreate.tsx @@ -2,11 +2,26 @@ import { useState } from "react"; import { useNavigate } from "react-router-dom"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Textarea } from "@/components/ui/textarea"; const apiBase = import.meta.env.VITE_API_URL; const TeamCreate = () => { const [teamName, setTeamName] = useState(""); + const [liga, setLiga] = useState(""); + const [suchtSpieler, setSuchtSpieler] = useState(false); + const [socialMedia, setSocialMedia] = useState(""); + const [trainerName, setTrainerName] = useState(""); + const [carouselImages, setCarouselImages] = useState(""); + const [trainingszeiten, setTrainingszeiten] = useState(""); + const [trainingsort, setTrainingsort] = useState(""); + const [kontaktName, setKontaktName] = useState(""); + const [kontaktEmail, setKontaktEmail] = useState(""); + const [teamfarben, setTeamfarben] = useState(""); + const [beschreibung, setBeschreibung] = useState(""); + const [tabellenlink, setTabellenlink] = useState(""); + const [saving, setSaving] = useState(false); const [errorMsg, setErrorMsg] = useState(""); @@ -14,23 +29,37 @@ const TeamCreate = () => { const handleSave = async () => { if (!teamName.trim()) return; - + setSaving(true); setErrorMsg(""); - + try { const res = await fetch(`${apiBase}/api/teams`, { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ name: teamName }), + body: JSON.stringify({ + name: teamName, + liga, + sucht_spieler: suchtSpieler, + social_media: socialMedia, + karussell_bilder: carouselImages.trim() ? JSON.parse(carouselImages) : [], + trainer_name: trainerName, + trainingszeiten, + trainingsort, + kontakt_name: kontaktName, + kontakt_email: kontaktEmail, + teamfarben, + beschreibung, + tabellenlink, + }), }); - + if (!res.ok) { const msg = await res.text(); setErrorMsg(msg); throw new Error(msg); } - + navigate("/admin/teams"); } catch (err) { console.error(err); @@ -38,22 +67,50 @@ const TeamCreate = () => { setSaving(false); } }; - return (

Neues Team anlegen

+
- setTeamName(e.target.value)} - /> + setTeamName(e.target.value)} /> + setLiga(e.target.value)} /> + setTrainerName(e.target.value)} /> + setTrainingszeiten(e.target.value)} /> + setTrainingsort(e.target.value)} /> + setKontaktName(e.target.value)} /> + setKontaktEmail(e.target.value)} /> + setTeamfarben(e.target.value)} /> +