5 Commits

Author SHA1 Message Date
440c193190 Merge version_4_1783201561428 into main
Merge version_4_1783201561428 into main
2026-07-04 21:51:57 +00:00
kudinDmitriyUp
8b388eb098 Bob AI: Updated hero and about sections to use user photos as backgr 2026-07-04 21:51:06 +00:00
b79c8d291d Merge version_3_1783201279644 into main
Merge version_3_1783201279644 into main
2026-07-04 21:43:38 +00:00
kudinDmitriyUp
d135411c09 Bob AI: Add dynamic gallery section with user images and remove old 2026-07-04 21:42:47 +00:00
36086e1079 Merge version_2_1783200811387 into main
Merge version_2_1783200811387 into main
2026-07-04 21:35:42 +00:00
7 changed files with 222 additions and 46 deletions

View File

@@ -9,10 +9,11 @@ import SiteBackgroundSlot from "@/components/ui/SiteBackgroundSlot";
import React from 'react'; import React from 'react';
import HeroSection from './HomePage/sections/Hero'; import HeroSection from './HomePage/sections/Hero';
import AboutSection from './HomePage/sections/About'; import AboutSection from './HomePage/sections/About';
import PropertiesSection from './HomePage/sections/Properties';
import ContactSection from './HomePage/sections/Contact'; import ContactSection from './HomePage/sections/Contact';
export default function HomePage(): React.JSX.Element {
import GallerySection from './HomePage/sections/Gallery';
import KartScrollerSection from './HomePage/sections/KartScroller';export default function HomePage(): React.JSX.Element {
return ( return (
<StyleProvider siteBackground="none" heroBackground="none" buttonVariant="stagger"> <StyleProvider siteBackground="none" heroBackground="none" buttonVariant="stagger">
<SiteBackgroundSlot /> <SiteBackgroundSlot />
@@ -23,11 +24,12 @@ export default function HomePage(): React.JSX.Element {
<AboutSection /> <AboutSection />
<PropertiesSection />
<ContactSection /> <ContactSection />
<GallerySection />
<KartScrollerSection />
</StyleProvider> </StyleProvider>
); );
} }

View File

@@ -1,17 +1,94 @@
// AUTO-GENERATED by per-section-migrate. Edit freely — Bob will treat this /* eslint-disable */
// file as the canonical source for the "about" section. // @ts-nocheck — generated by catalog-eject; runtime-correct but TS strict-mode false-positives on inlined catalog body
import { useRef } from "react";
import { useScroll, useTransform, motion } from "motion/react";
import Button from "@/components/ui/Button";
import TextAnimation from "@/components/ui/TextAnimation";
import ImageOrVideo from "@/components/ui/ImageOrVideo";
import React from 'react'; type AboutTextFillProps = {
import AboutTextFill from "@/components/sections/about/AboutTextFill"; tag?: string;
title: string;
description?: string;
primaryButton?: { text: string; href: string };
secondaryButton?: { text: string; href: string };
textAnimation: "slide-up" | "fade-blur" | "fade";
} & ({ imageSrc: string; videoSrc?: never } | { videoSrc: string; imageSrc?: never });
const AboutInline = () => {
const sectionRef = useRef<HTMLDivElement>(null);
const words = "Úspechy sa nerodia cez noc. Sú výsledkom tvrdej práce.".split(" ");
const { scrollYProgress } = useScroll({
target: sectionRef,
offset: ["start 0.8", "start 0.2"],
});
const Word = ({ word, index }: { word: string; index: number }) => {
const start = index / words.length;
const end = (index + 1) / words.length;
const opacity = useTransform(scrollYProgress, [start, end], [0.15, 1]);
return (
<motion.span className="inline-block" style={{ opacity }}>
{word}
</motion.span>
);
};
export default function AboutSection(): React.JSX.Element {
return ( return (
<div id="about" data-section="about"> <section
<AboutTextFill ref={sectionRef}
textAnimation="fade" aria-label="About section"
title="Úspechy sa nerodia cez noc. Sú výsledkom tvrdej práce." className="relative py-32 md:py-48 overflow-hidden"
imageSrc="https://picsum.photos/seed/1510900608/1200/800" >
/> <div className="absolute inset-0 z-0">
<ImageOrVideo imageSrc={"https://storage.googleapis.com/webild/users/user_3G3RRYMNJY63CoZ96oJOAlJc2Et/uploaded-1783201278652-k4urrscu.jpg"} className="w-full h-full object-cover opacity-40" />
<div className="absolute inset-0 bg-gradient-to-t from-background via-background/60 to-background"></div>
</div>
<div className="relative z-10 flex flex-col gap-8 md:gap-10 mx-auto w-content-width">
<div className="flex flex-col items-center gap-2">
{undefined && (
<div className="px-3 py-1 mb-1 text-sm card rounded w-fit">
<p>{undefined}</p>
</div> </div>
)}
<h2 className="md:max-w-8/10 text-7xl 2xl:text-8xl leading-[1.15] font-semibold text-center text-balance">
{words.map((word, i) => (
<span key={i}>
{i > 0 && " "}
<Word word={word} index={i} />
</span>
))}
</h2>
{undefined && (
<TextAnimation
variant={"fade"}
gradientText={false}
tag="p"
className="md:max-w-7/10 text-lg md:text-xl leading-snug text-center text-balance"
/>
)}
{(undefined || undefined) && (
<div className="flex flex-wrap justify-center gap-3 mt-2 md:mt-3">
{undefined && <Button text={undefined.text} href={undefined.href} variant="primary"/>}
{undefined && <Button text={undefined.text} href={undefined.href} variant="secondary" animationDelay={0.1} />}
</div>
)}
</div>
{/* Removed inline image to use as background instead */}
</div>
</section>
);
};
export default function AboutSection() {
return (
<div data-webild-section="about" data-section="about" id="about">
<AboutInline />
</div>
); );
} }

View File

@@ -9,7 +9,7 @@ export default function ContactSection(): React.JSX.Element {
<div id="contact" data-section="contact"> <div id="contact" data-section="contact">
<ContactParallaxCard <ContactParallaxCard
title="Kontaktujte ma" title="Kontaktujte ma"
imageSrc="https://picsum.photos/seed/556000234/1200/800" imageSrc="https://storage.googleapis.com/webild/users/user_3G3RRYMNJY63CoZ96oJOAlJc2Et/uploaded-1783201278653-doj07as6.jpg"
inputs={[{"type":"text","name":"name","placeholder":"Vaše meno"},{"name":"email","placeholder":"Váš email","type":"email"}]} inputs={[{"type":"text","name":"name","placeholder":"Vaše meno"},{"name":"email","placeholder":"Váš email","type":"email"}]}
textarea={{"placeholder":"Vaša správa...","name":"message","rows":4}} textarea={{"placeholder":"Vaša správa...","name":"message","rows":4}}
buttonText="Odoslať správu" buttonText="Odoslať správu"

View File

@@ -0,0 +1,83 @@
import React from 'react';
import ScrollReveal from '@/components/ui/ScrollReveal';
import TextAnimation from '@/components/ui/TextAnimation';
import ImageOrVideo from '@/components/ui/ImageOrVideo';
import Tag from '@/components/ui/Tag';
export default function GallerySection() {
const images = [
{
src: "https://storage.googleapis.com/webild/users/user_3G3RRYMNJY63CoZ96oJOAlJc2Et/uploaded-1783201278651-n1egshdk.jpg",
title: "Sústredenie pred štartom",
colSpan: "col-span-1 md:col-span-2",
rowSpan: "row-span-2"
},
{
src: "https://storage.googleapis.com/webild/users/user_3G3RRYMNJY63CoZ96oJOAlJc2Et/uploaded-1783201278652-k4urrscu.jpg",
title: "Súboj na trati",
colSpan: "col-span-1",
rowSpan: "row-span-1"
},
{
src: "https://storage.googleapis.com/webild/users/user_3G3RRYMNJY63CoZ96oJOAlJc2Et/uploaded-1783201278653-doj07as6.jpg",
title: "V plnom nasadení",
colSpan: "col-span-1",
rowSpan: "row-span-1"
},
{
src: "https://storage.googleapis.com/webild/users/user_3G3RRYMNJY63CoZ96oJOAlJc2Et/uploaded-1783201278654-948qc5yh.jpg",
title: "Detail prilby",
colSpan: "col-span-1",
rowSpan: "row-span-1"
},
{
src: "https://storage.googleapis.com/webild/users/user_3G3RRYMNJY63CoZ96oJOAlJc2Et/uploaded-1783201278654-0pk26pgo.jpg",
title: "Pretekársky špeciál",
colSpan: "col-span-1 md:col-span-2",
rowSpan: "row-span-1"
}
];
return (
<div id="gallery" data-webild-section="gallery" className="py-24 bg-background relative overflow-hidden">
<div className="w-content-width mx-auto">
<ScrollReveal variant="slide-up">
<div className="flex flex-col items-center text-center mb-16">
<Tag text="Galéria" className="mb-6" />
<TextAnimation
text="Dynamika a Adrenalín"
variant="fade-blur"
tag="h2"
gradientText={false}
className="text-4xl md:text-5xl font-bold text-foreground mb-6"
/>
<p className="text-lg text-accent max-w-2xl">
Zábery z pretekov, tréningov a zákulisia motoršportu. Každá fotografia zachytáva zlomok sekundy plný vášne a rýchlosti.
</p>
</div>
</ScrollReveal>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 auto-rows-[250px]">
{images.map((img, idx) => (
<ScrollReveal
key={idx}
variant="fade-blur"
delay={idx * 0.1}
className={`relative group overflow-hidden rounded-lg card ${img.colSpan} ${img.rowSpan}`}
>
<ImageOrVideo
imageSrc={img.src}
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-black/20 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500 flex items-end p-6">
<h3 className="text-xl font-bold text-white translate-y-4 group-hover:translate-y-0 transition-transform duration-500">
{img.title}
</h3>
</div>
</ScrollReveal>
))}
</div>
</div>
</div>
);
}

View File

@@ -1,22 +1,20 @@
// AUTO-GENERATED by per-section-migrate. Edit freely — Bob will treat this // Created by add_section_from_catalog (HeroOverlay).
// file as the canonical source for the "hero" section.
import React from 'react'; import React from 'react';
import HeroVideoScroll from "@/components/sections/hero/HeroVideoScroll"; import HeroOverlay from '@/components/sections/hero/HeroOverlay';
export default function HeroSection(): React.JSX.Element { export default function HeroSection(): React.JSX.Element {
return ( return (
<div id="hero" data-section="hero"> <div data-webild-section="hero" data-section="hero" id="hero">
<HeroVideoScroll <HeroOverlay
textAnimation="fade"
videoSrc="https://storage.googleapis.com/webild/default/templates/racing/hero/hero.mp4"
tag="Samuel Uváček Racing"
title="Adrenalín na štyroch kolesách"
description="Rýchlosť, precíznosť a vášeň pre motoršport. Sledujte moju cestu za víťazstvami na najprestížnejších pretekoch." description="Rýchlosť, precíznosť a vášeň pre motoršport. Sledujte moju cestu za víťazstvami na najprestížnejších pretekoch."
primaryButton={{"href":"#gallery","text":"Pozrieť galériu"}} primaryButton={{"href":"#gallery","text":"Pozrieť galériu"}}
secondaryButton={{"text":"Kontaktovať","href":"#contact"}} tag="Samuel Uváček Racing"
bottomText="Profesionálny pretekár reprezentujúci Slovensko na medzinárodných okruhoch" title="Adrenalín na štyroch kolesách"
secondaryButton={{"href":"#contact","text":"Kontaktovať"}}
imageSrc="https://storage.googleapis.com/webild/users/user_3G3RRYMNJY63CoZ96oJOAlJc2Et/uploaded-1783201278651-n1egshdk.jpg"
textAnimation="fade"
/> />
</div> </div>
); );
} }

View File

@@ -0,0 +1,35 @@
import React from 'react';
import { motion, useScroll, useTransform, useVelocity, useSpring } from 'motion/react';
export default function KartScrollerSection() {
const { scrollYProgress } = useScroll();
const y = useTransform(scrollYProgress, [0, 1], ['10vh', '85vh']);
const scrollVelocity = useVelocity(scrollYProgress);
const smoothVelocity = useSpring(scrollVelocity, { damping: 50, stiffness: 400 });
const scaleY = useTransform(smoothVelocity, [-2, 0, 2], [1.5, 1, 1.5]);
const fireOpacity = useTransform(smoothVelocity, [0, 0.5], [0, 1]);
return (
<div id="kart-scroller" data-webild-section="kart-scroller">
<motion.div
style={{ y, scaleY }}
className="fixed right-2 md:right-6 top-0 z-50 pointer-events-none flex flex-col items-center justify-center"
>
<motion.div
style={{ opacity: fireOpacity }}
className="text-3xl md:text-5xl -mb-3 origin-bottom"
>
🔥
</motion.div>
<div className="text-4xl md:text-6xl transform -rotate-90 drop-shadow-[0_0_15px_rgba(255,51,51,0.5)]">
🏎
</div>
</motion.div>
</div>
);
}

View File

@@ -1,19 +0,0 @@
// AUTO-GENERATED by per-section-migrate. Edit freely — Bob will treat this
// file as the canonical source for the "properties" section.
import React from 'react';
import FeaturesMediaColumns from "@/components/sections/features/FeaturesMediaColumns";
export default function PropertiesSection(): React.JSX.Element {
return (
<div id="properties" data-section="properties">
<FeaturesMediaColumns
textAnimation="fade"
tag="Galéria"
title="Fotogaléria"
description="Zábery z pretekov, tréningov a zákulisia motoršportu."
items={[{"title":"Na trati","imageSrc":"https://storage.googleapis.com/webild/default/templates/racing/gallery/gallery-1.webp","description":"Záber z posledných pretekov sezóny."},{"title":"V boxoch","description":"Príprava vozidla pred štartom.","imageSrc":"https://storage.googleapis.com/webild/default/templates/racing/gallery/gallery-2.webp"},{"title":"Pódium","description":"Oslava víťazstva na pódiu.","imageSrc":"https://storage.googleapis.com/webild/default/templates/racing/gallery/gallery-3.webp"},{"description":"Detailný pohľad na pretekársky špeciál.","imageSrc":"https://storage.googleapis.com/webild/default/templates/racing/gallery/gallery-4.webp","title":"Technika"},{"title":"Fokus","description":"Sústredenie pred dôležitým pretekom.","imageSrc":"https://storage.googleapis.com/webild/default/templates/racing/gallery/gallery-5.webp"},{"imageSrc":"https://storage.googleapis.com/webild/default/templates/racing/gallery/gallery-6.webp","description":"Akčný záber zo zákruty.","title":"Adrenalín"}]}
/>
</div>
);
}