| Server IP : 193.86.120.172 / Your IP : 216.73.216.215 Web Server : Apache/2.4.63 (Unix) System : Linux JServices 3.10.108 #86003 SMP Wed Oct 22 13:20:46 CST 2025 x86_64 User : kubec ( 1026) PHP Version : 8.2.28 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /volume1/web/hotellesnizatisi_cz/new/ |
Upload File : |
<?php
require_once __DIR__ . '/includes/auth.php';
$user = require_section('fotky');
require_once __DIR__ . '/includes/layout.php';
$slugMap = ['pokoje' => 'typ_pokoje', 'hotel' => 'hotel', 'okoli' => 'okoli', 'restaurace' => 'restaurace'];
$kategorieSlug = $_GET['kategorie'] ?? 'pokoje';
if (!isset($slugMap[$kategorieSlug])) {
$kategorieSlug = 'pokoje';
}
$kategorieDb = $slugMap[$kategorieSlug];
$stmt = db()->prepare('
SELECT * FROM web_fotky
WHERE kategorie = ? AND referencni_id IS NULL
ORDER BY poradi
');
$stmt->execute([$kategorieDb]);
$fotky = $stmt->fetchAll();
admin_layout_start('fotky', 'Fotky', 'Fotky pokojů, hotelu a okolí — hvězdička označuje titulní fotku', $user);
render_flash();
?>
<div class="photo-tabs">
<a class="photo-tab <?= $kategorieSlug === 'pokoje' ? 'active' : '' ?>" href="?kategorie=pokoje">Pokoje</a>
<a class="photo-tab <?= $kategorieSlug === 'hotel' ? 'active' : '' ?>" href="?kategorie=hotel">Hotel</a>
<a class="photo-tab <?= $kategorieSlug === 'okoli' ? 'active' : '' ?>" href="?kategorie=okoli">V okolí</a>
<a class="photo-tab <?= $kategorieSlug === 'restaurace' ? 'active' : '' ?>" href="?kategorie=restaurace">Restaurace</a>
</div>
<form method="post" action="fotky-upload.php" enctype="multipart/form-data" class="upload-row">
<input type="hidden" name="kategorie" value="<?= htmlspecialchars($kategorieSlug) ?>">
<input type="file" name="foto[]" accept="image/jpeg,image/png,image/webp" required multiple>
<button type="submit" class="btn btn-primary btn-sm">Nahrát fotky</button>
<span style="font-size:.76rem;color:var(--ink-faint);">JPG, PNG nebo WEBP, max 15 MB/fotku — automaticky se zmenší a optimalizují. Lze vybrat víc souborů najednou.</span>
</form>
<form method="post" action="fotky-smazat.php" id="bulkDeleteForm" style="display:none;">
<input type="hidden" name="kategorie" value="<?= htmlspecialchars($kategorieSlug) ?>">
</form>
<div class="bulk-bar" id="bulkBar" style="display:none;">
<button type="button" class="btn btn-secondary btn-sm" id="bulkDeleteBtn" style="color:var(--red);border-color:var(--red-soft);">Smazat vybrané (<span id="bulkCount">0</span>)</button>
</div>
<div class="photo-grid" id="photoGrid">
<?php foreach ($fotky as $f): ?>
<div class="photo-card-wrap" draggable="true" data-id="<?= (int) $f['id'] ?>">
<div class="photo-card" style="background-image:url('uploads/fotky/<?= htmlspecialchars($f['nazev_souboru']) ?>');">
<label class="photo-card__check" title="Vybrat pro hromadnou akci">
<input type="checkbox" class="photo-select" value="<?= (int) $f['id'] ?>">
</label>
<form method="post" action="fotky-hlavni.php">
<input type="hidden" name="id" value="<?= (int) $f['id'] ?>">
<input type="hidden" name="kategorie" value="<?= htmlspecialchars($kategorieSlug) ?>">
<button type="submit" class="photo-card__star <?= $f['hlavni'] ? 'is-main' : '' ?>" title="Nastavit jako titulní fotku">★</button>
</form>
<form method="post" action="fotky-smazat.php" onsubmit="return confirm('Opravdu smazat tuto fotku?');">
<input type="hidden" name="id" value="<?= (int) $f['id'] ?>">
<input type="hidden" name="kategorie" value="<?= htmlspecialchars($kategorieSlug) ?>">
<button type="submit" class="photo-card__del" title="Smazat fotku">✕</button>
</form>
</div>
</div>
<?php endforeach; ?>
<?php if (!$fotky): ?>
<p style="color:var(--ink-soft);grid-column:1/-1;">Zatím žádné fotky v této kategorii.</p>
<?php endif; ?>
</div>
<script>
(function () {
const grid = document.getElementById('photoGrid');
if (!grid) return;
let dragEl = null;
grid.addEventListener('dragstart', function (e) {
const card = e.target.closest('.photo-card-wrap');
if (!card) return;
dragEl = card;
e.dataTransfer.effectAllowed = 'move';
setTimeout(function () { card.style.opacity = '0.4'; }, 0);
});
grid.addEventListener('dragend', function () {
if (dragEl) dragEl.style.opacity = '1';
dragEl = null;
savePoradi();
});
grid.addEventListener('dragover', function (e) {
e.preventDefault();
const target = e.target.closest('.photo-card-wrap');
if (!target || target === dragEl || !dragEl) return;
const rect = target.getBoundingClientRect();
const before = (e.clientX - rect.left) < rect.width / 2;
grid.insertBefore(dragEl, before ? target : target.nextSibling);
});
// Dotykové přesouvání (telefony/tablety) — HTML5 drag-and-drop výše funguje jen myší.
let touchActive = false;
let touchStartX = 0;
let touchStartY = 0;
grid.addEventListener('touchstart', function (e) {
const card = e.target.closest('.photo-card-wrap');
if (!card) return;
dragEl = card;
touchActive = false;
touchStartX = e.touches[0].clientX;
touchStartY = e.touches[0].clientY;
}, { passive: true });
grid.addEventListener('touchmove', function (e) {
if (!dragEl) return;
const touch = e.touches[0];
if (!touchActive) {
const dx = Math.abs(touch.clientX - touchStartX);
const dy = Math.abs(touch.clientY - touchStartY);
if (dx < 10 && dy < 10) return; // ještě rozhodujeme, jestli jde o tah, nebo o klepnutí na hvězdičku/křížek
touchActive = true;
dragEl.style.opacity = '0.4';
}
e.preventDefault(); // až ve chvíli, kdy víme, že jde o přesouvání — ať nebrání běžnému scrollování stránky
const el = document.elementFromPoint(touch.clientX, touch.clientY);
const target = el ? el.closest('.photo-card-wrap') : null;
if (!target || target === dragEl) return;
const rect = target.getBoundingClientRect();
const before = (touch.clientX - rect.left) < rect.width / 2;
grid.insertBefore(dragEl, before ? target : target.nextSibling);
}, { passive: false });
grid.addEventListener('touchend', function () {
if (dragEl) dragEl.style.opacity = '1';
if (touchActive) savePoradi();
dragEl = null;
touchActive = false;
});
grid.addEventListener('touchcancel', function () {
if (dragEl) dragEl.style.opacity = '1';
dragEl = null;
touchActive = false;
});
function savePoradi() {
const ids = Array.from(grid.querySelectorAll('.photo-card-wrap')).map(function (el) { return el.dataset.id; });
fetch('fotky-poradi.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ids: ids })
});
}
// Hromadný výběr a mazání
const bulkBar = document.getElementById('bulkBar');
const bulkCount = document.getElementById('bulkCount');
const bulkForm = document.getElementById('bulkDeleteForm');
const bulkBtn = document.getElementById('bulkDeleteBtn');
function updateBulkBar() {
const checked = grid.querySelectorAll('.photo-select:checked');
bulkCount.textContent = checked.length;
bulkBar.style.display = checked.length > 0 ? 'flex' : 'none';
}
grid.addEventListener('change', function (e) {
if (e.target.classList.contains('photo-select')) {
updateBulkBar();
}
});
bulkBtn.addEventListener('click', function () {
const checked = Array.from(grid.querySelectorAll('.photo-select:checked'));
if (!checked.length) return;
if (!confirm('Opravdu smazat ' + checked.length + ' vybraných fotek?')) return;
bulkForm.innerHTML = '<input type="hidden" name="kategorie" value="<?= htmlspecialchars($kategorieSlug) ?>">';
checked.forEach(function (cb) {
const input = document.createElement('input');
input.type = 'hidden';
input.name = 'ids[]';
input.value = cb.value;
bulkForm.appendChild(input);
});
bulkForm.submit();
});
})();
</script>
<?php admin_layout_end(); ?>