refactor
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import toast from 'react-hot-toast';
|
||||
import api from '../api';
|
||||
import { useClickOutside } from '../hooks/useClickOutside';
|
||||
|
||||
export default function ChallengeList() {
|
||||
const [challenges, setChallenges] = useState([]);
|
||||
@@ -10,6 +12,10 @@ export default function ChallengeList() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [creating, setCreating] = useState(false);
|
||||
const [searchTimeout, setSearchTimeout] = useState(null);
|
||||
const [respondingTo, setRespondingTo] = useState(null);
|
||||
const searchRef = useRef(null);
|
||||
|
||||
useClickOutside(searchRef, () => setShowResults([]));
|
||||
|
||||
useEffect(() => {
|
||||
loadChallenges();
|
||||
@@ -31,11 +37,15 @@ export default function ChallengeList() {
|
||||
};
|
||||
|
||||
const handleRespondToInvite = async (challengeId, status) => {
|
||||
setRespondingTo(challengeId);
|
||||
try {
|
||||
await api.respondToChallenge(challengeId, status);
|
||||
toast.success(status === 'accepted' ? 'Challenge accepted!' : 'Challenge declined');
|
||||
await loadChallenges();
|
||||
} catch (err) {
|
||||
alert('Failed to respond: ' + err.message);
|
||||
toast.error('Failed to respond: ' + err.message);
|
||||
} finally {
|
||||
setRespondingTo(null);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -72,18 +82,19 @@ export default function ChallengeList() {
|
||||
? `https://image.tmdb.org/t/p/w500${show.poster_path}`
|
||||
: null;
|
||||
|
||||
const result = await api.createChallenge({
|
||||
await api.createChallenge({
|
||||
title: show.title,
|
||||
cover_image_url: coverImage,
|
||||
tmdb_id: show.id,
|
||||
media_type: show.media_type
|
||||
});
|
||||
|
||||
toast.success('Challenge created!');
|
||||
setSearchQuery('');
|
||||
setShowResults([]);
|
||||
await loadChallenges();
|
||||
} catch (err) {
|
||||
alert('Failed to create challenge: ' + err.message);
|
||||
toast.error('Failed to create challenge: ' + err.message);
|
||||
} finally {
|
||||
setCreating(false);
|
||||
}
|
||||
@@ -124,14 +135,16 @@ export default function ChallengeList() {
|
||||
<button
|
||||
className="btn btn-success btn-sm"
|
||||
onClick={() => handleRespondToInvite(challenge.id, 'accepted')}
|
||||
disabled={respondingTo === challenge.id}
|
||||
>
|
||||
Accept
|
||||
{respondingTo === challenge.id ? '...' : 'Accept'}
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-danger btn-sm"
|
||||
onClick={() => handleRespondToInvite(challenge.id, 'rejected')}
|
||||
disabled={respondingTo === challenge.id}
|
||||
>
|
||||
Decline
|
||||
{respondingTo === challenge.id ? '...' : 'Decline'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -141,7 +154,7 @@ export default function ChallengeList() {
|
||||
)}
|
||||
|
||||
{/* Search/Create */}
|
||||
<div style={{ marginBottom: '2rem', position: 'relative' }}>
|
||||
<div style={{ marginBottom: '2rem', position: 'relative' }} ref={searchRef}>
|
||||
<input
|
||||
type="text"
|
||||
className="input"
|
||||
|
||||
Reference in New Issue
Block a user