feat: add AnniversaryBanner component with visibility animation and update Home page layout
This commit is contained in:
parent
d306548209
commit
c2e8d68b47
4 changed files with 129 additions and 11 deletions
|
|
@ -2,7 +2,7 @@ import { getCookie, setCookie } from "cookies-next/client";
|
|||
import { add } from "date-fns";
|
||||
import { X } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { type MouseEvent, useEffect, useState } from "react";
|
||||
import { type MouseEvent, useEffect, useRef, useState } from "react";
|
||||
import { IconMatrix, type IconType } from "~/components/IconComponents";
|
||||
import { cn } from "~/lib/utils";
|
||||
import type { Banners } from "~/schemas/public/Banners";
|
||||
|
|
@ -116,3 +116,119 @@ export const BannerFactory = (bannerData: Banners) => {
|
|||
};
|
||||
return <NewBanner />;
|
||||
};
|
||||
|
||||
export function AnniversaryBanner() {
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
const bannerRef = useRef<HTMLDivElement>(null);
|
||||
const fundingDate = new Date("2000-08-01");
|
||||
const currentDate = new Date();
|
||||
const yearsOfExperience =
|
||||
currentDate.getFullYear() - fundingDate.getFullYear();
|
||||
|
||||
useEffect(() => {
|
||||
const observer = new IntersectionObserver(
|
||||
([entry]) => {
|
||||
if (entry?.isIntersecting) {
|
||||
setIsVisible(true);
|
||||
}
|
||||
},
|
||||
{ threshold: 0.3 },
|
||||
);
|
||||
|
||||
if (bannerRef.current) {
|
||||
observer.observe(bannerRef.current);
|
||||
}
|
||||
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="relative mx-auto w-full max-w-5xl overflow-hidden rounded-lg bg-secondary"
|
||||
ref={bannerRef}
|
||||
>
|
||||
{/* Decorative background "25" */}
|
||||
<div
|
||||
className={`absolute top-1/2 -right-8 -translate-y-1/2 font-bold text-[8rem] text-primary/10 leading-none transition-all duration-1000 md:text-[12rem] ${
|
||||
isVisible ? "translate-x-0 opacity-100" : "translate-x-16 opacity-0"
|
||||
}`}
|
||||
>
|
||||
{yearsOfExperience}
|
||||
</div>
|
||||
|
||||
{/* Main content - horizontal layout */}
|
||||
<div className="relative z-10 mx-auto flex max-w-7xl flex-col items-center justify-between gap-6 px-6 py-6 text-primary md:flex-row md:gap-8 md:px-8 md:py-8">
|
||||
{/* Left: Badge + Number */}
|
||||
<div
|
||||
className={`flex items-center gap-4 transition-all delay-100 duration-700 md:gap-6 ${
|
||||
isVisible ? "translate-x-0 opacity-100" : "-translate-x-8 opacity-0"
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-px w-6 bg-primary" />
|
||||
<span className="whitespace-nowrap font-medium text-[10px] uppercase tracking-[0.2em] md:text-xs">
|
||||
Da più di
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-baseline gap-2">
|
||||
<span className="font-bold text-5xl leading-none tracking-tight md:text-6xl lg:text-7xl">
|
||||
{yearsOfExperience}
|
||||
</span>
|
||||
<span className="font-light text-sm uppercase tracking-[0.2em] md:text-base">
|
||||
Anni
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Center: Tagline */}
|
||||
<div
|
||||
className={`flex-1 text-center text-primary transition-all delay-300 duration-700 md:text-left ${
|
||||
isVisible ? "translate-y-0 opacity-100" : "translate-y-4 opacity-0"
|
||||
}`}
|
||||
>
|
||||
<p className="font-light text-sm md:text-base lg:text-lg">
|
||||
Un quarto di secolo di{" "}
|
||||
<span className="font-semibold">eccellenza</span>,{" "}
|
||||
<span className="font-semibold">innovazione</span>, e{" "}
|
||||
<span className="font-semibold">fiducia</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Right: Mini stats */}
|
||||
<div
|
||||
className={`flex items-center gap-6 transition-all delay-500 duration-700 md:gap-8 lg:gap-10 ${
|
||||
isVisible ? "translate-x-0 opacity-100" : "translate-x-8 opacity-0"
|
||||
}`}
|
||||
>
|
||||
<Stat label="Clienti" value="7500+" />
|
||||
<Stat label="Affitti" value="10K+" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Accent lines */}
|
||||
<div
|
||||
className={`absolute bottom-0 left-0 h-1 bg-primary transition-all delay-700 duration-1000 ${
|
||||
isVisible ? "w-24 md:w-32" : "w-0"
|
||||
}`}
|
||||
/>
|
||||
<div
|
||||
className={`absolute top-0 right-0 h-1 bg-primary transition-all delay-700 duration-1000 ${
|
||||
isVisible ? "w-24 md:w-32" : "w-0"
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Stat({ value, label }: { value: string; label: string }) {
|
||||
return (
|
||||
<div className="flex flex-col items-center gap-0.5">
|
||||
<span className="font-bold text-primary text-xl md:text-2xl">
|
||||
{value}
|
||||
</span>
|
||||
<span className="font-medium text-primary text-xs uppercase tracking-wider">
|
||||
{label}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export const FrequentSearches = () => {
|
|||
const { locale } = useTranslation();
|
||||
const t = locale === "en" ? en : it;
|
||||
return (
|
||||
<Card className="mx-auto mb-4 max-w-4xl gap-4 border-0 bg-secondary shadow-none">
|
||||
<Card className="mx-auto w-full max-w-5xl gap-4 border-0 bg-secondary shadow-none">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-center font-bold text-3xl sm:text-2xl">
|
||||
{t.title}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ export function MobileNav({
|
|||
}: MobileNavProps) {
|
||||
const session = useSession();
|
||||
const { t } = useTranslation();
|
||||
const verySmallScreen = useMediaQuery("(max-width: 320px)");
|
||||
const verySmallScreen = useMediaQuery("(max-width: 280px)");
|
||||
return (
|
||||
<>
|
||||
<Sheet onOpenChange={setOpen} open={open}>
|
||||
|
|
@ -127,7 +127,7 @@ export function MobileNav({
|
|||
</Sheet>
|
||||
<Link
|
||||
aria-label="mainNavLink"
|
||||
className="ml-3 flex shrink-0 items-center md:hidden"
|
||||
className="flex shrink-0 items-center md:hidden"
|
||||
href="/"
|
||||
>
|
||||
{verySmallScreen ? (
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import type { NextPage } from "next";
|
|||
import Head from "next/head";
|
||||
import Link from "next/link";
|
||||
import { AccordionComp } from "~/components/accordionComp";
|
||||
import { AnniversaryBanner } from "~/components/banners";
|
||||
import { CodiceBox } from "~/components/codiceRicerca";
|
||||
import { ComeFunziona } from "~/components/expand_guida";
|
||||
import { FrequentSearches } from "~/components/frequent_searches";
|
||||
import { PricingChoice } from "~/components/prezzi";
|
||||
import { HeroSvg, LogoSvg } from "~/components/svgs";
|
||||
import { env } from "~/env";
|
||||
|
|
@ -42,8 +42,8 @@ const Home: NextPage = () => {
|
|||
<div className="mx-5 mt-0 mb-12 sm:mt-8">
|
||||
<main className="mx-auto mb-4 max-w-8xl space-y-5 lg:mb-20">
|
||||
<div className="flex flex-col items-center justify-center lg:flex-row lg:justify-around">
|
||||
<div className="-mt-2 xs:mt-5 flex h-76 max-w-full items-center justify-center min-[22rem]:h-92 min-[25rem]:h-104">
|
||||
<div className="flex scale-50 xxs:scale-[0.6] items-center justify-center drop-shadow-xl sm:scale-100 md:max-h-96 min-[22rem]:scale-[0.7] min-[25rem]:scale-[0.8]">
|
||||
<div className="-mt-2 xs:mt-5 flex h-68 max-w-full items-center justify-center min-[22rem]:h-76 min-[25rem]:h-92 min-[27rem]:h-104">
|
||||
<div className="flex scale-50 xxs:scale-[0.5] items-center justify-center drop-shadow-xl sm:scale-100 md:max-h-92 min-[22rem]:scale-[0.58] min-[25rem]:scale-[0.7]">
|
||||
<HeroSvg />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -51,13 +51,15 @@ const Home: NextPage = () => {
|
|||
<TrovaCasaCTA testi={t} />
|
||||
</div>
|
||||
</main>
|
||||
<div className="w-full space-y-10 md:space-y-20">
|
||||
<FrequentSearches />
|
||||
<div className="mx-auto max-w-4xl px-1 sm:px-0">
|
||||
|
||||
<div className="flex w-full flex-col gap-y-4 md:gap-y-6">
|
||||
<AnniversaryBanner />
|
||||
{/* <FrequentSearches /> */}
|
||||
<div className="mx-auto w-full max-w-5xl">
|
||||
<ComeFunziona />
|
||||
</div>
|
||||
<AccordionComp
|
||||
className="mb-4 max-w-4xl py-4 md:py-8"
|
||||
className="w-full max-w-5xl"
|
||||
texts={t.index.accordion_minifaq}
|
||||
/>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue