Refactor roster action handling in WorkflowRosterEditor to improve clarity and maintainability. Update player movement and roster manipulation logic to use structured action parameters. Enhance drag-and-drop functionality for roster slots and ensure proper state management in the UI.
This commit is contained in:
@@ -524,11 +524,21 @@ function WorkflowRosterEditor({ eventId, roster, players, locked, onChanged }: {
|
||||
| { kind: 'place'; teamId: string; reservePlayerId: string; role: 'Tank' | 'Damage' | 'Support' }
|
||||
| { kind: 'remove'; teamId: string; playerId: string }
|
||||
| { kind: 'captain'; teamId: string; playerId: string }) => {
|
||||
if (action.kind === 'swap') return api.swapRoster(eventId, { ...action, expectedVersion: roster.version })
|
||||
if (action.kind === 'substitute') return api.substituteRoster(eventId, { ...action, expectedVersion: roster.version })
|
||||
if (action.kind === 'move') return api.moveRosterPlayer(eventId, { ...action, expectedVersion: roster.version })
|
||||
if (action.kind === 'place') return api.placeReservePlayer(eventId, { ...action, expectedVersion: roster.version })
|
||||
if (action.kind === 'remove') return api.removeRosterPlayer(eventId, { ...action, expectedVersion: roster.version })
|
||||
if (action.kind === 'swap') return api.swapRoster(eventId, {
|
||||
teamAId: action.teamAId, playerAId: action.playerAId, teamBId: action.teamBId, playerBId: action.playerBId, expectedVersion: roster.version,
|
||||
})
|
||||
if (action.kind === 'substitute') return api.substituteRoster(eventId, {
|
||||
teamId: action.teamId, outgoingPlayerId: action.outgoingPlayerId, reservePlayerId: action.reservePlayerId, expectedVersion: roster.version,
|
||||
})
|
||||
if (action.kind === 'move') return api.moveRosterPlayer(eventId, {
|
||||
fromTeamId: action.fromTeamId, playerId: action.playerId, toTeamId: action.toTeamId, role: action.role, expectedVersion: roster.version,
|
||||
})
|
||||
if (action.kind === 'place') return api.placeReservePlayer(eventId, {
|
||||
teamId: action.teamId, reservePlayerId: action.reservePlayerId, role: action.role, expectedVersion: roster.version,
|
||||
})
|
||||
if (action.kind === 'remove') return api.removeRosterPlayer(eventId, {
|
||||
teamId: action.teamId, playerId: action.playerId, expectedVersion: roster.version,
|
||||
})
|
||||
return api.setRosterCaptain(eventId, action.teamId, action.playerId, roster.version)
|
||||
},
|
||||
onSuccess: (updated) => {
|
||||
@@ -564,7 +574,7 @@ function WorkflowRosterEditor({ eventId, roster, players, locked, onChanged }: {
|
||||
}
|
||||
return <section className="card roster-editor">
|
||||
<div className="section-title"><div><h2>Roster editor</h2><p>Version {roster.version} · drag players into any role slot or through reserve.</p></div>{roster.confirmed && <Badge tone="success"><Check />Locked</Badge>}</div>
|
||||
<div className="roster-editor-body"><div className="teams-grid">{roster.teams.map((team) => <article className="workflow-team" key={team.id}><header><h3>{team.name}</h3><label>Captain<select disabled={locked || mutate.isPending} value={team.captainPlayerId} onChange={(event) => mutate.mutate({ kind: 'captain', teamId: team.id, playerId: event.target.value })}><option value="">Choose captain</option>{team.slots.filter((slot) => slot.playerId).map((slot) => <option value={slot.playerId} key={slot.playerId}>{names.get(slot.playerId) ?? slot.playerId}</option>)}</select></label></header>{team.slots.map((slot, slotIndex) => <div className={`roster-slot ${slot.playerId ? '' : 'empty'}`} key={`${slot.role}-${slotIndex}`} onDragOver={(event) => { if (!locked) event.preventDefault() }} onDrop={(event) => dropOnSlot(event, team.id, slot)}><span className={`role-chip ${slot.role.toLowerCase()}`}>{slot.role[0]}</span>{slot.playerId ? <><strong draggable={!locked} onDragStart={(event) => startDrag(event, { kind: 'team', teamId: team.id, playerId: slot.playerId, role: slot.role })}>{names.get(slot.playerId) ?? slot.playerId}</strong><small>{rankLabel(slot.rating, language)}</small>{!locked && <button className="icon-button slot-remove" type="button" aria-label={`Move ${names.get(slot.playerId) ?? slot.playerId} to reserve`} onClick={() => mutate.mutate({ kind: 'remove', teamId: team.id, playerId: slot.playerId })}><X /></button>}</> : <><strong>Empty</strong><small>{slot.role}</small></>}</div>)}</article>)}</div>
|
||||
<div className="roster-editor-body"><div className="teams-grid">{roster.teams.map((team) => <article className="workflow-team" key={team.id}><header><h3>{team.name}</h3><label>Captain<select disabled={locked || mutate.isPending} value={team.captainPlayerId} onChange={(event) => mutate.mutate({ kind: 'captain', teamId: team.id, playerId: event.target.value })}><option value="">Choose captain</option>{team.slots.filter((slot) => slot.playerId).map((slot) => <option value={slot.playerId} key={slot.playerId}>{names.get(slot.playerId) ?? slot.playerId}</option>)}</select></label></header>{team.slots.map((slot, slotIndex) => <div className={`roster-slot ${slot.playerId ? '' : 'empty'}`} key={`${slot.role}-${slotIndex}`} draggable={!locked && Boolean(slot.playerId)} onDragStart={(event) => { if (slot.playerId) startDrag(event, { kind: 'team', teamId: team.id, playerId: slot.playerId, role: slot.role }) }} onDragOver={(event) => { if (!locked) event.preventDefault() }} onDrop={(event) => dropOnSlot(event, team.id, slot)}><span className={`role-chip ${slot.role.toLowerCase()}`}>{slot.role[0]}</span>{slot.playerId ? <><strong>{names.get(slot.playerId) ?? slot.playerId}</strong><small>{rankLabel(slot.rating, language)}</small>{!locked && <button className="icon-button slot-remove" type="button" aria-label={`Move ${names.get(slot.playerId) ?? slot.playerId} to reserve`} onClick={() => mutate.mutate({ kind: 'remove', teamId: team.id, playerId: slot.playerId })}><X /></button>}</> : <><strong>Empty</strong><small>{slot.role}</small></>}</div>)}</article>)}</div>
|
||||
<aside className="roster-reserve" onDragOver={(event) => { if (!locked) event.preventDefault() }} onDrop={(event) => { event.preventDefault(); const source = readDrag(event); if (!locked && source?.kind === 'team') mutate.mutate({ kind: 'remove', teamId: source.teamId, playerId: source.playerId }) }}><div><UsersRound /><span><strong>Reserve</strong><small>Drop a player here to remove them from a team</small></span></div><div className="reserve-list">{roster.reserve.length === 0 ? <p>Reserve is empty</p> : roster.reserve.map((id) => <button type="button" draggable={!locked} onDragStart={(event) => startDrag(event, { kind: 'reserve', playerId: id })} key={id}><span className="mini-avatar">{(names.get(id) ?? id).slice(0, 2).toUpperCase()}</span><strong>{names.get(id) ?? id}</strong></button>)}</div></aside>
|
||||
</div>
|
||||
{mutate.isError && <p className="error-note">{mutate.error.message}</p>}
|
||||
|
||||
Reference in New Issue
Block a user