This commit is contained in:
2026-05-10 21:46:00 +02:00
parent 6e9efd2dbc
commit 02510fb224
11 changed files with 745 additions and 72 deletions

BIN
assets/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 KiB

BIN
assets/2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 KiB

BIN
assets/3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 KiB

View File

@@ -15,16 +15,44 @@
<hr>
<p class="page-paragraph">Ti dodatki so tukaj saj sem jih moral narediti za pogoje naloge. Nimajo praktične uporabe.</p>
<br>
<div class="page-btn-collection" style="margin-left: 20px;">
<div class="page-btn-collection" style="margin-left: 23px;">
<button id="open-fin-modal" class="page-btn">Finančni kalkulator</button>
<button id="open-game-modal" class="page-btn">Igra</button>
</div>
<br>
<button style="margin-left: 23px; margin-bottom: 20px;" id="toggle-collapse" class="page-btn">Prikaži/Skrij galerijo slik</button>
<div id="page-collapse" class="page-collapse">
<p class="page-paragraph">To je skrit del strani. Kliknite gumb zgoraj, da ga prikažete ali skrijete.</p>
<div class="page-image-gallery">
<img src="./assets/1.jpg" alt="Slika 1" class="page-gallery-image">
<img src="./assets/2.jpg" alt="Slika 2" class="page-gallery-image">
<img src="./assets/3.jpg" alt="Slika 3" class="page-gallery-image">
</div>
</div>
<div class="modal" id="fin-modal">
<div class="modal-content">
<span class="close-fin-modal close">&times;</span>
<h2>Finančni kalkulator</h2>
<br>
<p>To je finančni kalkulator. Kliknite gumb spodaj, da ga zaprete.</p>
<div class="fin-calculator-form">
<div class="form-group">
<label for="amount-input">Letna davčna osnova (EUR):</label>
<input type="text" id="amount-input" class="page-input" placeholder="Vnesite znesek (npr. 12.345,67)">
</div>
<div class="form-group checkbox-group">
<input type="checkbox" id="deduction-checkbox">
<label for="deduction-checkbox">Uporabi splošno olajšavo (5.551,93 EUR)</label>
</div>
<div id="calculator-result" class="calculator-result" style="display: none;">
<p><strong>Razred:</strong> <span id="result-razred">-</span></p>
<p><strong>Stopnja dohodnjine:</strong> <span id="result-rate">-</span></p>
<p><strong>Davčna osnova (z olajšavo):</strong> <span id="result-basis">-</span></p>
<p><strong>Obdavčeni znesek:</strong> <span id="result-tax">-</span></p>
</div>
</div>
<div class="modal-buttons">
<button class="close-fin-modal page-btn">Zapri modal</button>
</div>
@@ -35,7 +63,42 @@
<span class="close-game-modal close">&times;</span>
<h2>Igra</h2>
<br>
<p>To je igra. Kliknite gumb spodaj, da jo zaprete.</p>
<div id="game-start-screen" class="game-panel">
<p class="game-intro">Uganite besedo iz naključno izbranega vnosa. Imate 3 poskuse na besedo, točke pa padajo po zaporedju 100, 50 in 25.</p>
<div class="modal-buttons modal-buttons-left">
<button id="start-game-button" class="page-btn nav-btn-primary">Začni igro</button>
</div>
</div>
<div id="game-play-screen" class="game-panel" hidden>
<p class="game-meta" style="margin-top: 10px;"><strong>Tip:</strong> <span id="game-word-type">-</span></p>
<div class="game-definition-box">
<p class="game-section-label">Definicije</p>
<div id="game-definitions" class="game-definitions"></div>
</div>
<div class="game-input-row">
<input id="game-guess-input" class="page-input game-guess-input" type="text" placeholder="Vnesite svojo rešitev">
<button id="submit-guess-button" class="page-btn nav-btn-primary">Preveri</button>
</div>
<p id="game-feedback" class="game-feedback" aria-live="polite"></p>
<p class="game-meta">Preostali poskusi: <strong id="game-attempts-left">3</strong></p>
<p class="game-meta">Točke v tej besedi: <strong id="game-round-points">100</strong></p>
</div>
<br>
<div id="game-stats-screen" class="game-panel" hidden>
<div class="game-stats-grid">
<p><strong>Skupne točke:</strong> <span id="game-stat-score">0</span></p>
<p><strong>Pravilno uganjene besede:</strong> <span id="game-stat-correct">0</span></p>
<p><strong>Spodletele besede:</strong> <span id="game-stat-failed">0</span></p>
<p><strong>Skupni poskusi:</strong> <span id="game-stat-guesses">0</span></p>
</div>
<div class="modal-buttons modal-buttons-left">
<button id="restart-game-button" class="page-btn nav-btn-primary">Igraj znova</button>
</div>
</div>
<div class="modal-buttons">
<button class="close-game-modal page-btn">Zapri modal</button>
</div>

View File

@@ -16,4 +16,386 @@ document.querySelectorAll(".close-game-modal").forEach(function(button) {
button.addEventListener("click", function() {
document.getElementById("game-modal").style.visibility = "hidden";
});
});
});
document.getElementById("toggle-collapse").addEventListener("click", function() {
const collapseDiv = document.getElementById("page-collapse");
if (collapseDiv.style.visibility === "visible") {
collapseDiv.style.visibility = "hidden";
} else {
collapseDiv.style.visibility = "visible";
}
});
// Igra
const gameState = {
active: false,
loading: false,
currentEntry: null,
normalizedAnswer: "",
attemptsLeft: 3,
roundPoints: 100,
score: 0,
correct: 0,
failed: 0,
guesses: 0,
currentWordGuessed: false
};
const gameElements = {};
function stripHtmlTags(html) {
return String(html || "")
.replace(/<\s*br\s*\/?>/gi, "\n")
.replace(/<\s*\/p\s*>/gi, "\n")
.replace(/<\s*p[^>]*>/gi, "")
.replace(/<[^>]+>/g, "")
.replace(/&nbsp;/g, " ")
.replace(/&amp;/g, "&")
.replace(/&lt;/g, "<")
.replace(/&gt;/g, ">")
.replace(/&quot;/g, '"')
.replace(/&#39;/g, "'")
.replace(/\n{3,}/g, "\n\n")
.trim();
}
function normalizeGuess(value) {
return String(value || "")
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/\s+/g, "")
.trim();
}
function parseDefinitions(html) {
const plain = stripHtmlTags(html);
return plain
.split(/\n+/)
.map(line => line.trim())
.filter(Boolean);
}
function setGameMessage(message, type) {
if (!gameElements.feedback) {
return;
}
gameElements.feedback.textContent = message;
gameElements.feedback.classList.remove("is-success", "is-error", "is-neutral");
gameElements.feedback.classList.add(type || "is-neutral");
}
function updateGameStats() {
if (gameElements.attemptsLeft) {
gameElements.attemptsLeft.textContent = String(gameState.attemptsLeft);
}
if (gameElements.roundPoints) {
gameElements.roundPoints.textContent = String(gameState.roundPoints);
}
if (gameElements.score) {
gameElements.score.textContent = String(gameState.score);
}
if (gameElements.correct) {
gameElements.correct.textContent = String(gameState.correct);
}
if (gameElements.failed) {
gameElements.failed.textContent = String(gameState.failed);
}
if (gameElements.guesses) {
gameElements.guesses.textContent = String(gameState.guesses);
}
}
function setGameScreen(screen) {
const screens = ["start", "play", "stats"];
screens.forEach(name => {
const element = gameElements[`${name}Screen`];
if (element) {
element.hidden = name !== screen;
}
});
}
function resetRoundState() {
gameState.loading = false;
gameState.attemptsLeft = 3;
gameState.roundPoints = 100;
gameState.currentWordGuessed = false;
updateGameStats();
setGameMessage("", "is-neutral");
if (gameElements.guessInput) {
gameElements.guessInput.value = "";
gameElements.guessInput.disabled = false;
gameElements.guessInput.focus();
}
if (gameElements.submitGuessButton) {
gameElements.submitGuessButton.disabled = false;
}
}
function renderCurrentEntry(entry) {
const definitions = parseDefinitions(entry?.Vsebina);
const typeText = entry?.Tip || "-";
if (gameElements.wordType) {
gameElements.wordType.textContent = typeText;
}
if (gameElements.definitions) {
if (!definitions.length) {
gameElements.definitions.innerHTML = '<p class="game-empty-state">Opis za ta vnos ni na voljo.</p>';
} else {
gameElements.definitions.innerHTML = definitions
.map(definition => `<div class="game-definition-line">${definition}</div>`)
.join("");
}
}
gameState.currentEntry = entry;
gameState.normalizedAnswer = normalizeGuess(entry?.Kljuc);
resetRoundState();
}
function showGameStats() {
if (gameElements.statScore) {
gameElements.statScore.textContent = String(gameState.score);
}
if (gameElements.statCorrect) {
gameElements.statCorrect.textContent = String(gameState.correct);
}
if (gameElements.statFailed) {
gameElements.statFailed.textContent = String(gameState.failed);
}
if (gameElements.statGuesses) {
gameElements.statGuesses.textContent = String(gameState.guesses);
}
setGameScreen("stats");
}
function nextWord() {
if (!gameState.active) {
return;
}
gameState.loading = true;
setGameMessage("Nalagam nov vnos ...", "is-neutral");
fetch("https://ssnj.dcrubro.com/api/random-vnos", { method: "GET" })
.then(response => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
})
.then(data => {
if (!data || !data.success || !data.data) {
throw new Error("Neveljaven odgovor strežnika");
}
renderCurrentEntry(data.data);
setGameScreen("play");
setGameMessage("Ugibajte besedo glede na definicijo.", "is-neutral");
})
.catch(error => {
console.error("random-vnos error", error);
setGameMessage("Napaka pri nalaganju novega vnosa. Poskusite znova.", "is-error");
gameState.loading = false;
})
.finally(() => {
gameState.loading = false;
});
}
function finishCurrentWord(correctlyGuessed) {
if (correctlyGuessed) {
gameState.correct += 1;
} else {
gameState.failed += 1;
gameState.score = Math.max(0, gameState.score - 30);
}
updateGameStats();
if (gameElements.guessInput) {
gameElements.guessInput.value = "";
}
setTimeout(() => {
if (gameState.active) {
nextWord();
}
}, 700);
}
function submitGuess() {
if (!gameState.active || gameState.loading || !gameState.currentEntry) {
return;
}
const guess = normalizeGuess(gameElements.guessInput ? gameElements.guessInput.value : "");
if (!guess) {
setGameMessage("Vnesite svoj ugib.", "is-error");
return;
}
gameState.guesses += 1;
updateGameStats();
if (guess === gameState.normalizedAnswer) {
gameState.currentWordGuessed = true;
gameState.score += gameState.roundPoints;
setGameMessage(`Pravilno. Rešitev je ${gameState.currentEntry.Kljuc}.`, "is-success");
updateGameStats();
finishCurrentWord(true);
return;
}
gameState.attemptsLeft -= 1;
gameState.roundPoints = gameState.attemptsLeft === 2 ? 50 : gameState.attemptsLeft === 1 ? 25 : 0;
updateGameStats();
if (gameState.attemptsLeft > 0) {
setGameMessage(`Napačno. Preostali poskusi: ${gameState.attemptsLeft}.`, "is-error");
if (gameElements.guessInput) {
gameElements.guessInput.value = "";
gameElements.guessInput.focus();
}
return;
}
setGameMessage(`Tudi tretji poskus ni uspel. Rešitev je ${gameState.currentEntry.Kljuc}.`, "is-error");
finishCurrentWord(false);
}
function startGame() {
gameState.active = true;
gameState.score = 0;
gameState.correct = 0;
gameState.failed = 0;
gameState.guesses = 0;
updateGameStats();
setGameScreen("play");
nextWord();
}
function bindGameElements() {
gameElements.startScreen = document.getElementById("game-start-screen");
gameElements.playScreen = document.getElementById("game-play-screen");
gameElements.statsScreen = document.getElementById("game-stats-screen");
gameElements.wordType = document.getElementById("game-word-type");
gameElements.definitions = document.getElementById("game-definitions");
gameElements.guessInput = document.getElementById("game-guess-input");
gameElements.submitGuessButton = document.getElementById("submit-guess-button");
gameElements.restartGameButton = document.getElementById("restart-game-button");
gameElements.feedback = document.getElementById("game-feedback");
gameElements.attemptsLeft = document.getElementById("game-attempts-left");
gameElements.roundPoints = document.getElementById("game-round-points");
gameElements.score = document.getElementById("game-stat-score");
gameElements.correct = document.getElementById("game-stat-correct");
gameElements.failed = document.getElementById("game-stat-failed");
gameElements.guesses = document.getElementById("game-stat-guesses");
gameElements.statScore = document.getElementById("game-stat-score");
gameElements.statCorrect = document.getElementById("game-stat-correct");
gameElements.statFailed = document.getElementById("game-stat-failed");
gameElements.statGuesses = document.getElementById("game-stat-guesses");
}
bindGameElements();
document.getElementById("start-game-button").addEventListener("click", startGame);
document.getElementById("submit-guess-button").addEventListener("click", submitGuess);
document.getElementById("restart-game-button").addEventListener("click", startGame);
document.getElementById("game-guess-input").addEventListener("keydown", function(event) {
if (event.key === "Enter") {
event.preventDefault();
submitGuess();
}
});
// Konec igre
// Davčne stopnje in razredi za leto 2025
const taxBrackets = [
{ razred: 1, min: 0, max: 9210.26, rate: 16 },
{ razred: 2, min: 9210.26, max: 27089.00, rate: 26 },
{ razred: 3, min: 27089.00, max: 54178.00, rate: 33 },
{ razred: 4, min: 54178.00, max: 78016.32, rate: 39 },
{ razred: 5, min: 78016.32, max: Infinity, rate: 50 }
];
const STANDARD_DEDUCTION = 5551.93;
function parseEurAmount(input) {
if (!input) return null;
// Remove spaces, replace . with empty (thousands separator) and , with . (decimal)
let normalized = input.trim().replace(/\s/g, "").replace(/\./g, "").replace(",", ".");
let num = parseFloat(normalized);
return isNaN(num) ? null : num;
}
function formatEurAmount(num) {
// Format with thousands separator (.) and decimal separator (,)
return num.toFixed(2).replace(".", ",").replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}
function calculateTaxBracket(amount) {
for (let bracket of taxBrackets) {
if (amount >= bracket.min && amount < bracket.max) {
return bracket;
}
}
return taxBrackets[taxBrackets.length - 1]; // Return highest bracket
}
function calculateProgressiveTax(amount) {
let totalTax = 0;
for (let bracket of taxBrackets) {
if (amount <= bracket.min) {
break;
}
let upperLimit = Math.min(amount, bracket.max);
let taxableInBracket = upperLimit - bracket.min;
totalTax += taxableInBracket * (bracket.rate / 100);
}
return totalTax;
}
function updateCalculator() {
const amountInput = document.getElementById("amount-input").value;
const useDeduction = document.getElementById("deduction-checkbox").checked;
const resultDiv = document.getElementById("calculator-result");
let amount = parseEurAmount(amountInput);
if (amount === null || amount < 0) {
resultDiv.style.display = "none";
return;
}
let taxBasis = amount;
if (useDeduction && amount > STANDARD_DEDUCTION) {
taxBasis = amount - STANDARD_DEDUCTION;
}
const bracket = calculateTaxBracket(taxBasis);
const taxAmount = calculateProgressiveTax(taxBasis);
document.getElementById("result-razred").textContent = bracket.razred;
document.getElementById("result-rate").textContent = bracket.rate + " %";
document.getElementById("result-basis").textContent = formatEurAmount(taxBasis) + " EUR";
document.getElementById("result-tax").textContent = formatEurAmount(taxAmount) + " EUR";
resultDiv.style.display = "block";
}
document.getElementById("amount-input").addEventListener("input", updateCalculator);
document.getElementById("deduction-checkbox").addEventListener("change", updateCalculator);

View File

@@ -5,9 +5,9 @@ function getSpecific(kljuc) {
function getLast() {
const url = `https://ssnj.dcrubro.com/api/vnosi`;
fetch(url, {
method: 'POST',
method: "POST",
headers: {
'Content-Type': 'application/json'
"Content-Type": "application/json"
},
body: JSON.stringify({
query: "*",
@@ -17,7 +17,7 @@ function getLast() {
.then(response => response.json())
.then(data => {
if (!data.success) {
console.error('API Error:', data.message);
console.error("API Error:", data.message);
return;
}
@@ -35,7 +35,7 @@ function getLast() {
}
})
.catch((error) => {
console.error('Error:', error);
console.error("Error:", error);
});
}
@@ -46,9 +46,9 @@ function search() {
const url = `https://ssnj.dcrubro.com/api/vnosi`;
fetch(url, {
method: 'POST',
method: "POST",
headers: {
'Content-Type': 'application/json'
"Content-Type": "application/json"
},
body: JSON.stringify({
query: `*${val}*`, // Potencialno mora biti tukaj en "*" wildcard
@@ -59,7 +59,7 @@ function search() {
.then(response => response.json())
.then(data => {
if (!data.success) {
console.error('API Error:', data.message);
console.error("API Error:", data.message);
return;
}
@@ -89,7 +89,7 @@ function search() {
}
})
.catch((error) => {
console.error('Error:', error);
console.error("Error:", error);
});
}

View File

@@ -26,26 +26,26 @@ const footerHtml = `
`;
function getCurrentTheme() {
return document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light';
return document.documentElement.getAttribute("data-theme") === "dark" ? "dark" : "light";
}
function updateToggleState(theme) {
const icon = document.getElementById('toggle-icon');
const toggleButton = document.getElementById('theme-toggle');
const icon = document.getElementById("toggle-icon");
const toggleButton = document.getElementById("theme-toggle");
if (!icon || !toggleButton) {
return;
}
icon.textContent = theme === 'dark' ? '🌙' : '☀';
toggleButton.setAttribute('aria-pressed', theme === 'dark' ? 'true' : 'false');
toggleButton.setAttribute('aria-label', theme === 'dark' ? 'Svetli način' : 'Temni način');
icon.textContent = theme === "dark" ? "🌙" : "☀";
toggleButton.setAttribute("aria-pressed", theme === "dark" ? "true" : "false");
toggleButton.setAttribute("aria-label", theme === "dark" ? "Svetli način" : "Temni način");
}
function logout() {
// Odstrani cookie tako, da ga nastaviš z max-age=0
document.cookie = 'token=; max-age=0; path=/; secure; samesite=strict';
document.cookie = 'username=; max-age=0; path=/; secure; samesite=strict';
document.cookie = "token=; max-age=0; path=/; secure; samesite=strict";
document.cookie = "username=; max-age=0; path=/; secure; samesite=strict";
window.location.href = "/";
}
@@ -59,23 +59,23 @@ document.addEventListener("DOMContentLoaded", function() {
}
// Dodaj gumb za prijavo, če uporabnik ni prijavljen
const isLoggedIn = document.cookie.split(';').some(cookie => cookie.trim().startsWith('token='));
const isLoggedIn = document.cookie.split(";").some(cookie => cookie.trim().startsWith("token="));
if (!isLoggedIn) {
const navRight = document.querySelector('.nav-right');
const navRight = document.querySelector(".nav-right");
if (navRight) {
const loginBtn = `<a class="nav-btn nav-btn-primary" href="/login.html">Prijava</a>`;
// Najdi zadnji <a> element in dodaj gumb za njim
const lastLink = navRight.querySelector('a:last-child');
const lastLink = navRight.querySelector("a:last-child");
document.getElementById("nav-login-holder").innerHTML = loginBtn;
}
} else {
const navRight = document.querySelector('.nav-right');
const navRight = document.querySelector(".nav-right");
if (navRight) {
const logoutBtn = `<a class="nav-btn nav-btn-primary" href="/">Odjava</a>`;
// Najdi zadnji <a> element in dodaj gumb za njim
const lastLink = navRight.querySelector('a:last-child');
const lastLink = navRight.querySelector("a:last-child");
document.getElementById("nav-login-holder").innerHTML = logoutBtn;
document.querySelector('.nav-btn-primary').addEventListener('click', logout);
document.querySelector(".nav-btn-primary").addEventListener("click", logout);
}
}
@@ -84,20 +84,45 @@ document.addEventListener("DOMContentLoaded", function() {
}
updateToggleState(getCurrentTheme());
// Univerzalne funkcionalnosti, ki so potrebne na več straneh
const galleryImages = document.querySelectorAll(".page-gallery-image");
galleryImages.forEach(image => {
image.addEventListener("click", () => {
const src = image.getAttribute("src");
const alt = image.getAttribute("alt");
const modalHtml = `
<div class="modal" id="image-modal">
<div class="modal-content">
<span class="close">&times;</span>
<img src="${src}" alt="${alt}" class="image-modal-img">
<p>${alt}</p>
</div>
</div>
`;
document.body.insertAdjacentHTML("beforeend", modalHtml);
const modal = document.getElementById("image-modal");
modal.style.visibility = "visible";
modal.querySelector(".close").addEventListener("click", () => {
modal.remove();
});
});
});
});
function toggleTheme() {
const current = getCurrentTheme();
const next = current === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
localStorage.setItem('theme', next);
const next = current === "dark" ? "light" : "dark";
document.documentElement.setAttribute("data-theme", next);
localStorage.setItem("theme", next);
updateToggleState(next);
}
matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
if (!localStorage.getItem('theme')) {
const theme = e.matches ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', theme);
matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => {
if (!localStorage.getItem("theme")) {
const theme = e.matches ? "dark" : "light";
document.documentElement.setAttribute("data-theme", theme);
updateToggleState(theme);
}
});

View File

@@ -1,9 +1,9 @@
(function() {
try {
const saved = localStorage.getItem('theme');
const osPref = matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', saved || osPref);
const saved = localStorage.getItem("theme");
const osPref = matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
document.documentElement.setAttribute("data-theme", saved || osPref);
} catch (e) {
document.documentElement.setAttribute('data-theme', 'light');
document.documentElement.setAttribute("data-theme", "light");
}
})();

View File

@@ -72,10 +72,10 @@ document.getElementById("login-form").addEventListener("submit", async function(
const serverMsg = (data && data.message) ? String(data.message).toLowerCase() : "";
let userMsg = "Uporabniško ime ali e-pošta je že zasedena.";
if (serverMsg.includes('username') || serverMsg.includes('uporab') || serverMsg.includes('user')) {
userMsg = 'Uporabniško ime je že zasedeno.';
} else if (serverMsg.includes('email') || serverMsg.includes('e-pošta') || serverMsg.includes('e-naslov')) {
userMsg = 'E-poštni naslov je že uporabljen.';
if (serverMsg.includes("username") || serverMsg.includes("uporab") || serverMsg.includes("user")) {
userMsg = "Uporabniško ime je že zasedeno.";
} else if (serverMsg.includes("email") || serverMsg.includes("e-pošta") || serverMsg.includes("e-naslov")) {
userMsg = "E-poštni naslov je že uporabljen.";
} else if (serverMsg) {
userMsg = data.message; // show server message if it's something specific
}

View File

@@ -8,9 +8,9 @@ function getCookie(name) {
function getKey() {
const url = `https://ssnj.dcrubro.com/api/vnos`;
fetch(url, {
method: 'POST',
method: "POST",
headers: {
'Content-Type': 'application/json'
"Content-Type": "application/json"
},
body: JSON.stringify({
pk: kljuc
@@ -19,7 +19,7 @@ function getKey() {
.then(response => response.json())
.then(data => {
if (!data.success) {
console.error('API Error:', data.message);
console.error("API Error:", data.message);
return;
}
@@ -96,39 +96,39 @@ function getKey() {
});
})
.catch((error) => {
console.error('Error:', error);
console.error("Error:", error);
});
}
getKey();
function initVoting(entryData) {
const upBtn = document.getElementById('vote-up');
const downBtn = document.getElementById('vote-down');
const sumEl = document.getElementById('vote-sum');
const upBtn = document.getElementById("vote-up");
const downBtn = document.getElementById("vote-down");
const sumEl = document.getElementById("vote-sum");
if (!upBtn || !downBtn || !sumEl) return;
const token = getCookie('token');
const token = getCookie("token");
let currentVote = 0;
function setActive(v) {
upBtn.classList.toggle('nav-btn-primary', v === 1);
downBtn.classList.toggle('nav-btn-primary', v === -1);
upBtn.classList.toggle("nav-btn-primary", v === 1);
downBtn.classList.toggle("nav-btn-primary", v === -1);
currentVote = v;
}
if (!token) {
const showLogin = () => alert('Prijavite se, da lahko glasujete.');
upBtn.addEventListener('click', showLogin);
downBtn.addEventListener('click', showLogin);
const showLogin = () => alert("Prijavite se, da lahko glasujete.");
upBtn.addEventListener("click", showLogin);
downBtn.addEventListener("click", showLogin);
return;
}
// fetch whether the current user has voted
fetch('https://ssnj.dcrubro.com/api/semvolil', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
fetch("https://ssnj.dcrubro.com/api/semvolil", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token: token, pk: kljuc })
})
.then(r => r.json())
@@ -136,29 +136,29 @@ function initVoting(entryData) {
const v = obj?.vote || 0;
setActive(v);
})
.catch(err => console.error('semvolil error', err));
.catch(err => console.error("semvolil error", err));
upBtn.addEventListener('click', () => submitVote(1));
downBtn.addEventListener('click', () => submitVote(-1));
upBtn.addEventListener("click", () => submitVote(1));
downBtn.addEventListener("click", () => submitVote(-1));
function submitVote(vote) {
const tokenNow = getCookie('token');
if (!tokenNow) { alert('Prijavite se, da lahko glasujete.'); return; }
const tokenNow = getCookie("token");
if (!tokenNow) { alert("Prijavite se, da lahko glasujete."); return; }
// if user clicks the same vote, send 0 to remove it
const sendVote = (vote === currentVote) ? 0 : vote;
fetch('https://ssnj.dcrubro.com/api/volI', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
fetch("https://ssnj.dcrubro.com/api/volI", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token: tokenNow, pk: kljuc, vote: sendVote })
})
.then(r => r.json())
.then(() => {
// refresh current score
return fetch('https://ssnj.dcrubro.com/api/vnos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
return fetch("https://ssnj.dcrubro.com/api/vnos", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ pk: kljuc })
});
})
@@ -170,6 +170,6 @@ function initVoting(entryData) {
setActive(sendVote);
}
})
.catch(err => console.error('vote error', err));
.catch(err => console.error("vote error", err));
}
}

View File

@@ -333,6 +333,61 @@ nav {
margin-right: 23px;
}
.fin-calculator-form {
display: flex;
flex-direction: column;
gap: 15px;
}
.fin-calculator-form .form-group {
display: flex;
flex-direction: column;
gap: 6px;
}
.fin-calculator-form label {
color: var(--text-color);
font-size: 0.92rem;
font-weight: 500;
/* Smooth Theme Transition */
transition: color 0.25s ease;
}
.fin-calculator-form .checkbox-group {
flex-direction: row;
align-items: center;
gap: 8px;
}
.fin-calculator-form .checkbox-group input[type="checkbox"] {
cursor: pointer;
width: 18px;
height: 18px;
}
.fin-calculator-form .checkbox-group label {
margin: 0;
cursor: pointer;
}
.calculator-result {
padding: 15px;
border: 1px solid var(--nav-btn-border);
border-radius: 4px;
background: var(--nav-btn-bg);
color: var(--text-color);
/* Smooth Theme Transition */
transition: background-color 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}
.calculator-result p {
margin: 8px 0;
font-size: 0.92rem;
line-height: 1.4;
}
.page-unordered-list {
list-style-type: disc;
padding-left: 20px;
@@ -382,20 +437,135 @@ nav {
.modal-content {
background: var(--nav-btn-bg);
padding: 20px;
padding: 28px;
border-radius: 8px;
width: 90%;
max-width: 400px;
max-width: 900px;
position: relative;
color: var(--text-color);
transition: background-color 0.25s ease, color 0.25s ease;
}
/* Make images inside modals larger while constraining to viewport */
.image-modal-img {
display: block;
max-width: 100%;
width: auto;
height: auto;
max-height: 80vh;
margin: 0 auto;
}
.modal-buttons {
display: flex;
justify-content: flex-end;
gap: 10px;
margin-top: 20px;
margin-top: 18px;
}
.modal-buttons-left {
justify-content: flex-start;
}
.game-panel {
display: flex;
flex-direction: column;
gap: 16px;
}
.game-intro {
margin: 0;
line-height: 1.5;
}
.game-meta {
line-height: 1.4;
margin: 0;
}
.game-definition-box {
padding: 18px;
border: 1px solid var(--nav-btn-border);
border-radius: 8px;
background: rgba(127, 127, 127, 0.08);
}
.game-section-label {
font-size: 0.85rem;
font-weight: 700;
margin-bottom: 12px;
text-transform: uppercase;
letter-spacing: 0.04em;
opacity: 0.8;
}
.game-definitions {
display: flex;
flex-direction: column;
gap: 10px;
}
.game-definition-line {
padding-left: 16px;
border-left: 3px solid var(--nav-btn-primary-bg);
line-height: 1.5;
}
.game-input-row {
display: flex;
gap: 12px;
align-items: center;
flex-wrap: wrap;
}
.game-guess-input {
flex: 1 1 260px;
min-width: 0;
}
.game-feedback {
min-height: 1.4em;
font-weight: 600;
}
.game-feedback.is-success {
color: #27ae60;
}
.game-feedback.is-error {
color: #e74c3c;
}
.game-feedback.is-neutral {
color: var(--text-color);
}
.game-stats-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 14px;
}
.game-stats-grid p {
padding: 12px 14px;
border: 1px solid var(--nav-btn-border);
border-radius: 8px;
background: rgba(127, 127, 127, 0.08);
}
.game-stats-grid strong {
display: block;
margin-bottom: 4px;
}
.game-secret-answer {
font-size: 0.95rem;
opacity: 0.95;
}
.game-empty-state {
font-style: italic;
opacity: 0.8;
}
.modal-buttons .page-btn:hover {
@@ -558,4 +728,37 @@ hr {
margin-top: 8px;
font-size: 0.75rem;
font-style: italic;
}
.page-collapse {
border: 1px solid var(--nav-btn-border);
border-radius: 8px;
padding: 12px;
padding-top: 18px;
background: var(--nav-btn-bg);
color: var(--text-color);
transition: background-color 0.25s ease, border-color 0.25s ease, color 0.25s ease;
margin: 0 23px;
visibility: hidden;
}
.page-image-gallery {
display: flex;
gap: 10px;
margin-top: 12px;
justify-content: center;
}
.page-gallery-image {
width: 100%;
max-width: 30%;
border-radius: 4px;
border: 1px solid var(--nav-btn-border);
object-fit: cover;
transition: transform 0.25s ease, border-color 0.25s ease;
}
.page-gallery-image:hover {
transform: scale(1.05);
border-color: var(--nav-btn-hover-border);
}