Merge version_4_1782901181918 into main #6
@@ -1,105 +1,28 @@
|
||||
import HeroBillboard from '@/components/sections/hero/HeroBillboard';
|
||||
import MetricsFeatureCards from '@/components/sections/metrics/MetricsFeatureCards';
|
||||
import TestimonialMarqueeOverlayCards from '@/components/sections/testimonial/TestimonialMarqueeOverlayCards';
|
||||
import TestimonialTrustCard from '@/components/sections/testimonial/TestimonialTrustCard';
|
||||
import AboutTestimonialParallax from '@/components/sections/about/AboutTestimonialParallax';
|
||||
import SectionErrorBoundary from "@/components/ui/SectionErrorBoundary";
|
||||
// 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.
|
||||
|
||||
export default function HomePage() {
|
||||
import React from 'react';
|
||||
import HeroSection from './HomePage/sections/Hero';
|
||||
import TestimonialsSection from './HomePage/sections/Testimonials';
|
||||
import MetricsSection from './HomePage/sections/Metrics';
|
||||
import TestimonialSection from './HomePage/sections/Testimonial';
|
||||
import AboutSection from './HomePage/sections/About';
|
||||
|
||||
export default function HomePage(): React.JSX.Element {
|
||||
return (
|
||||
<>
|
||||
<div id="hero" data-section="hero">
|
||||
<SectionErrorBoundary name="hero">
|
||||
<HeroBillboard
|
||||
title="Forvandl byggeplads til premium medieflade."
|
||||
description="Urban OOH forbinder bygherrer med de stærkeste storformat-placeringer i Danmark."
|
||||
primaryButton={{
|
||||
text: "For bygherrer", href: "/bygherrer"}}
|
||||
secondaryButton={{
|
||||
text: "For annoncører", href: "/annoncoerer"}}
|
||||
imageSrc="https://storage.googleapis.com/webild/users/user_3FrMethFYMocawsrxMGgPOOqDSP/uploaded-1782900317840-e2y1mi42.jpg"
|
||||
textAnimation="fade"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
<>
|
||||
<HeroSection />
|
||||
|
||||
<div id="testimonials" data-section="testimonials">
|
||||
<SectionErrorBoundary name="testimonials">
|
||||
<TestimonialMarqueeOverlayCards
|
||||
tag="Cases"
|
||||
title="Vi skaber værdi for alle parter."
|
||||
description="Hør hvad bygherrer og mediebureauer siger."
|
||||
testimonials={[
|
||||
{
|
||||
name: "Magnus Ebbesen", role: "Client Manager", company: "Dentsu", rating: 5,
|
||||
imageSrc: "https://images.unsplash.com/photo-1560250097-0b93528c311a?auto=format&fit=crop&q=80&w=256&h=256"},
|
||||
{
|
||||
name: "Christian Petersson", role: "Project Development Manager", company: "Urban Partners", rating: 5,
|
||||
imageSrc: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?auto=format&fit=crop&q=80&w=256&h=256"},
|
||||
]}
|
||||
textAnimation="fade"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
<TestimonialsSection />
|
||||
|
||||
<div id="metrics" data-section="metrics">
|
||||
<SectionErrorBoundary name="metrics">
|
||||
<MetricsFeatureCards
|
||||
tag="Resultater"
|
||||
title="Synlighed der flytter noget."
|
||||
description="Vi skaber markant impact for brands i byrummet."
|
||||
metrics={[
|
||||
{
|
||||
value: "200k+", title: "Månedlige visninger", features: [
|
||||
"Høj trafik flow", "Unik lokation", "Primetid eksponering"],
|
||||
},
|
||||
{
|
||||
value: "98%", title: "Kampagne recall", features: [
|
||||
"Høj gennemslagskraft", "Kreativ frihed", "Premium format"],
|
||||
},
|
||||
{
|
||||
value: "15+", title: "Nye lokationer", features: [
|
||||
"Vækst i byer", "Strategisk valg", "Bygherre fokus"],
|
||||
},
|
||||
]}
|
||||
textAnimation="slide-up"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
<MetricsSection />
|
||||
|
||||
<div id="testimonial" data-section="testimonial">
|
||||
<SectionErrorBoundary name="testimonial">
|
||||
<TestimonialTrustCard
|
||||
quote="Urban OOH har transformeret vores byggeplads til en moderne medieflade. En professionel proces fra start til slut."
|
||||
rating={5}
|
||||
author="Jesper Vester, Vester Byg"
|
||||
avatars={[
|
||||
{
|
||||
name: "Anders", imageSrc: "http://img.b2bpic.net/free-photo/male-cool-influencer-hosting-live-presentation-with-hands-free-microphone_482257-126542.jpg"},
|
||||
{
|
||||
name: "Mette", imageSrc: "http://img.b2bpic.net/free-photo/young-stylish-woman-exploring-city_23-2149186681.jpg"},
|
||||
{
|
||||
name: "Søren", imageSrc: "http://img.b2bpic.net/free-photo/young-japanese-woman-outdoors_23-2149010153.jpg"},
|
||||
{
|
||||
name: "Trine", imageSrc: "http://img.b2bpic.net/free-photo/young-adult-traveling-london_23-2149259455.jpg"},
|
||||
]}
|
||||
textAnimation="fade"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
<TestimonialSection />
|
||||
|
||||
<div id="about" data-section="about">
|
||||
<SectionErrorBoundary name="about">
|
||||
<AboutTestimonialParallax
|
||||
tag="Om os"
|
||||
quote="Vi bygger bro mellem byggepladser og brands."
|
||||
author="Urban OOH Team"
|
||||
role="Media Partner"
|
||||
videoSrc="https://storage.googleapis.com/webild/default/video-placeholder.mp4"
|
||||
textAnimation="fade"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
<AboutSection />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
23
src/pages/HomePage/sections/About.tsx
Normal file
23
src/pages/HomePage/sections/About.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
// AUTO-GENERATED by per-section-migrate. Edit freely — Bob will treat this
|
||||
// file as the canonical source for the "about" section.
|
||||
|
||||
import React from 'react';
|
||||
import AboutTestimonialParallax from '@/components/sections/about/AboutTestimonialParallax';
|
||||
import SectionErrorBoundary from "@/components/ui/SectionErrorBoundary";
|
||||
|
||||
export default function AboutSection(): React.JSX.Element {
|
||||
return (
|
||||
<div id="about" data-section="about">
|
||||
<SectionErrorBoundary name="about">
|
||||
<AboutTestimonialParallax
|
||||
tag="Om os"
|
||||
quote="Vi bygger bro mellem byggepladser og brands."
|
||||
author="Urban OOH Team"
|
||||
role="Media Partner"
|
||||
videoSrc="https://storage.googleapis.com/webild/default/video-placeholder.mp4"
|
||||
textAnimation="fade"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
25
src/pages/HomePage/sections/Hero.tsx
Normal file
25
src/pages/HomePage/sections/Hero.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
// AUTO-GENERATED by per-section-migrate. Edit freely — Bob will treat this
|
||||
// file as the canonical source for the "hero" section.
|
||||
|
||||
import React from 'react';
|
||||
import HeroBillboard from '@/components/sections/hero/HeroBillboard';
|
||||
import SectionErrorBoundary from "@/components/ui/SectionErrorBoundary";
|
||||
|
||||
export default function HeroSection(): React.JSX.Element {
|
||||
return (
|
||||
<div id="hero" data-section="hero">
|
||||
<SectionErrorBoundary name="hero">
|
||||
<HeroBillboard
|
||||
title="Forvandl byggeplads til premium medieflade."
|
||||
description="Urban OOH forbinder bygherrer med de stærkeste storformat-placeringer i Danmark."
|
||||
primaryButton={{
|
||||
text: "For bygherrer", href: "/bygherrer"}}
|
||||
secondaryButton={{
|
||||
text: "For annoncører", href: "/annoncoerer"}}
|
||||
imageSrc="https://storage.googleapis.com/webild/users/user_3FrMethFYMocawsrxMGgPOOqDSP/uploaded-1782900317840-e2y1mi42.jpg"
|
||||
textAnimation="fade"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
35
src/pages/HomePage/sections/Metrics.tsx
Normal file
35
src/pages/HomePage/sections/Metrics.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
// AUTO-GENERATED by per-section-migrate. Edit freely — Bob will treat this
|
||||
// file as the canonical source for the "metrics" section.
|
||||
|
||||
import React from 'react';
|
||||
import MetricsFeatureCards from '@/components/sections/metrics/MetricsFeatureCards';
|
||||
import SectionErrorBoundary from "@/components/ui/SectionErrorBoundary";
|
||||
|
||||
export default function MetricsSection(): React.JSX.Element {
|
||||
return (
|
||||
<div id="metrics" data-section="metrics">
|
||||
<SectionErrorBoundary name="metrics">
|
||||
<MetricsFeatureCards
|
||||
tag="Resultater"
|
||||
title="Synlighed der flytter noget."
|
||||
description="Vi skaber markant impact for brands i byrummet."
|
||||
metrics={[
|
||||
{
|
||||
value: "200k+", title: "Månedlige visninger", features: [
|
||||
"Høj trafik flow", "Unik lokation", "Primetid eksponering"],
|
||||
},
|
||||
{
|
||||
value: "98%", title: "Kampagne recall", features: [
|
||||
"Høj gennemslagskraft", "Kreativ frihed", "Premium format"],
|
||||
},
|
||||
{
|
||||
value: "15+", title: "Nye lokationer", features: [
|
||||
"Vækst i byer", "Strategisk valg", "Bygherre fokus"],
|
||||
},
|
||||
]}
|
||||
textAnimation="slide-up"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
31
src/pages/HomePage/sections/Testimonial.tsx
Normal file
31
src/pages/HomePage/sections/Testimonial.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
// AUTO-GENERATED by per-section-migrate. Edit freely — Bob will treat this
|
||||
// file as the canonical source for the "testimonial" section.
|
||||
|
||||
import React from 'react';
|
||||
import TestimonialTrustCard from '@/components/sections/testimonial/TestimonialTrustCard';
|
||||
import SectionErrorBoundary from "@/components/ui/SectionErrorBoundary";
|
||||
|
||||
export default function TestimonialSection(): React.JSX.Element {
|
||||
return (
|
||||
<div id="testimonial" data-section="testimonial">
|
||||
<SectionErrorBoundary name="testimonial">
|
||||
<TestimonialTrustCard
|
||||
quote="Urban OOH har transformeret vores byggeplads til en moderne medieflade. En professionel proces fra start til slut."
|
||||
rating={5}
|
||||
author="Jesper Vester, Vester Byg"
|
||||
avatars={[
|
||||
{
|
||||
name: "Anders", imageSrc: "http://img.b2bpic.net/free-photo/male-cool-influencer-hosting-live-presentation-with-hands-free-microphone_482257-126542.jpg"},
|
||||
{
|
||||
name: "Mette", imageSrc: "http://img.b2bpic.net/free-photo/young-stylish-woman-exploring-city_23-2149186681.jpg"},
|
||||
{
|
||||
name: "Søren", imageSrc: "http://img.b2bpic.net/free-photo/young-japanese-woman-outdoors_23-2149010153.jpg"},
|
||||
{
|
||||
name: "Trine", imageSrc: "http://img.b2bpic.net/free-photo/young-adult-traveling-london_23-2149259455.jpg"},
|
||||
]}
|
||||
textAnimation="fade"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
129
src/pages/HomePage/sections/Testimonials.tsx
Normal file
129
src/pages/HomePage/sections/Testimonials.tsx
Normal file
@@ -0,0 +1,129 @@
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck — generated by catalog-eject; runtime-correct but TS strict-mode false-positives on inlined catalog body
|
||||
import { Star } from "lucide-react";
|
||||
import { cls } from "@/lib/utils";
|
||||
import Button from "@/components/ui/Button";
|
||||
import TextAnimation from "@/components/ui/TextAnimation";
|
||||
import ImageOrVideo from "@/components/ui/ImageOrVideo";
|
||||
import ScrollReveal from "@/components/ui/ScrollReveal";
|
||||
|
||||
const testimonials = [
|
||||
{
|
||||
name: "Magnus Ebbesen",
|
||||
role: "Client Manager",
|
||||
company: "Dentsu",
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
name: "Christian Petersson",
|
||||
role: "Project Development Manager",
|
||||
company: "Urban Partners",
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
name: "Søren Haunstrup",
|
||||
role: "Administerende direktør",
|
||||
company: "S2 consult",
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
name: "Kasper Højmann",
|
||||
role: "Brand marketing manager",
|
||||
company: "HISENSE",
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
name: "Stephan Koldbjerg",
|
||||
role: "Media & Marketing manager",
|
||||
company: "LIDL",
|
||||
rating: 5
|
||||
}
|
||||
];
|
||||
|
||||
type Testimonial = {
|
||||
name: string;
|
||||
role: string;
|
||||
company: string;
|
||||
rating: number;
|
||||
imageSrc?: string;
|
||||
videoSrc?: string;
|
||||
};
|
||||
|
||||
const TestimonialsInline = () => {
|
||||
const duplicated = [...testimonials, ...testimonials, ...testimonials, ...testimonials];
|
||||
|
||||
return (
|
||||
<section aria-label="Testimonials section" className="pt-20 pb-10">
|
||||
<div className="flex flex-col gap-8 md:gap-10">
|
||||
<div className="flex flex-col items-center w-content-width mx-auto gap-2">
|
||||
<div className="px-3 py-1 mb-1 text-sm card rounded w-fit">
|
||||
<p>{"Cases"}</p>
|
||||
</div>
|
||||
|
||||
<TextAnimation
|
||||
text={"Vi skaber værdi for alle parter."}
|
||||
variant={"fade"}
|
||||
gradientText={true}
|
||||
tag="h2"
|
||||
className="md:max-w-8/10 text-6xl 2xl:text-7xl leading-[1.15] font-semibold text-center text-balance"
|
||||
/>
|
||||
|
||||
<TextAnimation
|
||||
text={"Hør hvad bygherrer og mediebureauer siger."}
|
||||
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>
|
||||
|
||||
<ScrollReveal variant="slide-up">
|
||||
<div className="w-content-width mx-auto overflow-hidden mask-fade-x-medium">
|
||||
<div className="flex w-max animate-marquee-horizontal" style={{ animationDuration: "60s" }}>
|
||||
{duplicated.map((testimonial, i) => (
|
||||
<div key={i} className="relative shrink-0 w-60 md:w-75 2xl:w-80 aspect-4/5 mb-10 mr-3 md:mr-5 rounded overflow-hidden card">
|
||||
<div className="absolute inset-x-4 bottom-4 xl:inset-x-5 xl:bottom-5 2xl:inset-x-6 2xl:bottom-6 flex flex-col gap-1 xl:gap-2 2xl:gap-3 p-4 xl:p-5 2xl:p-6">
|
||||
<div className="flex gap-1.5 mb-1">
|
||||
{Array.from({ length: 5 }).map((_, index) => (
|
||||
<Star
|
||||
key={index}
|
||||
className={cls(
|
||||
"size-5 text-accent",
|
||||
index < testimonial.rating ? "fill-accent" : "fill-transparent"
|
||||
)}
|
||||
strokeWidth={1.5}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<span className="text-2xl font-semibold leading-snug truncate">{testimonial.name}</span>
|
||||
|
||||
<div className="flex flex-col">
|
||||
<span className="text-base leading-snug truncate">{testimonial.role}</span>
|
||||
<span className="text-base leading-snug truncate">{testimonial.company}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</ScrollReveal>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default function TestimonialsSection() {
|
||||
return (
|
||||
<div data-webild-section="testimonials" id="testimonials">
|
||||
<TestimonialsInline />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user