Add DRF API app and real-time draft management UI
- Created new `api` Django app with serializers, viewsets, and routers to expose draft sessions, participants, and movie data. - Registered `api` app in settings and updated root URL configuration. - Extended WebSocket consumers with `inform.draft_status` / `request.draft_status` to allow fetching current draft state. - Updated `DraftSession` and related models to support reverse lookups for draft picks. - Enhanced draft state manager to include `draft_order` in summaries. - Added React WebSocket context provider, connection status component, and new admin/participant panels with phase and participant tracking. - Updated SCSS for participant lists, phase indicators, and status badges. - Modified Django templates to mount new React roots for admin and participant views. - Updated Webpack dev server config to proxy WebSocket connections.
This commit is contained in:
86
frontend/src/apps/draft/participant/DraftParticipant.jsx
Normal file
86
frontend/src/apps/draft/participant/DraftParticipant.jsx
Normal file
@@ -0,0 +1,86 @@
|
||||
// DraftAdmin.jsx
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
import { useWebSocket } from "../WebSocketContext.jsx";
|
||||
import { WebSocketStatus } from "../common/WebSocketStatus.jsx";
|
||||
import { DraftMessage, DraftPhases } from '../constants.js';
|
||||
|
||||
export const DraftParticipant = ({ draftSessionId }) => {
|
||||
const socket = useWebSocket();
|
||||
const [connectedParticipants, setConnectedParticipants] = useState([]);
|
||||
const [draftPhase, setDraftPhase] = useState();
|
||||
console.log(socket)
|
||||
|
||||
useEffect(() => {
|
||||
if (!socket) return;
|
||||
else {
|
||||
console.warn("socket doesn't exist")
|
||||
}
|
||||
console.log('socket created', socket)
|
||||
|
||||
const handleMessage = (event) => {
|
||||
const message = JSON.parse(event.data)
|
||||
const { type, payload } = message;
|
||||
console.log(type, event)
|
||||
if (type == DraftMessage.REQUEST.JOIN_PARTICIPANT) {
|
||||
console.log('join request', data)
|
||||
}
|
||||
else if (type == DraftMessage.CONFIRM.JOIN_PARTICIPANT) {
|
||||
setConnectedParticipants(data.connected_participants)
|
||||
}
|
||||
else if (type == DraftMessage.CONFIRM.PHASE_CHANGE || type == DraftMessage.INFORM.PHASE) {
|
||||
console.log('phase_change')
|
||||
setDraftPhase(payload.phase)
|
||||
}
|
||||
}
|
||||
|
||||
socket.addEventListener('message', handleMessage);
|
||||
|
||||
socket.onclose = (event) => {
|
||||
console.log('Websocket Closed')
|
||||
socket = null;
|
||||
}
|
||||
|
||||
return () => {
|
||||
socket.removeEventListener('message', handleMessage)
|
||||
socket.close();
|
||||
};
|
||||
}, [socket]);
|
||||
|
||||
const handlePhaseChange = (destinationPhase) => {
|
||||
socket.send(
|
||||
JSON.stringify({ type: DraftMessage.REQUEST.PHASE_CHANGE, "destination": destinationPhase })
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const handleRequestDraftSummary = () => {
|
||||
socket.send(JSON.stringify({ type: 'request_summary' }))
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container draft-panel">
|
||||
<h3>Draft Admin Panel</h3>
|
||||
<WebSocketStatus socket={socket} />
|
||||
{/* <MessageLogger socket={socketRef.current} /> */}
|
||||
<label>Connected Particpants</label>
|
||||
<input
|
||||
type="text"
|
||||
readOnly disabled
|
||||
value={connectedParticipants ? JSON.stringify(connectedParticipants) : ""}
|
||||
/>
|
||||
<label>Draft Phase</label>
|
||||
<input
|
||||
type="text"
|
||||
readOnly disabled
|
||||
value={draftPhase ? draftPhase : ""}
|
||||
/>
|
||||
<button onClick={() => handlePhaseChange(DraftPhases.DETERMINE_ORDER)} className="btn btn-primary mt-2 me-2">
|
||||
Determine Draft Order
|
||||
</button>
|
||||
<button onClick={handleRequestDraftSummary} className="btn btn-primary mt-2">
|
||||
Request status
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user