diff --git a/src/app.css b/src/app.css index 8fb6adf..32508bb 100644 --- a/src/app.css +++ b/src/app.css @@ -92,6 +92,29 @@ body { background: rgba(255, 255, 255, 0.08); color: #e5e4ea; } + +/* Style the native file input to match the rest of the dashboard UI. */ +input[type="file"] { + color: #9aa0a6; + font-family: inherit; + font-size: 0.9em; +} +input[type="file"]::file-selector-button { + background: rgba(255, 255, 255, 0.08); + color: #e5e4ea; + border: none; + border-radius: 8px; + padding: 0.5em 1em; + margin-right: 0.9em; + font-family: inherit; + font-size: 0.95em; + font-weight: 600; + cursor: pointer; + transition: background-color 0.15s ease; +} +input[type="file"]::file-selector-button:hover { + background: rgba(66, 175, 56, 0.25); +} .admin-msg { margin: 0; font-size: 0.9em; diff --git a/src/lib/Slideshow.svelte b/src/lib/Slideshow.svelte index 87b335f..380297f 100644 --- a/src/lib/Slideshow.svelte +++ b/src/lib/Slideshow.svelte @@ -4,8 +4,15 @@ images = [], interval = 4000, alt = '', - fit = 'cover' - }: { images: string[]; interval?: number; alt?: string; fit?: 'cover' | 'contain' } = $props(); + fit = 'cover', + hoverZoom = false + }: { + images: string[]; + interval?: number; + alt?: string; + fit?: 'cover' | 'contain'; + hoverZoom?: boolean; + } = $props(); let current = $state(0); @@ -19,7 +26,7 @@ {#if images.length > 0} -
+
{#each images as src, i (src)} {/each} @@ -47,13 +54,17 @@ width: 100%; height: 100%; opacity: 0; - transition: opacity 0.8s ease; + transition: opacity 0.8s ease, transform 0.35s ease; } .slideshow img.active { opacity: 1; } + .slideshow.zoom:hover img { + transform: scale(1.1); + } + .dots { position: absolute; bottom: 0.8em; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 737d48c..f20e56b 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -19,20 +19,22 @@ {#if data.services.length > 0}
{#each data.services as service, i (service.id)} -
- {#if service.images.length > 0} -
- -
- {/if} -
-

{service.title}

- {#if service.description}

{service.description}

{/if} - {#if service.bullets.length > 0} -
    - {#each service.bullets as bullet}
  • {bullet}
  • {/each} -
+
+

{service.title}

+
+ {#if service.images.length > 0} +
+ +
{/if} +
+ {#if service.description}

{service.description}

{/if} + {#if service.bullets.length > 0} +
    + {#each service.bullets as bullet}
  • {bullet}
  • {/each} +
+ {/if} +
{/each} @@ -104,34 +106,46 @@ .services { display: flex; flex-direction: column; - gap: 2.5em; + gap: 3.5em; } .service { display: flex; flex-direction: column; - gap: 1.5em; align-items: center; + gap: 1.5em; + } + + .service-title { + text-transform: uppercase; + text-align: center; + font-size: clamp(1.5em, 4vw, 2em); + margin: 0; + } + + .service-content { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + gap: 2em; } .service-media { width: 100%; - aspect-ratio: 4 / 3; - border-radius: 12px; + aspect-ratio: 16 / 10; + border-radius: 2em; overflow: hidden; background: #11161a; } .service-text { width: 100%; - } - - .service-text h2 { - margin: 0 0 0.4em; + font-size: 1.3em; + color: #bcc0c2; } .desc { - color: #c7c9cf; margin: 0 0 0.8em; } @@ -142,7 +156,6 @@ .service-text li { margin-bottom: 0.5em; - color: #c7c9cf; } .section-title { @@ -251,16 +264,17 @@ } @media (min-width: 800px) { - .service { + .service-content { flex-direction: row; + align-items: center; } - .service.reverse { + .service-content.reverse { flex-direction: row-reverse; } .service-media { - width: 48%; + width: 50%; flex-shrink: 0; } diff --git a/src/routes/admin/(dashboard)/services/+page.server.ts b/src/routes/admin/(dashboard)/services/+page.server.ts index 3f603ed..f33f6a5 100644 --- a/src/routes/admin/(dashboard)/services/+page.server.ts +++ b/src/routes/admin/(dashboard)/services/+page.server.ts @@ -1,7 +1,13 @@ import { fail } from '@sveltejs/kit'; import type { Actions, PageServerLoad } from './$types'; -import { deleteUpload } from '$lib/server/storage'; -import { createService, deleteService, listServices, moveService } from '$lib/server/content'; +import { deleteUpload, saveImage } from '$lib/server/storage'; +import { + addServiceImage, + createService, + deleteService, + listServices, + moveService +} from '$lib/server/content'; export const load: PageServerLoad = () => ({ services: listServices().map((s) => ({ @@ -17,11 +23,17 @@ export const actions: Actions = { const form = await request.formData(); const title = String(form.get('title') ?? '').trim(); if (!title) return fail(400, { error: 'Vnesite naziv storitve.' }); - createService({ + const id = createService({ title, description: String(form.get('description') ?? '').trim() || null, bullets: String(form.get('bullets') ?? '').trim() || null }); + const files = form + .getAll('images') + .filter((e): e is File => e instanceof File && e.size > 0); + for (const file of files) { + addServiceImage(id, await saveImage('services', file)); + } return { success: 'Storitev dodana.' }; }, diff --git a/src/routes/admin/(dashboard)/services/+page.svelte b/src/routes/admin/(dashboard)/services/+page.svelte index 3542d47..f855d18 100644 --- a/src/routes/admin/(dashboard)/services/+page.svelte +++ b/src/routes/admin/(dashboard)/services/+page.svelte @@ -3,12 +3,28 @@ import type { PageData, ActionData } from './$types'; let { data, form }: { data: PageData; form: ActionData } = $props(); + + let creating = $state(false); + let fileInput: HTMLInputElement | undefined = $state();

Storitve

-
+ { + creating = true; + return async ({ update }) => { + await update({ reset: true }); + creating = false; + if (fileInput) fileInput.value = ''; + }; + }} + >

Dodaj storitev

+ {#if form?.error}

{form.error}

{/if} {#if form?.success}

{form.success}

{/if} - +

Obstoječe storitve