Scaffold and Phase 1
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Real-time state hook for the live auction bidder view.
|
||||
* Subscribes to item_activated, next_live_bid, live_bid_accepted,
|
||||
* item_state_changed, item_sold.
|
||||
*/
|
||||
import { useState, useEffect } from "react";
|
||||
import { getSocket } from "../lib/socket.js";
|
||||
import type { AuctionItem, Bid, ItemState } from "@storybid/shared";
|
||||
|
||||
export interface LiveAuctionState {
|
||||
currentItem: AuctionItem | null;
|
||||
currentBid: number | null;
|
||||
calledAmount: number | null;
|
||||
state: ItemState | null;
|
||||
recentBids: Bid[];
|
||||
}
|
||||
|
||||
export function useLiveAuction(eventId: string) {
|
||||
const [state, setState] = useState<LiveAuctionState>({
|
||||
currentItem: null,
|
||||
currentBid: null,
|
||||
calledAmount: null,
|
||||
state: null,
|
||||
recentBids: [],
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const socket = getSocket();
|
||||
socket.emit("join_event", eventId);
|
||||
|
||||
socket.on("item_activated", ({ item }) => {
|
||||
setState({
|
||||
currentItem: item,
|
||||
currentBid: item.currentHighBid,
|
||||
calledAmount: item.openingBid,
|
||||
state: item.state,
|
||||
recentBids: [],
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("next_live_bid", ({ amount }) => {
|
||||
setState((prev) => ({ ...prev, calledAmount: amount }));
|
||||
});
|
||||
|
||||
socket.on("live_bid_accepted", ({ bid, item }) => {
|
||||
setState((prev) => ({
|
||||
...prev,
|
||||
currentBid: item.currentHighBid,
|
||||
state: item.state,
|
||||
currentItem: item,
|
||||
recentBids: [bid, ...prev.recentBids].slice(0, 10),
|
||||
}));
|
||||
});
|
||||
|
||||
socket.on("item_state_changed", ({ itemId, state: newState }) => {
|
||||
setState((prev) => {
|
||||
if (prev.currentItem?.id !== itemId) return prev;
|
||||
return { ...prev, state: newState };
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("item_sold", ({ itemId, amount }) => {
|
||||
setState((prev) => {
|
||||
if (prev.currentItem?.id !== itemId) return prev;
|
||||
return { ...prev, currentBid: amount, state: "sold" };
|
||||
});
|
||||
});
|
||||
|
||||
return () => {
|
||||
socket.emit("leave_event", eventId);
|
||||
socket.off("item_activated");
|
||||
socket.off("next_live_bid");
|
||||
socket.off("live_bid_accepted");
|
||||
socket.off("item_state_changed");
|
||||
socket.off("item_sold");
|
||||
};
|
||||
}, [eventId]);
|
||||
|
||||
const placeBid = (itemId: string, amount: number, deviceId: string, clientSeq: number) => {
|
||||
const socket = getSocket();
|
||||
socket.emit("place_live_bid", {
|
||||
itemId,
|
||||
amount,
|
||||
deviceId,
|
||||
clientSeq,
|
||||
clientCreatedAt: new Date().toISOString(),
|
||||
});
|
||||
};
|
||||
|
||||
return { ...state, placeBid };
|
||||
}
|
||||
Reference in New Issue
Block a user