Compare commits
8 Commits
version_1_
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 440c193190 | |||
|
|
8b388eb098 | ||
| b79c8d291d | |||
|
|
d135411c09 | ||
| 36086e1079 | |||
|
|
af39aa1baf | ||
|
|
c57fe741b4 | ||
|
|
cfc343c43d |
@@ -10,13 +10,13 @@ export default function Layout() {
|
||||
<StyleProvider buttonVariant="default" siteBackground="none" heroBackground="none">
|
||||
<SiteBackgroundSlot />
|
||||
<NavbarFullscreenStatic
|
||||
logo="Le Cercle"
|
||||
logo="Samuel Uváček"
|
||||
navItems={[
|
||||
{ name: "Properties", href: "#properties" },
|
||||
{ name: "About", href: "#about" },
|
||||
{ name: "Contact", href: "#contact" },
|
||||
{ name: "Galéria", href: "#gallery" },
|
||||
{ name: "Úspechy", href: "#achievements" },
|
||||
{ name: "Kontakt", href: "#contact" },
|
||||
]}
|
||||
ctaButton={{ text: "Book a Tour", href: "#contact" }}
|
||||
ctaButton={{ text: "Kontaktovať", href: "#contact" }}
|
||||
/>
|
||||
<main className="flex-grow">
|
||||
<Outlet />
|
||||
@@ -24,44 +24,24 @@ export default function Layout() {
|
||||
<FooterBasic
|
||||
columns={[
|
||||
{
|
||||
title: "Properties",
|
||||
title: "Rýchle odkazy",
|
||||
items: [
|
||||
{ label: "Villas", href: "#properties" },
|
||||
{ label: "Apartments", href: "#" },
|
||||
{ label: "Penthouses", href: "#" },
|
||||
{ label: "New Developments", href: "#" },
|
||||
{ label: "Galéria", href: "#gallery" },
|
||||
{ label: "Úspechy", href: "#achievements" },
|
||||
{ label: "Kontakt", href: "#contact" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Services",
|
||||
title: "Sledujte ma",
|
||||
items: [
|
||||
{ label: "Property Search", href: "#" },
|
||||
{ label: "Legal Assistance", href: "#" },
|
||||
{ label: "Interior Design", href: "#" },
|
||||
{ label: "Property Management", href: "#" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Locations",
|
||||
items: [
|
||||
{ label: "Golden Mile", href: "#" },
|
||||
{ label: "Puerto Banús", href: "#" },
|
||||
{ label: "Sierra Blanca", href: "#" },
|
||||
{ label: "La Zagaleta", href: "#" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Company",
|
||||
items: [
|
||||
{ label: "About Us", href: "#" },
|
||||
{ label: "Contact", href: "#contact" },
|
||||
{ label: "Privacy Policy", href: "#" },
|
||||
{ label: "Terms of Service", href: "#" },
|
||||
{ label: "Instagram", href: "#" },
|
||||
{ label: "Facebook", href: "#" },
|
||||
{ label: "YouTube", href: "#" },
|
||||
],
|
||||
},
|
||||
]}
|
||||
leftText="© 2026 Le Cercle. All rights reserved."
|
||||
rightText="Marbella, Costa del Sol"
|
||||
leftText="© 2026 Samuel Uváček. Všetky práva vyhradené."
|
||||
rightText="Profesionálny pretekár"
|
||||
/>
|
||||
</StyleProvider>
|
||||
);
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
|
||||
:root {
|
||||
/* @colorThemes/lightTheme/warm-luxury */
|
||||
--background: #faf8f5;
|
||||
--card: #ffffff;
|
||||
--foreground: #1a1a1a;
|
||||
--primary-cta: #1a1a1a;
|
||||
--primary-cta-text: #faf8f5;
|
||||
--secondary-cta: #f0ece6;
|
||||
--secondary-cta-text: #1a1a1a;
|
||||
--accent: #c9a96e;
|
||||
--background-accent: #f0ece6;
|
||||
--background: #0a0a0a;
|
||||
--card: #141414;
|
||||
--foreground: #f5f5f5;
|
||||
--primary-cta: #ff3333;
|
||||
--primary-cta-text: #ffffff;
|
||||
--secondary-cta: #262626;
|
||||
--secondary-cta-text: #f5f5f5;
|
||||
--accent: #ff3333;
|
||||
--background-accent: #1a1a1a;
|
||||
|
||||
/* @layout/border-radius/soft */
|
||||
--radius: 0.75rem;
|
||||
|
||||
@@ -1,71 +1,35 @@
|
||||
// AUTO-GENERATED shell by per-section-migrate.
|
||||
// Section bodies live in the sibling sections/ folder (one file per section).
|
||||
// Edit those section files directly. Non-block content (wrappers,
|
||||
// non-inlinable sections) is preserved inline; extracted section blocks
|
||||
// become component refs.
|
||||
|
||||
import { StyleProvider } from "@/components/ui/StyleProvider";
|
||||
import SiteBackgroundSlot from "@/components/ui/SiteBackgroundSlot";
|
||||
import HeroVideoScroll from "@/components/sections/hero/HeroVideoScroll";
|
||||
import AboutTextFill from "@/components/sections/about/AboutTextFill";
|
||||
import FeaturesMediaColumns from "@/components/sections/features/FeaturesMediaColumns";
|
||||
import ContactParallaxCard from "@/components/sections/contact/ContactParallaxCard";
|
||||
import React from 'react';
|
||||
import HeroSection from './HomePage/sections/Hero';
|
||||
import AboutSection from './HomePage/sections/About';
|
||||
import ContactSection from './HomePage/sections/Contact';
|
||||
|
||||
export default function HomePage() {
|
||||
|
||||
import GallerySection from './HomePage/sections/Gallery';
|
||||
import KartScrollerSection from './HomePage/sections/KartScroller';export default function HomePage(): React.JSX.Element {
|
||||
return (
|
||||
<StyleProvider siteBackground="none" heroBackground="none" buttonVariant="stagger">
|
||||
<SiteBackgroundSlot />
|
||||
|
||||
|
||||
|
||||
<div id="hero" data-section="hero">
|
||||
<HeroVideoScroll
|
||||
textAnimation="fade"
|
||||
videoSrc="https://storage.googleapis.com/webild/default/templates/marbella/hero/hero.mp4"
|
||||
tag="Le Cercle Premium Real Estate"
|
||||
title="Live Where the Sun Meets the Sea"
|
||||
description="Exclusive beachfront villas and luxury apartments on the Costa del Sol. Your Mediterranean dream, delivered turnkey."
|
||||
primaryButton={{ text: "View Properties", href: "#properties" }}
|
||||
secondaryButton={{ text: "Book a Tour", href: "#contact" }}
|
||||
bottomText="A premium real estate brand designed for those seeking a refined way of living on the Costa del Sol"
|
||||
/>
|
||||
</div>
|
||||
<HeroSection />
|
||||
|
||||
<div id="about" data-section="about">
|
||||
<AboutTextFill
|
||||
textAnimation="fade"
|
||||
title="For those who travel like it's an art form."
|
||||
imageSrc="https://storage.googleapis.com/webild/default/templates/marbella/about/statement.webp"
|
||||
/>
|
||||
</div>
|
||||
<AboutSection />
|
||||
|
||||
<div id="properties" data-section="properties">
|
||||
<FeaturesMediaColumns
|
||||
textAnimation="fade"
|
||||
tag="Properties"
|
||||
title="Our Villas"
|
||||
description="Handpicked residences in Marbella's most coveted locations, each designed for effortless Mediterranean living."
|
||||
items={[
|
||||
{ title: "Villa Serena", description: "A sunlit 5-bedroom retreat with infinity pool, panoramic sea views, and private garden terraces.", imageSrc: "https://storage.googleapis.com/webild/default/templates/marbella/properties/villa-1.webp" },
|
||||
{ title: "Casa del Sol", description: "Contemporary beachfront living with floor-to-ceiling glass, rooftop lounge, and direct beach access.", imageSrc: "https://storage.googleapis.com/webild/default/templates/marbella/properties/villa-2.webp" },
|
||||
{ title: "Villa Andalucía", description: "Traditional charm meets modern luxury — courtyard, olive grove, and a heated outdoor pool.", imageSrc: "https://storage.googleapis.com/webild/default/templates/marbella/properties/villa-3.webp" },
|
||||
{ title: "The Meridian", description: "Sleek 4-bedroom penthouse villa with smart home technology and sweeping coastal views.", imageSrc: "https://storage.googleapis.com/webild/default/templates/marbella/properties/villa-4.webp" },
|
||||
{ title: "Villa Blanca", description: "Minimalist white-washed estate with private cinema, spa suite, and landscaped Mediterranean gardens.", imageSrc: "https://storage.googleapis.com/webild/default/templates/marbella/properties/villa-5.webp" },
|
||||
{ title: "Casa Dorada", description: "Golden-hour perfection — west-facing terraces, wine cellar, and an open-plan chef's kitchen.", imageSrc: "https://storage.googleapis.com/webild/default/templates/marbella/properties/villa-6.webp" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="contact" data-section="contact">
|
||||
<ContactParallaxCard
|
||||
title="Get In Touch"
|
||||
imageSrc="https://storage.googleapis.com/webild/default/templates/marbella/contact/cta-bg.webp"
|
||||
inputs={[
|
||||
{ name: "name", type: "text", placeholder: "Your name" },
|
||||
{ name: "email", type: "email", placeholder: "Your email" },
|
||||
]}
|
||||
textarea={{ name: "message", placeholder: "Tell us about your dream property...", rows: 4 }}
|
||||
buttonText="Send Message"
|
||||
footerText="Prefer to talk? Book a private tour."
|
||||
footerLink={{ text: "Email Us", href: "mailto:hello@lecercle.com", imageSrc: "https://storage.googleapis.com/webild/default/templates/marbella/contact/avatar.webp" }}
|
||||
/>
|
||||
</div>
|
||||
<ContactSection />
|
||||
|
||||
|
||||
<GallerySection />
|
||||
<KartScrollerSection />
|
||||
</StyleProvider>
|
||||
);
|
||||
}
|
||||
|
||||
94
src/pages/HomePage/sections/About.tsx
Normal file
94
src/pages/HomePage/sections/About.tsx
Normal file
@@ -0,0 +1,94 @@
|
||||
/* eslint-disable */
|
||||
// @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";
|
||||
|
||||
type AboutTextFillProps = {
|
||||
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>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<section
|
||||
ref={sectionRef}
|
||||
aria-label="About section"
|
||||
className="relative py-32 md:py-48 overflow-hidden"
|
||||
>
|
||||
<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>
|
||||
)}
|
||||
|
||||
<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>
|
||||
);
|
||||
}
|
||||
21
src/pages/HomePage/sections/Contact.tsx
Normal file
21
src/pages/HomePage/sections/Contact.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
// AUTO-GENERATED by per-section-migrate. Edit freely — Bob will treat this
|
||||
// file as the canonical source for the "contact" section.
|
||||
|
||||
import React from 'react';
|
||||
import ContactParallaxCard from "@/components/sections/contact/ContactParallaxCard";
|
||||
|
||||
export default function ContactSection(): React.JSX.Element {
|
||||
return (
|
||||
<div id="contact" data-section="contact">
|
||||
<ContactParallaxCard
|
||||
title="Kontaktujte ma"
|
||||
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"}]}
|
||||
textarea={{"placeholder":"Vaša správa...","name":"message","rows":4}}
|
||||
buttonText="Odoslať správu"
|
||||
footerText="Máte záujem o spoluprácu? Ozvite sa mi."
|
||||
footerLink={{"href":"mailto:kontakt@samueluvacek.sk","imageSrc":"https://storage.googleapis.com/webild/default/templates/racing/contact/avatar.webp","text":"Napíšte mi"}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
83
src/pages/HomePage/sections/Gallery.tsx
Normal file
83
src/pages/HomePage/sections/Gallery.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
20
src/pages/HomePage/sections/Hero.tsx
Normal file
20
src/pages/HomePage/sections/Hero.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
// Created by add_section_from_catalog (HeroOverlay).
|
||||
|
||||
import React from 'react';
|
||||
import HeroOverlay from '@/components/sections/hero/HeroOverlay';
|
||||
|
||||
export default function HeroSection(): React.JSX.Element {
|
||||
return (
|
||||
<div data-webild-section="hero" data-section="hero" id="hero">
|
||||
<HeroOverlay
|
||||
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"}}
|
||||
tag="Samuel Uváček Racing"
|
||||
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>
|
||||
);
|
||||
}
|
||||
35
src/pages/HomePage/sections/KartScroller.tsx
Normal file
35
src/pages/HomePage/sections/KartScroller.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user