Compare commits
3 Commits
v0.22.0
...
3ba68ac973
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ba68ac973 | |||
| 67a72f9a92 | |||
| 51c45ad4a9 |
@@ -40,13 +40,17 @@ export function LeaderboardManager({ serverId, initialData }: LeaderboardManager
|
|||||||
const handleDriversChange = (newDrivers: LeaderboardDriver[]) => {
|
const handleDriversChange = (newDrivers: LeaderboardDriver[]) => {
|
||||||
const oldDrivers = draft.drivers;
|
const oldDrivers = draft.drivers;
|
||||||
|
|
||||||
// Build index map: for each position in newDrivers, what was the old index?
|
// Build index map by matching drivers by initials (their stable identifier)
|
||||||
const indexMap = newDrivers.map((d) => oldDrivers.indexOf(d));
|
// For each position in newDrivers, find where that driver was in oldDrivers
|
||||||
|
const indexMap = newDrivers.map((d) => {
|
||||||
|
const oldIndex = oldDrivers.findIndex((old) => old.initials === d.initials);
|
||||||
|
return oldIndex; // -1 if new driver, otherwise the old index
|
||||||
|
});
|
||||||
|
|
||||||
// If a driver was added (indexOf returns -1), it's new
|
// If a driver was added (findIndex returns -1), it's new, start with DNS
|
||||||
const newTracks = draft.tracks.map((t) => ({
|
const newTracks = draft.tracks.map((t) => ({
|
||||||
...t,
|
...t,
|
||||||
results: indexMap.map((i) => (i === -1 ? 0 : (t.results[i] ?? 0)))
|
results: indexMap.map((i) => (i === -1 ? 'DNS' : (t.results[i] ?? 'DNS')))
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setDraft({ ...draft, drivers: newDrivers, tracks: newTracks });
|
setDraft({ ...draft, drivers: newDrivers, tracks: newTracks });
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export function LeaderboardStandings({ leaderboard }: LeaderboardStandingsProps)
|
|||||||
(t) => t.fastestLapInitials === driver.initials
|
(t) => t.fastestLapInitials === driver.initials
|
||||||
).length;
|
).length;
|
||||||
const totalPoints =
|
const totalPoints =
|
||||||
trackResults.reduce((sum, r) => sum + (typeof r === 'number' ? r : 0), 0) +
|
trackResults.reduce((sum: number, r) => sum + (typeof r === 'number' ? r : 0), 0) +
|
||||||
fastestLapCount * leaderboard.flPoints.points;
|
fastestLapCount * leaderboard.flPoints.points;
|
||||||
return { driver, driverIndex: idx, totalPoints, trackResults, fastestLapCount };
|
return { driver, driverIndex: idx, totalPoints, trackResults, fastestLapCount };
|
||||||
})
|
})
|
||||||
@@ -100,9 +100,7 @@ export function LeaderboardStandings({ leaderboard }: LeaderboardStandingsProps)
|
|||||||
<td className="px-2 py-2 text-center text-xs text-purple-400">
|
<td className="px-2 py-2 text-center text-xs text-purple-400">
|
||||||
{row.fastestLapCount > 0 ? `×${row.fastestLapCount}` : '—'}
|
{row.fastestLapCount > 0 ? `×${row.fastestLapCount}` : '—'}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-2 py-2 text-center font-bold text-yellow-400">
|
<td className="px-2 py-2 text-center font-bold text-yellow-400">{row.totalPoints}</td>
|
||||||
{row.totalPoints}
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -10,20 +10,27 @@ interface ResultInputProps {
|
|||||||
|
|
||||||
function ResultInput({ value, pointsTable, onChange }: ResultInputProps) {
|
function ResultInput({ value, pointsTable, onChange }: ResultInputProps) {
|
||||||
const knownPoints = Array.from(new Set(pointsTable.map((e) => e.points))).sort((a, b) => b - a);
|
const knownPoints = Array.from(new Set(pointsTable.map((e) => e.points))).sort((a, b) => b - a);
|
||||||
|
// Fallback 0 to DNS if 0 is not a valid points option
|
||||||
|
const displayValue = value === 0 && !knownPoints.includes(0) ? 'DNS' : value;
|
||||||
|
// Ensure the current numeric value is always included in options
|
||||||
|
const allPoints = typeof displayValue === 'number'
|
||||||
|
? Array.from(new Set([...knownPoints, displayValue])).sort((a, b) => b - a)
|
||||||
|
: knownPoints;
|
||||||
|
|
||||||
const handleChange = (raw: string) => {
|
const handleChange = (raw: string) => {
|
||||||
if (raw === 'DNF') return onChange('DNF');
|
if (raw === 'DNF') return onChange('DNF');
|
||||||
if (raw === 'DNS') return onChange('DNS');
|
if (raw === 'DNS') return onChange('DNS');
|
||||||
onChange(parseInt(raw) || 0);
|
const parsed = parseInt(raw);
|
||||||
|
onChange(isNaN(parsed) ? 0 : parsed);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<select
|
<select
|
||||||
value={String(value)}
|
value={String(displayValue)}
|
||||||
onChange={(e) => handleChange(e.target.value)}
|
onChange={(e) => handleChange(e.target.value)}
|
||||||
className="w-full rounded bg-gray-600 px-1 py-1 text-xs text-white"
|
className="w-full rounded bg-gray-600 px-1 py-1 text-xs text-white"
|
||||||
>
|
>
|
||||||
{knownPoints.map((p) => (
|
{allPoints.map((p) => (
|
||||||
<option key={p} value={String(p)}>
|
<option key={p} value={String(p)}>
|
||||||
{p}
|
{p}
|
||||||
</option>
|
</option>
|
||||||
|
|||||||
Reference in New Issue
Block a user