Add nomination submission and bidding start workflow

- Added `BID_START_REQUEST` and `NOMINATION_SUBMIT_REQUEST` handling in backend consumers.
- Extended draft state to include `current_movie` and `bids` cache keys.
- Updated frontend to:
  - Allow participants to nominate movies when it's their turn.
  - Enable admins to start bidding for the nominated movie.
  - Highlight the current nominated movie and the current user.
- Synced state updates across clients via WebSocket events.
This commit is contained in:
2025-08-10 16:30:27 -05:00
parent 28c98afc32
commit b08a345563
10 changed files with 151 additions and 28 deletions

View File

@@ -30,6 +30,7 @@ class DraftMessage(StrEnum):
# Bidding (examples, adjust to your flow)
BID_START_INFORM = "bid.start.inform" # server -> client (movie, ends_at)
BID_START_REQUEST = "bid.start.request" # server -> client (movie, ends_at)
BID_PLACE_REQUEST = "bid.place.request" # client -> server (amount)
BID_UPDATE_INFORM = "bid.update.inform" # server -> client (high bid)
BID_END_INFORM = "bid.end.inform" # server -> client (winner)

View File

@@ -182,6 +182,34 @@ class DraftAdminConsumer(DraftConsumerBase):
},
)
if event_type == DraftMessage.NOMINATION_SUBMIT_REQUEST:
movie_id = content.get('payload',{}).get('movie_id')
user = content.get('payload',{}).get('user')
self.draft_state.start_nomination(movie_id)
await self.channel_layer.group_send(
self.group_names.session,
{
"type": "broadcast.session",
"subtype": DraftMessage.NOMINATION_CONFIRM,
"payload": {
"current_movie": self.draft_state.get_summary()['current_movie'],
"nominating_participant": user
}
}
)
if event_type == DraftMessage.BID_START_REQUEST:
self.draft_state
await self.channel_layer.group_send(
self.group_names.session,
{
"type": "broadcast.session",
"subtype": DraftMessage.BID_START_INFORM,
"payload": {
"current_movie": self.draft_state.get_summary()['current_movie']
}
}
)
def should_accept_user(self):
return super().should_accept_user() and self.user.is_staff
@@ -276,6 +304,20 @@ class DraftParticipantConsumer(DraftConsumerBase):
async def receive_json(self, content):
await super().receive_json(content)
event_type = content.get('type')
if event_type == DraftMessage.NOMINATION_SUBMIT_REQUEST:
await self.channel_layer.group_send(
self.group_names.admin,
{
"type": "broadcast.admin",
"subtype": event_type,
"payload": {
"movie_id": content.get('payload',{}).get('id'),
"user": content.get('payload',{}).get('user')
}
}
)
# === Broadcast handlers ===

View File

@@ -37,6 +37,10 @@ class DraftCacheKeys:
def draft_index(self):
return f"{self.prefix}:draft_index"
@property
def current_movie(self):
return f"{self.prefix}:current_movie"
# @property
# def state(self):
# return f"{self.prefix}:state"
@@ -45,9 +49,9 @@ class DraftCacheKeys:
# def current_movie(self):
# return f"{self.prefix}:current_movie"
# @property
# def bids(self):
# return f"{self.prefix}:bids"
@property
def bids(self):
return f"{self.prefix}:bids"
# @property
# def participants(self):
@@ -146,7 +150,7 @@ class DraftStateManager:
"draft_order": self.draft_order,
"draft_index": self.draft_index,
"connected_participants": self.connected_participants,
# "current_movie": self.cache.get(self.keys.current_movie),
"current_movie": self.cache.get(self.keys.current_movie),
# "bids": self.get_bids(),
# "timer_end": self.get_timer_end(),
}