diff --git a/frontend/src/pages/ChallengeDetail.jsx b/frontend/src/pages/ChallengeDetail.jsx index 7df80f3..2034b5d 100644 --- a/frontend/src/pages/ChallengeDetail.jsx +++ b/frontend/src/pages/ChallengeDetail.jsx @@ -23,6 +23,8 @@ export default function ChallengeDetail() { const [submitting, setSubmitting] = useState(false); const [validating, setValidating] = useState(null); const [deleting, setDeleting] = useState(false); + const [friends, setFriends] = useState([]); + const [inviting, setInviting] = useState(null); const searchRef = useRef(null); useClickOutside(searchRef, () => setSearchResults([])); @@ -56,11 +58,23 @@ export default function ChallengeDetail() { } }, [id]); + const loadFriends = useCallback(async () => { + try { + const data = await api.getFriends(); + // Combine regular friends and challenge friends + const allFriends = [...(data.friends || []), ...(data.challenge_friends || [])]; + setFriends(allFriends); + } catch (err) { + console.error('Failed to load friends:', err); + } + }, []); + useEffect(() => { loadChallenge(); loadPredictions(); loadLeaderboard(); - }, [loadChallenge, loadPredictions, loadLeaderboard]); + loadFriends(); + }, [loadChallenge, loadPredictions, loadLeaderboard, loadFriends]); // Join challenge room for real-time updates useEffect(() => { @@ -190,14 +204,18 @@ export default function ChallengeDetail() { setSearchTimeout(timeout); }; - const handleInvite = async (userId) => { + const handleInvite = async (userId, userName) => { + setInviting(userId); try { await api.inviteToChallenge(id, { user_ids: [userId] }); - toast.success('Invitation sent!'); + toast.success(`Invitation sent to ${userName || 'user'}!`); setInviteQuery(''); setSearchResults([]); + await loadChallenge(); // Refresh to update participant list } catch (err) { toast.error('Failed to send invite: ' + err.message); + } finally { + setInviting(null); } }; @@ -270,19 +288,64 @@ export default function ChallengeDetail() { {showInvite && (