Refactor TypeScript schemas and enums for consistency and readability

- Updated enum definitions in PaymentStatusEnum and TipologiaPosizioneEnum to use single quotes and consistent formatting.
- Refactored Payments, Prezziario, Ratelimiter, Servizio, and other schema files to ensure consistent indentation and formatting.
- Added `updated_at` field to various queries in interests and servizio controllers.
- Removed unused imageCache utility file.
This commit is contained in:
Marco Pedone 2025-10-21 18:42:03 +02:00
parent 40076ce48a
commit 8fe0b6636d
46 changed files with 451 additions and 890 deletions

View file

@ -89,7 +89,8 @@ func AnnunciInsert(annunci typesdefs.AnnunciParsed, resetAllBeforeUpdate bool) e
og_url = $48, og_url = $48,
disponibile_da = $49, disponibile_da = $49,
permanenza = $50, permanenza = $50,
persone = $51 persone = $51,
updated_at = NOW()
WHERE codice = $47 WHERE codice = $47
`, annuncio.Locatore, annuncio.Numero, annuncio.Idlocatore, `, annuncio.Locatore, annuncio.Numero, annuncio.Idlocatore,
annuncio.Email, annuncio.Creato_il, annuncio.Modificato_il, annuncio.Email, annuncio.Creato_il, annuncio.Modificato_il,
@ -157,9 +158,10 @@ func AnnunciInsert(annunci typesdefs.AnnunciParsed, resetAllBeforeUpdate bool) e
og_url, og_url,
disponibile_da, disponibile_da,
permanenza, permanenza,
persone persone,
updated_at
) )
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, $40, $41, $42, $43, $44, $45, $46, $47, $48, $49, $50, $51) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, $40, $41, $42, $43, $44, $45, $46, $47, $48, $49, $50, $51, NOW())
`, annuncio.Locatore, annuncio.Numero, annuncio.Idlocatore, `, annuncio.Locatore, annuncio.Numero, annuncio.Idlocatore,
annuncio.Email, annuncio.Creato_il, annuncio.Modificato_il, annuncio.Email, annuncio.Creato_il, annuncio.Modificato_il,
annuncio.Indirizzo, annuncio.Civico, annuncio.Comune, annuncio.Cap, annuncio.Indirizzo, annuncio.Civico, annuncio.Comune, annuncio.Cap,

View file

@ -21,10 +21,6 @@ async function createNextConfig(): Promise<NextConfig> {
// esmExternals: "loose", // This if react-pdf gives compilation issues // esmExternals: "loose", // This if react-pdf gives compilation issues
}, },
env: {
NEXT_PUBLIC_BUILD_ID: Math.random().toString(36).slice(2, 8),
},
devIndicators: false, devIndicators: false,
headers: async () => { headers: async () => {
return [ return [

View file

@ -27,6 +27,7 @@ export const AnnunciGrid = ({ pagedata }: { pagedata: AnnuncioRicerca[] }) => {
titolo_en: annuncio.titolo_en, titolo_en: annuncio.titolo_en,
titolo_it: annuncio.titolo_it, titolo_it: annuncio.titolo_it,
})} })}
updated_at={annuncio.updated_at}
videos={annuncio.url_video || undefined} videos={annuncio.url_video || undefined}
/> />
))} ))}

View file

@ -16,7 +16,6 @@ import { useTranslation } from "~/providers/I18nProvider";
import { useRicerca } from "~/providers/RicercaProvider"; import { useRicerca } from "~/providers/RicercaProvider";
import type { AnnuncioRicercaWPosition } from "~/server/controllers/annunci.controller"; import type { AnnuncioRicercaWPosition } from "~/server/controllers/annunci.controller";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { CacheKey } from "~/utils/imageCache";
const MapComp = dynamic(() => import("~/components/map/Map"), { const MapComp = dynamic(() => import("~/components/map/Map"), {
ssr: false, ssr: false,
@ -124,7 +123,7 @@ const SelectedComp = memo(
alt="a" alt="a"
className="size-24 rounded-md object-cover sm:size-40" className="size-24 rounded-md object-cover sm:size-40"
height={500} height={500}
src={`${selected.url_immagini[0]}?${CacheKey}`} src={`${selected.url_immagini[0]}?${selected.updated_at?.toString() || new Date().toString()}`}
width={500} width={500}
/> />
) : ( ) : (

View file

@ -20,7 +20,7 @@ import {
import { camereTesti, handleConsegna } from "~/lib/annuncio_details"; import { camereTesti, handleConsegna } from "~/lib/annuncio_details";
import { cn, formatCurrency } from "~/lib/utils"; import { cn, formatCurrency } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider"; import { useTranslation } from "~/providers/I18nProvider";
import { CacheKey } from "~/utils/imageCache";
import { VideoPlayer } from "./videoPlayer"; import { VideoPlayer } from "./videoPlayer";
type CardAnnuncioProps = { type CardAnnuncioProps = {
@ -38,6 +38,7 @@ type CardAnnuncioProps = {
stato: string | null; stato: string | null;
className?: string; className?: string;
videos?: string[] | undefined; videos?: string[] | undefined;
updated_at: Date | null;
}; };
export const CardAnnuncio = ({ export const CardAnnuncio = ({
@ -55,6 +56,7 @@ export const CardAnnuncio = ({
stato, stato,
className, className,
videos, videos,
updated_at,
}: CardAnnuncioProps) => { }: CardAnnuncioProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -93,7 +95,7 @@ export const CardAnnuncio = ({
} }
height={400} height={400}
priority={idx === 0} priority={idx === 0}
src={`${img}?${CacheKey}`} src={`${img}?${updated_at?.toString() || new Date().toString()}`}
width={800} width={800}
/> />
</CarouselItem> </CarouselItem>
@ -113,10 +115,11 @@ export const CardAnnuncio = ({
}} }}
> >
<VideoPlayer <VideoPlayer
cacheKey={updated_at?.toString() || new Date().toString()}
className="h-56" className="h-56"
coverImage={immagini?.[0] ? immagini[0] : ""} coverImage={immagini?.[0] ? immagini[0] : ""}
key={`videoplayer-${idx}`} key={`videoplayer-${idx}`}
videoSrc={`${video}?${CacheKey}`} videoSrc={video}
/> />
</CarouselItem> </CarouselItem>
); );
@ -233,10 +236,12 @@ export const CarouselAnnuncio = ({
single, single,
immagini, immagini,
videos, videos,
updated_at,
}: { }: {
single?: boolean; single?: boolean;
immagini: string[] | null; immagini: string[] | null;
videos: string[] | null; videos: string[] | null;
updated_at: Date | null;
}) => { }) => {
const [openModal, setOpenModal] = useState(false); const [openModal, setOpenModal] = useState(false);
const [idxModal, setIdxModal] = useState(0); const [idxModal, setIdxModal] = useState(0);
@ -269,7 +274,7 @@ export const CarouselAnnuncio = ({
height={400} height={400}
onClick={() => handleOpenModal(idx)} onClick={() => handleOpenModal(idx)}
priority={idx === 0} priority={idx === 0}
src={`${img}?${CacheKey}`} src={`${img}?${updated_at?.toString() || new Date().toString()}`}
width={800} width={800}
/> />
<Maximize2 <Maximize2
@ -294,10 +299,11 @@ export const CarouselAnnuncio = ({
key={`videoplayer-${video}`} key={`videoplayer-${video}`}
> >
<VideoPlayer <VideoPlayer
cacheKey={updated_at?.toString() || new Date().toString()}
className="h-72" className="h-72"
coverImage={immagini?.[0] ? immagini[0] : ""} coverImage={immagini?.[0] ? immagini[0] : ""}
key={`videoplayer-${idx}-${openModal}`} key={`videoplayer-${idx}-${openModal}`}
videoSrc={`${video}?${CacheKey}`} videoSrc={video}
/> />
<Maximize2 <Maximize2
@ -338,7 +344,7 @@ export const CarouselAnnuncio = ({
alt={`carousel-img-${idx}`} alt={`carousel-img-${idx}`}
className="mx-auto h-[90vh] w-full rounded-md object-contain sm:w-[80vw]" className="mx-auto h-[90vh] w-full rounded-md object-contain sm:w-[80vw]"
height={1080} height={1080}
src={`${img}?${CacheKey}`} src={`${img}?${updated_at?.toString() || new Date().toString()}`}
width={1920} width={1920}
/> />
</CarouselItem> </CarouselItem>
@ -354,9 +360,10 @@ export const CarouselAnnuncio = ({
key={`carousel-videoplayer-${video}`} key={`carousel-videoplayer-${video}`}
> >
<VideoPlayer <VideoPlayer
cacheKey={updated_at?.toString() || new Date().toString()}
className="absolute mx-auto h-[90vh] w-full max-w-fit rounded-md object-contain" className="absolute mx-auto h-[90vh] w-full max-w-fit rounded-md object-contain"
coverImage={immagini?.[0] ? immagini[0] : ""} coverImage={immagini?.[0] ? immagini[0] : ""}
videoSrc={`${video}?${CacheKey}`} videoSrc={video}
/> />
</CarouselItem> </CarouselItem>
); );

View file

@ -29,30 +29,8 @@ import { cn, formatCurrency } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider"; import { useTranslation } from "~/providers/I18nProvider";
import { useServizioAnnuncio } from "~/providers/ServizioProvider"; import { useServizioAnnuncio } from "~/providers/ServizioProvider";
import type { Annunci } from "~/schemas/public/Annunci"; import type { Annunci } from "~/schemas/public/Annunci";
import { CacheKey } from "~/utils/imageCache";
export const AnnuncioCard = ({ className }: { className?: string }) => { type AnnuncioData = Pick<
const { data } = useServizioAnnuncio();
return (
<BasicAnnuncioCard
actions={<AnnuncioActions />}
className={className}
data={data}
interactions={<Interactions />}
/>
);
};
export const BasicAnnuncioCard = ({
actions,
interactions,
className,
data,
}: {
actions?: React.ReactNode;
interactions?: React.ReactNode;
className?: string;
data: Pick<
Annunci, Annunci,
| "id" | "id"
| "codice" | "codice"
@ -66,7 +44,33 @@ export const BasicAnnuncioCard = ({
| "consegna" | "consegna"
| "stato" | "stato"
| "web" | "web"
| "updated_at"
>; >;
export const AnnuncioCard = ({ className }: { className?: string }) => {
const { data } = useServizioAnnuncio();
return (
<BasicAnnuncioCard
actions={<AnnuncioActions />}
className={className}
data={{
...data,
updated_at: data.updated_at ? new Date(data.updated_at) : null,
}}
interactions={<Interactions />}
/>
);
};
export const BasicAnnuncioCard = ({
actions,
interactions,
className,
data,
}: {
actions?: React.ReactNode;
interactions?: React.ReactNode;
className?: string;
data: AnnuncioData;
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -85,7 +89,7 @@ export const BasicAnnuncioCard = ({
priority priority
src={ src={
(data.url_immagini && (data.url_immagini &&
`/go-api/images/get/${data.url_immagini[0]}?${CacheKey}`) || `/go-api/images/get/${data.url_immagini[0]}?${data.updated_at?.toString() || new Date().toString()}`) ||
"/fallback-image.png" "/fallback-image.png"
} }
width={1920} width={1920}
@ -148,25 +152,7 @@ const TipoBadge = ({ tipo }: { tipo: Annunci["tipo"] }) => {
); );
}; };
const AnnuncioDettaglio = ({ const AnnuncioDettaglio = ({ data }: { data: AnnuncioData }) => {
data,
}: {
data: Pick<
Annunci,
| "id"
| "codice"
| "prezzo"
| "desc_en"
| "desc_it"
| "url_immagini"
| "titolo_en"
| "titolo_it"
| "tipo"
| "consegna"
| "stato"
| "web"
>;
}) => {
const { locale, t } = useTranslation(); const { locale, t } = useTranslation();
return ( return (
@ -200,7 +186,7 @@ const AnnuncioDettaglio = ({
className={"h-80 w-full object-contain sm:h-[35rem]"} className={"h-80 w-full object-contain sm:h-[35rem]"}
height={200} height={200}
priority={idx === 0} priority={idx === 0}
src={`/go-api/images/get/${img}?${CacheKey}`} src={`/go-api/images/get/${img}?${data.updated_at?.toString() || new Date().toString()}`}
width={400} width={400}
/> />
</CarouselItem> </CarouselItem>

View file

@ -3,14 +3,10 @@ import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useEffect } from "react"; import { useEffect } from "react";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { AnnuncioCard } from "~/components/servizio/annuncio_card"; import { AnnuncioCard } from "~/components/servizio/annuncio_card";
import { SaldoButton } from "~/components/servizio/interactions"; import { SaldoButton } from "~/components/servizio/interactions";
import { ServizioDuration } from "~/components/servizio/service-duration-display"; import { ServizioDuration } from "~/components/servizio/service-duration-display";
import { import { ServizioActions2 } from "~/components/servizio/servizio_actions";
ServizioActions,
ServizioActions2,
} from "~/components/servizio/servizio_actions";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { import {
Card, Card,
@ -23,11 +19,8 @@ import { Progress } from "~/components/ui/progress";
import { cn } from "~/lib/utils"; import { cn } from "~/lib/utils";
import { import {
ServizioAnnuncioProvider, ServizioAnnuncioProvider,
ServizioProvider,
useServizio, useServizio,
} from "~/providers/ServizioProvider"; } from "~/providers/ServizioProvider";
import type { UsersId } from "~/schemas/public/Users";
import type { ServizioData } from "~/server/controllers/servizio.controller";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { import {
AnnunciCompatibili, AnnunciCompatibili,
@ -35,27 +28,6 @@ import {
AnnunciSelezionati, AnnunciSelezionati,
} from "./servizio_annunci_accordions"; } from "./servizio_annunci_accordions";
export const ServizioContainer = ({
servizio,
userId,
isAdmin,
}: {
servizio: ServizioData;
userId: UsersId;
isAdmin: boolean;
}) => {
return (
<ServizioProvider
isAdmin={isAdmin}
servizio={servizio}
servizioId={servizio.servizio_id}
userId={userId}
>
<ServizioMain />
</ServizioProvider>
);
};
const ServizioCard = ({ const ServizioCard = ({
cardClassName, cardClassName,
header, header,
@ -299,257 +271,3 @@ export const ServizioContent = () => {
/> />
); );
}; };
const ServizioMain = () => {
const { servizio, isAdmin, userId } = useServizio();
const utils = api.useUtils();
const { mutate: updateServizio } = api.servizio.updateServizio.useMutation({
onError: (error) => {
toast.error(error.message);
},
onSuccess: async () => {
toast.success("Servizio modificato con successo");
await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
},
});
const router = useRouter();
useEffect(() => {
const id = router.asPath.split("#")[1];
if (id) {
document.getElementById(id)?.scrollIntoView({
behavior: "smooth",
});
}
}, []);
if (servizio.isInterrotto) {
return (
<ServizioCard
cardClassName="bg-neutral-100 border-neutral-300"
content={
<>
<p className="font-medium text-lg">Servizio interrotto</p>
<p>
Non è possibile riutilizzare questo servizio, poichè è stato
interrotto.
</p>
</>
}
header={
<>
<div className="flex flex-col gap-4">
<CardTitle className="flex items-center gap-2 text-xl sm:text-2xl">
<Package className="size-6 text-primary" />
Cerco Affitto {servizio.tipologia}
</CardTitle>
<CardDescription className="space-y-2 pl-2 text-foreground/70">
<p>
aggiunto il{" "}
{servizio.created_at.toLocaleDateString("it", {
day: "2-digit",
month: "2-digit",
year: "numeric",
})}
</p>
</CardDescription>
</div>
</>
}
/>
);
}
if (!servizio.isOkAcconto || servizio.decorrenza === null) {
return (
<ServizioCard
content={
<div className="flex flex-col gap-4">
<div className="flex flex-wrap gap-3">
<Link
aria-label="Attiva Servizio"
href={`/servizio/onboard/${servizio.servizio_id}`}
>
<Button>Procedi all&apos;attivazione</Button>
</Link>
{isAdmin && (
<Button
onClick={() =>
updateServizio({
data: {
decorrenza: new Date(),
isOkAcconto: true,
},
servizioId: servizio.servizio_id,
})
}
variant="success"
>
Attiva Manualmente (Azione Admin)
</Button>
)}
</div>
{isAdmin && <AnnunciSelezionati annunci={servizio.annunci} />}
</div>
}
header={
<>
<div className="flex w-full flex-col gap-4">
<CardTitle className="flex items-center gap-2 text-xl sm:text-2xl">
<Package className="size-6 text-primary" />
Cerco Affitto {servizio.tipologia}
</CardTitle>
<CardDescription className="pl-2 text-foreground/70">
<p>Servizio non attivo</p>
</CardDescription>
</div>
<ServizioActions />
</>
}
/>
);
}
const annuncioConfermato = servizio.annunci.filter(
(a) => a.accettato_conferma_at !== null,
);
if (servizio.isOkSaldo) {
return (
<ServizioCard
content={
<>
{annuncioConfermato.map((data) => {
return (
<ServizioAnnuncioProvider data={data} key={data.id}>
<AnnuncioCard />
</ServizioAnnuncioProvider>
);
})}
</>
}
header={
<>
<div className="flex w-full flex-wrap items-center gap-2">
<CardTitle className="flex items-center gap-2 text-xl sm:text-2xl">
<Package className="size-6 text-primary" />
Cerco Affitto {servizio.tipologia}
</CardTitle>
<CardDescription className="space-y-2 pl-2 text-foreground/70">
<p>
aggiunto il{" "}
{servizio.created_at.toLocaleDateString("it", {
day: "2-digit",
month: "2-digit",
year: "numeric",
})}
</p>
</CardDescription>
</div>
<ServizioActions />
</>
}
/>
);
}
const openContattiCount = servizio.annunci.filter(
(a) => a.open_contatti_at !== null,
).length;
const annunciInConferma = servizio.annunci.filter(
(a) => a.user_confirmed_at !== null,
);
const annunciNotInConferma = servizio.annunci.filter(
(a) => a.user_confirmed_at === null,
);
return (
<ServizioCard
content={
<>
<div className="flex flex-col gap-2">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<UserCircle className="size-6 text-primary" />
<span className="font-medium">Contatti sbloccati</span>
</div>
<span className="text-sm">{openContattiCount} / 10</span>
</div>
<Progress className="h-2" value={openContattiCount * 10} />
</div>
<ServizioDuration decorrenza={servizio.decorrenza} />
{annuncioConfermato.length > 0 && (
<div className="flex flex-col gap-2">
<div className="flex items-center gap-2">
<PackageCheck className="size-6 text-primary" />
<span className="font-medium">Saldi in attesa:</span>
</div>
{servizio.annunci
.filter((a) => a.accettato_conferma_at !== null)
.map((a) => (
<div
className="flex items-center gap-2 rounded-md bg-sky-400 p-2"
key={a.annunci_id}
>
<h3>
{a.codice} - confermato il:{" "}
{/** biome-ignore lint/style/noNonNullAssertion: <already checked> */}
{new Date(a.accettato_conferma_at!).toLocaleDateString(
"it",
{
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
month: "2-digit",
year: "numeric",
},
)}
</h3>
<SaldoButton
annuncioId={a.annunci_id}
className="border-none"
variant={"outline"}
/>
</div>
))}
</div>
)}
<div className="space-y-2">
<AnnunciInConferma annunci={annunciInConferma} />
<AnnunciSelezionati annunci={annunciNotInConferma} />
<AnnunciCompatibili />
</div>
</>
}
header={
<>
<div className="flex w-full flex-col gap-2">
<CardTitle className="flex items-center gap-2 text-xl sm:text-2xl">
<Package className="size-6 text-primary" />
Cerco Affitto {servizio.tipologia}
</CardTitle>
<CardDescription className="space-y-2 pl-2 text-foreground/70">
<p>
aggiunto il{" "}
{servizio.created_at.toLocaleDateString("it", {
day: "2-digit",
month: "2-digit",
year: "numeric",
})}
</p>
</CardDescription>
</div>
<ServizioActions />
</>
}
/>
);
};

View file

@ -50,35 +50,6 @@ import type { ServizioServizioId } from "~/schemas/public/Servizio";
import type { UsersId } from "~/schemas/public/Users"; import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
export const ServizioActions = () => {
const { servizio, isAdmin, userId } = useServizio();
const canUserEdit =
servizio.isOkAcconto &&
servizio.decorrenza !== null &&
!servizio.annunci.some((a) => a.user_confirmed_at !== null);
if (!isAdmin && !canUserEdit) {
return null; // If the user is not an admin and cannot edit, do not render the actions
}
return (
<div className="flex w-full flex-wrap justify-start gap-3 sm:justify-end">
{(isAdmin || canUserEdit) && (
<>
<EditPreferenze />
<InterruzioneServizio />
</>
)}
{isAdmin && (
<>
<AddAnnuncio servizioId={servizio.servizio_id} userId={userId} />
<EditServizioAdmin />
</>
)}
</div>
);
};
export const ServizioActions2 = () => { export const ServizioActions2 = () => {
const { servizio, isAdmin, userId } = useServizio(); const { servizio, isAdmin, userId } = useServizio();

View file

@ -5,7 +5,6 @@ import { Play } from "lucide-react";
import Image from "next/image"; import Image from "next/image";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { cn } from "~/lib/utils"; import { cn } from "~/lib/utils";
import { CacheKey } from "~/utils/imageCache";
interface VideoPlayerProps { interface VideoPlayerProps {
coverImage: string; coverImage: string;
@ -13,6 +12,7 @@ interface VideoPlayerProps {
title?: string; title?: string;
aspectRatio?: "square" | "video" | "vertical"; aspectRatio?: "square" | "video" | "vertical";
className?: string; className?: string;
cacheKey: string;
} }
export function VideoPlayer({ export function VideoPlayer({
@ -21,6 +21,7 @@ export function VideoPlayer({
title, title,
aspectRatio = "video", aspectRatio = "video",
className, className,
cacheKey,
}: VideoPlayerProps) { }: VideoPlayerProps) {
const [isPlaying, setIsPlaying] = useState(false); const [isPlaying, setIsPlaying] = useState(false);
const videoRef = useRef<HTMLDivElement>(null); const videoRef = useRef<HTMLDivElement>(null);
@ -63,7 +64,7 @@ export function VideoPlayer({
className="object-cover" className="object-cover"
fill fill
priority priority
src={`${coverImage}?${CacheKey}` || "/fallback-video.png"} src={`${coverImage}?${cacheKey}` || "/fallback-video.png"}
/> />
<div className="absolute inset-0 flex items-center justify-center bg-black/20"> <div className="absolute inset-0 flex items-center justify-center bg-black/20">
<motion.div <motion.div
@ -98,7 +99,7 @@ export function VideoPlayer({
disableRemotePlayback disableRemotePlayback
muted muted
onEnded={() => setIsPlaying(false)} onEnded={() => setIsPlaying(false)}
src={`${videoSrc}?${CacheKey}`} src={`${videoSrc}?${cacheKey}`}
> >
Your browser does not support the video tag. Your browser does not support the video tag.
</video> </video>

View file

@ -236,6 +236,7 @@ export const AnnuncioEditForm = ({ data }: { data: Annunci }) => {
Annuncio {data.codice} Annuncio {data.codice}
</h1> </h1>
<StatusBadge status={data.stato} /> <StatusBadge status={data.stato} />
<span>{data.updated_at?.toLocaleString("it-IT")}</span>
<div className="ml-auto flex items-center gap-2"> <div className="ml-auto flex items-center gap-2">
<Button className="bg-green-500" size="sm" type="submit"> <Button className="bg-green-500" size="sm" type="submit">
Salva Salva
@ -539,6 +540,7 @@ export const AnnuncioEditForm = ({ data }: { data: Annunci }) => {
) || null ) || null
} }
single single
updated_at={data.updated_at}
videos={data.url_video} videos={data.url_video}
/> />
</CardContent> </CardContent>

View file

@ -61,7 +61,6 @@ import type { Annunci } from "~/schemas/public/Annunci";
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum"; import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
import { generateSSGHelper } from "~/server/utils/ssgHelper"; import { generateSSGHelper } from "~/server/utils/ssgHelper";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { CacheKey } from "~/utils/imageCache";
type AnnuncioProps = { type AnnuncioProps = {
cod: string; cod: string;
@ -136,6 +135,7 @@ const AnnuncioView = ({ cod, flag }: Omit<AnnuncioProps, "meta">) => {
<div className="mx-auto w-full px-2 sm:px-8"> <div className="mx-auto w-full px-2 sm:px-8">
<CarouselAnnuncio <CarouselAnnuncio
immagini={data.url_immagini} immagini={data.url_immagini}
updated_at={data.updated_at}
videos={data.url_video} videos={data.url_video}
/> />
@ -204,6 +204,7 @@ const AnnuncioView = ({ cod, flag }: Omit<AnnuncioProps, "meta">) => {
consegna={data.consegna} consegna={data.consegna}
first_image={data.url_immagini?.[0] ? data.url_immagini[0] : ""} first_image={data.url_immagini?.[0] ? data.url_immagini[0] : ""}
tipo={data.tipo} tipo={data.tipo}
updated_at={data.updated_at}
url_video={data.url_video || []} url_video={data.url_video || []}
/> />
</div> </div>
@ -623,12 +624,14 @@ const AnnuncioFooter = ({
consegna, consegna,
url_video, url_video,
first_image, first_image,
updated_at,
}: { }: {
tipo: string | null; tipo: string | null;
comune: string | null; comune: string | null;
consegna: number | null; consegna: number | null;
url_video: string[]; url_video: string[];
first_image: string; first_image: string;
updated_at: Date | null;
}) => { }) => {
return ( return (
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
@ -641,10 +644,11 @@ const AnnuncioFooter = ({
} }
return ( return (
<VideoPlayer <VideoPlayer
cacheKey={updated_at?.toString() || new Date().toString()}
className="h-96 max-w-96" className="h-96 max-w-96"
coverImage={first_image} coverImage={first_image}
key={`videoplayer-${video}`} key={`videoplayer-${video}`} // Cache busting
videoSrc={`${video}?${CacheKey}`} videoSrc={video}
/> />
); );
})} })}

View file

@ -1,7 +1,7 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { default as PublicSchema } from "./public/PublicSchema"; import type { default as PublicSchema } from './public/PublicSchema';
type Database = PublicSchema; type Database = PublicSchema;

View file

@ -1,11 +1,11 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { Caratteristiche } from '../../utils/kanel-types.ts';
import type { Caratteristiche } from "../../utils/kanel-types.ts"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.annunci */ /** Identifier type for public.annunci */
export type AnnunciId = number & { __brand: "public.annunci" }; export type AnnunciId = number & { __brand: 'public.annunci' };
/** Represents the table public.annunci */ /** Represents the table public.annunci */
export default interface AnnunciTable { export default interface AnnunciTable {
@ -89,11 +89,7 @@ export default interface AnnunciTable {
web: ColumnType<boolean | null, boolean | null, boolean | null>; web: ColumnType<boolean | null, boolean | null, boolean | null>;
caratteristiche: ColumnType< caratteristiche: ColumnType<Caratteristiche | null, Caratteristiche | null, Caratteristiche | null>;
Caratteristiche | null,
Caratteristiche | null,
Caratteristiche | null
>;
url_immagini: ColumnType<string[] | null, string[] | null, string[] | null>; url_immagini: ColumnType<string[] | null, string[] | null, string[] | null>;
@ -103,31 +99,21 @@ export default interface AnnunciTable {
email: ColumnType<string | null, string | null, string | null>; email: ColumnType<string | null, string | null, string | null>;
creato_il: ColumnType< creato_il: ColumnType<Date | null, Date | string | null, Date | string | null>;
Date | null,
Date | string | null,
Date | string | null
>;
modificato_il: ColumnType< modificato_il: ColumnType<Date | null, Date | string | null, Date | string | null>;
Date | null,
Date | string | null,
Date | string | null
>;
consegna: ColumnType<number | null, number | null, number | null>; consegna: ColumnType<number | null, number | null, number | null>;
og_url: ColumnType<string | null, string | null, string | null>; og_url: ColumnType<string | null, string | null, string | null>;
disponibile_da: ColumnType< disponibile_da: ColumnType<Date | null, Date | string | null, Date | string | null>;
Date | null,
Date | string | null,
Date | string | null
>;
permanenza: ColumnType<number[] | null, number[] | null, number[] | null>; permanenza: ColumnType<number[] | null, number[] | null, number[] | null>;
persone: ColumnType<string[] | null, string[] | null, string[] | null>; persone: ColumnType<string[] | null, string[] | null, string[] | null>;
updated_at: ColumnType<Date | null, Date | string | null, Date | string | null>;
} }
export type Annunci = Selectable<AnnunciTable>; export type Annunci = Selectable<AnnunciTable>;

View file

@ -3,10 +3,10 @@
/** Represents the enum public.BanType */ /** Represents the enum public.BanType */
enum BanType { enum BanType {
ip = "ip", ip = 'ip',
email = "email", email = 'email',
phone = "phone", phone = 'phone',
cf = "cf", cf = 'cf',
} };
export default BanType; export default BanType;

View file

@ -1,11 +1,11 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { default as BanType } from './BanType';
import type { default as BanType } from "./BanType"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.banlist */ /** Identifier type for public.banlist */
export type BanlistId = number & { __brand: "public.banlist" }; export type BanlistId = number & { __brand: 'public.banlist' };
/** Represents the table public.banlist */ /** Represents the table public.banlist */
export default interface BanlistTable { export default interface BanlistTable {

View file

@ -1,10 +1,10 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.banners */ /** Identifier type for public.banners */
export type BannersIdbanner = string & { __brand: "public.banners" }; export type BannersIdbanner = string & { __brand: 'public.banners' };
/** Represents the table public.banners */ /** Represents the table public.banners */
export default interface BannersTable { export default interface BannersTable {

View file

@ -1,11 +1,11 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { UsersId } from './Users';
import type { UsersId } from "./Users"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.chats */ /** Identifier type for public.chats */
export type ChatsChatid = string & { __brand: "public.chats" }; export type ChatsChatid = string & { __brand: 'public.chats' };
/** Represents the table public.chats */ /** Represents the table public.chats */
export default interface ChatsTable { export default interface ChatsTable {

View file

@ -1,19 +1,15 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { ChatsChatid } from './Chats';
import type { ChatsChatid } from "./Chats"; import type { EtichetteIdEtichetta } from './Etichette';
import type { EtichetteIdEtichetta } from "./Etichette"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Represents the table public.chats_etichette */ /** Represents the table public.chats_etichette */
export default interface ChatsEtichetteTable { export default interface ChatsEtichetteTable {
chatid: ColumnType<ChatsChatid, ChatsChatid, ChatsChatid>; chatid: ColumnType<ChatsChatid, ChatsChatid, ChatsChatid>;
etichettaid: ColumnType< etichettaid: ColumnType<EtichetteIdEtichetta, EtichetteIdEtichetta, EtichetteIdEtichetta>;
EtichetteIdEtichetta,
EtichetteIdEtichetta,
EtichetteIdEtichetta
>;
} }
export type ChatsEtichette = Selectable<ChatsEtichetteTable>; export type ChatsEtichette = Selectable<ChatsEtichetteTable>;

View file

@ -1,11 +1,11 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { UsersId } from './Users';
import type { UsersId } from "./Users"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.emails */ /** Identifier type for public.emails */
export type EmailsIdEmail = number & { __brand: "public.emails" }; export type EmailsIdEmail = number & { __brand: 'public.emails' };
/** Represents the table public.emails */ /** Represents the table public.emails */
export default interface EmailsTable { export default interface EmailsTable {

View file

@ -1,18 +1,14 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.etichette */ /** Identifier type for public.etichette */
export type EtichetteIdEtichetta = number & { __brand: "public.etichette" }; export type EtichetteIdEtichetta = number & { __brand: 'public.etichette' };
/** Represents the table public.etichette */ /** Represents the table public.etichette */
export default interface EtichetteTable { export default interface EtichetteTable {
id_etichetta: ColumnType< id_etichetta: ColumnType<EtichetteIdEtichetta, EtichetteIdEtichetta | undefined, EtichetteIdEtichetta>;
EtichetteIdEtichetta,
EtichetteIdEtichetta | undefined,
EtichetteIdEtichetta
>;
title: ColumnType<string, string, string>; title: ColumnType<string, string, string>;

View file

@ -1,18 +1,14 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.event_queue */ /** Identifier type for public.event_queue */
export type EventQueueEventId = number & { __brand: "public.event_queue" }; export type EventQueueEventId = number & { __brand: 'public.event_queue' };
/** Represents the table public.event_queue */ /** Represents the table public.event_queue */
export default interface EventQueueTable { export default interface EventQueueTable {
event_id: ColumnType< event_id: ColumnType<EventQueueEventId, EventQueueEventId | undefined, EventQueueEventId>;
EventQueueEventId,
EventQueueEventId | undefined,
EventQueueEventId
>;
lock_expires: ColumnType<Date, Date | string, Date | string>; lock_expires: ColumnType<Date, Date | string, Date | string>;

View file

@ -1,10 +1,10 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.flags */ /** Identifier type for public.flags */
export type FlagsId = string & { __brand: "public.flags" }; export type FlagsId = string & { __brand: 'public.flags' };
/** Represents the table public.flags */ /** Represents the table public.flags */
export default interface FlagsTable { export default interface FlagsTable {

View file

@ -3,9 +3,9 @@
/** Represents the enum public.GenericStatusEnum */ /** Represents the enum public.GenericStatusEnum */
enum GenericStatusEnum { enum GenericStatusEnum {
pending = "pending", pending = 'pending',
success = "success", success = 'success',
failed = "failed", failed = 'failed',
} };
export default GenericStatusEnum; export default GenericStatusEnum;

View file

@ -1,20 +1,16 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { ChatsChatid } from './Chats';
import type { ChatsChatid } from "./Chats"; import type { UsersId } from './Users';
import type { UsersId } from "./Users"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.messages */ /** Identifier type for public.messages */
export type MessagesMessageid = string & { __brand: "public.messages" }; export type MessagesMessageid = string & { __brand: 'public.messages' };
/** Represents the table public.messages */ /** Represents the table public.messages */
export default interface MessagesTable { export default interface MessagesTable {
messageid: ColumnType< messageid: ColumnType<MessagesMessageid, MessagesMessageid | undefined, MessagesMessageid>;
MessagesMessageid,
MessagesMessageid | undefined,
MessagesMessageid
>;
chatid: ColumnType<ChatsChatid, ChatsChatid, ChatsChatid>; chatid: ColumnType<ChatsChatid, ChatsChatid, ChatsChatid>;

View file

@ -1,20 +1,14 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.miogest_images_ref */ /** Identifier type for public.miogest_images_ref */
export type MiogestImagesRefCodice = string & { export type MiogestImagesRefCodice = string & { __brand: 'public.miogest_images_ref' };
__brand: "public.miogest_images_ref";
};
/** Represents the table public.miogest_images_ref */ /** Represents the table public.miogest_images_ref */
export default interface MiogestImagesRefTable { export default interface MiogestImagesRefTable {
codice: ColumnType< codice: ColumnType<MiogestImagesRefCodice, MiogestImagesRefCodice, MiogestImagesRefCodice>;
MiogestImagesRefCodice,
MiogestImagesRefCodice,
MiogestImagesRefCodice
>;
foto: ColumnType<string[] | null, string[] | null, string[] | null>; foto: ColumnType<string[] | null, string[] | null, string[] | null>;
} }

View file

@ -3,10 +3,10 @@
/** Represents the enum public.OrderTypeEnum */ /** Represents the enum public.OrderTypeEnum */
enum OrderTypeEnum { enum OrderTypeEnum {
Acconto = "Acconto", Acconto = 'Acconto',
Saldo = "Saldo", Saldo = 'Saldo',
Consulenza = "Consulenza", Consulenza = 'Consulenza',
Altro = "Altro", Altro = 'Altro',
} };
export default OrderTypeEnum; export default OrderTypeEnum;

View file

@ -1,38 +1,26 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { UsersId } from './Users';
import type { default as OrderTypeEnum } from "./OrderTypeEnum"; import type { PrezziarioIdprezziario } from './Prezziario';
import type { PrezziarioIdprezziario } from "./Prezziario"; import type { ServizioServizioId } from './Servizio';
import type { ServizioServizioId } from "./Servizio"; import type { default as OrderTypeEnum } from './OrderTypeEnum';
import type { UsersId } from "./Users"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.ordini */ /** Identifier type for public.ordini */
export type OrdiniOrdineId = string & { __brand: "public.ordini" }; export type OrdiniOrdineId = string & { __brand: 'public.ordini' };
/** Represents the table public.ordini */ /** Represents the table public.ordini */
export default interface OrdiniTable { export default interface OrdiniTable {
ordine_id: ColumnType< ordine_id: ColumnType<OrdiniOrdineId, OrdiniOrdineId | undefined, OrdiniOrdineId>;
OrdiniOrdineId,
OrdiniOrdineId | undefined,
OrdiniOrdineId
>;
userid: ColumnType<UsersId, UsersId, UsersId>; userid: ColumnType<UsersId, UsersId, UsersId>;
created_at: ColumnType<Date, Date | string | undefined, Date | string>; created_at: ColumnType<Date, Date | string | undefined, Date | string>;
packid: ColumnType< packid: ColumnType<PrezziarioIdprezziario, PrezziarioIdprezziario, PrezziarioIdprezziario>;
PrezziarioIdprezziario,
PrezziarioIdprezziario,
PrezziarioIdprezziario
>;
servizio_id: ColumnType< servizio_id: ColumnType<ServizioServizioId, ServizioServizioId, ServizioServizioId>;
ServizioServizioId,
ServizioServizioId,
ServizioServizioId
>;
type: ColumnType<OrderTypeEnum, OrderTypeEnum, OrderTypeEnum>; type: ColumnType<OrderTypeEnum, OrderTypeEnum, OrderTypeEnum>;

View file

@ -3,9 +3,9 @@
/** Represents the enum public.PaymentStatusEnum */ /** Represents the enum public.PaymentStatusEnum */
enum PaymentStatusEnum { enum PaymentStatusEnum {
processing = "processing", processing = 'processing',
success = "success", success = 'success',
failed = "failed", failed = 'failed',
} };
export default PaymentStatusEnum; export default PaymentStatusEnum;

View file

@ -1,14 +1,14 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { UsersId } from './Users';
import type { OrdiniOrdineId } from "./Ordini"; import type { default as PaymentStatusEnum } from './PaymentStatusEnum';
import type { default as PaymentStatusEnum } from "./PaymentStatusEnum"; import type { ServizioServizioId } from './Servizio';
import type { ServizioServizioId } from "./Servizio"; import type { OrdiniOrdineId } from './Ordini';
import type { UsersId } from "./Users"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.payments */ /** Identifier type for public.payments */
export type PaymentsId = string & { __brand: "public.payments" }; export type PaymentsId = string & { __brand: 'public.payments' };
/** Represents the table public.payments */ /** Represents the table public.payments */
export default interface PaymentsTable { export default interface PaymentsTable {
@ -28,17 +28,9 @@ export default interface PaymentsTable {
intent_id: ColumnType<string | null, string | null, string | null>; intent_id: ColumnType<string | null, string | null, string | null>;
paymentstatus: ColumnType< paymentstatus: ColumnType<PaymentStatusEnum | null, PaymentStatusEnum | null, PaymentStatusEnum | null>;
PaymentStatusEnum | null,
PaymentStatusEnum | null,
PaymentStatusEnum | null
>;
servizio_id: ColumnType< servizio_id: ColumnType<ServizioServizioId, ServizioServizioId, ServizioServizioId>;
ServizioServizioId,
ServizioServizioId,
ServizioServizioId
>;
ordine_id: ColumnType<OrdiniOrdineId, OrdiniOrdineId, OrdiniOrdineId>; ordine_id: ColumnType<OrdiniOrdineId, OrdiniOrdineId, OrdiniOrdineId>;
} }

View file

@ -1,18 +1,14 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.prezziario */ /** Identifier type for public.prezziario */
export type PrezziarioIdprezziario = string & { __brand: "public.prezziario" }; export type PrezziarioIdprezziario = string & { __brand: 'public.prezziario' };
/** Represents the table public.prezziario */ /** Represents the table public.prezziario */
export default interface PrezziarioTable { export default interface PrezziarioTable {
idprezziario: ColumnType< idprezziario: ColumnType<PrezziarioIdprezziario, PrezziarioIdprezziario, PrezziarioIdprezziario>;
PrezziarioIdprezziario,
PrezziarioIdprezziario,
PrezziarioIdprezziario
>;
prezzo_cent: ColumnType<number, number, number>; prezzo_cent: ColumnType<number, number, number>;

View file

@ -1,30 +1,30 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { default as AnnunciTable } from "./Annunci"; import type { default as ServizioInteressiTable } from './ServizioInteressi';
import type { default as BanlistTable } from "./Banlist"; import type { default as FlagsTable } from './Flags';
import type { default as BannersTable } from "./Banners"; import type { default as AnnunciTable } from './Annunci';
import type { default as ChatsTable } from "./Chats"; import type { default as UsersTable } from './Users';
import type { default as ChatsEtichetteTable } from "./ChatsEtichette"; import type { default as ChatsEtichetteTable } from './ChatsEtichette';
import type { default as EmailsTable } from "./Emails"; import type { default as TestiEStringheTable } from './TestiEStringhe';
import type { default as EtichetteTable } from "./Etichette"; import type { default as UsersStorageTable } from './UsersStorage';
import type { default as EventQueueTable } from "./EventQueue"; import type { default as ServizioAnnunciTable } from './ServizioAnnunci';
import type { default as FlagsTable } from "./Flags"; import type { default as EmailsTable } from './Emails';
import type { default as MessagesTable } from "./Messages"; import type { default as PaymentsTable } from './Payments';
import type { default as MiogestImagesRefTable } from "./MiogestImagesRef"; import type { default as MiogestImagesRefTable } from './MiogestImagesRef';
import type { default as OrdiniTable } from "./Ordini"; import type { default as TempTokensTable } from './TempTokens';
import type { default as PaymentsTable } from "./Payments"; import type { default as EventQueueTable } from './EventQueue';
import type { default as PrezziarioTable } from "./Prezziario"; import type { default as OrdiniTable } from './Ordini';
import type { default as RatelimiterTable } from "./Ratelimiter"; import type { default as PrezziarioTable } from './Prezziario';
import type { default as ServizioTable } from "./Servizio"; import type { default as RatelimiterTable } from './Ratelimiter';
import type { default as ServizioAnnunciTable } from "./ServizioAnnunci"; import type { default as ChatsTable } from './Chats';
import type { default as ServizioInteressiTable } from "./ServizioInteressi"; import type { default as EtichetteTable } from './Etichette';
import type { default as StorageindexTable } from "./Storageindex"; import type { default as StorageindexTable } from './Storageindex';
import type { default as TempTokensTable } from "./TempTokens"; import type { default as MessagesTable } from './Messages';
import type { default as TestiEStringheTable } from "./TestiEStringhe"; import type { default as UsersAnagraficaTable } from './UsersAnagrafica';
import type { default as UsersTable } from "./Users"; import type { default as BanlistTable } from './Banlist';
import type { default as UsersAnagraficaTable } from "./UsersAnagrafica"; import type { default as BannersTable } from './Banners';
import type { default as UsersStorageTable } from "./UsersStorage"; import type { default as ServizioTable } from './Servizio';
export default interface PublicSchema { export default interface PublicSchema {
servizio_interessi: ServizioInteressiTable; servizio_interessi: ServizioInteressiTable;

View file

@ -1,7 +1,7 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Represents the table public.ratelimiter */ /** Represents the table public.ratelimiter */
export default interface RatelimiterTable { export default interface RatelimiterTable {

View file

@ -1,30 +1,22 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { UsersId } from './Users';
import type { default as TipologiaPosizioneEnum } from "./TipologiaPosizioneEnum"; import type { default as TipologiaPosizioneEnum } from './TipologiaPosizioneEnum';
import type { UsersId } from "./Users"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.servizio */ /** Identifier type for public.servizio */
export type ServizioServizioId = string & { __brand: "public.servizio" }; export type ServizioServizioId = string & { __brand: 'public.servizio' };
/** Represents the table public.servizio */ /** Represents the table public.servizio */
export default interface ServizioTable { export default interface ServizioTable {
servizio_id: ColumnType< servizio_id: ColumnType<ServizioServizioId, ServizioServizioId | undefined, ServizioServizioId>;
ServizioServizioId,
ServizioServizioId | undefined,
ServizioServizioId
>;
user_id: ColumnType<UsersId, UsersId, UsersId>; user_id: ColumnType<UsersId, UsersId, UsersId>;
created_at: ColumnType<Date, Date | string | undefined, Date | string>; created_at: ColumnType<Date, Date | string | undefined, Date | string>;
tipologia: ColumnType< tipologia: ColumnType<TipologiaPosizioneEnum, TipologiaPosizioneEnum, TipologiaPosizioneEnum>;
TipologiaPosizioneEnum,
TipologiaPosizioneEnum,
TipologiaPosizioneEnum
>;
arredato: ColumnType<boolean, boolean | undefined, boolean>; arredato: ColumnType<boolean, boolean | undefined, boolean>;
@ -48,21 +40,13 @@ export default interface ServizioTable {
pianoterra: ColumnType<boolean, boolean | undefined, boolean>; pianoterra: ColumnType<boolean, boolean | undefined, boolean>;
motivazione_transitorio: ColumnType< motivazione_transitorio: ColumnType<string | null, string | null, string | null>;
string | null,
string | null,
string | null
>;
reddito: ColumnType<string | null, string | null, string | null>; reddito: ColumnType<string | null, string | null, string | null>;
isSent: ColumnType<boolean, boolean | undefined, boolean>; isSent: ColumnType<boolean, boolean | undefined, boolean>;
decorrenza: ColumnType< decorrenza: ColumnType<Date | null, Date | string | null, Date | string | null>;
Date | null,
Date | string | null,
Date | string | null
>;
isInterrotto: ColumnType<boolean, boolean | undefined, boolean>; isInterrotto: ColumnType<boolean, boolean | undefined, boolean>;

View file

@ -1,46 +1,26 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { ServizioServizioId } from './Servizio';
import type { AnnunciId } from "./Annunci"; import type { AnnunciId } from './Annunci';
import type { ServizioServizioId } from "./Servizio"; import type { StorageindexId } from './Storageindex';
import type { StorageindexId } from "./Storageindex"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Represents the table public.servizio_annunci */ /** Represents the table public.servizio_annunci */
export default interface ServizioAnnunciTable { export default interface ServizioAnnunciTable {
servizio_id: ColumnType< servizio_id: ColumnType<ServizioServizioId, ServizioServizioId, ServizioServizioId>;
ServizioServizioId,
ServizioServizioId,
ServizioServizioId
>;
annunci_id: ColumnType<AnnunciId, AnnunciId, AnnunciId>; annunci_id: ColumnType<AnnunciId, AnnunciId, AnnunciId>;
created_at: ColumnType<Date, Date | string | undefined, Date | string>; created_at: ColumnType<Date, Date | string | undefined, Date | string>;
open_contatti_at: ColumnType< open_contatti_at: ColumnType<Date | null, Date | string | null, Date | string | null>;
Date | null,
Date | string | null,
Date | string | null
>;
doc_conferma_ref: ColumnType< doc_conferma_ref: ColumnType<StorageindexId | null, StorageindexId | null, StorageindexId | null>;
StorageindexId | null,
StorageindexId | null,
StorageindexId | null
>;
user_confirmed_at: ColumnType< user_confirmed_at: ColumnType<Date | null, Date | string | null, Date | string | null>;
Date | null,
Date | string | null,
Date | string | null
>;
accettato_conferma_at: ColumnType< accettato_conferma_at: ColumnType<Date | null, Date | string | null, Date | string | null>;
Date | null,
Date | string | null,
Date | string | null
>;
caparra_causale: ColumnType<string | null, string | null, string | null>; caparra_causale: ColumnType<string | null, string | null, string | null>;
@ -52,33 +32,17 @@ export default interface ServizioAnnunciTable {
hasConfermaAdmin: ColumnType<boolean, boolean | undefined, boolean>; hasConfermaAdmin: ColumnType<boolean, boolean | undefined, boolean>;
doc_contratto_ref: ColumnType< doc_contratto_ref: ColumnType<StorageindexId | null, StorageindexId | null, StorageindexId | null>;
StorageindexId | null,
StorageindexId | null,
StorageindexId | null
>;
gestionale_id: ColumnType<number | null, number | null, number | null>; gestionale_id: ColumnType<number | null, number | null, number | null>;
contratto_decorrenza: ColumnType< contratto_decorrenza: ColumnType<Date | null, Date | string | null, Date | string | null>;
Date | null,
Date | string | null,
Date | string | null
>;
contratto_scadenza: ColumnType< contratto_scadenza: ColumnType<Date | null, Date | string | null, Date | string | null>;
Date | null,
Date | string | null,
Date | string | null
>;
contratto_tipo: ColumnType<string | null, string | null, string | null>; contratto_tipo: ColumnType<string | null, string | null, string | null>;
doc_registrazione_ref: ColumnType< doc_registrazione_ref: ColumnType<StorageindexId | null, StorageindexId | null, StorageindexId | null>;
StorageindexId | null,
StorageindexId | null,
StorageindexId | null
>;
doc_conferma_added: ColumnType<boolean, boolean | undefined, boolean>; doc_conferma_added: ColumnType<boolean, boolean | undefined, boolean>;

View file

@ -1,9 +1,9 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { AnnunciId } from './Annunci';
import type { AnnunciId } from "./Annunci"; import type { UsersId } from './Users';
import type { UsersId } from "./Users"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Represents the table public.servizio_interessi */ /** Represents the table public.servizio_interessi */
export default interface ServizioInteressiTable { export default interface ServizioInteressiTable {

View file

@ -1,10 +1,10 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.storageindex */ /** Identifier type for public.storageindex */
export type StorageindexId = string & { __brand: "public.storageindex" }; export type StorageindexId = string & { __brand: 'public.storageindex' };
/** Represents the table public.storageindex */ /** Represents the table public.storageindex */
export default interface StorageindexTable { export default interface StorageindexTable {
@ -18,11 +18,7 @@ export default interface StorageindexTable {
from_admin: ColumnType<boolean, boolean | undefined, boolean>; from_admin: ColumnType<boolean, boolean | undefined, boolean>;
expires_at: ColumnType< expires_at: ColumnType<Date | null, Date | string | null, Date | string | null>;
Date | null,
Date | string | null,
Date | string | null
>;
} }
export type Storageindex = Selectable<StorageindexTable>; export type Storageindex = Selectable<StorageindexTable>;

View file

@ -1,18 +1,14 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.temp_tokens */ /** Identifier type for public.temp_tokens */
export type TempTokensToken = string & { __brand: "public.temp_tokens" }; export type TempTokensToken = string & { __brand: 'public.temp_tokens' };
/** Represents the table public.temp_tokens */ /** Represents the table public.temp_tokens */
export default interface TempTokensTable { export default interface TempTokensTable {
token: ColumnType< token: ColumnType<TempTokensToken, TempTokensToken | undefined, TempTokensToken>;
TempTokensToken,
TempTokensToken | undefined,
TempTokensToken
>;
elapse: ColumnType<Date, Date | string | undefined, Date | string>; elapse: ColumnType<Date, Date | string | undefined, Date | string>;
} }

View file

@ -1,20 +1,14 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.testi_e_stringhe */ /** Identifier type for public.testi_e_stringhe */
export type TestiEStringheStingaId = string & { export type TestiEStringheStingaId = string & { __brand: 'public.testi_e_stringhe' };
__brand: "public.testi_e_stringhe";
};
/** Represents the table public.testi_e_stringhe */ /** Represents the table public.testi_e_stringhe */
export default interface TestiEStringheTable { export default interface TestiEStringheTable {
stinga_id: ColumnType< stinga_id: ColumnType<TestiEStringheStingaId, TestiEStringheStingaId, TestiEStringheStingaId>;
TestiEStringheStingaId,
TestiEStringheStingaId,
TestiEStringheStingaId
>;
stringa_value: ColumnType<string | null, string | null, string | null>; stringa_value: ColumnType<string | null, string | null, string | null>;
} }

View file

@ -3,8 +3,8 @@
/** Represents the enum public.TipologiaPosizioneEnum */ /** Represents the enum public.TipologiaPosizioneEnum */
enum TipologiaPosizioneEnum { enum TipologiaPosizioneEnum {
Transitorio = "Transitorio", Transitorio = 'Transitorio',
Stabile = "Stabile", Stabile = 'Stabile',
} };
export default TipologiaPosizioneEnum; export default TipologiaPosizioneEnum;

View file

@ -1,10 +1,10 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.users */ /** Identifier type for public.users */
export type UsersId = string & { __brand: "public.users" }; export type UsersId = string & { __brand: 'public.users' };
/** Represents the table public.users */ /** Represents the table public.users */
export default interface UsersTable { export default interface UsersTable {
@ -28,11 +28,7 @@ export default interface UsersTable {
reset_password_token: ColumnType<string | null, string | null, string | null>; reset_password_token: ColumnType<string | null, string | null, string | null>;
reset_password_expires: ColumnType< reset_password_expires: ColumnType<Date | null, Date | string | null, Date | string | null>;
Date | null,
Date | string | null,
Date | string | null
>;
telefono: ColumnType<string, string, string>; telefono: ColumnType<string, string, string>;
@ -42,11 +38,7 @@ export default interface UsersTable {
verificationToken: ColumnType<string | null, string | null, string | null>; verificationToken: ColumnType<string | null, string | null, string | null>;
verificationTokenExpires: ColumnType< verificationTokenExpires: ColumnType<Date | null, Date | string | null, Date | string | null>;
Date | null,
Date | string | null,
Date | string | null
>;
salt: ColumnType<string, string, string>; salt: ColumnType<string, string, string>;
} }

View file

@ -1,31 +1,21 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { UsersId } from './Users';
import type { UsersId } from "./Users"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Identifier type for public.users_anagrafica */ /** Identifier type for public.users_anagrafica */
export type UsersAnagraficaIdanagrafica = string & { export type UsersAnagraficaIdanagrafica = string & { __brand: 'public.users_anagrafica' };
__brand: "public.users_anagrafica";
};
/** Represents the table public.users_anagrafica */ /** Represents the table public.users_anagrafica */
export default interface UsersAnagraficaTable { export default interface UsersAnagraficaTable {
idanagrafica: ColumnType< idanagrafica: ColumnType<UsersAnagraficaIdanagrafica, UsersAnagraficaIdanagrafica | undefined, UsersAnagraficaIdanagrafica>;
UsersAnagraficaIdanagrafica,
UsersAnagraficaIdanagrafica | undefined,
UsersAnagraficaIdanagrafica
>;
userid: ColumnType<UsersId, UsersId, UsersId>; userid: ColumnType<UsersId, UsersId, UsersId>;
luogo_nascita: ColumnType<string | null, string | null, string | null>; luogo_nascita: ColumnType<string | null, string | null, string | null>;
data_nascita: ColumnType< data_nascita: ColumnType<Date | null, Date | string | null, Date | string | null>;
Date | null,
Date | string | null,
Date | string | null
>;
nazione_nascita: ColumnType<string | null, string | null, string | null>; nazione_nascita: ColumnType<string | null, string | null, string | null>;
@ -57,11 +47,7 @@ export default interface UsersAnagraficaTable {
codice_destinatario: ColumnType<string | null, string | null, string | null>; codice_destinatario: ColumnType<string | null, string | null, string | null>;
legale_rappresentante: ColumnType< legale_rappresentante: ColumnType<string | null, string | null, string | null>;
string | null,
string | null,
string | null
>;
} }
export type UsersAnagrafica = Selectable<UsersAnagraficaTable>; export type UsersAnagrafica = Selectable<UsersAnagraficaTable>;

View file

@ -1,9 +1,9 @@
// @generated // @generated
// This file is automatically generated by Kanel. Do not modify manually. // This file is automatically generated by Kanel. Do not modify manually.
import type { ColumnType, Insertable, Selectable, Updateable } from "kysely"; import type { UsersId } from './Users';
import type { StorageindexId } from "./Storageindex"; import type { StorageindexId } from './Storageindex';
import type { UsersId } from "./Users"; import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
/** Represents the table public.users_storage */ /** Represents the table public.users_storage */
export default interface UsersStorageTable { export default interface UsersStorageTable {

View file

@ -102,6 +102,7 @@ export const intrestsRouter = createTRPCRouter({
"annunci.consegna", "annunci.consegna",
"annunci.stato", "annunci.stato",
"annunci.web", "annunci.web",
"annunci.updated_at",
]) ])
.where("web", "=", true) .where("web", "=", true)
.where("stato", "!=", "Sospeso") .where("stato", "!=", "Sospeso")

View file

@ -185,6 +185,7 @@ export const get_AnnunciPositionsHandler = async ({
"url_video", "url_video",
"lon_secondario", "lon_secondario",
"lat_secondario", "lat_secondario",
"updated_at",
]) ])
.where("web", "=", true) .where("web", "=", true)
@ -237,6 +238,7 @@ export type AnnuncioRicerca = Pick<
| "modificato_il" | "modificato_il"
| "stato" | "stato"
| "url_video" | "url_video"
| "updated_at"
>; >;
export const getCursor_AnnunciHandler = async ({ export const getCursor_AnnunciHandler = async ({
@ -273,6 +275,7 @@ export const getCursor_AnnunciHandler = async ({
"modificato_il", "modificato_il",
"stato", "stato",
"url_video", "url_video",
"updated_at",
]) ])
.where("web", "=", true) .where("web", "=", true)

View file

@ -5,7 +5,7 @@ import { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/postgres";
import { z } from "zod/v4"; import { z } from "zod/v4";
import type { PurchaseData } from "~/components/acquisto_receipt"; import type { PurchaseData } from "~/components/acquisto_receipt";
import { env } from "~/env"; import { env } from "~/env";
import type { AnnunciId } from "~/schemas/public/Annunci"; import type { Annunci, AnnunciId } from "~/schemas/public/Annunci";
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum"; import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
import type { OrdiniOrdineId } from "~/schemas/public/Ordini"; import type { OrdiniOrdineId } from "~/schemas/public/Ordini";
import PaymentStatusEnum from "~/schemas/public/PaymentStatusEnum"; import PaymentStatusEnum from "~/schemas/public/PaymentStatusEnum";
@ -645,6 +645,7 @@ export const getAllServizioAnnunci = async (userId: UsersId) => {
"annunci.consegna", "annunci.consegna",
"annunci.stato", "annunci.stato",
"annunci.web", "annunci.web",
"annunci.updated_at",
]) ])
//ignora annunci che non sono disponibili //ignora annunci che non sono disponibili
.where("annunci.web", "=", true) .where("annunci.web", "=", true)
@ -1463,6 +1464,23 @@ export const SendContactEmail = async ({
} }
}; };
export type AnnuncioData = Pick<
Annunci,
| "id"
| "codice"
| "prezzo"
| "desc_en"
| "desc_it"
| "url_immagini"
| "titolo_en"
| "titolo_it"
| "tipo"
| "consegna"
| "stato"
| "web"
| "updated_at"
>;
export const getCompatibileAnnunci = async (servizioId: ServizioServizioId) => { export const getCompatibileAnnunci = async (servizioId: ServizioServizioId) => {
try { try {
const servizio = await getServizioById(servizioId); const servizio = await getServizioById(servizioId);
@ -1488,6 +1506,7 @@ export const getCompatibileAnnunci = async (servizioId: ServizioServizioId) => {
"annunci.consegna", "annunci.consegna",
"annunci.stato", "annunci.stato",
"annunci.web", "annunci.web",
"annunci.updated_at",
]) ])
.where("web", "=", true) .where("web", "=", true)
.where("stato", "!=", "Sospeso") .where("stato", "!=", "Sospeso")

View file

@ -1 +0,0 @@
export const CacheKey = `cachekey=${process.env.NEXT_PUBLIC_BUILD_ID}`;