feat: add incroci page and API integration for managing incroci data
This commit is contained in:
parent
5579dfeed0
commit
81337c852f
6 changed files with 166 additions and 0 deletions
|
|
@ -659,6 +659,7 @@ export const en: LangDict = {
|
||||||
{ href: "/area-riservata/admin/utenti", title: "Users" },
|
{ href: "/area-riservata/admin/utenti", title: "Users" },
|
||||||
{ href: "/area-riservata/admin/chats", title: "Chat List" },
|
{ href: "/area-riservata/admin/chats", title: "Chat List" },
|
||||||
{ href: "/area-riservata/admin/ordini", title: "Orders" },
|
{ href: "/area-riservata/admin/ordini", title: "Orders" },
|
||||||
|
{ href: "/area-riservata/admin/incroci", title: "Incroci" },
|
||||||
{ href: "/area-riservata/admin/annunci", title: "Ads" },
|
{ href: "/area-riservata/admin/annunci", title: "Ads" },
|
||||||
{ href: "/area-riservata/admin/prezziario", title: "Pricing" },
|
{ href: "/area-riservata/admin/prezziario", title: "Pricing" },
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -664,6 +664,7 @@ export const it: LangDict = {
|
||||||
{ href: "/area-riservata/admin/utenti", title: "Utenti" },
|
{ href: "/area-riservata/admin/utenti", title: "Utenti" },
|
||||||
{ href: "/area-riservata/admin/chats", title: "Lista Chat" },
|
{ href: "/area-riservata/admin/chats", title: "Lista Chat" },
|
||||||
{ href: "/area-riservata/admin/ordini", title: "Ordini" },
|
{ href: "/area-riservata/admin/ordini", title: "Ordini" },
|
||||||
|
{ href: "/area-riservata/admin/incroci", title: "Incroci" },
|
||||||
{ href: "/area-riservata/admin/annunci", title: "Annunci" },
|
{ href: "/area-riservata/admin/annunci", title: "Annunci" },
|
||||||
{ href: "/area-riservata/admin/prezziario", title: "Prezziario" },
|
{ href: "/area-riservata/admin/prezziario", title: "Prezziario" },
|
||||||
],
|
],
|
||||||
|
|
|
||||||
118
apps/infoalloggi/src/pages/area-riservata/admin/incroci.tsx
Normal file
118
apps/infoalloggi/src/pages/area-riservata/admin/incroci.tsx
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
import { format } from "date-fns";
|
||||||
|
import type { GetServerSideProps } from "next";
|
||||||
|
import Head from "next/head";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { AreaRiservataLayout } from "~/components/Layout";
|
||||||
|
import { LoadingPage } from "~/components/loading";
|
||||||
|
import { Status500 } from "~/components/status-page";
|
||||||
|
import { Button } from "~/components/ui/button";
|
||||||
|
import { Separator } from "~/components/ui/separator";
|
||||||
|
import type { NextPageWithLayout } from "~/pages/_app";
|
||||||
|
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
|
||||||
|
import { api } from "~/utils/api";
|
||||||
|
|
||||||
|
const Incroci: NextPageWithLayout = () => {
|
||||||
|
const { data, isLoading } = api.incroci.getAll.useQuery();
|
||||||
|
|
||||||
|
if (isLoading) return <LoadingPage />;
|
||||||
|
if (!data) return <Status500 />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>Incorici - Infoalloggi.it</title>
|
||||||
|
</Head>
|
||||||
|
|
||||||
|
<div className="mx-3 flex flex-1 flex-col gap-4 overflow-auto pt-5">
|
||||||
|
<div className="items-start justify-between md:flex">
|
||||||
|
<div className="mx-1 flex items-center">
|
||||||
|
<h3 className="font-bold text-2xl">Incroci</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-4">
|
||||||
|
{data.map((incrocio) => (
|
||||||
|
<div className="rounded-md border p-4" key={incrocio.id}>
|
||||||
|
<div className="flex items-center gap-2 font-bold text-xl">
|
||||||
|
<span>Cod:</span>
|
||||||
|
<span>{incrocio.codice}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="font-bold">Titolo:</span>
|
||||||
|
<span>{incrocio.titolo_it}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="font-bold">Richieste:</span>
|
||||||
|
</div>
|
||||||
|
<ul className="ml-4 space-y-2">
|
||||||
|
{incrocio.richieste.map((r) => (
|
||||||
|
<li key={r.servizio_id}>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="font-bold">Username:</span>
|
||||||
|
<span>{r.username}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="font-bold">Aggiunto il:</span>
|
||||||
|
<span>
|
||||||
|
{format(new Date(r.created_at), "dd/MM/yyyy")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="font-bold">Aperto Contatti il:</span>
|
||||||
|
<span>
|
||||||
|
{r.open_contatti_at
|
||||||
|
? format(new Date(r.open_contatti_at), "dd/MM/yyyy")
|
||||||
|
: "Non aperto"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="font-bold">Mandato conferma il:</span>
|
||||||
|
<span>
|
||||||
|
{r.user_confirmed_at
|
||||||
|
? format(new Date(r.user_confirmed_at), "dd/MM/yyyy")
|
||||||
|
: "Non confermato"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="font-bold">Conferma da Admin:</span>
|
||||||
|
<span>{r.hasConfermaAdmin ? "Si" : "No"}</span>
|
||||||
|
</div>
|
||||||
|
<Link
|
||||||
|
href={`/area-riservata/admin/user-view/servizio/${r.userId}/${r.servizio_id}`}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<Button size="sm">Apri Servizio</Button>
|
||||||
|
</Link>
|
||||||
|
<Separator className="mt-2" />
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Incroci;
|
||||||
|
|
||||||
|
export const getServerSideProps = (async (context) => {
|
||||||
|
const access_token = context.req.cookies.access_token;
|
||||||
|
|
||||||
|
const helpers = await TrpcAuthedFetchingIstance({ access_token });
|
||||||
|
if (helpers) {
|
||||||
|
await helpers.trpc.incroci.getAll.prefetch();
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
trpcState: helpers.trpc.dehydrate(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
props: {},
|
||||||
|
};
|
||||||
|
}) satisfies GetServerSideProps;
|
||||||
|
|
||||||
|
Incroci.getLayout = function getLayout(page) {
|
||||||
|
return <AreaRiservataLayout>{page}</AreaRiservataLayout>;
|
||||||
|
};
|
||||||
|
|
@ -22,6 +22,7 @@ import { bannersRouter } from "./routers/banners";
|
||||||
import { catastoRouter } from "./routers/catasto";
|
import { catastoRouter } from "./routers/catasto";
|
||||||
import { etichetteRouter } from "./routers/etichette";
|
import { etichetteRouter } from "./routers/etichette";
|
||||||
import { flagsRouter } from "./routers/flags";
|
import { flagsRouter } from "./routers/flags";
|
||||||
|
import { incrociRouter } from "./routers/incroci";
|
||||||
import { inviteRouter } from "./routers/invite";
|
import { inviteRouter } from "./routers/invite";
|
||||||
import { potenzialiRouter } from "./routers/potenziali";
|
import { potenzialiRouter } from "./routers/potenziali";
|
||||||
import { revalidationRouter } from "./routers/revalidation";
|
import { revalidationRouter } from "./routers/revalidation";
|
||||||
|
|
@ -59,5 +60,6 @@ export const appRouter = createTRPCRouter({
|
||||||
revalidation: revalidationRouter,
|
revalidation: revalidationRouter,
|
||||||
potenziali: potenzialiRouter,
|
potenziali: potenzialiRouter,
|
||||||
invite: inviteRouter,
|
invite: inviteRouter,
|
||||||
|
incroci: incrociRouter,
|
||||||
});
|
});
|
||||||
export type AppRouter = typeof appRouter;
|
export type AppRouter = typeof appRouter;
|
||||||
|
|
|
||||||
8
apps/infoalloggi/src/server/api/routers/incroci.ts
Normal file
8
apps/infoalloggi/src/server/api/routers/incroci.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { adminProcedure, createTRPCRouter } from "~/server/api/trpc";
|
||||||
|
import { getAll } from "~/server/controllers/incroci.controller";
|
||||||
|
|
||||||
|
export const incrociRouter = createTRPCRouter({
|
||||||
|
getAll: adminProcedure.query(async () => {
|
||||||
|
return await getAll();
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { jsonArrayFrom } from "kysely/helpers/postgres";
|
||||||
|
import { db } from "../db";
|
||||||
|
|
||||||
|
export const getAll = async () => {
|
||||||
|
const data = await db
|
||||||
|
.selectFrom("annunci")
|
||||||
|
.innerJoin("servizio_annunci", "servizio_annunci.annunci_id", "annunci.id")
|
||||||
|
|
||||||
|
.select((eb) => [
|
||||||
|
"annunci.id",
|
||||||
|
"annunci.titolo_it",
|
||||||
|
"annunci.codice",
|
||||||
|
jsonArrayFrom(
|
||||||
|
eb
|
||||||
|
.selectFrom("servizio_annunci")
|
||||||
|
.select([
|
||||||
|
"servizio_annunci.open_contatti_at",
|
||||||
|
"servizio_annunci.servizio_id",
|
||||||
|
"servizio_annunci.created_at",
|
||||||
|
"servizio_annunci.user_confirmed_at",
|
||||||
|
"servizio_annunci.hasConfermaAdmin",
|
||||||
|
])
|
||||||
|
.leftJoin(
|
||||||
|
"servizio",
|
||||||
|
"servizio.servizio_id",
|
||||||
|
"servizio_annunci.servizio_id",
|
||||||
|
)
|
||||||
|
.leftJoin("users", "users.id", "servizio.user_id")
|
||||||
|
.select(["users.username", "users.id as userId"])
|
||||||
|
.whereRef("servizio_annunci.annunci_id", "=", "annunci.id"),
|
||||||
|
).as("richieste"),
|
||||||
|
])
|
||||||
|
.groupBy("annunci.id")
|
||||||
|
.execute();
|
||||||
|
return data;
|
||||||
|
};
|
||||||
Loading…
Add table
Reference in a new issue