Merge APP_V2/main: Combine quality updates with league features

- Merged remote changes: Liga krog3 and league state management
- Resolved merge conflicts in locale files and templates
- Kept local v1.0.1 version and styling improvements
- Added league combine functionality from remote
- Preserved new league_state.json and tournament_results.json
- Integrated i18n improvements

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-08 19:35:27 +01:00
17 changed files with 2913 additions and 49 deletions
+98 -2
View File
@@ -718,6 +718,44 @@
font-weight: bold;
}
.joker-checkbox-wrapper {
margin-top: 8px;
}
.joker-label {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
padding: 6px 12px;
background: #fff3cd;
border: 2px solid #ffc107;
border-radius: 8px;
transition: all 0.2s ease;
}
.joker-label:hover {
background: #ffc107;
border-color: #ff9800;
}
.joker-checkbox-calc {
cursor: pointer;
width: 18px;
height: 18px;
}
.joker-checkbox-calc:disabled {
cursor: not-allowed;
opacity: 0.6;
}
.joker-text {
font-size: 0.9rem;
font-weight: 600;
color: #856404;
}
.participant-status {
display: flex;
align-items: center;
@@ -1970,6 +2008,49 @@
}
}
// Handle joker checkbox change
function handleJokerChange(playerId) {
const checkbox = document.getElementById(`joker-calc-${playerId}`);
const isChecked = checkbox.checked;
// If checked, warn user that all scores will be set to zero
if (isChecked) {
if (confirm('Marking this player as using their Joker will set all their scores to zero. Continue?')) {
// Set all scores to zero
const participant = results.participants[playerId];
if (participant && participant.targets) {
Object.keys(participant.targets).forEach(targetId => {
const target = participant.targets[targetId];
Object.keys(target).forEach(shotKey => {
if (shotKey.startsWith('shot')) {
target[shotKey] = 0;
}
});
});
}
participant.total_score = 0;
participant.completed = true; // Mark as completed since joker is used
participant.joker_selected = true; // Mark joker as selected in results
// Update UI
updateParticipantTotal(playerId);
updateParticipantStatus(playerId);
updateParticipantTens(playerId);
updateOverallProgress();
updateOverallTens();
// Disable the checkbox so it can't be unchecked
checkbox.disabled = true;
// Save the change
savePlayerData(playerId);
} else {
// User cancelled, uncheck the box
checkbox.checked = false;
}
}
}
// Keyboard shortcuts
document.addEventListener('keydown', function(event) {
if (event.ctrlKey && event.key === 's') {
@@ -1984,7 +2065,7 @@
// Initialize targets for all players
Object.keys(results.participants).forEach(playerId => {
initializeTargetsForPlayer(parseInt(playerId));
// Update initial states
for (let i = 1; i <= numTargets; i++) {
updateTargetGroupStyling(parseInt(playerId), i);
@@ -1992,7 +2073,22 @@
updateParticipantStatus(parseInt(playerId));
updateParticipantTens(parseInt(playerId));
});
// Initialize joker checkboxes for league tournaments
{% if league_state %}
const leagueState = {{ league_state | tojson | safe }};
Object.keys(results.participants).forEach(playerId => {
const checkbox = document.getElementById(`joker-calc-${playerId}`);
if (checkbox && leagueState.participants && leagueState.participants[playerId]) {
const participant = leagueState.participants[playerId];
if (participant.joker_used) {
checkbox.checked = true;
checkbox.disabled = true;
}
}
});
{% endif %}
updateOverallProgress();
updateOverallTens();