import React, { useState, useEffect } from 'react'; import { initializeApp } from 'firebase/app'; import { getAuth, signInAnonymously, onAuthStateChanged, signInWithCustomToken } from 'firebase/auth'; import { getFirestore, collection, addDoc, onSnapshot, doc, updateDoc, deleteDoc, serverTimestamp } from 'firebase/firestore'; import { Calendar, Clock, Users, PlusCircle, Trash2, UserPlus, UserMinus, Share2, AlertCircle, Trophy } from 'lucide-react'; // --- Konfiguracja Firebase (Zgodna z instrukcjami) --- const firebaseConfig = JSON.parse(__firebase_config); const app = initializeApp(firebaseConfig); const auth = getAuth(app); const db = getFirestore(app); const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; // Główny komponent aplikacji export default function FootballApp() { const [user, setUser] = useState(null); const [matches, setMatches] = useState([]); const [loading, setLoading] = useState(true); // Stan formularzy const [newMatchData, setNewMatchData] = useState({ date: '', time: '20:00', location: 'Orlik', maxPlayers: 14 }); const [playerName, setPlayerName] = useState(''); const [showCreateForm, setShowCreateForm] = useState(false); const [errorMsg, setErrorMsg] = useState(''); // 1. Inicjalizacja Autentykacji useEffect(() => { const initAuth = async () => { try { if (typeof __initial_auth_token !== 'undefined' && __initial_auth_token) { await signInWithCustomToken(auth, __initial_auth_token); } else { await signInAnonymously(auth); } } catch (error) { console.error("Błąd autoryzacji:", error); } }; initAuth(); const unsubscribe = onAuthStateChanged(auth, (currentUser) => { setUser(currentUser); // Próbujemy odzyskać imię z localStorage jeśli użytkownik wraca const savedName = localStorage.getItem('football_player_name'); if (savedName) setPlayerName(savedName); }); return () => unsubscribe(); }, []); // 2. Pobieranie danych (Mecze) - Realtime useEffect(() => { if (!user) return; // Ścieżka publiczna - wszyscy widzą te same mecze const matchesRef = collection(db, 'artifacts', appId, 'public', 'data', 'matches'); const unsubscribe = onSnapshot(matchesRef, (snapshot) => { const matchesList = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); // Sortowanie po dacie (najbliższe najpierw) - robimy to w JS // Zakładamy format YYYY-MM-DD matchesList.sort((a, b) => { const dateA = new Date(`${a.date}T${a.time}`); const dateB = new Date(`${b.date}T${b.time}`); return dateA - dateB; }); setMatches(matchesList); setLoading(false); }, (error) => { console.error("Błąd pobierania danych:", error); setErrorMsg("Nie udało się pobrać listy meczów."); setLoading(false); } ); return () => unsubscribe(); }, [user]); // Funkcja tworzenia meczu const handleCreateMatch = async (e) => { e.preventDefault(); if (!user) return; if (!newMatchData.date || !newMatchData.time) { setErrorMsg("Podaj datę i godzinę."); return; } try { const matchesRef = collection(db, 'artifacts', appId, 'public', 'data', 'matches'); await addDoc(matchesRef, { ...newMatchData, createdBy: user.uid, createdAt: serverTimestamp(), players: [] // Pusta tablica na start }); setShowCreateForm(false); setNewMatchData({ ...newMatchData, date: '' }); // Reset daty } catch (err) { console.error(err); setErrorMsg("Błąd podczas tworzenia meczu."); } }; // Funkcja usuwania meczu (tylko twórca lub dla uproszczenia każdy w tym demo) const handleDeleteMatch = async (matchId) => { if (!confirm("Czy na pewno chcesz usunąć to wydarzenie?")) return; try { const matchDoc = doc(db, 'artifacts', appId, 'public', 'data', 'matches', matchId); await deleteDoc(matchDoc); } catch (err) { console.error(err); } }; // Funkcja dołączenia do meczu const handleJoin = async (match) => { if (!playerName.trim()) { setErrorMsg("Wpisz swoje imię/ksywkę, aby dołączyć."); return; } // Zapisz imię w pamięci lokalnej dla wygody localStorage.setItem('football_player_name', playerName); // Sprawdź czy gracz już jest na liście const isAlreadyJoined = match.players.some(p => p.uid === user.uid || p.name.toLowerCase() === playerName.toLowerCase()); if (isAlreadyJoined) { setErrorMsg("Już jesteś na liście!"); setTimeout(() => setErrorMsg(''), 3000); return; } const newPlayer = { name: playerName, uid: user.uid, joinedAt: Date.now() }; try { const matchDoc = doc(db, 'artifacts', appId, 'public', 'data', 'matches', match.id); // Kopiujemy tablicę i dodajemy nowego gracza const updatedPlayers = [...match.players, newPlayer]; await updateDoc(matchDoc, { players: updatedPlayers }); setErrorMsg(''); } catch (err) { console.error(err); setErrorMsg("Nie udało się zapisać."); } }; // Funkcja wypisania się const handleLeave = async (match, playerUid) => { // Pozwalamy usuwać tylko siebie, chyba że jesteśmy twórcą meczu (tu uproszczone: każdy może usunąć siebie) // Dodajemy małe zabezpieczenie UI try { const matchDoc = doc(db, 'artifacts', appId, 'public', 'data', 'matches', match.id); const updatedPlayers = match.players.filter(p => p.uid !== playerUid); await updateDoc(matchDoc, { players: updatedPlayers }); } catch (err) { console.error(err); } }; // Kopiowanie linku const copyLink = () => { const url = window.location.href; // Fallback dla iframe const textArea = document.createElement("textarea"); textArea.value = url; document.body.appendChild(textArea); textArea.select(); try { document.execCommand('copy'); alert("Link skopiowany do schowka! Wyślij go na Messengerze."); } catch (err) { console.error('Nie udało się skopiować', err); } document.body.removeChild(textArea); }; if (loading) { return (
); } return (
{/* Header */}

Piłka - Zapisy

{/* Error Message Toast */} {errorMsg && (

{errorMsg}

)} {/* Formularz tworzenia (ukryty domyślnie) */} {showCreateForm && (

Utwórz nowe wydarzenie

setNewMatchData({...newMatchData, date: e.target.value})} required />
setNewMatchData({...newMatchData, time: e.target.value})} required />
setNewMatchData({...newMatchData, maxPlayers: parseInt(e.target.value)})} min="2" max="30" />
setNewMatchData({...newMatchData, location: e.target.value})} placeholder="np. Orlik Centrum" />
)} {/* Lista Meczów */} {matches.length === 0 ? (

Brak zaplanowanych gier.

Kliknij "Nowy Mecz" aby rozpocząć zapisy.

) : ( matches.map(match => { const playerCount = match.players.length; const isFull = playerCount >= match.maxPlayers; const spotsLeft = match.maxPlayers - playerCount; // Podział na skład i rezerwę const mainSquad = match.players.slice(0, match.maxPlayers); const reserves = match.players.slice(match.maxPlayers); const myEntry = match.players.find(p => p.uid === user?.uid); return (
{/* Karta Meczu Header */}

{match.location}

{match.date} {match.time}
{/* Pasek postępu */}
{isFull ? "Lista Pełna!" : `Wolne miejsca: ${spotsLeft}`} {playerCount}/{match.maxPlayers}
{/* Sekcja Zapisów */}
{!myEntry ? (
setPlayerName(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') handleJoin(match); }} />
) : (
Jesteś na liście jako {myEntry.name}
)} {/* Lista Graczy */}

SKŁAD PODSTAWOWY

    {mainSquad.map((player, idx) => (
  • {idx + 1} {player.name} {/* Opcja usunięcia kogoś innego (dla admina/organizatora) - tutaj dostępna dla każdego dla wygody */}
  • ))} {mainSquad.length === 0 &&
  • Lista jest pusta. Bądź pierwszy!
  • }
{/* Lista Rezerwowa */} {reserves.length > 0 && (

LISTA REZERWOWA

    {reserves.map((player, idx) => (
  • R{idx + 1} {player.name}
  • ))}
)} {/* Przycisk Udostępnij */}
); }) )}
); }