Files
Sdk_TV_app/templates/calculator.html
T

504 lines
14 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Kalkulator</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/static/css/base.css">
<link rel="stylesheet" href="/static/css/navbar.css">
<link rel="stylesheet" href="/static/css/buttons.css">
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
body {
display: flex;
flex-direction: column;
height: 100vh;
background: #f0f2f5;
}
.navbar { flex-shrink: 0; z-index: 100; }
/* ── PAGE WRAPPER ── */
.page {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
overflow: hidden;
min-height: 0;
}
/* ── MAIN CARD ── */
.main-card {
background: white;
border-radius: 16px;
box-shadow: 0 8px 32px rgba(0,0,0,0.12);
width: 100%;
max-width: 1100px;
max-height: 100%;
display: flex;
flex-direction: row;
overflow: hidden;
}
/* ── LEFT PANEL: config ── */
.left-panel {
width: 260px;
flex-shrink: 0;
display: flex;
flex-direction: column;
border-right: 1px solid #e9ecef;
background: #f8f9fa;
}
.left-header {
padding: 22px 24px 16px;
border-bottom: 1px solid #e9ecef;
}
.left-header h3 {
margin: 0;
font-size: 1.1rem;
font-weight: 700;
color: #2c3e50;
}
.left-body {
padding: 20px 24px;
display: flex;
flex-direction: column;
gap: 20px;
flex: 1;
}
.setup-field {
display: flex;
flex-direction: column;
gap: 8px;
}
.setup-field label {
font-size: 0.8rem;
font-weight: 700;
color: #6c757d;
text-transform: uppercase;
letter-spacing: 0.4px;
}
.setup-input {
padding: 13px 14px;
border: 2px solid #dee2e6;
border-radius: 10px;
font-size: 1.15rem;
font-weight: 600;
color: #2c3e50;
text-align: center;
background: white;
transition: border-color 0.2s;
outline: none;
width: 100%;
box-sizing: border-box;
}
.setup-input:focus {
border-color: #28a745;
box-shadow: 0 0 0 3px rgba(40,167,69,0.12);
}
.setup-hint {
font-size: 0.72rem;
color: #adb5bd;
}
.gen-btn {
background: #28a745;
color: white;
border: none;
border-radius: 10px;
padding: 14px;
font-size: 1rem;
font-weight: 700;
cursor: pointer;
transition: background 0.2s, transform 0.1s;
width: 100%;
}
.gen-btn:hover:not(:disabled) { background: #1e7e34; transform: translateY(-1px); }
.gen-btn:disabled { background: #ced4da; cursor: not-allowed; }
/* stats + actions below the fold */
.left-stats {
display: none;
flex-direction: column;
gap: 14px;
padding: 20px 24px;
border-top: 1px solid #e9ecef;
}
.left-stats.visible { display: flex; }
.stat-row {
display: flex;
justify-content: space-between;
align-items: baseline;
}
.stat-label {
font-size: 0.8rem;
font-weight: 600;
color: #6c757d;
text-transform: uppercase;
letter-spacing: 0.3px;
}
.stat-value {
font-size: 1.8rem;
font-weight: 700;
line-height: 1;
}
#totalScore { color: #28a745; }
#tensCount { color: #ffc107; }
.progress-bar-wrap {
height: 6px;
background: #e9ecef;
border-radius: 3px;
overflow: hidden;
}
.progress-bar-fill {
height: 100%;
background: #28a745;
border-radius: 3px;
transition: width 0.25s ease;
}
.left-actions {
padding: 0 24px 24px;
display: none;
flex-direction: column;
gap: 10px;
}
.left-actions.visible { display: flex; }
.action-btn {
padding: 11px 12px;
border-radius: 8px;
font-size: 0.88rem;
font-weight: 600;
cursor: pointer;
transition: all 0.15s;
width: 100%;
text-align: center;
}
.btn-zeros {
background: white;
border: 2px solid #6c757d;
color: #6c757d;
}
.btn-zeros:hover { background: #6c757d; color: white; }
.btn-reset {
background: white;
border: 2px solid #dc3545;
color: #dc3545;
}
.btn-reset:hover { background: #dc3545; color: white; }
/* ── RIGHT PANEL: grid ── */
.right-panel {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
overflow: hidden;
}
.right-empty {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #adb5bd;
gap: 10px;
font-size: 1rem;
}
.right-empty .empty-icon { font-size: 3rem; }
.targets-wrapper {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding: 18px 20px 20px;
min-height: 0;
display: none;
}
.targets-wrapper.visible { display: block; }
.targets-wrapper::-webkit-scrollbar { width: 7px; }
.targets-wrapper::-webkit-scrollbar-track { background: transparent; }
.targets-wrapper::-webkit-scrollbar-thumb { background: #ced4da; border-radius: 4px; }
.targets-grid {
display: grid;
gap: 10px;
}
.target-group {
border: 2px solid #e9ecef;
border-radius: 8px;
background: #f8f9fa;
display: flex;
flex-direction: column;
overflow: hidden;
transition: border-color 0.15s, background 0.15s;
}
.target-group.completed {
border-color: #28a745;
background: #f0f8f5;
}
.target-num {
background: #e9ecef;
border-bottom: 1px solid #dee2e6;
font-size: 0.75rem;
font-weight: 700;
color: #495057;
text-align: center;
padding: 5px 4px;
flex-shrink: 0;
transition: background 0.15s, color 0.15s;
}
.target-group.completed .target-num {
background: linear-gradient(135deg, #e8f5e8, #c8e6c9);
border-bottom-color: #28a745;
color: #28a745;
}
.shots-col {
display: flex;
flex-direction: column;
gap: 5px;
padding: 6px;
}
.shot-input {
width: 100%;
padding: 6px 2px;
border: 1.5px solid #dee2e6;
border-radius: 4px;
text-align: center;
font-size: 1rem;
font-weight: 700;
color: #333;
background: white;
min-height: 32px;
box-sizing: border-box;
transition: border-color 0.15s, color 0.15s;
outline: none;
}
.shot-input:focus {
border-color: #28a745;
box-shadow: 0 0 0 2px rgba(40,167,69,0.2);
}
.shot-input.valid { border-color: #28a745; }
.shot-input.ten { border-color: #ffc107; color: #ffc107; }
</style>
<script src="/static/js/i18n.js"></script>
</head>
<body>
<div class="navbar">
<div class="navbar-title">🎯 Kalkulator</div>
<div class="navbar-controls">
<a href="/" class="nav-btn">✕</a>
</div>
</div>
<div class="page">
<div class="main-card">
<!-- LEFT: config + stats -->
<div class="left-panel">
<div class="left-header">
<h3>🎯 Konfiguracija</h3>
</div>
<div class="left-body">
<div class="setup-field">
<label>Število tarč</label>
<input type="number" id="inputTargets" class="setup-input" min="1" max="100" value="20" oninput="validateSetup()">
</div>
<div class="setup-field">
<label>Strelov na tarčo</label>
<input type="number" id="inputShots" class="setup-input" min="1" max="10" value="2" oninput="validateSetup()">
<span class="setup-hint">Maks. vrednost strela: 10</span>
</div>
<button class="gen-btn" id="startBtn" onclick="startCalculator()">Generiraj</button>
</div>
<div class="left-stats" id="leftStats">
<div class="stat-row">
<span class="stat-label">Točke</span>
<span class="stat-value" id="totalScore">0</span>
</div>
<div class="stat-row">
<span class="stat-label">10-ke</span>
<span class="stat-value" id="tensCount">0</span>
</div>
<div class="progress-bar-wrap">
<div class="progress-bar-fill" id="progressBar" style="width:0%"></div>
</div>
<span class="setup-hint" id="calcMeta" style="text-align:center;"></span>
</div>
<div class="left-actions" id="leftActions">
<button class="action-btn btn-zeros" onclick="fillZeros()">Zapolni 0</button>
<button class="action-btn btn-reset" onclick="resetScores()">Pobriši vse</button>
</div>
</div>
<!-- RIGHT: grid -->
<div class="right-panel">
<div class="right-empty" id="rightEmpty">
<span class="empty-icon">🎯</span>
<span>Nastavi konfiguracijo in klikni Generiraj</span>
</div>
<div class="targets-wrapper" id="targetsWrapper">
<div class="targets-grid" id="targetsGrid"></div>
</div>
</div>
</div>
</div>
<script>
let numTargets = 20;
let shotsPerTarget = 2;
let scores = {};
function validateSetup() {
const t = parseInt(document.getElementById('inputTargets').value);
const s = parseInt(document.getElementById('inputShots').value);
document.getElementById('startBtn').disabled = !(t >= 1 && t <= 100 && s >= 1 && s <= 10);
}
function startCalculator() {
numTargets = parseInt(document.getElementById('inputTargets').value);
shotsPerTarget = parseInt(document.getElementById('inputShots').value);
scores = {};
for (let t = 1; t <= numTargets; t++) {
scores[t] = {};
for (let s = 1; s <= shotsPerTarget; s++) scores[t][s] = null;
}
document.getElementById('calcMeta').textContent =
`${numTargets} × ${shotsPerTarget} = maks. ${numTargets * shotsPerTarget * 10} točk`;
buildGrid();
document.getElementById('rightEmpty').style.display = 'none';
document.getElementById('targetsWrapper').classList.add('visible');
document.getElementById('leftStats').classList.add('visible');
document.getElementById('leftActions').classList.add('visible');
updateStats();
const first = document.querySelector('.shot-input');
if (first) { first.focus(); first.select(); }
}
function buildGrid() {
const grid = document.getElementById('targetsGrid');
let cols;
if (numTargets <= 4) cols = numTargets;
else if (numTargets <= 10) cols = 5;
else if (numTargets <= 20) cols = 5;
else if (numTargets <= 40) cols = 8;
else cols = 10;
grid.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
let html = '';
for (let t = 1; t <= numTargets; t++) {
html += `<div class="target-group" id="tg-${t}">
<div class="target-num">${t}</div>
<div class="shots-col">`;
for (let s = 1; s <= shotsPerTarget; s++) {
html += `<input type="number" class="shot-input" id="si-${t}-${s}"
min="0" max="10" data-t="${t}" data-s="${s}"
oninput="onShot(${t},${s},this.value)"
onkeydown="onShotKey(event,${t},${s})">`;
}
html += `</div></div>`;
}
grid.innerHTML = html;
}
function onShot(t, s, raw) {
const input = document.getElementById(`si-${t}-${s}`);
let val = null;
if (raw !== '' && raw !== null) {
val = Math.max(0, Math.min(10, parseInt(raw) || 0));
if (input.value !== val.toString()) input.value = val;
}
scores[t][s] = val;
input.classList.remove('valid', 'ten');
if (val !== null) input.classList.add(val === 10 ? 'ten' : 'valid');
updateTargetGroup(t);
updateStats();
}
function onShotKey(e, t, s) {
if (e.key === 'Enter' || e.key === 'Tab') {
e.preventDefault();
const inputs = Array.from(document.querySelectorAll('.shot-input'));
const idx = inputs.indexOf(document.getElementById(`si-${t}-${s}`));
const next = inputs[idx + 1];
if (next) { next.focus(); next.select(); }
}
}
function updateTargetGroup(t) {
const allFilled = Object.values(scores[t]).every(v => v !== null);
document.getElementById(`tg-${t}`).classList.toggle('completed', allFilled);
}
function updateStats() {
let total = 0, tens = 0, filled = 0;
const totalSlots = numTargets * shotsPerTarget;
for (let t = 1; t <= numTargets; t++)
for (let s = 1; s <= shotsPerTarget; s++) {
const v = scores[t][s];
if (v !== null) { total += v; filled++; if (v === 10) tens++; }
}
document.getElementById('totalScore').textContent = total;
document.getElementById('tensCount').textContent = tens;
document.getElementById('progressBar').style.width = `${(filled / totalSlots) * 100}%`;
}
function fillZeros() {
for (let t = 1; t <= numTargets; t++) {
for (let s = 1; s <= shotsPerTarget; s++) {
if (scores[t][s] === null) {
scores[t][s] = 0;
const inp = document.getElementById(`si-${t}-${s}`);
inp.value = 0;
inp.classList.remove('ten');
inp.classList.add('valid');
}
}
updateTargetGroup(t);
}
updateStats();
}
function resetScores() {
if (!confirm('Pobrisati vse vnose?')) return;
for (let t = 1; t <= numTargets; t++) {
for (let s = 1; s <= shotsPerTarget; s++) {
scores[t][s] = null;
const inp = document.getElementById(`si-${t}-${s}`);
inp.value = '';
inp.classList.remove('valid', 'ten');
}
updateTargetGroup(t);
}
updateStats();
}
validateSetup();
</script>
</body>
</html>