Fix Team Race duplicate-membership bug and two related team-roster gaps
Reported by the user: creating a team, adding the wrong driver, then moving that driver to another team by ticking them on the new team's edit form left the driver on both teams at once. Root cause: there was never a "move" action - the edit form only ever added a driver to the team being saved, never removed them from wherever they already were. Live laps from a driver on two teams were then silently credited to only the first-matching team, with no clear error. reassignTeamMembers (event_race_logic.js) now strips a driver/car being saved onto one team out of every other team in the same event, and the team checkbox list shows which team a driver is already on before you move them. Also fixed two related gaps found while investigating, at the user's request to fix everything: getTeamDriverPool had regressed to ignoring the event's class/participant scoping entirely (showing every driver in the club), and deleting a driver or car left them behind in team rosters forever. Added a duplicate_team_members Race Day preflight check as defense in depth for any already-corrupted saved state. Verified with new unit tests for reassignTeamMembers, getTeamDriverPool and the new preflight check, plus a new permanent browser test reproducing the user's exact reported scenario end to end. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -47,6 +47,13 @@ export function renderEventManagerMarkup(context) {
|
||||
getModeLabel,
|
||||
renderTable,
|
||||
} = context;
|
||||
// Checking a driver/car here moves them off whichever other team already has them (see
|
||||
// reassignTeamMembers in event_race_logic.js) - name that team here so the admin sees
|
||||
// the move coming rather than discovering it after saving.
|
||||
const driverTeamElsewhere = (driverId, excludeTeamId = "") =>
|
||||
raceTeams.find((team) => team.id !== excludeTeamId && team.driverIds.includes(driverId))?.name || "";
|
||||
const carTeamElsewhere = (carId, excludeTeamId = "") =>
|
||||
raceTeams.find((team) => team.id !== excludeTeamId && team.carIds.includes(carId))?.name || "";
|
||||
const sessionChannelMarkup = sessions
|
||||
.map((session) => ({ session, markup: renderSessionChannelAnalysis(session) }))
|
||||
.filter((entry) => entry.markup)
|
||||
@@ -324,7 +331,7 @@ export function renderEventManagerMarkup(context) {
|
||||
(driver) => `
|
||||
<label class="check-card">
|
||||
<input type="checkbox" name="teamDriverIds" form="teamForm" value="${driver.id}" />
|
||||
<span>${escapeHtml(driver.name)}${driver.transponder ? ` (${escapeHtml(driver.transponder)})` : ""}</span>
|
||||
<span>${escapeHtml(driver.name)}${driver.transponder ? ` (${escapeHtml(driver.transponder)})` : ""}${driverTeamElsewhere(driver.id) ? `<small>${escapeHtml(t("events.team_member_elsewhere", { team: driverTeamElsewhere(driver.id) }))}</small>` : ""}</span>
|
||||
</label>
|
||||
`
|
||||
)
|
||||
@@ -344,7 +351,7 @@ export function renderEventManagerMarkup(context) {
|
||||
(car) => `
|
||||
<label class="check-card">
|
||||
<input type="checkbox" name="teamCarIds" form="teamForm" value="${car.id}" />
|
||||
<span>${escapeHtml(car.name)} (${escapeHtml(car.transponder || "-")})</span>
|
||||
<span>${escapeHtml(car.name)} (${escapeHtml(car.transponder || "-")})${carTeamElsewhere(car.id) ? `<small>${escapeHtml(t("events.team_member_elsewhere", { team: carTeamElsewhere(car.id) }))}</small>` : ""}</span>
|
||||
</label>
|
||||
`
|
||||
)
|
||||
@@ -757,7 +764,7 @@ export function renderEventManagerMarkup(context) {
|
||||
(driver) => `
|
||||
<label class="check-card">
|
||||
<input type="checkbox" name="teamDriverIds" value="${driver.id}" ${editingTeam.driverIds.includes(driver.id) ? "checked" : ""} />
|
||||
<span>${escapeHtml(driver.name)}${driver.transponder ? ` (${escapeHtml(driver.transponder)})` : ""}</span>
|
||||
<span>${escapeHtml(driver.name)}${driver.transponder ? ` (${escapeHtml(driver.transponder)})` : ""}${driverTeamElsewhere(driver.id, editingTeam.id) ? `<small>${escapeHtml(t("events.team_member_elsewhere", { team: driverTeamElsewhere(driver.id, editingTeam.id) }))}</small>` : ""}</span>
|
||||
</label>
|
||||
`
|
||||
)
|
||||
@@ -772,7 +779,7 @@ export function renderEventManagerMarkup(context) {
|
||||
(car) => `
|
||||
<label class="check-card">
|
||||
<input type="checkbox" name="teamCarIds" value="${car.id}" ${editingTeam.carIds.includes(car.id) ? "checked" : ""} />
|
||||
<span>${escapeHtml(car.name)} (${escapeHtml(car.transponder || "-")})</span>
|
||||
<span>${escapeHtml(car.name)} (${escapeHtml(car.transponder || "-")})${carTeamElsewhere(car.id, editingTeam.id) ? `<small>${escapeHtml(t("events.team_member_elsewhere", { team: carTeamElsewhere(car.id, editingTeam.id) }))}</small>` : ""}</span>
|
||||
</label>
|
||||
`
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user