mirror of
https://github.com/Lapikud/lapikud.github.io.git
synced 2026-08-08 19:49:13 +00:00
updated and fixed most pages + navbar update on home page
This commit is contained in:
@@ -1,52 +1,41 @@
|
||||
# Workshops & courses conducted by Lapikud members
|
||||
#
|
||||
- title:
|
||||
en: Go Programming Language Workshop
|
||||
est: Go programmeerimiskeele töötuba
|
||||
en: C workshop
|
||||
est: C koolitus
|
||||
description:
|
||||
en: Introduction to Go through practical exercises. Covered basic syntax, goroutines, channels and concurrency with real-world examples.
|
||||
est: Sissejuhatus Go keelde läbi praktiliste ülesannete. Kaetud on põhisüntaks, goroutiinid, kanalid ja konkurentsus reaaleluliste näidete kaudu.
|
||||
en: Three-part introductory C workshop series for beginners and early-stage programmers. Covered core programming foundations and practical C basics in Estonian at TalTech IT College.
|
||||
est: Kolmeosaline C programmeerimiskeele koolitus algajatele ja varasema kogemusega huvilistele. Käsitleti programmeerimise alusteadmisi ja C keele põhiteemasid praktiliste näidete kaudu TalTech IT Kolledžis.
|
||||
mentor:
|
||||
en: Henri Karba
|
||||
est: Henri Karba
|
||||
en: Lapikud mentors
|
||||
est: MTÜ Lapikud mentorid
|
||||
duration:
|
||||
en: 3 × 2h
|
||||
est: 3 × 2h
|
||||
en: 3 × 1h 30min
|
||||
est: 3 × 1h 30min
|
||||
date:
|
||||
en: March 2025
|
||||
est: Märts 2025
|
||||
gallery: 3
|
||||
en: March 2026
|
||||
est: Märts 2026
|
||||
gallery:
|
||||
- temp1.jpg
|
||||
- temp2.jpg
|
||||
|
||||
- title:
|
||||
en: Figma Design Workshop
|
||||
est: Figma disainitöötuba
|
||||
en: C workshop
|
||||
est: C koolitus
|
||||
description:
|
||||
en: Over two days we learned the Figma workflow, covering components, auto-layout, prototyping and presenting to clients.
|
||||
est: Kahe päeva jooksul õppisime Figma töövoogu, komponendid, auto-layout, prototüüpimine ja klientidele esitamine.
|
||||
en: Three-part introductory C workshop series for beginners and early-stage programmers. Covered core programming foundations and practical C basics in Estonian at TalTech IT College.
|
||||
est: Kolmeosaline C programmeerimiskeele koolitus algajatele ja varasema kogemusega huvilistele. Käsitleti programmeerimise alusteadmisi ja C keele põhiteemasid praktiliste näidete kaudu TalTech IT Kolledžis.
|
||||
mentor:
|
||||
en: Maris Tamm
|
||||
est: Maris Tamm
|
||||
en: Lapikud mentors
|
||||
est: MTÜ Lapikud mentorid
|
||||
duration:
|
||||
en: 2 days
|
||||
est: 2 päeva
|
||||
en: 3 × 1h 30min
|
||||
est: 3 × 1h 30min
|
||||
date:
|
||||
en: November 2024
|
||||
est: Nov 2024
|
||||
gallery: 2
|
||||
en: March 2026
|
||||
est: Märts 2026
|
||||
gallery:
|
||||
- temp1.jpg
|
||||
- temp2.jpg
|
||||
- temp3.jpg
|
||||
|
||||
- title:
|
||||
en: Web Security Basics
|
||||
est: Veebiturvalisuse alused
|
||||
description:
|
||||
en: Practical seminar on OWASP Top 10 attacks and defense methods. Lab work involved fixing real vulnerabilities in a controlled environment.
|
||||
est: Praktiline seminar OWASP Top 10 rünnakute ja kaitsmismeetodite kohta. Laboris lahendati päris haavatavusi kontrollitud keskkonnas.
|
||||
mentor:
|
||||
en: Juku Rebane
|
||||
est: Juku Rebane
|
||||
duration:
|
||||
en: 4 hours
|
||||
est: 4 tundi
|
||||
date:
|
||||
en: September 2024
|
||||
est: Sept 2024
|
||||
gallery: 4
|
||||
|
||||
BIN
public/assets/workshops/temp1.jpg
Normal file
BIN
public/assets/workshops/temp1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
BIN
public/assets/workshops/temp2.jpg
Normal file
BIN
public/assets/workshops/temp2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 241 KiB |
11
src/app.css
11
src/app.css
@@ -1,6 +1,6 @@
|
||||
/* Global stylesheet */
|
||||
|
||||
@import url("https://fonts.googleapis.com/css2?family=Unbounded:wght@300;400;500;600;700&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700;900&display=swap");
|
||||
@import "tailwindcss";
|
||||
|
||||
/* Overwriting tailwindcss specific variables */
|
||||
@@ -46,12 +46,7 @@
|
||||
--spacing-6: 48px;
|
||||
|
||||
/* type scale (fluid base + modular sizes) */
|
||||
--fs-base: clamp(0.95rem, 0.9vw + 0.9rem, 1rem);
|
||||
--fs-xs: 0.85rem;
|
||||
--fs-sm: 0.92rem;
|
||||
--fs-md: 1rem;
|
||||
--fs-lg: 1.125rem;
|
||||
--fs-xl: 1.5rem;
|
||||
--fs-base: clamp(1.1rem, 1vw + 1rem, 1.2rem);
|
||||
--line-height: 1.6;
|
||||
}
|
||||
|
||||
@@ -62,7 +57,7 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html {
|
||||
font-family: "Unbounded", ui-sans-serif, system-ui, -apple-system, "Segoe UI",
|
||||
font-family: "Lato", ui-sans-serif, system-ui, -apple-system, "Segoe UI",
|
||||
Roboto, "Helvetica Neue", Arial;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
} = $props();
|
||||
|
||||
let isOpen = $state(false);
|
||||
let panelElement = $state(null);
|
||||
|
||||
const toggle = () => (isOpen = !isOpen);
|
||||
const close = () => (isOpen = false);
|
||||
@@ -21,6 +22,26 @@
|
||||
return;
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
$effect(() => {
|
||||
if (!isOpen) return;
|
||||
|
||||
const handleDocumentClick = (event) => {
|
||||
const target = event.target;
|
||||
if (!(target instanceof HTMLElement) || !panelElement) return;
|
||||
|
||||
if (
|
||||
panelElement.contains(target) &&
|
||||
target.closest("button, a, [role='menuitem']")
|
||||
) {
|
||||
close();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("click", handleDocumentClick);
|
||||
return () => document.removeEventListener("click", handleDocumentClick);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="relative inline-block" onfocusout={handleFocusOut}>
|
||||
@@ -38,6 +59,7 @@
|
||||
<div
|
||||
class="{panelClass} absolute mt-2 rounded-md shadow-lg overflow-visible flex flex-col"
|
||||
style:visibility={isOpen ? "visible" : "hidden"}
|
||||
bind:this={panelElement}
|
||||
>
|
||||
<div>
|
||||
{@render children?.()}
|
||||
|
||||
@@ -44,63 +44,19 @@
|
||||
return paths.includes(currentPath);
|
||||
}
|
||||
|
||||
function isHomePage() {
|
||||
return currentPath === "/";
|
||||
}
|
||||
|
||||
function headerShellClass() {
|
||||
return isHomePage()
|
||||
? "bg-transparent"
|
||||
: "border-b-2 border-orange-500 bg-gray-900 backdrop-blur-md";
|
||||
}
|
||||
|
||||
function headerRowClass() {
|
||||
return isHomePage()
|
||||
? "flex min-h-16 items-center w-full relative gap-4"
|
||||
: "flex min-h-16 items-center gap-4";
|
||||
}
|
||||
|
||||
function headerWrapClass() {
|
||||
return isHomePage()
|
||||
? "ml-auto flex w-full self-stretch items-center justify-end md:w-auto md:border-b-3 md:border-white backdrop-blur-lg bg-black/35 pr-(--page-padding-inline)"
|
||||
: "flex items-center justify-end ml-auto w-full md:w-auto";
|
||||
}
|
||||
|
||||
function desktopNavClass() {
|
||||
return isHomePage()
|
||||
? "z-10 hidden md:flex gap-1 justify-end text-lg"
|
||||
: "z-10 hidden md:flex items-center gap-1 justify-end text-lg";
|
||||
}
|
||||
|
||||
function navButtonClass(active = false) {
|
||||
if (isHomePage()) {
|
||||
return active
|
||||
? "border-transparent text-orange-500 bg-transparent"
|
||||
: "border-transparent bg-transparent text-white/75 hover:text-orange-500";
|
||||
}
|
||||
|
||||
return active
|
||||
? "border-transparent text-orange-500 hover:bg-white/5"
|
||||
: "border-transparent text-white/75 hover:bg-white/5";
|
||||
}
|
||||
|
||||
function dropdownButtonClass(active = false) {
|
||||
if (isHomePage()) {
|
||||
return active
|
||||
? "border-transparent text-orange-500 bg-transparent"
|
||||
: "border-transparent bg-transparent text-white/75 hover:text-orange-500";
|
||||
}
|
||||
|
||||
return active
|
||||
? "border-transparent text-orange-500 hover:bg-white/5"
|
||||
: "border-transparent text-white/75 hover:bg-white/5";
|
||||
}
|
||||
|
||||
function languageButtonClass() {
|
||||
if (isHomePage()) {
|
||||
return "ml-3 border-transparent bg-transparent px-3 py-1 text-sm text-white/75 hover:text-orange-500";
|
||||
}
|
||||
|
||||
return "ml-3 border-transparent bg-transparent px-3 py-1 text-sm text-white/75 hover:bg-white/5";
|
||||
}
|
||||
|
||||
@@ -217,21 +173,19 @@
|
||||
</style>
|
||||
|
||||
<header class="fixed inset-x-0 top-0 z-50 text-white">
|
||||
<div class={headerShellClass()}>
|
||||
<Container maxWidth={true} center={!isHomePage()} class="py-0">
|
||||
<div class="border-b-2 border-orange-500 bg-gray-900 backdrop-blur-md">
|
||||
<Container class="py-0">
|
||||
{#if $text && Object.keys($text).length > 0}
|
||||
<div class={headerRowClass()}>
|
||||
{#if !isHomePage()}
|
||||
<div class="flex min-h-16 items-center gap-4">
|
||||
<Button
|
||||
onClick={() => handleNavigation("/")}
|
||||
class="nav-logo-button border-transparent bg-transparent px-0 py-3"
|
||||
>
|
||||
<img src="/assets/logo.svg" alt="Lapikud logo" class="h-12 md:h-14 w-auto" />
|
||||
</Button>
|
||||
{/if}
|
||||
|
||||
<div class={headerWrapClass()}>
|
||||
<nav class={desktopNavClass()}>
|
||||
<div class="ml-auto flex w-full items-center justify-end md:w-auto">
|
||||
<nav class="z-10 hidden items-center gap-1 justify-end text-lg md:flex">
|
||||
<Dropdown
|
||||
name={$text.about}
|
||||
buttonClass={`${dropdownButtonClass(isInGroup(aboutRoutes))} ${isInGroup(aboutRoutes) ? "nav-active-parent" : ""}`}
|
||||
@@ -309,7 +263,7 @@
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
class={languageButtonClass()}
|
||||
class="ml-3 border-transparent bg-transparent px-3 py-1 text-sm text-white/75 hover:bg-white/5"
|
||||
onClick={() => switchLanguageRoute($currentLang === "est" ? "en" : "est")}
|
||||
>
|
||||
{$currentLang === "est" ? "EN" : "EST"}
|
||||
|
||||
@@ -11,7 +11,23 @@
|
||||
let { routes } = $props();
|
||||
|
||||
let currentPath = $state(window.location.pathname);
|
||||
let CurrentComponent = $derived(routes[currentPath] || routes["/"]);
|
||||
let CurrentComponent = $state(null);
|
||||
|
||||
async function resolveCurrentComponent(path) {
|
||||
const routeEntry = routes[path] || routes["/"];
|
||||
|
||||
if (typeof routeEntry === "function") {
|
||||
try {
|
||||
const module = await routeEntry();
|
||||
CurrentComponent = module?.default || null;
|
||||
} catch {
|
||||
CurrentComponent = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentComponent = routeEntry || null;
|
||||
}
|
||||
|
||||
function navigate(path) {
|
||||
window.history.pushState({}, "", path);
|
||||
@@ -46,6 +62,10 @@
|
||||
|
||||
return () => window.removeEventListener("click", handleClick);
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
resolveCurrentComponent(currentPath);
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if CurrentComponent}
|
||||
|
||||
@@ -54,12 +54,7 @@
|
||||
</div>
|
||||
<div class="pointer-events-none absolute inset-y-0 left-1/2 w-screen -translate-x-1/2 bg-linear-to-r from-black/65 via-black/35 to-transparent" aria-hidden="true"></div>
|
||||
<div class="relative z-20 flex min-h-screen w-full items-stretch py-8 md:py-12">
|
||||
<div class="flex w-full max-w-115 flex-col justify-between">
|
||||
<Image
|
||||
src="/assets/logo.svg"
|
||||
alt={$text["hero"]?.logoAlt || "MTÜ Lapikud"}
|
||||
class="w-full max-w-65 md:max-w-80 h-auto pt-5 md:pt-10"
|
||||
/>
|
||||
<div class="flex w-full max-w-115 flex-col justify-end">
|
||||
<div class="flex flex-col items-start gap-5">
|
||||
<p class="w-full max-w-110 text-left text-lg leading-[165%] text-white drop-shadow-[0_2px_8px_rgba(0,0,0,0.6)] md:max-w-125 md:text-xl">
|
||||
{$text["hero"]?.description || "MTÜ Lapikud on Tallinna Tehnikaülikooli Tarkvaraarendusklubi, mis ühendab endisi ja praegusi IT huvilisi tudengeid."}
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
</Section>
|
||||
|
||||
<Section padding="large">
|
||||
<div class="mb-12">
|
||||
<div class="mb-22">
|
||||
<p class="mb-3 text-[0.72rem] font-bold uppercase tracking-[0.12em] text-orange-500">{$text["portfolio"]?.label || "Tehtud tööd"}</p>
|
||||
<h1 class="m-0 max-w-[20ch] text-[clamp(1.9rem,4vw,3.15rem)] leading-[1.08] tracking-[-0.03em]">{$text["portfolio"]?.title || "Projektid, mis räägivad enda eest."}</h1>
|
||||
<p class="mt-4 max-w-[62ch] leading-[1.65] text-gray-900">
|
||||
@@ -114,13 +114,13 @@
|
||||
</div>
|
||||
|
||||
{#if featuredProject}
|
||||
<Card class="mb-5! grid! overflow-hidden! rounded-none! border-0! bg-white! p-0! ring-1 ring-gray-200 md:grid-cols-[1.25fr_1fr]!" variant="default">
|
||||
<div class="min-h-[220px] overflow-hidden bg-gray-100/70 p-2 md:min-h-[280px]">
|
||||
<Card class="mb-5! grid! gap-4 rounded-none! border-0! bg-white! p-0! md:grid-cols-[1.25fr_1fr]! md:gap-6" variant="default">
|
||||
<div class="flex min-h-[220px] items-center justify-center md:min-h-[280px]">
|
||||
{#if featuredProject.photo}
|
||||
<img
|
||||
src={projectImage(featuredProject)}
|
||||
alt={projectTitle(featuredProject)}
|
||||
class="block h-full w-full border border-gray-200 bg-white object-contain object-center shadow-[0_1px_2px_rgba(13,13,13,0.05)]"
|
||||
class="block h-auto max-h-full w-auto max-w-full object-contain object-center shadow-[0_1px_2px_rgba(13,13,13,0.05)]"
|
||||
on:error={(event) => handleImageError(event, featuredProject.photo)}
|
||||
/>
|
||||
{:else}
|
||||
@@ -128,17 +128,19 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col justify-center gap-2 p-[clamp(1.5rem,3vw,2.5rem)]">
|
||||
<div class="flex h-full flex-1 flex-col justify-between gap-[clamp(0.75rem,2vw,1.5rem)] p-[clamp(1.5rem,3vw,2.5rem)]">
|
||||
<div class="flex flex-col gap-[clamp(0.45rem,1vw,0.8rem)]">
|
||||
<h2 class="m-0 text-[clamp(1.45rem,2.7vw,2rem)] leading-[1.2] tracking-[-0.02em]">{projectTitle(featuredProject)}</h2>
|
||||
{#if projectDescription(featuredProject)}
|
||||
<p class="m-0 text-[0.9rem] leading-[1.6] text-gray-900">{projectDescription(featuredProject)}</p>
|
||||
{/if}
|
||||
</div>
|
||||
{#if featuredProject.url}
|
||||
<a
|
||||
href={featuredProject.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="mt-0.5 inline-flex w-fit items-center gap-1.5 font-semibold text-orange-500 hover:underline"
|
||||
class="mt-auto inline-flex w-fit items-center gap-1.5 pt-1 font-semibold text-orange-500 hover:underline"
|
||||
>
|
||||
{$text["portfolio"]?.projectLink || "Vaata projekti"}
|
||||
<ExternalLink size={16} />
|
||||
@@ -149,13 +151,13 @@
|
||||
{/if}
|
||||
<div class="ourwork-grid">
|
||||
{#each regularProjects as project}
|
||||
<Card variant="default" class="ourwork-grid-card rounded-none! border-0! bg-white! p-0!">
|
||||
<div class="aspect-16/10 overflow-hidden bg-gray-100/70 p-2">
|
||||
<Card variant="default" class="ourwork-grid-card gap-4 rounded-none! border-0! bg-white! p-0!">
|
||||
<div class="flex aspect-16/10 items-center justify-center">
|
||||
{#if project.photo}
|
||||
<img
|
||||
src={projectImage(project)}
|
||||
alt={projectTitle(project)}
|
||||
class="block h-full w-full border border-gray-200 bg-white object-contain object-center shadow-[0_1px_2px_rgba(13,13,13,0.05)]"
|
||||
class="block h-auto max-h-full w-auto max-w-full object-contain object-center shadow-[0_1px_2px_rgba(13,13,13,0.05)]"
|
||||
on:error={(event) => handleImageError(event, project.photo)}
|
||||
/>
|
||||
{:else}
|
||||
@@ -163,13 +165,15 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="ourwork-card-content flex h-full flex-1 flex-col gap-2 p-5">
|
||||
<div class="ourwork-card-content flex h-full flex-1 flex-col justify-between gap-[clamp(0.55rem,1vw,0.95rem)] px-5 pb-5 pt-1.5">
|
||||
<div class="flex flex-col gap-[clamp(0.4rem,0.9vw,0.75rem)]">
|
||||
<h3 class="ourwork-card-title m-0 text-base leading-[1.2] tracking-[-0.02em]">{projectTitle(project)}</h3>
|
||||
{#if projectDescription(project)}
|
||||
<p class="ourwork-card-description m-0 text-[0.9rem] leading-[1.6] text-gray-900">{projectDescription(project)}</p>
|
||||
{:else}
|
||||
<p class="ourwork-card-description m-0 text-[0.9rem] leading-[1.6] text-gray-900 italic">{$text["portfolio"]?.noDescription || "Kirjeldus lisamisel."}</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if project.url}
|
||||
<a
|
||||
@@ -191,10 +195,10 @@
|
||||
|
||||
<style>
|
||||
.ourwork-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1px;
|
||||
justify-content: center;
|
||||
display: grid;
|
||||
gap: clamp(0.75rem, 1.5vw, 1.1rem);
|
||||
align-items: stretch;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.ourwork-grid :global(.ourwork-grid-card) {
|
||||
@@ -205,37 +209,15 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ourwork-card-content {
|
||||
min-height: 10.25rem;
|
||||
}
|
||||
|
||||
.ourwork-card-title {
|
||||
min-height: calc(1.2em * 2);
|
||||
display: -webkit-box;
|
||||
line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ourwork-card-description {
|
||||
min-height: calc(1.6em * 3);
|
||||
display: -webkit-box;
|
||||
line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 3;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.ourwork-grid :global(.ourwork-grid-card) {
|
||||
width: calc((100% - 1px) / 2);
|
||||
.ourwork-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.ourwork-grid :global(.ourwork-grid-card) {
|
||||
width: calc((100% - 2px) / 3);
|
||||
.ourwork-grid {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
</script>
|
||||
|
||||
<div class="safe-area-navbar">
|
||||
<Section class="overflow-hidden bg-[#0f0f0f]" padding="none" fullWidth={true} contentClass="relative !px-0">
|
||||
<Section class="overflow-hidden bg-gray-900" padding="none" fullWidth={true} contentClass="relative !px-0">
|
||||
<div class="relative overflow-hidden py-[clamp(3rem,8vw,6rem)]">
|
||||
<div class="relative z-10 mx-auto w-full max-w-(--page-max-width) px-(--page-padding-inline)">
|
||||
<div class="relative z-10 w-full max-w-3xl">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import { Section, Stack, Container } from "$components";
|
||||
import { Section, Stack, Image } from "$components";
|
||||
import { onMount, onDestroy } from "svelte";
|
||||
import yaml from "js-yaml";
|
||||
import { currentLang, getLangText, createPageTextStore } from "$lib";
|
||||
@@ -22,6 +22,10 @@
|
||||
return getLangText(workshop, field, $currentLang);
|
||||
}
|
||||
|
||||
function getGallery(workshop) {
|
||||
return Array.isArray(workshop?.gallery) ? workshop.gallery : [];
|
||||
}
|
||||
|
||||
function getGalleryClass(count) {
|
||||
const classes = {
|
||||
1: "grid-cols-1 grid-rows-1",
|
||||
@@ -29,7 +33,7 @@
|
||||
3: "grid-cols-2 grid-rows-2",
|
||||
4: "grid-cols-2 grid-rows-2",
|
||||
};
|
||||
return classes[count] || classes[1];
|
||||
return classes[count] || "grid-cols-2";
|
||||
}
|
||||
|
||||
function getImageHeightClass(count, index) {
|
||||
@@ -39,13 +43,13 @@
|
||||
return index === 0 ? "h-72 row-span-2" : "h-32";
|
||||
}
|
||||
if (count === 4) return "h-32";
|
||||
return "h-40";
|
||||
return "h-32";
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="safe-area-navbar">
|
||||
<!-- Hero Section -->
|
||||
<Section bg="bg-black" class="text-white">
|
||||
<Section bg="bg-gray-900" class="text-white">
|
||||
<div class="max-w-2xl">
|
||||
<p class="font-dm-mono text-xs uppercase tracking-widest text-orange-500 mb-4">
|
||||
{$text["hero"]?.label}
|
||||
@@ -66,29 +70,23 @@
|
||||
<Section>
|
||||
<Stack gap="lg">
|
||||
{#each workshops as workshop, index (index)}
|
||||
<div class={`grid grid-cols-1 md:grid-cols-2 gap-14 md:gap-16 py-16 border-b border-gray-100 ${index === workshops.length - 1 ? "border-b-0" : ""}`}>
|
||||
<div class={`grid grid-cols-1 md:grid-cols-2 gap-14 md:gap-16 py-16 border-b border-orange-500 ${index === workshops.length - 1 ? "border-b-0" : ""}`}>
|
||||
<!-- Gallery -->
|
||||
<div
|
||||
class={`grid gap-1.5 ${index % 2 === 1 ? "md:order-2" : ""}`}
|
||||
>
|
||||
<div class={`grid ${getGalleryClass(workshop.gallery)} gap-1.5`}>
|
||||
{#each Array(workshop.gallery) as _, i}
|
||||
<div class={`grid ${getGalleryClass(getGallery(workshop).length)} gap-1.5`}>
|
||||
{#each getGallery(workshop) as filename, i (filename)}
|
||||
<div
|
||||
class={`bg-gray-100 overflow-hidden flex items-center justify-center ${getImageHeightClass(workshop.gallery, i)}`}
|
||||
class={`overflow-hidden ${getImageHeightClass(getGallery(workshop).length, i)}`}
|
||||
>
|
||||
<svg
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1"
|
||||
class="text-gray-300"
|
||||
>
|
||||
<rect x="3" y="3" width="18" height="18" rx="1" />
|
||||
<circle cx="8.5" cy="8.5" r="1.5" />
|
||||
<polyline points="21 15 16 10 5 21" />
|
||||
</svg>
|
||||
<Image
|
||||
src={`/assets/workshops/${filename}`}
|
||||
alt={`${getField(workshop, "title")} ${i + 1}`}
|
||||
objectFit="cover"
|
||||
class="h-full w-full"
|
||||
pictureClass="h-full w-full"
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
// ADD PAGES HERE TO REGISTER ROUTES
|
||||
// examples: '/page', '/page/:id'
|
||||
|
||||
import Home from './Home.svelte'
|
||||
import Student from './Student.svelte'
|
||||
import Mentors from './Mentors.svelte'
|
||||
import Helpdesk from './Helpdesk.svelte'
|
||||
import OurWork from './OurWork.svelte'
|
||||
import AboutUs from './AboutUs.svelte'
|
||||
import Contact from './Contact.svelte'
|
||||
import Managment from './Managment.svelte'
|
||||
import Striim from './Striim.svelte'
|
||||
import Calendar from './Calendar.svelte'
|
||||
import Workshops from './Workshops.svelte';
|
||||
const loadHome = () => import('./Home.svelte');
|
||||
const loadStudent = () => import('./Student.svelte');
|
||||
const loadMentors = () => import('./Mentors.svelte');
|
||||
const loadHelpdesk = () => import('./Helpdesk.svelte');
|
||||
const loadOurWork = () => import('./OurWork.svelte');
|
||||
const loadAboutUs = () => import('./AboutUs.svelte');
|
||||
const loadContact = () => import('./Contact.svelte');
|
||||
const loadManagment = () => import('./Managment.svelte');
|
||||
const loadStriim = () => import('./Striim.svelte');
|
||||
const loadCalendar = () => import('./Calendar.svelte');
|
||||
const loadWorkshops = () => import('./Workshops.svelte');
|
||||
|
||||
// Route mapping for language switching
|
||||
export const routeMap = {
|
||||
@@ -91,23 +91,23 @@ export function getTranslatedRoute(currentPath, targetLang) {
|
||||
}
|
||||
|
||||
export const routes = {
|
||||
'/': Home,
|
||||
'/tudengile': Student,
|
||||
'/student': Student,
|
||||
'/mentorid': Mentors,
|
||||
'/mentors': Mentors,
|
||||
'/helpdesk': Helpdesk,
|
||||
'/ettevottele': OurWork,
|
||||
'/ourwork': OurWork,
|
||||
'/lapikutest': AboutUs,
|
||||
'/aboutus': AboutUs,
|
||||
'/kontakt': Contact,
|
||||
'/contact': Contact,
|
||||
'/juhatus': Managment,
|
||||
'/management': Managment,
|
||||
'/koolitused': Workshops,
|
||||
'/workshops': Workshops,
|
||||
'/striim': Striim,
|
||||
'/kalender': Calendar,
|
||||
'/calendar': Calendar,
|
||||
'/': loadHome,
|
||||
'/tudengile': loadStudent,
|
||||
'/student': loadStudent,
|
||||
'/mentorid': loadMentors,
|
||||
'/mentors': loadMentors,
|
||||
'/helpdesk': loadHelpdesk,
|
||||
'/ettevottele': loadOurWork,
|
||||
'/ourwork': loadOurWork,
|
||||
'/lapikutest': loadAboutUs,
|
||||
'/aboutus': loadAboutUs,
|
||||
'/kontakt': loadContact,
|
||||
'/contact': loadContact,
|
||||
'/juhatus': loadManagment,
|
||||
'/management': loadManagment,
|
||||
'/koolitused': loadWorkshops,
|
||||
'/workshops': loadWorkshops,
|
||||
'/striim': loadStriim,
|
||||
'/kalender': loadCalendar,
|
||||
'/calendar': loadCalendar,
|
||||
}
|
||||
Reference in New Issue
Block a user