mirror of
https://github.com/Dvorinka/ClubLogos.git
synced 2026-06-03 19:42:58 +00:00
133 lines
4.4 KiB
JavaScript
133 lines
4.4 KiB
JavaScript
import './style.css'
|
|
|
|
const API_BASE_URL = '/api'
|
|
|
|
const grid = document.getElementById('allLogoGrid')
|
|
const loading = document.getElementById('allLoading')
|
|
const empty = document.getElementById('allEmpty')
|
|
const loadMoreBtn = document.getElementById('loadMoreBtn')
|
|
const searchInput = document.getElementById('allLogoSearch')
|
|
|
|
let page = 1
|
|
const limit = 20
|
|
let query = ''
|
|
let isLoading = false
|
|
let hasMore = true
|
|
|
|
async function loadPage(reset = false) {
|
|
if (isLoading) return
|
|
if (reset) {
|
|
page = 1
|
|
hasMore = true
|
|
grid.innerHTML = ''
|
|
empty.classList.add('hidden')
|
|
loading.classList.remove('hidden')
|
|
} else {
|
|
loadMoreBtn.disabled = true
|
|
loadMoreBtn.textContent = 'Načítání...'
|
|
}
|
|
|
|
isLoading = true
|
|
try {
|
|
const url = new URL(`${API_BASE_URL}/logos`, window.location.origin)
|
|
url.searchParams.set('sort', 'recent')
|
|
url.searchParams.set('limit', String(limit))
|
|
url.searchParams.set('page', String(page))
|
|
if (query) url.searchParams.set('q', query)
|
|
|
|
const resp = await fetch(url.toString().replace(window.location.origin, ''))
|
|
if (!resp.ok) throw new Error('Failed to fetch logos')
|
|
const data = await resp.json()
|
|
|
|
if (reset) loading.classList.add('hidden')
|
|
|
|
if (Array.isArray(data) && data.length > 0) {
|
|
appendCards(data)
|
|
page += 1
|
|
if (data.length < limit) {
|
|
hasMore = false
|
|
loadMoreBtn.classList.add('hidden')
|
|
} else {
|
|
loadMoreBtn.classList.remove('hidden')
|
|
}
|
|
} else {
|
|
if (reset) empty.classList.remove('hidden')
|
|
hasMore = false
|
|
loadMoreBtn.classList.add('hidden')
|
|
}
|
|
} catch (_) {
|
|
if (reset) {
|
|
loading.classList.add('hidden')
|
|
empty.classList.remove('hidden')
|
|
}
|
|
} finally {
|
|
isLoading = false
|
|
loadMoreBtn.disabled = false
|
|
loadMoreBtn.textContent = 'Načíst další'
|
|
}
|
|
}
|
|
|
|
function appendCards(items) {
|
|
const html = items.map(logo => {
|
|
const logoUrl = `${API_BASE_URL}/logos/${logo.id}`
|
|
return `
|
|
<div class="logo-card bg-dark-card rounded-xl p-4 border border-dark-border hover:border-accent-blue transition-smooth group" data-id="${logo.id}">
|
|
<div class="aspect-square bg-dark-bg rounded-lg flex items-center justify-center mb-3 overflow-hidden cursor-pointer">
|
|
<img src="${logoUrl}" alt="${logo.club_name}" class="max-w-full max-h-full object-contain p-2 group-hover:scale-110 transition-transform duration-300" loading="lazy" onerror="this.parentElement.innerHTML='<svg class=\'w-8 h-8 text-gray-500\' fill=\'none\' stroke=\'currentColor\' viewBox=\'0 0 24 24\'><path stroke-linecap=\'round\' stroke-linejoin=\'round\' stroke-width=\'2\' d=\'M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\'></path></svg>'">
|
|
</div>
|
|
<div class="flex items-center gap-3">
|
|
<div class="flex-1 min-w-0 cursor-pointer">
|
|
<h3 class="font-semibold text-sm truncate mb-0.5">${logo.club_name}</h3>
|
|
<p class="text-xs text-gray-400 truncate">${logo.club_type || 'fotbal'}</p>
|
|
</div>
|
|
<button class="delete-logo px-3 py-1.5 text-xs bg-red-600 rounded hover:bg-red-500 transition-smooth">Smazat</button>
|
|
</div>
|
|
</div>
|
|
`
|
|
}).join('')
|
|
grid.insertAdjacentHTML('beforeend', html)
|
|
}
|
|
|
|
grid.addEventListener('click', async (e) => {
|
|
const delBtn = e.target.closest('.delete-logo')
|
|
if (delBtn) {
|
|
const card = delBtn.closest('.logo-card')
|
|
const id = card.dataset.id
|
|
const ok = confirm('Smazat toto logo?')
|
|
if (!ok) return
|
|
delBtn.disabled = true
|
|
delBtn.textContent = 'Mazání...'
|
|
try {
|
|
const resp = await fetch(`${API_BASE_URL}/logos/${id}`, { method: 'DELETE' })
|
|
if (!resp.ok) throw new Error('Delete failed')
|
|
card.remove()
|
|
if (!grid.children.length) empty.classList.remove('hidden')
|
|
} catch (_) {
|
|
delBtn.textContent = 'Smazat'
|
|
delBtn.disabled = false
|
|
alert('Mazání selhalo')
|
|
}
|
|
return
|
|
}
|
|
const card = e.target.closest('.logo-card')
|
|
if (card && !e.target.closest('.delete-logo')) {
|
|
const id = card.dataset.id
|
|
window.location.href = `/logo.html?id=${id}`
|
|
}
|
|
})
|
|
|
|
let searchTimer
|
|
searchInput.addEventListener('input', () => {
|
|
clearTimeout(searchTimer)
|
|
searchTimer = setTimeout(() => {
|
|
query = searchInput.value.trim()
|
|
loadPage(true)
|
|
}, 300)
|
|
})
|
|
|
|
loadMoreBtn.addEventListener('click', () => {
|
|
if (hasMore) loadPage(false)
|
|
})
|
|
|
|
loadPage(true)
|