refactor: Restructure category and product data fetching/syncing and add a product detail pop-up UI.

This commit is contained in:
sebseb7
2025-11-24 15:08:42 +01:00
parent b4d202bb23
commit d251daa075
7 changed files with 185 additions and 5 deletions

View File

@@ -411,6 +411,99 @@
font-size: 0.8rem;
}
}
/* Product Detail Popper */
.product-popper {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: white;
padding: 2rem;
border-radius: 12px;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
z-index: 1000;
max-width: 600px;
width: 90%;
max-height: 80vh;
overflow-y: auto;
display: none;
}
.product-popper.visible {
display: block;
animation: fadeIn 0.2s ease-out;
}
.popper-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
display: none;
backdrop-filter: blur(2px);
}
.popper-overlay.visible {
display: block;
animation: fadeIn 0.2s ease-out;
}
.popper-close {
position: absolute;
top: 1rem;
right: 1rem;
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: #666;
padding: 0.5rem;
line-height: 1;
border-radius: 50%;
transition: background 0.2s;
}
.popper-close:hover {
background: #f0f0f0;
color: #333;
}
.popper-content h3 {
margin-bottom: 1rem;
color: #2d3748;
font-size: 1.25rem;
}
.popper-content {
line-height: 1.6;
color: #4a5568;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.product-name-link {
cursor: pointer;
color: #4a5568;
transition: color 0.2s;
text-decoration: none;
}
.product-name-link:hover {
color: #667eea;
text-decoration: underline;
}
</style>
</head>
@@ -426,6 +519,14 @@
</div>
<button id="version-reload-btn" onclick="location.reload()">New version - [reload]</button>
<!-- Product Detail Popper -->
<div id="popper-overlay" class="popper-overlay"></div>
<div id="product-popper" class="product-popper">
<button class="popper-close" onclick="closePopper()">×</button>
<div id="popper-content" class="popper-content"></div>
</div>
<script src="/socket.io/socket.io.js" async></script>
<script>
// Initialize socket when io is available (async)
@@ -881,7 +982,12 @@
}
const span = document.createElement('span');
span.className = 'product-name-link';
span.textContent = p.cName;
span.onclick = (e) => {
e.stopPropagation();
showProductDetails(p.kArtikel);
};
li.appendChild(span);
ul.appendChild(li);
});
@@ -941,6 +1047,44 @@
if (node.children) collapseAllProducts(node.children);
});
}
// Product Details Popper Logic
const popperOverlay = document.getElementById('popper-overlay');
const productPopper = document.getElementById('product-popper');
const popperContent = document.getElementById('popper-content');
function closePopper() {
popperOverlay.classList.remove('visible');
productPopper.classList.remove('visible');
popperContent.innerHTML = '';
}
popperOverlay.addEventListener('click', closePopper);
// Close on Escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') closePopper();
});
async function showProductDetails(id) {
// Show loading state
popperContent.innerHTML = '<div class="loading">Loading details...</div>';
popperOverlay.classList.add('visible');
productPopper.classList.add('visible');
try {
const response = await fetch(`/api/products/${id}/details`);
if (!response.ok) throw new Error('Failed to load details');
const data = await response.json();
// The description is in cBeschreibung
popperContent.innerHTML = data.cBeschreibung || 'No description available.';
} catch (err) {
console.error('Error fetching product details:', err);
popperContent.innerHTML = `<div class="error">❌ Failed to load details: ${err.message}</div>`;
}
}
</script>
</body>