- Added `bidding_duration` field to `DraftSessionSettings` model and migration. - Updated `DraftStateManager` to manage bidding start/end times using session settings. - Extended WebSocket payloads to include bidding timer data. - Added `DraftCountdownClock` React component and integrated into admin and participant UIs. - Created new `DraftDebug` view, template, and front-end component for real-time state debugging. - Updated utility functions to handle new timer fields in draft state. - Changed script tags in templates to load with `defer` for non-blocking execution.
169 lines
5.6 KiB
JavaScript
169 lines
5.6 KiB
JavaScript
import React, { useEffect, useState } from "react";
|
|
|
|
import { useWebSocket } from "../WebSocketContext.jsx";
|
|
import { WebSocketStatus } from "../common/WebSocketStatus.jsx";
|
|
import { ParticipantList } from "../common/ParticipantList.jsx";
|
|
import { DraftMessage, DraftPhase, DraftPhaseLabel, DraftPhasesOrdered } from '../constants.js';
|
|
import { fetchDraftDetails, isEmptyObject, handleDraftStatusMessages, handleUserIdentifyMessages } from "../common/utils.js"
|
|
import { DraftMoviePool } from "../common/DraftMoviePool.jsx"
|
|
import { DraftCountdownClock } from "../common/DraftCountdownClock.jsx"
|
|
import { jsxs } from "react/jsx-runtime";
|
|
|
|
|
|
|
|
const DraftPhaseDisplay = ({ draftPhase, nextPhaseHandler, prevPhaseHandler }) => {
|
|
return (
|
|
<div className="draft-phase-container">
|
|
<label>Phase</label>
|
|
<div className="d-flex">
|
|
<div className="change-phase"><button onClick={prevPhaseHandler}><i className="bi bi-chevron-left"></i></button></div>
|
|
<ol>
|
|
{
|
|
DraftPhasesOrdered.map((p) => (
|
|
<li key={p} className={p === draftPhase ? "current-phase" : ""}>
|
|
<span>{DraftPhaseLabel[p]}</span>
|
|
</li>
|
|
))
|
|
}
|
|
</ol>
|
|
<div className="change-phase"><button onClick={nextPhaseHandler}><i className="bi bi-chevron-right"></i></button></div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export const DraftAdmin = ({ draftSessionId }) => {
|
|
const socket = useWebSocket();
|
|
const [draftDetails, setDraftDetails] = useState();
|
|
const [draftState, setDraftState] = useState({})
|
|
const [currentUser, setCurrentUser] = useState(null);
|
|
|
|
useEffect(() => {
|
|
fetchDraftDetails(draftSessionId)
|
|
.then((data) => {
|
|
console.log("Fetched draft data", data)
|
|
setDraftDetails(data)
|
|
})
|
|
}, [])
|
|
|
|
useEffect(()=>{
|
|
if (!socket) return;
|
|
const openHandler = (event)=>{
|
|
console.log('Websocket Opened')
|
|
}
|
|
const closeHandler = (event)=>{
|
|
console.log('Websocket Closed')
|
|
}
|
|
socket.addEventListener('open', openHandler );
|
|
socket.addEventListener('close', closeHandler );
|
|
return ()=>{
|
|
socket.removeEventListener('open', openHandler );
|
|
socket.removeEventListener('close', closeHandler );
|
|
}
|
|
}, [socket])
|
|
|
|
useEffect(() => {
|
|
if (!socket) return;
|
|
|
|
const draftStatusMessageHandler = (event) => handleDraftStatusMessages(event, setDraftState)
|
|
const userIdentifyMessageHandler = (event) => handleUserIdentifyMessages(event, setCurrentUser)
|
|
const handleNominationRequest = (event)=> {
|
|
const message = JSON.parse(event.data)
|
|
const { type, payload } = message;
|
|
if (type == DraftMessage.NOMINATION_SUBMIT_REQUEST) {
|
|
socket.send(JSON.stringify(
|
|
{
|
|
type: DraftMessage.NOMINATION_SUBMIT_REQUEST,
|
|
payload
|
|
}
|
|
))
|
|
}
|
|
}
|
|
socket.addEventListener('message', draftStatusMessageHandler );
|
|
socket.addEventListener('message', userIdentifyMessageHandler );
|
|
socket.addEventListener('message', handleNominationRequest );
|
|
|
|
|
|
return () => {
|
|
socket.removeEventListener('message', draftStatusMessageHandler)
|
|
socket.removeEventListener('message', userIdentifyMessageHandler );
|
|
socket.removeEventListener('message', handleNominationRequest );
|
|
};
|
|
}, [socket]);
|
|
|
|
const handlePhaseChange = (target) => {
|
|
let destination
|
|
const origin = draftState.phase
|
|
const originPhaseIndex = DraftPhasesOrdered.findIndex(i => i == origin)
|
|
console.log('origin phase index', originPhaseIndex)
|
|
if (target == "next" && originPhaseIndex < DraftPhasesOrdered.length) {
|
|
destination = DraftPhasesOrdered[originPhaseIndex + 1]
|
|
}
|
|
else if (target == "previous" && originPhaseIndex > 0) {
|
|
destination = DraftPhasesOrdered[originPhaseIndex - 1]
|
|
}
|
|
console.log(destination)
|
|
socket.send(
|
|
JSON.stringify(
|
|
{ type: DraftMessage.PHASE_CHANGE_REQUEST, origin, destination }
|
|
)
|
|
)
|
|
|
|
}
|
|
|
|
const handleStartDraft = () => {
|
|
|
|
}
|
|
|
|
const handleAdvanceDraft = () => {
|
|
socket.send(
|
|
JSON.stringify(
|
|
{ type: DraftMessage.DRAFT_INDEX_ADVANCE_REQUEST }
|
|
)
|
|
)
|
|
}
|
|
|
|
const handleRequestDraftSummary = () => {
|
|
socket.send(
|
|
JSON.stringify(
|
|
{ type: DraftMessage.STATUS_SYNC_REQUEST }
|
|
)
|
|
)
|
|
}
|
|
|
|
const handleStartBidding = () => {
|
|
socket.send(
|
|
JSON.stringify(
|
|
{type: DraftMessage.BID_START_REQUEST}
|
|
)
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="container draft-panel admin">
|
|
<div className="d-flex justify-content-between border-bottom mb-2 p-1">
|
|
<h3>Draft Panel</h3>
|
|
<div className="d-flex gap-1">
|
|
<WebSocketStatus socket={socket} />
|
|
<button onClick={() => handleRequestDraftSummary()} className="btn btn-small btn-light">
|
|
<i className="bi bi-arrow-clockwise"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<ParticipantList
|
|
currentUser = {currentUser}
|
|
draftState={draftState}
|
|
draftDetails={draftDetails}
|
|
isAdmin={true}
|
|
/>
|
|
<div className="d-flex gap-1 m-1">
|
|
<button onClick={handleAdvanceDraft} className="btn btn-primary">Advance Draft</button>
|
|
<button onClick={handleStartBidding} className="btn btn-primary">Start Bidding</button>
|
|
</div>
|
|
<DraftMoviePool draftDetails={draftDetails} draftState={draftState}></DraftMoviePool>
|
|
<DraftPhaseDisplay draftPhase={draftState.phase} nextPhaseHandler={() => { handlePhaseChange('next') }} prevPhaseHandler={() => { handlePhaseChange('previous') }}></DraftPhaseDisplay>
|
|
<DraftCountdownClock endTime={draftState.bidding_timer_end}></DraftCountdownClock>
|
|
</div>
|
|
);
|
|
}; |