feat: add match data to suggestions and chat link for accepted recordings
Backend changes:
- Modified getUserSuggestions to include match data (id, slug, status)
- Returns match info for both toBeRecorded and toRecord suggestions
Frontend changes:
- Added useNavigate hook to RecordingTab
- Capture match data from updateSuggestionStatus response
- Added MessageCircle icon and chat button to SuggestionCard
- Show "Open Chat" button for accepted suggestions with active matches
- Navigate to /matches/{matchSlug}/chat when clicked
This completes the recording stats flow by allowing users to easily
access the match chat after accepting a recording suggestion.
This commit is contained in:
@@ -511,6 +511,13 @@ async function getUserSuggestions(eventId, userId) {
|
|||||||
city: true,
|
city: true,
|
||||||
country: true,
|
country: true,
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
match: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
slug: true,
|
||||||
|
status: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -534,6 +541,13 @@ async function getUserSuggestions(eventId, userId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
match: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
slug: true,
|
||||||
|
status: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Video, VideoOff, Clock, CheckCircle, XCircle, AlertTriangle, RefreshCw } from 'lucide-react';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { Video, VideoOff, Clock, CheckCircle, XCircle, AlertTriangle, RefreshCw, MessageCircle } from 'lucide-react';
|
||||||
import { matchingAPI } from '../../services/api';
|
import { matchingAPI } from '../../services/api';
|
||||||
import Avatar from '../common/Avatar';
|
import Avatar from '../common/Avatar';
|
||||||
import { SUGGESTION_STATUS, SUGGESTION_TYPE } from '../../constants';
|
import { SUGGESTION_STATUS, SUGGESTION_TYPE } from '../../constants';
|
||||||
@@ -9,6 +10,7 @@ import { SUGGESTION_STATUS, SUGGESTION_TYPE } from '../../constants';
|
|||||||
* Shows suggestions for who will record user's heats and who user needs to record
|
* Shows suggestions for who will record user's heats and who user needs to record
|
||||||
*/
|
*/
|
||||||
const RecordingTab = ({ slug, event, myHeats }) => {
|
const RecordingTab = ({ slug, event, myHeats }) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
const [suggestions, setSuggestions] = useState(null);
|
const [suggestions, setSuggestions] = useState(null);
|
||||||
@@ -49,8 +51,15 @@ const RecordingTab = ({ slug, event, myHeats }) => {
|
|||||||
|
|
||||||
const handleUpdateStatus = async (suggestionId, status) => {
|
const handleUpdateStatus = async (suggestionId, status) => {
|
||||||
try {
|
try {
|
||||||
await matchingAPI.updateSuggestionStatus(slug, suggestionId, status);
|
const response = await matchingAPI.updateSuggestionStatus(slug, suggestionId, status);
|
||||||
// Reload suggestions
|
|
||||||
|
// If suggestion was accepted and a match was created, show notification
|
||||||
|
if (status === SUGGESTION_STATUS.ACCEPTED && response?.match) {
|
||||||
|
// Optional: Show toast notification here if you have a toast system
|
||||||
|
console.log('Match created:', response.match);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload suggestions to show updated status and match data
|
||||||
await loadSuggestions();
|
await loadSuggestions();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to update suggestion status:', err);
|
console.error('Failed to update suggestion status:', err);
|
||||||
@@ -202,6 +211,7 @@ const RecordingTab = ({ slug, event, myHeats }) => {
|
|||||||
type={SUGGESTION_TYPE.TO_BE_RECORDED}
|
type={SUGGESTION_TYPE.TO_BE_RECORDED}
|
||||||
onAccept={() => handleUpdateStatus(suggestion.id, SUGGESTION_STATUS.ACCEPTED)}
|
onAccept={() => handleUpdateStatus(suggestion.id, SUGGESTION_STATUS.ACCEPTED)}
|
||||||
onReject={() => handleUpdateStatus(suggestion.id, SUGGESTION_STATUS.REJECTED)}
|
onReject={() => handleUpdateStatus(suggestion.id, SUGGESTION_STATUS.REJECTED)}
|
||||||
|
navigate={navigate}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -228,6 +238,7 @@ const RecordingTab = ({ slug, event, myHeats }) => {
|
|||||||
type={SUGGESTION_TYPE.TO_RECORD}
|
type={SUGGESTION_TYPE.TO_RECORD}
|
||||||
onAccept={() => handleUpdateStatus(suggestion.id, SUGGESTION_STATUS.ACCEPTED)}
|
onAccept={() => handleUpdateStatus(suggestion.id, SUGGESTION_STATUS.ACCEPTED)}
|
||||||
onReject={() => handleUpdateStatus(suggestion.id, SUGGESTION_STATUS.REJECTED)}
|
onReject={() => handleUpdateStatus(suggestion.id, SUGGESTION_STATUS.REJECTED)}
|
||||||
|
navigate={navigate}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -262,11 +273,12 @@ const RecordingTab = ({ slug, event, myHeats }) => {
|
|||||||
/**
|
/**
|
||||||
* SuggestionCard - Single suggestion item
|
* SuggestionCard - Single suggestion item
|
||||||
*/
|
*/
|
||||||
const SuggestionCard = ({ suggestion, type, onAccept, onReject }) => {
|
const SuggestionCard = ({ suggestion, type, onAccept, onReject, navigate }) => {
|
||||||
const heat = suggestion.heat;
|
const heat = suggestion.heat;
|
||||||
const recorder = suggestion.recorder;
|
const recorder = suggestion.recorder;
|
||||||
const dancer = heat?.user;
|
const dancer = heat?.user;
|
||||||
const status = suggestion.status;
|
const status = suggestion.status;
|
||||||
|
const match = suggestion.match;
|
||||||
|
|
||||||
// Format heat info
|
// Format heat info
|
||||||
const heatInfo = heat
|
const heatInfo = heat
|
||||||
@@ -365,7 +377,18 @@ const SuggestionCard = ({ suggestion, type, onAccept, onReject }) => {
|
|||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
getStatusBadge()
|
<>
|
||||||
|
{getStatusBadge()}
|
||||||
|
{status === SUGGESTION_STATUS.ACCEPTED && match?.slug && (
|
||||||
|
<button
|
||||||
|
onClick={() => navigate(`/matches/${match.slug}/chat`)}
|
||||||
|
className="p-2 text-primary-600 hover:bg-primary-50 rounded-md transition-colors"
|
||||||
|
title="Open Chat"
|
||||||
|
>
|
||||||
|
<MessageCircle className="w-5 h-5" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user