Skip to content

Commit cd93d47

Browse files
committed
restore question Report button, add separate Report Player button alongside it
1 parent 4e5b8db commit cd93d47

1 file changed

Lines changed: 108 additions & 27 deletions

File tree

frontend/src/SharePlay.js

Lines changed: 108 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,18 @@ export default function SharePlay() {
248248
// Report / Suggest (persist across question changes intentionally)
249249
const [showRequestModal, setShowRequestModal] = useState(false);
250250
const [showReportMenu, setShowReportMenu] = useState(false);
251-
const [reportPlayerId, setReportPlayerId] = useState('');
252251
const [reportType, setReportType] = useState('general');
253252
const [reportNote, setReportNote] = useState('');
254253
const [reportMessage, setReportMessage] = useState('');
255254
const reportMenuRef = useRef(null);
255+
const reportingQIdRef = useRef(null);
256+
// Player report
257+
const [showPlayerReportMenu, setShowPlayerReportMenu] = useState(false);
258+
const [reportPlayerId, setReportPlayerId] = useState('');
259+
const [playerReportType, setPlayerReportType] = useState('general');
260+
const [playerReportNote, setPlayerReportNote] = useState('');
261+
const [playerReportMsg, setPlayerReportMsg] = useState('');
262+
const playerReportRef = useRef(null);
256263

257264
// Question / voting
258265
const [currentQuestion, setCurrentQuestion] = useState(null);
@@ -411,6 +418,13 @@ export default function SharePlay() {
411418
return () => document.removeEventListener('mousedown', handler);
412419
}, [showReportMenu]);
413420

421+
useEffect(() => {
422+
if (!showPlayerReportMenu) return;
423+
const handler = e => { if (playerReportRef.current && !playerReportRef.current.contains(e.target)) setShowPlayerReportMenu(false); };
424+
document.addEventListener('mousedown', handler);
425+
return () => document.removeEventListener('mousedown', handler);
426+
}, [showPlayerReportMenu]);
427+
414428
useEffect(() => {
415429
const handler = e => { if (e.key === 'Escape') setTvMode(false); };
416430
document.addEventListener('keydown', handler);
@@ -504,7 +518,31 @@ export default function SharePlay() {
504518

505519
const handleSuggest = useCallback(() => setShowRequestModal(true), []);
506520

507-
const handleReport = useCallback(async (reasonOverride) => {
521+
const handleQuestionReport = useCallback(async (reasonOverride) => {
522+
const qId = reportingQIdRef.current;
523+
if (!qId) return;
524+
try {
525+
const token = getToken();
526+
const headers = token ? { Authorization: `Bearer ${token}` } : undefined;
527+
await axios.post(`${REST_BASE}/api/game/report`, { questionId: qId, reason: reasonOverride || 'General Report' }, { headers });
528+
setReportMessage('✅ Reported successfully.');
529+
} catch (err) {
530+
setReportMessage(`⚠️ ${err.response?.data?.error || 'Question flagged for review.'}`);
531+
}
532+
}, []);
533+
534+
const submitQuestionReport = useCallback(async () => {
535+
const trimmed = reportNote.trim();
536+
const needsNote = reportType === 'inappropriate' || reportType === 'incorrect';
537+
if (needsNote && !trimmed) { setReportMessage('⚠️ Please add a short description.'); return; }
538+
const label = reportType === 'inappropriate' ? 'Inappropriate' : reportType === 'incorrect' ? 'Incorrect Answer' : 'General Report';
539+
await handleQuestionReport(needsNote ? `${label}: ${trimmed}` : label);
540+
setShowReportMenu(false);
541+
setReportNote('');
542+
setReportType('general');
543+
}, [reportNote, reportType, handleQuestionReport]);
544+
545+
const handlePlayerReport = useCallback(async (reasonOverride) => {
508546
if (!reportPlayerId) return;
509547
try {
510548
const token = getToken();
@@ -514,26 +552,26 @@ export default function SharePlay() {
514552
reportedUserId: Number(reportPlayerId),
515553
roomCode,
516554
reason: reasonOverride || 'General Report',
517-
note: reportNote.trim() || undefined,
555+
note: playerReportNote.trim() || undefined,
518556
}, { headers });
519-
setReportMessage(`✅ Reported ${reportedPlayer?.displayName || 'player'} successfully.`);
557+
setPlayerReportMsg(`✅ Reported ${reportedPlayer?.displayName || 'player'} successfully.`);
520558
} catch (err) {
521-
setReportMessage(`⚠️ ${err.response?.data?.error || 'Failed to report player.'}`);
559+
setPlayerReportMsg(`⚠️ ${err.response?.data?.error || 'Failed to report player.'}`);
522560
}
523-
}, [reportPlayerId, players, roomCode, reportNote]);
524-
525-
const submitReport = useCallback(async () => {
526-
if (!reportPlayerId) { setReportMessage('⚠️ Select a player to report.'); return; }
527-
const trimmed = reportNote.trim();
528-
const needsNote = reportType === 'inappropriate' || reportType === 'cheating';
529-
if (needsNote && !trimmed) { setReportMessage('⚠️ Please add a short description.'); return; }
530-
const label = reportType === 'inappropriate' ? 'Inappropriate' : reportType === 'cheating' ? 'Cheating' : reportType === 'harassment' ? 'Harassment' : 'General Report';
531-
await handleReport(needsNote ? `${label}: ${trimmed}` : label);
532-
setShowReportMenu(false);
533-
setReportNote('');
534-
setReportType('general');
561+
}, [reportPlayerId, players, roomCode, playerReportNote]);
562+
563+
const submitPlayerReport = useCallback(async () => {
564+
if (!reportPlayerId) { setPlayerReportMsg('⚠️ Select a player to report.'); return; }
565+
const trimmed = playerReportNote.trim();
566+
const needsNote = playerReportType === 'inappropriate' || playerReportType === 'cheating' || playerReportType === 'harassment';
567+
if (needsNote && !trimmed) { setPlayerReportMsg('⚠️ Please add a short description.'); return; }
568+
const label = playerReportType === 'inappropriate' ? 'Inappropriate' : playerReportType === 'cheating' ? 'Cheating' : playerReportType === 'harassment' ? 'Harassment' : 'General Report';
569+
await handlePlayerReport(needsNote ? `${label}: ${trimmed}` : label);
570+
setShowPlayerReportMenu(false);
571+
setPlayerReportNote('');
572+
setPlayerReportType('general');
535573
setReportPlayerId('');
536-
}, [reportNote, reportType, reportPlayerId, handleReport]);
574+
}, [playerReportNote, playerReportType, reportPlayerId, handlePlayerReport]);
537575

538576
const copyCode = useCallback(() => {
539577
navigator.clipboard?.writeText(roomCode).then(() => { setCopied(true); setTimeout(() => setCopied(false), 2000); }).catch(() => {});
@@ -1163,15 +1201,55 @@ export default function SharePlay() {
11631201
<button
11641202
style={{ ...btn('#6c757d'), fontSize: '0.85rem', padding: '7px 14px' }}
11651203
onClick={() => {
1204+
reportingQIdRef.current = currentQuestion.id;
11661205
setShowReportMenu(v => !v);
11671206
setReportMessage('');
1168-
setReportPlayerId('');
11691207
}}
11701208
>
11711209
⚠ Report
11721210
</button>
11731211

11741212
{showReportMenu && (
1213+
<div style={{ position: 'absolute', bottom: '110%', left: 0, background: 'var(--card-bg,#fff)', border: '1px solid var(--border-color,#ddd)', borderRadius: '10px', padding: '14px', width: '260px', zIndex: 20, boxShadow: '0 6px 20px rgba(0,0,0,0.15)' }}>
1214+
<div style={{ fontSize: '0.8rem', color: '#888', marginBottom: '6px' }}>Report Question</div>
1215+
<select value={reportType} onChange={e => setReportType(e.target.value)}
1216+
style={{ width: '100%', padding: '6px 8px', borderRadius: '6px', border: '1px solid var(--border-color,#ddd)', background: 'var(--card-bg,#fff)', color: 'var(--text-color,#333)', marginBottom: '8px' }}>
1217+
<option value="general">General Report</option>
1218+
<option value="inappropriate">Inappropriate</option>
1219+
<option value="incorrect">Incorrect Answer</option>
1220+
</select>
1221+
{(reportType === 'inappropriate' || reportType === 'incorrect') && (
1222+
<textarea value={reportNote} onChange={e => setReportNote(e.target.value)}
1223+
placeholder="Add a short description..."
1224+
rows={3}
1225+
style={{ width: '100%', padding: '6px 8px', borderRadius: '6px', border: '1px solid var(--border-color,#ddd)', background: 'var(--card-bg,#fff)', color: 'var(--text-color,#333)', resize: 'vertical', boxSizing: 'border-box', marginBottom: '8px' }} />
1226+
)}
1227+
{reportMessage && (
1228+
<div style={{ fontSize: '0.8rem', marginBottom: '8px', color: reportMessage.startsWith('✅') ? '#155724' : '#856404' }}>
1229+
{reportMessage}
1230+
</div>
1231+
)}
1232+
<div style={{ display: 'flex', gap: '8px' }}>
1233+
<button style={{ ...btn(), flex: 1, padding: '7px', fontSize: '0.85rem' }} onClick={submitQuestionReport}>Submit</button>
1234+
<button style={{ ...btn('#6c757d'), padding: '7px 12px', fontSize: '0.85rem' }} onClick={() => { setShowReportMenu(false); setReportMessage(''); }}>Cancel</button>
1235+
</div>
1236+
</div>
1237+
)}
1238+
</div>
1239+
1240+
<div style={{ position: 'relative' }} ref={playerReportRef}>
1241+
<button
1242+
style={{ ...btn('#6c757d'), fontSize: '0.85rem', padding: '7px 14px' }}
1243+
onClick={() => {
1244+
setShowPlayerReportMenu(v => !v);
1245+
setPlayerReportMsg('');
1246+
setReportPlayerId('');
1247+
}}
1248+
>
1249+
🚩 Report Player
1250+
</button>
1251+
1252+
{showPlayerReportMenu && (
11751253
<div style={{ position: 'absolute', bottom: '110%', left: 0, background: 'var(--card-bg,#fff)', border: '1px solid var(--border-color,#ddd)', borderRadius: '10px', padding: '14px', width: '280px', zIndex: 20, boxShadow: '0 6px 20px rgba(0,0,0,0.15)' }}>
11761254
<div style={{ fontSize: '0.8rem', color: '#888', marginBottom: '6px' }}>Report Player</div>
11771255
<select value={reportPlayerId} onChange={e => setReportPlayerId(e.target.value)}
@@ -1181,27 +1259,27 @@ export default function SharePlay() {
11811259
<option key={p.userId} value={p.userId}>{p.displayName}</option>
11821260
))}
11831261
</select>
1184-
<select value={reportType} onChange={e => setReportType(e.target.value)}
1262+
<select value={playerReportType} onChange={e => setPlayerReportType(e.target.value)}
11851263
style={{ width: '100%', padding: '6px 8px', borderRadius: '6px', border: '1px solid var(--border-color,#ddd)', background: 'var(--card-bg,#fff)', color: 'var(--text-color,#333)', marginBottom: '8px' }}>
11861264
<option value="general">General Report</option>
11871265
<option value="inappropriate">Inappropriate Behavior</option>
11881266
<option value="cheating">Cheating</option>
11891267
<option value="harassment">Harassment</option>
11901268
</select>
1191-
{(reportType === 'inappropriate' || reportType === 'cheating' || reportType === 'harassment') && (
1192-
<textarea value={reportNote} onChange={e => setReportNote(e.target.value)}
1269+
{(playerReportType === 'inappropriate' || playerReportType === 'cheating' || playerReportType === 'harassment') && (
1270+
<textarea value={playerReportNote} onChange={e => setPlayerReportNote(e.target.value)}
11931271
placeholder="Add a short description..."
11941272
rows={3}
11951273
style={{ width: '100%', padding: '6px 8px', borderRadius: '6px', border: '1px solid var(--border-color,#ddd)', background: 'var(--card-bg,#fff)', color: 'var(--text-color,#333)', resize: 'vertical', boxSizing: 'border-box', marginBottom: '8px' }} />
11961274
)}
1197-
{reportMessage && (
1198-
<div style={{ fontSize: '0.8rem', marginBottom: '8px', color: reportMessage.startsWith('✅') ? '#155724' : '#856404' }}>
1199-
{reportMessage}
1275+
{playerReportMsg && (
1276+
<div style={{ fontSize: '0.8rem', marginBottom: '8px', color: playerReportMsg.startsWith('✅') ? '#155724' : '#856404' }}>
1277+
{playerReportMsg}
12001278
</div>
12011279
)}
12021280
<div style={{ display: 'flex', gap: '8px' }}>
1203-
<button style={{ ...btn(), flex: 1, padding: '7px', fontSize: '0.85rem' }} onClick={submitReport}>Submit</button>
1204-
<button style={{ ...btn('#6c757d'), padding: '7px 12px', fontSize: '0.85rem' }} onClick={() => { setShowReportMenu(false); setReportMessage(''); }}>Cancel</button>
1281+
<button style={{ ...btn(), flex: 1, padding: '7px', fontSize: '0.85rem' }} onClick={submitPlayerReport}>Submit</button>
1282+
<button style={{ ...btn('#6c757d'), padding: '7px 12px', fontSize: '0.85rem' }} onClick={() => { setShowPlayerReportMenu(false); setPlayerReportMsg(''); }}>Cancel</button>
12051283
</div>
12061284
</div>
12071285
)}
@@ -1210,6 +1288,9 @@ export default function SharePlay() {
12101288
{reportMessage && !showReportMenu && (
12111289
<span style={{ fontSize: '0.85rem', color: reportMessage.startsWith('✅') ? '#155724' : '#856404' }}>{reportMessage}</span>
12121290
)}
1291+
{playerReportMsg && !showPlayerReportMenu && (
1292+
<span style={{ fontSize: '0.85rem', color: playerReportMsg.startsWith('✅') ? '#155724' : '#856404' }}>{playerReportMsg}</span>
1293+
)}
12131294
</div>
12141295
)}
12151296

0 commit comments

Comments
 (0)