diff --git a/apps/infoalloggi/src/components/annunci_grid.tsx b/apps/infoalloggi/src/components/annunci_grid.tsx deleted file mode 100644 index f6b11ea..0000000 --- a/apps/infoalloggi/src/components/annunci_grid.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { CardAnnuncio } from "~/components/annuncio_card"; -import type { AnnuncioRicerca } from "~/server/controllers/annunci.controller"; - -//TODO usare anche in accordion e dialog pag ricerca servizio - -export const AnnunciGrid = ({ pagedata }: { pagedata: AnnuncioRicerca[] }) => { - return ( -
- {pagedata.map((annuncio) => ( - - ))} -
- ); -}; diff --git a/apps/infoalloggi/src/components/annuncio-interactions/annuncio_interactions.tsx b/apps/infoalloggi/src/components/annuncio-interactions/annuncio_interactions.tsx index 2629dbf..468bcc1 100644 --- a/apps/infoalloggi/src/components/annuncio-interactions/annuncio_interactions.tsx +++ b/apps/infoalloggi/src/components/annuncio-interactions/annuncio_interactions.tsx @@ -7,6 +7,7 @@ import LoadingButton from "~/components/custom_ui/loading-button"; import { Button, buttonVariants } from "~/components/ui/button"; import { cn } from "~/lib/utils"; import { useAnnuncio } from "~/providers/AnnuncioProvider"; +import { useServizio } from "~/providers/ServizioProvider"; import type { SessionContextType } from "~/providers/SessionProvider"; import type { AnnunciId } from "~/schemas/public/Annunci"; import type { UsersId } from "~/schemas/public/Users"; @@ -108,10 +109,14 @@ const ServizioInteraction = ({ ); } - return ; + return ; }; -const InteressatoButton = ({ annuncioId }: { annuncioId: AnnunciId }) => { +const InteressatoButtonUserOnly = ({ + annuncioId, +}: { + annuncioId: AnnunciId; +}) => { const { data: hasInterest, isLoading } = api.intrests.hasUserInterest.useQuery({ annuncioId, @@ -161,36 +166,57 @@ const InteressatoButton = ({ annuncioId }: { annuncioId: AnnunciId }) => { ); }; -export const InteressatoButtonBatchV = ({ +export const InteressatoButtonServizio = ({ annuncioId, - hasInterest, }: { annuncioId: AnnunciId; - hasInterest: boolean; }) => { + const { isAdmin, servizioId, userId } = useServizio(); const utils = api.useUtils(); - const { mutate: add } = api.intrests.addIntrest.useMutation({ + + const { mutate: adminAdd, isPending: isAdminPending } = + api.servizio.addServizioAnnunci.useMutation({ + onError: (error) => { + console.error(error); + toast.error("Errore durante l'aggiunta dell'annuncio"); + }, + onSuccess: async () => { + await utils.servizio.getAllServizioAnnunci.invalidate({ userId }); + await utils.servizio.getAnnunciAvailableToAdd.invalidate({ + servizioId, + }); + await utils.servizio.AnnuncioServizioTipologiaMatch.invalidate({ + userId, + }); + await utils.servizio.getCompatibileAnnunci.invalidate({ + servizioId, + }); + + toast.success("Annuncio aggiunto alla ricerca"); + }, + }); + + const { mutate: add, isPending } = api.intrests.addIntrest.useMutation({ onSuccess: async () => { await utils.intrests.getUserInterests.invalidate(); toast.success("Richiesta di interesse inviata con successo!"); }, }); - if (hasInterest) { - return ( - - - Hai già mandato una richiesta - - ); - } - return ( - + {isAdmin ? "Aggiungi annuncio" : "Sono interessato"} + ); }; diff --git a/apps/infoalloggi/src/components/annuncio_card.tsx b/apps/infoalloggi/src/components/annuncio_card.tsx index da64e0a..9dfce10 100644 --- a/apps/infoalloggi/src/components/annuncio_card.tsx +++ b/apps/infoalloggi/src/components/annuncio_card.tsx @@ -35,6 +35,8 @@ import { VideoPlayer } from "./videoPlayer"; type CardAnnuncioProps = AnnuncioRicerca & { className?: string; + noLink?: boolean; + onlyFirstImage?: boolean; }; export const CardAnnuncio = ({ @@ -55,23 +57,36 @@ export const CardAnnuncio = ({ updated_at, images, homepage, + noLink = false, + onlyFirstImage = false, }: CardAnnuncioProps) => { const { t, locale } = useTranslation(); const currentMonth = new Date().getMonth() + 1; const isAvailableNow = consegna === 0 || consegna === currentMonth; + const Wrapper = ({ children }: { children: React.ReactNode }) => { + if (noLink) { + return
{children}
; + } + return ( + + {children} + + ); + }; + return (
- +
@@ -120,69 +135,99 @@ export const CardAnnuncio = ({
)} - - - - {images?.map((img, idx) => ( - - - - ))} - {videos?.map((video) => { - if (!video) return null; - if (video.includes("youtu")) { - return null; - } - return ( - { - e.preventDefault(); - e.stopPropagation(); - }} - > - + + {images?.map((img, idx) => ( + + - ); - })} - + ))} + {videos?.map((video) => { + if (!video) return null; + if (video.includes("youtu")) { + return null; + } + return ( + { + e.preventDefault(); + e.stopPropagation(); + }} + > + + + ); + })} + -
e.preventDefault()} - onKeyDown={(e) => e.stopPropagation()} - role="button" - tabIndex={0} - > - - -
-
+
{ + e.preventDefault(); + e.stopPropagation(); + }} + onKeyDown={(e) => e.stopPropagation()} + role="button" + tabIndex={0} + > + { + e.preventDefault(); + e.stopPropagation(); // Add this to the buttons too + }} + /> + { + e.preventDefault(); + e.stopPropagation(); // Add this to the buttons too + }} + /> +
+ + ) : ( + <> + {images && images.length > 0 && images[0] ? ( + + ) : ( +
+ )} + + )}
- + ); }; diff --git a/apps/infoalloggi/src/components/custom_ui/loading-button.tsx b/apps/infoalloggi/src/components/custom_ui/loading-button.tsx index 08f13a6..9297f77 100644 --- a/apps/infoalloggi/src/components/custom_ui/loading-button.tsx +++ b/apps/infoalloggi/src/components/custom_ui/loading-button.tsx @@ -15,17 +15,14 @@ const LoadingButton = ({ }: ButtonProps & { loading?: boolean }) => { return ( ); diff --git a/apps/infoalloggi/src/components/servizio/annuncio_actions.tsx b/apps/infoalloggi/src/components/servizio/annuncio_actions.tsx index 1c72d87..ec1a7af 100644 --- a/apps/infoalloggi/src/components/servizio/annuncio_actions.tsx +++ b/apps/infoalloggi/src/components/servizio/annuncio_actions.tsx @@ -6,21 +6,16 @@ import { ExternalLink, FolderKanban, Pen, - Plus, ShieldUser, Trash2, Wrench, } from "lucide-react"; import Link from "next/link"; -import { useRef, useState } from "react"; +import { useState } from "react"; import toast from "react-hot-toast"; import { z } from "zod/v4"; import { ExtIcon } from "~/components/area-riservata/allegati"; import { Confirm } from "~/components/confirm"; -import { - AnimatedButton, - type AnimatedButtonRef, -} from "~/components/custom_ui/animated-button"; import { Credenza, CredenzaBody, @@ -62,7 +57,6 @@ import { UploadModal } from "~/components/upload_modal"; import { cn, formatCurrency } from "~/lib/utils"; import { useTranslation } from "~/providers/I18nProvider"; import { useServizio, useServizioAnnuncio } from "~/providers/ServizioProvider"; -import type { AnnunciId } from "~/schemas/public/Annunci"; import type { ServizioAnnunciUpdate } from "~/schemas/public/ServizioAnnunci"; import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum"; import type { FileMetadataWithAdmin } from "~/server/services/storage.service"; @@ -117,7 +111,7 @@ export const AnnuncioActions = () => { ); }; - -export const AddButton = ({ annuncioId }: { annuncioId: AnnunciId }) => { - const { servizioId, userId } = useServizio(); - const utils = api.useUtils(); - const { mutate } = api.servizio.addServizioAnnunci.useMutation({ - onError: (error) => { - console.error(error); - toast.error("Errore durante l'aggiunta dell'annuncio"); - }, - onSuccess: async () => { - await utils.servizio.getAllServizioAnnunci.invalidate({ userId }); - await utils.servizio.getAnnunciAvailableToAdd.invalidate({ - servizioId, - }); - await utils.servizio.AnnuncioServizioTipologiaMatch.invalidate({ - userId, - }); - await utils.servizio.getCompatibileAnnunci.invalidate({ - servizioId, - }); - - toast.success("Annuncio aggiunto alla ricerca"); - }, - }); - - const buttonRef = useRef(null); - return ( - { - buttonRef.current?.sparkle(); - //wait for the animation to finish - await new Promise((resolve) => setTimeout(resolve, 1000)); - mutate({ annunci: [annuncioId], servizioId }); - }} - ref={buttonRef} - sparklesClassName="fill-yellow-500 stroke-transparent" - sparklesIcon="thumbs-up" - sparklesNumber={15} - sparklesRadius={60} - sparklesScale={[1, 1.5]} - variant="info" - > - - Aggiungi agli annunci da contattare - - ); -}; diff --git a/apps/infoalloggi/src/components/servizio/main.tsx b/apps/infoalloggi/src/components/servizio/main.tsx index 7f6fbf1..29c030b 100644 --- a/apps/infoalloggi/src/components/servizio/main.tsx +++ b/apps/infoalloggi/src/components/servizio/main.tsx @@ -1,5 +1,5 @@ import { add } from "date-fns"; -import { Package, PackageCheck, UserCircle } from "lucide-react"; +import { CalendarClock, Package, PackageCheck, UserCircle } from "lucide-react"; import Link from "next/link"; import { useRouter } from "next/router"; import { useEffect } from "react"; @@ -209,7 +209,7 @@ export const ServizioContent = () => { -
+
@@ -225,10 +225,15 @@ export const ServizioContent = () => { value={openContattiAnnunci.length * 10} />
- - {`Durata servizio: ${new Date(servizio.decorrenza).toLocaleDateString("it-IT")} - ${new Date(add(servizio.decorrenza, { days: 60 })).toLocaleDateString("it-IT")}`} - - {/* */} +
+
+ + Durata servizio: +
+ + {`${new Date(servizio.decorrenza).toLocaleDateString("it-IT")} - ${new Date(add(servizio.decorrenza, { days: 60 })).toLocaleDateString("it-IT")}`} + +
{annuncioConfermato.length > 0 && (
@@ -245,17 +250,17 @@ export const ServizioContent = () => { >

{a.codice} - confermato il:{" "} - {/** biome-ignore lint/style/noNonNullAssertion: */} - {new Date(a.accettato_conferma_at!).toLocaleDateString( - "it", - { - day: "2-digit", - hour: "2-digit", - minute: "2-digit", - month: "2-digit", - year: "numeric", - }, - )} + {a.accettato_conferma_at && + new Date(a.accettato_conferma_at).toLocaleDateString( + "it", + { + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + month: "2-digit", + year: "numeric", + }, + )}

{ Preferenze - + {isLoading ? ( ) : ( diff --git a/apps/infoalloggi/src/components/servizio/servizio_annunci_accordions.tsx b/apps/infoalloggi/src/components/servizio/servizio_annunci_accordions.tsx index 658a6c8..894504b 100644 --- a/apps/infoalloggi/src/components/servizio/servizio_annunci_accordions.tsx +++ b/apps/infoalloggi/src/components/servizio/servizio_annunci_accordions.tsx @@ -2,8 +2,7 @@ import { ExternalLink, Trash2 } from "lucide-react"; import Link from "next/link"; import type { ReactNode } from "react"; import toast from "react-hot-toast"; -import { InteressatoButtonBatchV } from "~/components/annuncio-interactions/annuncio_interactions"; -import { AddButton } from "~/components/servizio/annuncio_actions"; +import { InteressatoButtonServizio } from "~/components/annuncio-interactions/annuncio_interactions"; import { AnnuncioCard, BasicAnnuncioCard, @@ -22,6 +21,7 @@ import { import type { UsersId } from "~/schemas/public/Users"; import type { ServizioData } from "~/server/controllers/servizio.controller"; import { api } from "~/utils/api"; +import { CardAnnuncio } from "../annuncio_card"; import { LoadingPage } from "../loading"; import { Dialog, @@ -44,7 +44,7 @@ const DialogServizio = ({ return ( {trigger} - + {title} @@ -221,25 +221,21 @@ export const AnnunciSelezionatiAccordion = ({ ); }; export const AnnunciCompatibili = () => { - const { servizioId, userId, isAdmin } = useServizio(); + const { servizioId } = useServizio(); const { data, isLoading } = api.servizio.getCompatibileAnnunci.useQuery({ servizioId, }); - const { data: userIntrests } = api.intrests.getUserInterests.useQuery({ - userId, - }); - return ( Esplora Annunci Compatibili } > -
+
{isLoading ? ( ) : ( @@ -252,25 +248,23 @@ export const AnnunciCompatibili = () => {
) : ( - data.map((a) => ( - - {isAdmin ? ( - - ) : ( - - )} - - } - key={a.id} - /> - )) +
+ {data.map((annuncio) => ( +
+ + + +
+ ))} +
)} )} diff --git a/apps/infoalloggi/src/forms/FormNewServizio.tsx b/apps/infoalloggi/src/forms/FormNewServizio.tsx index 4bf05a2..6bad77d 100644 --- a/apps/infoalloggi/src/forms/FormNewServizio.tsx +++ b/apps/infoalloggi/src/forms/FormNewServizio.tsx @@ -471,42 +471,56 @@ export const FormNewServizio = ({
- - - - - - - - - - + {isLimited ? ( +
+

+ {field.value + ? format(field.value, "dd/MM/yyyy") + : "Errore data invalida"} +

+

+ La scadenza non può essere modificata. Contatta il + supporto se necessario. +

+
+ ) : ( + + + + + + + + + + + )} )} /> diff --git a/apps/infoalloggi/src/pages/annunci.tsx b/apps/infoalloggi/src/pages/annunci.tsx index 14b5352..eb76684 100644 --- a/apps/infoalloggi/src/pages/annunci.tsx +++ b/apps/infoalloggi/src/pages/annunci.tsx @@ -15,9 +15,9 @@ import type { GetServerSideProps } from "next"; import Head from "next/head"; import { useEffect, useMemo, useState } from "react"; import { AccordionComp } from "~/components/accordionComp"; -import { AnnunciGrid } from "~/components/annunci_grid"; import { MapSection } from "~/components/annunci_map"; import { CTA_TipologiaModal } from "~/components/annunci_tutorial"; +import { CardAnnuncio } from "~/components/annuncio_card"; import { CodiceBox } from "~/components/codiceRicerca"; import { Layout } from "~/components/Layout"; import { LoadingPage } from "~/components/loading"; @@ -367,7 +367,11 @@ const AnnunciList = () => { {status === "pending" ? ( ) : ( - +
+ {data.annunci.map((annuncio) => ( + + ))} +
)}
diff --git a/apps/infoalloggi/src/pages/area-riservata/admin/user-view/servizio/[userId].tsx b/apps/infoalloggi/src/pages/area-riservata/admin/user-view/servizio/[userId].tsx index 20060a3..ff4651e 100644 --- a/apps/infoalloggi/src/pages/area-riservata/admin/user-view/servizio/[userId].tsx +++ b/apps/infoalloggi/src/pages/area-riservata/admin/user-view/servizio/[userId].tsx @@ -152,7 +152,7 @@ const NewServizioModal = ({ Nuovo Servizio - + Creazione Servizio desc diff --git a/apps/infoalloggi/src/server/controllers/servizio.controller.ts b/apps/infoalloggi/src/server/controllers/servizio.controller.ts index 352070e..3a6bed8 100644 --- a/apps/infoalloggi/src/server/controllers/servizio.controller.ts +++ b/apps/infoalloggi/src/server/controllers/servizio.controller.ts @@ -41,6 +41,7 @@ import { import { db } from "~/server/db"; import { NewMail, type NewMailProps } from "~/server/services/mailer"; import { getUser } from "~/server/services/user.service"; +import type { AnnuncioRicerca } from "./annunci.controller"; export const addServizio = async (data: NewServizio) => { try { @@ -1514,7 +1515,9 @@ export const SendContactEmail = async ({ } }; -export const getCompatibileAnnunci = async (servizioId: ServizioServizioId) => { +export const getCompatibileAnnunci = async ( + servizioId: ServizioServizioId, +): Promise => { try { const servizio = await getServizioById(servizioId); if (!servizio) { @@ -1527,18 +1530,25 @@ export const getCompatibileAnnunci = async (servizioId: ServizioServizioId) => { let qry = db .selectFrom("annunci") .select((eb) => [ - "annunci.id", - "annunci.codice", - "annunci.prezzo", - "annunci.desc_en", - "annunci.desc_it", - "annunci.titolo_en", - "annunci.titolo_it", - "annunci.tipo", - "annunci.consegna", - "annunci.stato", - "annunci.web", - "annunci.updated_at", + "id", + "codice", + "comune", + "provincia", + "mq", + "prezzo", + "desc_en", + "desc_it", + "titolo_en", + "titolo_it", + "tipo", + "consegna", + "stato", + "web", + "updated_at", + "homepage", + "numero_camere", + "url_video", + "modificato_il", jsonArrayFrom( eb .selectFrom("images_refs")