feat: implement TabRicerca component for user service search and integrate collapsible functionality
This commit is contained in:
parent
4982d064e3
commit
243148267b
6 changed files with 464 additions and 16 deletions
|
|
@ -1,7 +1,6 @@
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import { LoadingPage } from "~/components/loading";
|
import { LoadingPage } from "~/components/loading";
|
||||||
import type { UsersId } from "~/schemas/public/Users";
|
import type { UsersId } from "~/schemas/public/Users";
|
||||||
import { ServizioContainer } from "~/components/servizio/main";
|
|
||||||
import { AccordionComp } from "~/components/accordionComp";
|
import { AccordionComp } from "~/components/accordionComp";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import TimeserieBarChart from "~/components/timeserieBarChart";
|
import TimeserieBarChart from "~/components/timeserieBarChart";
|
||||||
|
|
@ -13,6 +12,7 @@ import {
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "~/components/ui/card";
|
} from "~/components/ui/card";
|
||||||
import TimeserieBarChartStacked from "~/components/timeserieBarChartStacked";
|
import TimeserieBarChartStacked from "~/components/timeserieBarChartStacked";
|
||||||
|
import { TabRicerca } from "~/components/tables/ricerca-table";
|
||||||
|
|
||||||
export const AdminDashboard = () => {
|
export const AdminDashboard = () => {
|
||||||
const { data: stats, isLoading } = api.stats.adminDashStats.useQuery();
|
const { data: stats, isLoading } = api.stats.adminDashStats.useQuery();
|
||||||
|
|
@ -66,8 +66,8 @@ export const AdminDashboard = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UserDashboard = ({ userId }: { userId: UsersId }) => {
|
export const UserDashboard = ({ userId }: { userId: UsersId }) => {
|
||||||
const { data: servizi, isLoading: loadingServizi } =
|
// const { data: servizi, isLoading: loadingServizi } =
|
||||||
api.servizio.getAllServizioAnnunci.useQuery({ userId });
|
// api.servizio.getAllServizioAnnunci.useQuery({ userId });
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<div className="mx-1 flex-1 overflow-auto">
|
<div className="mx-1 flex-1 overflow-auto">
|
||||||
|
|
@ -79,7 +79,8 @@ export const UserDashboard = ({ userId }: { userId: UsersId }) => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col space-y-5 px-2">
|
<div className="flex flex-col space-y-5 px-2">
|
||||||
{loadingServizi ? (
|
<TabRicerca userId={userId} isAdmin={false} />
|
||||||
|
{/* {loadingServizi ? (
|
||||||
<LoadingPage />
|
<LoadingPage />
|
||||||
) : (
|
) : (
|
||||||
servizi?.map((servizio, idx) => (
|
servizi?.map((servizio, idx) => (
|
||||||
|
|
@ -90,7 +91,7 @@ export const UserDashboard = ({ userId }: { userId: UsersId }) => {
|
||||||
isAdmin={false}
|
isAdmin={false}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
)}
|
)} */}
|
||||||
</div>
|
</div>
|
||||||
<AccordionComp
|
<AccordionComp
|
||||||
texts={t.area_riservata.dash_accordion_minifaq}
|
texts={t.area_riservata.dash_accordion_minifaq}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,10 @@ import type { ServizioData } from "~/server/controllers/servizio.controller";
|
||||||
import { Package, PackageCheck, UserCircle } from "lucide-react";
|
import { Package, PackageCheck, UserCircle } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Progress } from "~/components/ui/progress";
|
import { Progress } from "~/components/ui/progress";
|
||||||
import { ServizioActions } from "~/components/servizio/servizio_actions";
|
import {
|
||||||
|
ServizioActions,
|
||||||
|
ServizioActions2,
|
||||||
|
} from "~/components/servizio/servizio_actions";
|
||||||
import { SaldoButton } from "~/components/servizio/interactions";
|
import { SaldoButton } from "~/components/servizio/interactions";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import {
|
import {
|
||||||
|
|
@ -84,6 +87,270 @@ const ServizioCard = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const ServizioContent = () => {
|
||||||
|
const { servizio, isAdmin, userId } = useServizio();
|
||||||
|
const utils = api.useUtils();
|
||||||
|
const { mutate: updateServizio } = api.servizio.updateServizio.useMutation({
|
||||||
|
onSuccess: async () => {
|
||||||
|
toast.success("Servizio modificato con successo");
|
||||||
|
await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast.error(error.message);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
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"
|
||||||
|
header={
|
||||||
|
<>
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<CardTitle className="flex items-center gap-2 text-xl sm:text-2xl">
|
||||||
|
<Package className="text-primary size-6" />
|
||||||
|
Cerco Affitto {servizio.tipologia}
|
||||||
|
</CardTitle>
|
||||||
|
|
||||||
|
<CardDescription className="text-foreground/70 space-y-2 pl-2">
|
||||||
|
<p>
|
||||||
|
aggiunto il{" "}
|
||||||
|
{servizio.created_at.toLocaleDateString("it", {
|
||||||
|
year: "numeric",
|
||||||
|
month: "2-digit",
|
||||||
|
day: "2-digit",
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
</CardDescription>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
content={
|
||||||
|
<>
|
||||||
|
<p className="text-lg font-medium">Servizio interrotto</p>
|
||||||
|
<p>
|
||||||
|
Non è possibile riutilizzare questo servizio, poichè è stato
|
||||||
|
interrotto.
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!servizio.isOkAcconto || servizio.decorrenza === null) {
|
||||||
|
return (
|
||||||
|
<ServizioCard
|
||||||
|
header={
|
||||||
|
<div className="flex w-full flex-col gap-2">
|
||||||
|
{/* <div className="flex w-full flex-col gap-4">
|
||||||
|
<CardTitle className="flex items-center gap-2 text-xl sm:text-2xl">
|
||||||
|
<Package className="text-primary size-6" />
|
||||||
|
Cerco Affitto {servizio.tipologia}
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription className="text-foreground/70 pl-2">
|
||||||
|
<p>Servizio non attivo</p>
|
||||||
|
</CardDescription>
|
||||||
|
</div> */}
|
||||||
|
<span className="text-foreground/70 text-lg">
|
||||||
|
Servizio non attivo
|
||||||
|
</span>
|
||||||
|
<ServizioActions2 />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
content={
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<div className="flex flex-wrap gap-3">
|
||||||
|
<Link
|
||||||
|
href={`/servizio/onboard/${servizio.servizio_id}`}
|
||||||
|
aria-label="Attiva Servizio"
|
||||||
|
>
|
||||||
|
<Button>Procedi all'attivazione</Button>
|
||||||
|
</Link>
|
||||||
|
{isAdmin && (
|
||||||
|
<Button
|
||||||
|
onClick={() =>
|
||||||
|
updateServizio({
|
||||||
|
servizioId: servizio.servizio_id,
|
||||||
|
data: {
|
||||||
|
isOkAcconto: true,
|
||||||
|
decorrenza: new Date(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
variant="success"
|
||||||
|
>
|
||||||
|
Attiva Manualmente (Azione Admin)
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{isAdmin && (
|
||||||
|
<AnnunciSelezionati
|
||||||
|
isConfirming={false}
|
||||||
|
annunci={servizio.annunci}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const annuncioConfermato = servizio.annunci.filter(
|
||||||
|
(a) => a.accettato_conferma_at !== null,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (servizio.isOkSaldo) {
|
||||||
|
return (
|
||||||
|
<ServizioCard
|
||||||
|
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="text-primary size-6" />
|
||||||
|
Cerco Affitto {servizio.tipologia}
|
||||||
|
</CardTitle>
|
||||||
|
|
||||||
|
<CardDescription className="text-foreground/70 space-y-2 pl-2">
|
||||||
|
<p>
|
||||||
|
aggiunto il{" "}
|
||||||
|
{servizio.created_at.toLocaleDateString("it", {
|
||||||
|
year: "numeric",
|
||||||
|
month: "2-digit",
|
||||||
|
day: "2-digit",
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
</CardDescription>
|
||||||
|
</div> */}
|
||||||
|
|
||||||
|
<ServizioActions2 />
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
content={
|
||||||
|
<>
|
||||||
|
{annuncioConfermato.map((data) => {
|
||||||
|
return (
|
||||||
|
<ServizioAnnuncioProvider data={data} key={data.id}>
|
||||||
|
<AnnuncioCard />
|
||||||
|
</ServizioAnnuncioProvider>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
header={
|
||||||
|
<>
|
||||||
|
{/* <div className="flex w-full flex-col gap-2">
|
||||||
|
<CardTitle className="flex items-center gap-2 text-xl sm:text-2xl">
|
||||||
|
<Package className="text-primary size-6" />
|
||||||
|
Cerco Affitto {servizio.tipologia}
|
||||||
|
</CardTitle>
|
||||||
|
|
||||||
|
<CardDescription className="text-foreground/70 space-y-2 pl-2">
|
||||||
|
<p>
|
||||||
|
aggiunto il{" "}
|
||||||
|
{servizio.created_at.toLocaleDateString("it", {
|
||||||
|
year: "numeric",
|
||||||
|
month: "2-digit",
|
||||||
|
day: "2-digit",
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
</CardDescription>
|
||||||
|
</div> */}
|
||||||
|
|
||||||
|
<ServizioActions2 />
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
content={
|
||||||
|
<>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<UserCircle className="text-primary size-6" />
|
||||||
|
<span className="font-medium">Contatti sbloccati</span>
|
||||||
|
</div>
|
||||||
|
<span className="text-sm">{openContattiCount} / 10</span>
|
||||||
|
</div>
|
||||||
|
<Progress value={openContattiCount * 10} className="h-2" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ServizioDuration decorrenza={servizio.decorrenza} />
|
||||||
|
|
||||||
|
{annuncioConfermato.length > 0 && (
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<PackageCheck className="text-primary size-6" />
|
||||||
|
<span className="font-medium">Saldi in attesa:</span>
|
||||||
|
</div>
|
||||||
|
{servizio.annunci
|
||||||
|
.filter((a) => a.accettato_conferma_at !== null)
|
||||||
|
.map((a) => (
|
||||||
|
<div
|
||||||
|
key={a.annunci_id}
|
||||||
|
className="flex items-center gap-2 rounded-md bg-sky-400 p-2"
|
||||||
|
>
|
||||||
|
<h3>
|
||||||
|
{a.codice} - confermato il:{" "}
|
||||||
|
{new Date(a.accettato_conferma_at!).toLocaleDateString(
|
||||||
|
"it",
|
||||||
|
{
|
||||||
|
year: "numeric",
|
||||||
|
month: "2-digit",
|
||||||
|
day: "2-digit",
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
</h3>
|
||||||
|
<SaldoButton
|
||||||
|
variant={"outline"}
|
||||||
|
className="border-none"
|
||||||
|
annuncioId={a.annunci_id}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<AnnunciInConferma annunci={annunciInConferma} />
|
||||||
|
<AnnunciSelezionati
|
||||||
|
isConfirming={annunciInConferma.length > 0}
|
||||||
|
annunci={annunciNotInConferma}
|
||||||
|
/>
|
||||||
|
<AnnunciCompatibili />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const ServizioMain = () => {
|
const ServizioMain = () => {
|
||||||
const { servizio, isAdmin, userId } = useServizio();
|
const { servizio, isAdmin, userId } = useServizio();
|
||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import {
|
||||||
AlertDialogTitle,
|
AlertDialogTitle,
|
||||||
AlertDialogTrigger,
|
AlertDialogTrigger,
|
||||||
} from "~/components/ui/alert-dialog";
|
} from "~/components/ui/alert-dialog";
|
||||||
import { Calculator, ClockAlert, Plus, Wrench } from "lucide-react";
|
import { Bug, Calculator, ClockAlert, Plus, Wrench } from "lucide-react";
|
||||||
import { FormNewServizio, type FormValues } from "~/forms/FormNewServizio";
|
import { FormNewServizio, type FormValues } from "~/forms/FormNewServizio";
|
||||||
import {
|
import {
|
||||||
Credenza,
|
Credenza,
|
||||||
|
|
@ -45,6 +45,11 @@ import {
|
||||||
FormEditServizio,
|
FormEditServizio,
|
||||||
type FormValues as EditFormValues,
|
type FormValues as EditFormValues,
|
||||||
} from "~/forms/FormEditServizioAdmin";
|
} from "~/forms/FormEditServizioAdmin";
|
||||||
|
import {
|
||||||
|
Collapsible,
|
||||||
|
CollapsibleContent,
|
||||||
|
CollapsibleTrigger,
|
||||||
|
} from "~/components/ui/collapsible";
|
||||||
|
|
||||||
export const ServizioActions = () => {
|
export const ServizioActions = () => {
|
||||||
const { servizio, isAdmin, userId } = useServizio();
|
const { servizio, isAdmin, userId } = useServizio();
|
||||||
|
|
@ -74,6 +79,36 @@ export const ServizioActions = () => {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const ServizioActions2 = () => {
|
||||||
|
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-col flex-wrap justify-between gap-3 sm:flex-row">
|
||||||
|
{(isAdmin || canUserEdit) && (
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<span className="hidden sm:block">Azioni: </span>
|
||||||
|
<EditPreferenze />
|
||||||
|
<InterruzioneServizio />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{isAdmin && (
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<AddAnnuncio servizioId={servizio.servizio_id} userId={userId} />
|
||||||
|
<EditServizioAdmin />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
export const AddAnnuncio = ({
|
export const AddAnnuncio = ({
|
||||||
servizioId,
|
servizioId,
|
||||||
userId,
|
userId,
|
||||||
|
|
@ -315,7 +350,7 @@ const EditPreferenze = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const EditServizioAdmin = () => {
|
const EditServizioAdmin = () => {
|
||||||
const { servizioId, userId } = useServizio();
|
const { servizioId, userId, servizio } = useServizio();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const { data, isLoading } = api.servizio.getServizio.useQuery({ servizioId });
|
const { data, isLoading } = api.servizio.getServizio.useQuery({ servizioId });
|
||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
|
|
@ -362,12 +397,26 @@ const EditServizioAdmin = () => {
|
||||||
Modifica
|
Modifica
|
||||||
</CredenzaDescription>
|
</CredenzaDescription>
|
||||||
</CredenzaHeader>
|
</CredenzaHeader>
|
||||||
<CredenzaBody className="max-h-[80vh] w-full overflow-y-auto pb-5">
|
<CredenzaBody className="max-h-[80vh] w-full space-y-2 overflow-y-auto pb-5">
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<LoadingPage />
|
<LoadingPage />
|
||||||
) : (
|
) : (
|
||||||
<FormEditServizio initialData={data} onSubmit={onSubmit} />
|
<FormEditServizio initialData={data} onSubmit={onSubmit} />
|
||||||
)}
|
)}
|
||||||
|
<Collapsible>
|
||||||
|
<CollapsibleTrigger asChild>
|
||||||
|
<Button variant="warning" className="items-center gap-2">
|
||||||
|
<Bug /> Debug Info Servizio
|
||||||
|
</Button>
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
<CollapsibleContent>
|
||||||
|
{(() => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const { annunci, ...rest } = servizio;
|
||||||
|
return <pre>{JSON.stringify(rest, null, 2)}</pre>;
|
||||||
|
})()}
|
||||||
|
</CollapsibleContent>
|
||||||
|
</Collapsible>
|
||||||
</CredenzaBody>
|
</CredenzaBody>
|
||||||
</CredenzaContent>
|
</CredenzaContent>
|
||||||
</Credenza>
|
</Credenza>
|
||||||
|
|
|
||||||
109
apps/infoalloggi/src/components/tables/ricerca-table.tsx
Normal file
109
apps/infoalloggi/src/components/tables/ricerca-table.tsx
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
import type { UsersId } from "~/schemas/public/Users";
|
||||||
|
import { api } from "~/utils/api";
|
||||||
|
import { LoadingPage } from "~/components/loading";
|
||||||
|
import { Package } from "lucide-react";
|
||||||
|
import { ServizioProvider } from "~/providers/ServizioProvider";
|
||||||
|
import {
|
||||||
|
Collapsible,
|
||||||
|
CollapsibleContent,
|
||||||
|
CollapsibleTrigger,
|
||||||
|
} from "~/components/ui/collapsible";
|
||||||
|
import { useState } from "react";
|
||||||
|
import type { ServizioData } from "~/server/controllers/servizio.controller";
|
||||||
|
import { ServizioContent } from "~/components/servizio/main";
|
||||||
|
|
||||||
|
export const TabRicerca = ({
|
||||||
|
userId,
|
||||||
|
isAdmin,
|
||||||
|
}: {
|
||||||
|
userId: UsersId;
|
||||||
|
isAdmin: boolean;
|
||||||
|
}) => {
|
||||||
|
const { data, isLoading } = api.servizio.getAllServizioAnnunci.useQuery({
|
||||||
|
userId,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isLoading) return <LoadingPage />;
|
||||||
|
if (!data || data.length === 0) {
|
||||||
|
return (
|
||||||
|
<div className="m-4 rounded-md bg-yellow-100 p-4 text-yellow-900">
|
||||||
|
Nessun servizio attualmente inserito
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
{data.map((servizio, idx) => {
|
||||||
|
return (
|
||||||
|
<Row
|
||||||
|
key={idx}
|
||||||
|
servizio={servizio}
|
||||||
|
userId={userId}
|
||||||
|
isAdmin={isAdmin}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Row = ({
|
||||||
|
servizio,
|
||||||
|
userId,
|
||||||
|
isAdmin,
|
||||||
|
}: {
|
||||||
|
servizio: ServizioData;
|
||||||
|
userId: UsersId;
|
||||||
|
isAdmin: boolean;
|
||||||
|
}) => {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
return (
|
||||||
|
<ServizioProvider
|
||||||
|
isAdmin={isAdmin}
|
||||||
|
userId={userId}
|
||||||
|
servizioId={servizio.servizio_id}
|
||||||
|
servizio={servizio}
|
||||||
|
>
|
||||||
|
<Collapsible open={isOpen} onOpenChange={setIsOpen}>
|
||||||
|
<div className="border-border flex items-center rounded-md border py-2 shadow-sm hover:shadow-md">
|
||||||
|
<CollapsibleTrigger className="grid w-full cursor-pointer grid-cols-10 items-center">
|
||||||
|
<div className="col-span-2 sm:col-span-1">
|
||||||
|
<span className="text-xl">{isOpen ? "👇" : "👉"}</span>
|
||||||
|
</div>
|
||||||
|
<div className="col-span-6 flex items-center gap-2 font-semibold sm:text-lg">
|
||||||
|
<Package className="text-primary size-6" />
|
||||||
|
Affitto {servizio.tipologia}
|
||||||
|
</div>
|
||||||
|
<div className="col-span-2">
|
||||||
|
{servizio.isInterrotto ? (
|
||||||
|
<span className="text-red-500">Interrotto</span>
|
||||||
|
) : servizio.isOkAcconto && servizio.decorrenza !== null ? (
|
||||||
|
<span className="text-green-500">Attivo</span>
|
||||||
|
) : (
|
||||||
|
<span className="text-neutral-500">Inattivo</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="hidden text-sm sm:col-span-2 sm:contents sm:text-base">
|
||||||
|
{servizio.created_at.toLocaleDateString("it", {
|
||||||
|
month: "short",
|
||||||
|
day: "2-digit",
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</CollapsibleTrigger>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CollapsibleContent className="data-[state=open]:animate-collapsible-down data-[state=closed]:animate-collapsible-up mt-2 overflow-hidden transition-all duration-300 ease-in-out">
|
||||||
|
<ServizioProvider
|
||||||
|
isAdmin={isAdmin}
|
||||||
|
userId={userId}
|
||||||
|
servizioId={servizio.servizio_id}
|
||||||
|
servizio={servizio}
|
||||||
|
>
|
||||||
|
<ServizioContent />
|
||||||
|
</ServizioProvider>
|
||||||
|
</CollapsibleContent>
|
||||||
|
</Collapsible>
|
||||||
|
</ServizioProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
import { LoadingPage } from "~/components/loading";
|
|
||||||
import { AreaRiservataLayoutUserView } from "~/components/Layout";
|
import { AreaRiservataLayoutUserView } from "~/components/Layout";
|
||||||
import type { GetStaticProps } from "next";
|
import type { GetStaticProps } from "next";
|
||||||
import type { NextPageWithLayout } from "~/pages/_app";
|
import type { NextPageWithLayout } from "~/pages/_app";
|
||||||
import type { UsersId } from "~/schemas/public/Users";
|
import type { UsersId } from "~/schemas/public/Users";
|
||||||
import { api } from "~/utils/api";
|
|
||||||
import { zUserId } from "~/server/utils/zod_types";
|
import { zUserId } from "~/server/utils/zod_types";
|
||||||
import { ServizioContainer } from "~/components/servizio/main";
|
|
||||||
import { AnnunciRichiesti } from "~/components/servizio/servizio_annunci_accordions";
|
import { AnnunciRichiesti } from "~/components/servizio/servizio_annunci_accordions";
|
||||||
|
import { TabRicerca } from "~/components/tables/ricerca-table";
|
||||||
|
|
||||||
type RicercaUserProps = {
|
type RicercaUserProps = {
|
||||||
userId: UsersId;
|
userId: UsersId;
|
||||||
|
|
@ -15,8 +13,8 @@ type RicercaUserProps = {
|
||||||
const RicercaUser: NextPageWithLayout<RicercaUserProps> = ({
|
const RicercaUser: NextPageWithLayout<RicercaUserProps> = ({
|
||||||
userId,
|
userId,
|
||||||
}: RicercaUserProps) => {
|
}: RicercaUserProps) => {
|
||||||
const { data: servizi, isLoading: loadingServizi } =
|
// const { data: servizi, isLoading: loadingServizi } =
|
||||||
api.servizio.getAllServizioAnnunci.useQuery({ userId });
|
// api.servizio.getAllServizioAnnunci.useQuery({ userId });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-5">
|
<div className="space-y-5">
|
||||||
|
|
@ -27,7 +25,8 @@ const RicercaUser: NextPageWithLayout<RicercaUserProps> = ({
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col space-y-5">
|
<div className="flex flex-col space-y-5">
|
||||||
<AnnunciRichiesti userId={userId} />
|
<AnnunciRichiesti userId={userId} />
|
||||||
{loadingServizi ? (
|
<TabRicerca userId={userId} isAdmin />
|
||||||
|
{/* {loadingServizi ? (
|
||||||
<LoadingPage />
|
<LoadingPage />
|
||||||
) : (
|
) : (
|
||||||
servizi?.map((servizio, idx) => (
|
servizi?.map((servizio, idx) => (
|
||||||
|
|
@ -38,7 +37,7 @@ const RicercaUser: NextPageWithLayout<RicercaUserProps> = ({
|
||||||
isAdmin
|
isAdmin
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
)}
|
)} */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -100,8 +100,31 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes collapsible-down {
|
||||||
|
0% {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
height: var(--radix-collapsible-content-height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes collapsible-up {
|
||||||
|
0% {
|
||||||
|
height: var(--radix-collapsible-content-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
--animate-accordion-down: accordion-down 0.3s ease-out;
|
--animate-accordion-down: accordion-down 0.3s ease-out;
|
||||||
--animate-accordion-up: accordion-up 0.3s ease-out;
|
--animate-accordion-up: accordion-up 0.3s ease-out;
|
||||||
|
--animate-collapsible-down: collapsible-down 0.3s ease-out;
|
||||||
|
--animate-collapsible-up: collapsible-up 0.3s ease-in;
|
||||||
|
|
||||||
|
|
||||||
@keyframes caret-blink {
|
@keyframes caret-blink {
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue