diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 7f23b0e..87e16cc 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -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

Roster editor

Version {roster.version} ยท drag players into any role slot or through reserve.

{roster.confirmed && Locked}
-
{roster.teams.map((team) =>

{team.name}

{team.slots.map((slot, slotIndex) =>
{ if (!locked) event.preventDefault() }} onDrop={(event) => dropOnSlot(event, team.id, slot)}>{slot.role[0]}{slot.playerId ? <> startDrag(event, { kind: 'team', teamId: team.id, playerId: slot.playerId, role: slot.role })}>{names.get(slot.playerId) ?? slot.playerId}{rankLabel(slot.rating, language)}{!locked && } : <>Empty{slot.role}}
)}
)}
+
{roster.teams.map((team) =>

{team.name}

{team.slots.map((slot, slotIndex) =>
{ 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)}>{slot.role[0]}{slot.playerId ? <>{names.get(slot.playerId) ?? slot.playerId}{rankLabel(slot.rating, language)}{!locked && } : <>Empty{slot.role}}
)}
)}
{mutate.isError &&

{mutate.error.message}

} diff --git a/frontend/src/index.css b/frontend/src/index.css index 8f5da2e..57967c5 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -244,7 +244,7 @@ textarea { min-height: 85px; resize: vertical; } .workflow-team header { padding: 14px; display: flex; align-items: end; justify-content: space-between; gap: 12px; border-bottom: 1px solid var(--border); } .workflow-team header label { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 9px; }.workflow-team header select { padding: 7px; } .roster-slot { min-height: 54px; padding: 8px 12px; display: grid; grid-template-columns: 24px minmax(100px,1fr) auto 30px; align-items: center; gap: 8px; border-bottom: 1px solid #22272e; font-size: 10px; transition: background .15s,border-color .15s; } -.roster-slot > small { color: var(--muted); }.roster-slot > strong[draggable="true"] { cursor: grab; }.roster-slot > strong[draggable="true"]:active { cursor: grabbing; } +.roster-slot > small { color: var(--muted); }.roster-slot[draggable="true"] { cursor: grab; }.roster-slot[draggable="true"]:active { cursor: grabbing; } .roster-slot.empty { border: 1px dashed #424a55; background: #15181d; }.roster-slot.empty > strong { color: #737b86; font-style: italic; }.slot-remove { width: 28px; height: 28px; }.slot-remove svg { width: 13px; } .roster-reserve { min-height: 100%; padding: 14px; border: 1px dashed #3b424c; border-radius: 9px; background: #0d1015; } .roster-reserve > div:first-child { display: flex; gap: 9px; align-items: center; margin-bottom: 13px; }.roster-reserve > div:first-child svg { width: 17px; color: var(--orange); }.roster-reserve span { display: grid; }.roster-reserve small,.reserve-list p { color: var(--muted); font-size: 9px; }