feat: replace BannerFactory with BannerSection for improved banner handling in Layout and Banners components

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Marco Pedone 2026-04-30 15:40:33 +02:00
parent a0bb309f16
commit 95e06b7e9e
2 changed files with 75 additions and 61 deletions

View file

@ -5,7 +5,7 @@ import {
SIDEBAR_COOKIE_NAME,
Sidebar,
} from "~/components/area-riservata/sidebar";
import { BannerFactory } from "~/components/banners";
import { BannerSection } from "~/components/banners";
import { Footer } from "~/components/footer";
import { LoadingPage } from "~/components/loading";
import { SiteHeader } from "~/components/navbar/site-header";
@ -16,7 +16,6 @@ import {
useSession,
} from "~/providers/SessionProvider";
import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api";
import { UserViewHeader } from "./area-riservata/userViewHeader";
interface Props {
@ -33,18 +32,16 @@ export const Layout = ({
containerClassName,
footerClassName,
}: Props) => {
const { data: bannerData } = api.banners.getBannerData.useQuery({
area_riservata: false,
});
return (
<div className={cn("flex min-h-screen w-full flex-col", bodyClassName)}>
<div
className={cn(
"relative flex min-h-screen w-full flex-col",
bodyClassName,
)}
>
<SiteHeader />
{bannerData?.map((banner) => (
<div key={`banner-elem-${banner.idbanner}`}>
{BannerFactory(banner)}
</div>
))}
<BannerSection area_riservata={false} />
<main
className={cn("flex h-full flex-1 grow flex-col", containerClassName)}
>
@ -69,9 +66,6 @@ export const AreaRiservataLayout = ({
bodyClassName,
containerClassName,
}: AreaRiservataLayoutProps) => {
const { data: bannerData } = api.banners.getBannerData.useQuery({
area_riservata: true,
});
const { status, user } = useSession();
if (!ignoreSessionCheck) {
if (status === "LOADING")
@ -151,11 +145,7 @@ export const AreaRiservataLayout = ({
)}
>
<SiteHeader />
{bannerData?.map((banner) => (
<div key={`banner-elem-${banner.idbanner}`}>
{BannerFactory(banner)}
</div>
))}
<BannerSection area_riservata={true} />
<main
className={cn("flex h-full flex-1 overflow-auto", containerClassName)}
>

View file

@ -6,9 +6,30 @@ 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";
import { api } from "~/utils/api";
const defaultHideDuration = 365; // days
export const BannerFactory = (bannerData: Banners) => {
export const BannerSection = ({
area_riservata,
}: {
area_riservata: boolean;
}) => {
const { data: bannerData } = api.banners.getBannerData.useQuery({
area_riservata,
});
if (!bannerData) return null;
return (
<div className="w-full space-y-1 p-1">
{bannerData.map((banner) => (
<div key={`banner-elem-${banner.idbanner}`}>
{BannerFactory(banner)}
</div>
))}
</div>
);
};
const BannerFactory = (bannerData: Banners) => {
const NEW_BANNER_KEY = `bannercookie_${bannerData.idbanner}`;
let bgColor = "";
@ -68,49 +89,52 @@ export const BannerFactory = (bannerData: Banners) => {
return null;
}
return (
<div className={cn("bg-indigo-600", bgColor)}>
<div className="mx-auto flex max-w-7xl items-start justify-between px-4 py-3 text-white sm:items-center md:px-8">
<div className="flex flex-1 items-start justify-center gap-x-4 sm:items-center">
<div
className={cn(
"flex flex-none items-center justify-center rounded-full bg-indigo-800 p-1.5 px-4 font-medium text-sm",
accentColor,
)}
>
{bannerData.titolo}{" "}
</div>
<p className="flex gap-2 p-2 font-medium">
<span> {bannerData.testo}</span>
{bannerData.has_cta &&
bannerData.cta_href &&
bannerData.cta_icon && (
<Link
className="inline-flex items-center gap-x-1 font-semibold underline duration-150 hover:text-indigo-100"
href={bannerData.cta_href}
>
{bannerData.cta_text}
<IconMatrix
className="size-4"
type={bannerData.cta_icon as IconType}
/>
</Link>
)}
</p>
<div
className={cn(
"mx-auto flex max-w-7xl items-center justify-between rounded-md bg-indigo-600 py-1 text-sm text-white sm:items-center sm:text-base",
bgColor,
)}
>
<div className="flex flex-1 items-center justify-center gap-x-2 px-2 sm:gap-x-4">
<div
className={cn(
"flex flex-none items-center justify-center rounded-full bg-indigo-800 px-2 py-0.5 font-medium sm:px-3 sm:py-1",
accentColor,
)}
>
{bannerData.titolo}{" "}
</div>
{bannerData.is_unskippable === false && (
<button
className={cn(
"rounded-lg p-2 ring-offset-2 duration-150 hover:bg-indigo-500 focus:ring",
closeHoverColor,
<p className="flex gap-2 p-1 font-medium">
<span className="break-all"> {bannerData.testo}</span>
{bannerData.has_cta &&
bannerData.cta_href &&
bannerData.cta_icon && (
<Link
className="inline-flex items-center gap-x-1 font-semibold underline duration-150 hover:text-indigo-100"
href={bannerData.cta_href}
>
{bannerData.cta_text}
<IconMatrix
className="size-4"
type={bannerData.cta_icon as IconType}
/>
</Link>
)}
onClick={onClick}
type="button"
>
<X className="size-5" />
</button>
)}
</p>
</div>
{bannerData.is_unskippable === false && (
<button
className={cn(
"rounded-lg p-2 ring-offset-2 duration-150 hover:bg-indigo-500 focus:ring",
closeHoverColor,
)}
onClick={onClick}
type="button"
>
<X className="size-5" />
</button>
)}
</div>
);
};