fix: render before/after gallery images from API with tab filtering
CI/CD / CI · dotnet build (push) Successful in 40s
CI/CD / Deploy · drsousan (push) Failing after 52s

- Gallery section now fetches /api/gallery and renders real items
  instead of hardcoded placeholders
- Before+after pairs render as side-by-side split with قبل/بعد labels
- Single imageUrl items render as a standard gallery card
- Tab buttons now filter items by category via data-cat attribute
- CSS added for .before-after, .ba-half, .ba-divider, .ba-label, .gallery-caption
- Fixes applied to correct file (Index.cshtml Razor page, not root index.html)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-01 23:59:57 +03:30
parent f034f70ae3
commit 7f5444085b
2 changed files with 145 additions and 80 deletions
+105 -62
View File
@@ -609,6 +609,56 @@
.gallery-item:hover .gallery-item-overlay { background: rgba(184,149,90,0.15); }
/* Before/After split layout */
.gallery-item.before-after {
display: flex;
flex-direction: row;
}
.gallery-item.before-after .ba-half {
flex: 1;
position: relative;
overflow: hidden;
}
.gallery-item.before-after .ba-half img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
transition: transform 0.4s;
}
.gallery-item.before-after:hover .ba-half img { transform: scale(1.05); }
.gallery-item.before-after .ba-label {
position: absolute;
bottom: 6px;
left: 50%;
transform: translateX(-50%);
background: rgba(0,0,0,0.55);
color: #fff;
font-size: 0.65rem;
padding: 2px 8px;
border-radius: 20px;
white-space: nowrap;
pointer-events: none;
}
.gallery-item.before-after .ba-divider {
width: 2px;
background: rgba(255,255,255,0.7);
position: relative;
z-index: 2;
flex-shrink: 0;
}
.gallery-caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(transparent, rgba(0,0,0,0.5));
color: #fff;
font-size: 0.75rem;
padding: 1.2rem 0.8rem 0.5rem;
text-align: center;
}
/* ─── Testimonials ──────────────────────────────────────────── */
#testimonials { background: var(--section-bg); }
@@ -1145,68 +1195,8 @@
<button class="tab-btn">پاکسازی</button>
</div>
<div class="gallery-grid">
<!-- Replace placeholders with actual before/after images -->
<div class="gallery-item fade-in">
<div class="gallery-placeholder">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/>
<polyline points="21 15 16 10 5 21"/>
</svg>
<p>تصویر قبل و بعد</p>
</div>
<div class="gallery-item-overlay"></div>
</div>
<div class="gallery-item fade-in">
<div class="gallery-placeholder">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/>
<polyline points="21 15 16 10 5 21"/>
</svg>
<p>تصویر قبل و بعد</p>
</div>
<div class="gallery-item-overlay"></div>
</div>
<div class="gallery-item fade-in">
<div class="gallery-placeholder">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/>
<polyline points="21 15 16 10 5 21"/>
</svg>
<p>تصویر قبل و بعد</p>
</div>
<div class="gallery-item-overlay"></div>
</div>
<div class="gallery-item fade-in">
<div class="gallery-placeholder">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/>
<polyline points="21 15 16 10 5 21"/>
</svg>
<p>تصویر قبل و بعد</p>
</div>
<div class="gallery-item-overlay"></div>
</div>
<div class="gallery-item fade-in">
<div class="gallery-placeholder">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/>
<polyline points="21 15 16 10 5 21"/>
</svg>
<p>تصویر قبل و بعد</p>
</div>
<div class="gallery-item-overlay"></div>
</div>
<div class="gallery-item fade-in">
<div class="gallery-placeholder">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/>
<polyline points="21 15 16 10 5 21"/>
</svg>
<p>تصویر قبل و بعد</p>
</div>
<div class="gallery-item-overlay"></div>
</div>
<div class="gallery-grid" id="galleryGrid">
<!-- Loaded dynamically from API -->
</div>
</div>
</section>
@@ -1426,11 +1416,64 @@
document.querySelectorAll('.fade-in').forEach(el => observer.observe(el));
// Gallery — load from API
let allGalleryItems = [];
function renderGallery(items) {
const grid = document.getElementById('galleryGrid');
if (!items.length) {
grid.innerHTML = '<p style="color:var(--mid);text-align:center;grid-column:1/-1;padding:2rem">تصویری یافت نشد.</p>';
return;
}
grid.innerHTML = items.map(g => {
const hasBoth = g.beforeImageUrl && g.afterImageUrl;
const hasImg = g.imageUrl;
if (hasBoth) {
return `<div class="gallery-item before-after fade-in" data-cat="${g.category||''}">
<div class="ba-half">
<img src="${g.beforeImageUrl}" alt="قبل" loading="lazy"/>
<span class="ba-label">قبل</span>
</div>
<div class="ba-divider"></div>
<div class="ba-half">
<img src="${g.afterImageUrl}" alt="بعد" loading="lazy"/>
<span class="ba-label">بعد</span>
</div>
${g.caption ? `<div class="gallery-caption">${g.caption}</div>` : ''}
<div class="gallery-item-overlay"></div>
</div>`;
}
if (hasImg) {
return `<div class="gallery-item fade-in" data-cat="${g.category||''}">
<img src="${g.imageUrl}" alt="${g.caption||'گالری'}" loading="lazy"/>
${g.caption ? `<div class="gallery-caption">${g.caption}</div>` : ''}
<div class="gallery-item-overlay"></div>
</div>`;
}
return '';
}).join('');
grid.querySelectorAll('.fade-in').forEach(el => observer.observe(el));
}
async function loadGallery(category) {
try {
const url = category && category !== 'همه' ? `/api/gallery?category=${encodeURIComponent(category)}` : '/api/gallery';
const res = await fetch(url);
if (!res.ok) return;
const data = await res.json();
allGalleryItems = data;
renderGallery(data);
} catch(e) { /* silent — placeholders stay hidden */ }
}
loadGallery();
// Tab buttons
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
loadGallery(btn.textContent.trim());
});
});