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:
parent
d5368067d6
commit
8a8f19133f
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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() };
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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,18 +84,20 @@
|
||||||
{#if data.contact.address}
|
{#if data.contact.address}
|
||||||
<p class="address">{data.contact.address}</p>
|
<p class="address">{data.contact.address}</p>
|
||||||
{/if}
|
{/if}
|
||||||
{#if data.contact.email}
|
<div class="contact-methods">
|
||||||
<div class="contact-line">
|
{#if data.contact.email}
|
||||||
<SvgImage image_src="/mail.svg" icon_color="#42af38" width="1.4em" height="1.4em" />
|
<div class="contact-line">
|
||||||
<a href="mailto:{data.contact.email}">{data.contact.email}</a>
|
<SvgImage image_src="/mail.svg" icon_color="#42af38" width="1.4em" height="1.4em" />
|
||||||
</div>
|
<a href="mailto:{data.contact.email}">{data.contact.email}</a>
|
||||||
{/if}
|
</div>
|
||||||
{#if data.contact.phone}
|
{/if}
|
||||||
<div class="contact-line">
|
{#if data.contact.phone}
|
||||||
<SvgImage image_src="/phone.svg" icon_color="#42af38" width="1.4em" height="1.4em" />
|
<div class="contact-line">
|
||||||
<a href="tel:{data.contact.phone.replace(/\s+/g, '')}">{data.contact.phone}</a>
|
<SvgImage image_src="/phone.svg" icon_color="#42af38" width="1.4em" height="1.4em" />
|
||||||
</div>
|
<a href="tel:{data.contact.phone.replace(/\s+/g, '')}">{data.contact.phone}</a>
|
||||||
{/if}
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#if data.contact.showMap && data.contact.address}
|
{#if data.contact.showMap && data.contact.address}
|
||||||
<div class="map">
|
<div class="map">
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue