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 && (
)}
{/* Formularz tworzenia (ukryty domyślnie) */}
{showCreateForm && (
)}
{/* 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 */}
);
})
)}
);
}