Home: gallery preview grid, side-by-side contact, larger section titles

- Add a homepage gallery preview: "Galerija" heading + 4-wide image grid that
  fades out toward the bottom, linking to /gallery (up to 12 images)
- Put contact email + phone side by side
- Make section titles (Galerija/Novice/Kontakt) larger than service names
- listGalleryImages() added to the content service

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Matic Ivešić 2026-08-03 19:06:06 +02:00
parent d5368067d6
commit 8a8f19133f
4 changed files with 89 additions and 30 deletions

View File

@ -33,31 +33,18 @@
} }
.nav-link{ .nav-link{
display: inline-flex;
align-items: center; align-items: center;
gap: 0.5em;
color: #e5e4ea; color: #e5e4ea;
text-decoration: none; text-decoration: none;
font-weight: 500; font-weight: 500;
letter-spacing: 0.02em;
padding: 0.35em 0.9em;
border: 1px solid rgba(229, 228, 234, 0.25);
border-radius: 999px;
transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
} }
.nav-icon{ .nav-icon{
width: 1.15em; width: 2em;
height: 1.15em; height: 2em;
display: block; display: block;
} }
.nav-link:hover{
background-color: rgba(66, 175, 56, 0.15);
border-color: rgba(66, 175, 56, 0.8);
color: #ffffff;
}
.banner-link{ .banner-link{
display: inline-flex; display: inline-flex;
} }
@ -88,7 +75,6 @@
<nav class="nav"> <nav class="nav">
<a class="nav-link" href="/gallery"> <a class="nav-link" href="/gallery">
<img class="nav-icon" src={gallery_icon} alt="" /> <img class="nav-icon" src={gallery_icon} alt="" />
<span>Galerija</span>
</a> </a>
</nav> </nav>
<a class="banner-link" href="/" aria-label="Domov"> <a class="banner-link" href="/" aria-label="Domov">

View File

@ -3,6 +3,7 @@ import { randomUUID } from 'node:crypto';
import { db } from './db'; import { db } from './db';
import { import {
bannerImages, bannerImages,
galleryImages,
newsPosts, newsPosts,
serviceImages, serviceImages,
services, services,
@ -43,6 +44,15 @@ export function deleteBannerImage(id: string): string | null {
return row.imagePath; return row.imagePath;
} }
/** Gallery images (used by the /gallery page and the homepage preview grid). */
export function listGalleryImages(limit?: number) {
const base = db
.select()
.from(galleryImages)
.orderBy(asc(galleryImages.sortOrder), desc(galleryImages.createdAt));
return (limit ? base.limit(limit) : base).all();
}
export function moveBanner(id: string, dir: 'up' | 'down') { export function moveBanner(id: string, dir: 'up' | 'down') {
const rows = listBannerImages(); const rows = listBannerImages();
const idx = rows.findIndex((r) => r.id === id); const idx = rows.findIndex((r) => r.id === id);

View File

@ -1,9 +1,18 @@
import type { PageServerLoad } from './$types'; import type { PageServerLoad } from './$types';
import { getContact, listBannerImages, listPosts, listServices } from '$lib/server/content'; import {
getContact,
listBannerImages,
listGalleryImages,
listPosts,
listServices
} from '$lib/server/content';
export const load: PageServerLoad = () => { export const load: PageServerLoad = () => {
const banner = listBannerImages().map((i) => `/uploads/${i.imagePath}`); const banner = listBannerImages().map((i) => `/uploads/${i.imagePath}`);
// Up to 12 (4x3) images for the homepage gallery preview grid.
const gallery = listGalleryImages(12).map((i) => `/uploads/${i.imagePath}`);
const services = listServices().map((s) => ({ const services = listServices().map((s) => ({
id: s.id, id: s.id,
title: s.title, title: s.title,
@ -25,5 +34,5 @@ export const load: PageServerLoad = () => {
date: (p.publishedAt ?? p.createdAt).toISOString() date: (p.publishedAt ?? p.createdAt).toISOString()
})); }));
return { banner, services, posts, contact: getContact() }; return { banner, services, gallery, posts, contact: getContact() };
}; };

View File

@ -42,6 +42,19 @@
</section> </section>
{/if} {/if}
{#if data.gallery.length > 0}
<section class="gallery-preview" id="galerija">
<h2 class="section-title">Galerija</h2>
<a class="gallery-link" href="/gallery" aria-label="Odpri galerijo">
<div class="gallery-grid">
{#each data.gallery as url (url)}
<div class="g-tile"><img src={url} alt="" loading="lazy" /></div>
{/each}
</div>
</a>
</section>
{/if}
{#if data.posts.length > 0} {#if data.posts.length > 0}
<section class="news" id="novice"> <section class="news" id="novice">
<h2 class="section-title">Novice</h2> <h2 class="section-title">Novice</h2>
@ -71,6 +84,7 @@
{#if data.contact.address} {#if data.contact.address}
<p class="address">{data.contact.address}</p> <p class="address">{data.contact.address}</p>
{/if} {/if}
<div class="contact-methods">
{#if data.contact.email} {#if data.contact.email}
<div class="contact-line"> <div class="contact-line">
<SvgImage image_src="/mail.svg" icon_color="#42af38" width="1.4em" height="1.4em" /> <SvgImage image_src="/mail.svg" icon_color="#42af38" width="1.4em" height="1.4em" />
@ -84,6 +98,7 @@
</div> </div>
{/if} {/if}
</div> </div>
</div>
{#if data.contact.showMap && data.contact.address} {#if data.contact.showMap && data.contact.address}
<div class="map"> <div class="map">
<iframe title="Zemljevid" src={mapSrc(data.contact.address)} loading="lazy"></iframe> <iframe title="Zemljevid" src={mapSrc(data.contact.address)} loading="lazy"></iframe>
@ -170,6 +185,39 @@
.section-title { .section-title {
text-align: center; text-align: center;
margin: 0 0 1em; margin: 0 0 1em;
font-size: clamp(2em, 5vw, 2.8em);
}
.gallery-link {
display: block;
text-decoration: none;
}
.gallery-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0.6em;
-webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
}
.g-tile {
aspect-ratio: 1;
border-radius: 8px;
overflow: hidden;
background: #11161a;
}
.g-tile img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
transition: transform 0.3s ease;
}
.g-tile:hover img {
transform: scale(1.05);
} }
.news-grid { .news-grid {
@ -261,6 +309,12 @@
margin: 0; margin: 0;
} }
.contact-methods {
display: flex;
flex-wrap: wrap;
gap: 1.5em;
}
.contact-line { .contact-line {
display: flex; display: flex;
align-items: center; align-items: center;