2026-01-14 12:02:03 +01:00
|
|
|
import Head from "next/head";
|
2026-01-27 16:30:19 +01:00
|
|
|
import { useState } from "react";
|
|
|
|
|
import toast from "react-hot-toast";
|
|
|
|
|
import Input from "~/components/custom_ui/input";
|
|
|
|
|
import { MultiSelect } from "~/components/custom_ui/multiselect";
|
2026-01-14 12:02:03 +01:00
|
|
|
import { AreaRiservataLayout } from "~/components/Layout";
|
2026-01-27 16:30:19 +01:00
|
|
|
import { LoadingPage } from "~/components/loading";
|
|
|
|
|
import { Button } from "~/components/ui/button";
|
|
|
|
|
import { Label } from "~/components/ui/label";
|
2026-01-14 12:02:03 +01:00
|
|
|
import type { NextPageWithLayout } from "~/pages/_app";
|
2026-01-27 16:30:19 +01:00
|
|
|
import type { AnnunciId } from "~/schemas/public/Annunci";
|
2026-01-14 12:02:03 +01:00
|
|
|
import { api } from "~/utils/api";
|
|
|
|
|
|
|
|
|
|
const Impostazioni: NextPageWithLayout = () => {
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<Head>
|
2026-01-19 10:23:16 +01:00
|
|
|
<title>Impostazioni - Infoalloggi.it</title>
|
2026-01-14 12:02:03 +01:00
|
|
|
</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">Impostazioni</h3>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<StripeSection />
|
2026-01-27 16:30:19 +01:00
|
|
|
<SendEmailSection />
|
2026-01-14 12:02:03 +01:00
|
|
|
</div>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
export default Impostazioni;
|
|
|
|
|
|
|
|
|
|
Impostazioni.getLayout = function getLayout(page) {
|
|
|
|
|
return <AreaRiservataLayout>{page}</AreaRiservataLayout>;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const StripeSection = () => {
|
|
|
|
|
const { data, isLoading } = api.stripe.health.useQuery();
|
|
|
|
|
if (isLoading) {
|
|
|
|
|
return <div>Loading...</div>;
|
|
|
|
|
}
|
2026-01-19 10:23:16 +01:00
|
|
|
|
2026-01-14 12:02:03 +01:00
|
|
|
return (
|
|
|
|
|
<div className="rounded-lg border p-4">
|
|
|
|
|
<h4 className="mb-2 font-semibold text-lg">
|
|
|
|
|
Stripe Status: {data?.success ? "Sano" : "Non sano"}
|
|
|
|
|
</h4>
|
2026-02-20 11:36:47 +01:00
|
|
|
<p>Keys:</p>
|
|
|
|
|
<p>
|
|
|
|
|
Secret Key: <span className="wrap-anywhere">{data?.secretKey}</span>
|
|
|
|
|
</p>
|
|
|
|
|
<p>
|
|
|
|
|
Public Key: <span className="wrap-anywhere">{data?.publicKey}</span>
|
|
|
|
|
</p>
|
|
|
|
|
<hr />
|
2026-01-14 12:02:03 +01:00
|
|
|
<p>Endpoint Webhook:</p>
|
|
|
|
|
{data?.endpoints?.data.map((endpoint) => (
|
|
|
|
|
<div className="mb-2" key={endpoint.id}>
|
2026-01-19 09:36:35 +01:00
|
|
|
<p>ID: {endpoint.id}</p>
|
|
|
|
|
<p>URL: {endpoint.url}</p>
|
2026-01-14 12:02:03 +01:00
|
|
|
|
|
|
|
|
<p>Eventi attivi: </p>
|
|
|
|
|
<ul className="list-inside list-disc">
|
|
|
|
|
{endpoint.enabled_events.map((event) => (
|
|
|
|
|
<li key={event}>{event}</li>
|
|
|
|
|
))}
|
|
|
|
|
</ul>
|
|
|
|
|
<p>Versione Api: {endpoint.api_version}</p>
|
2026-01-19 09:36:35 +01:00
|
|
|
<p>Stato: {endpoint.status}</p>
|
|
|
|
|
|
2026-01-14 12:02:03 +01:00
|
|
|
<hr className="my-2" />
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
2026-01-27 16:30:19 +01:00
|
|
|
|
|
|
|
|
const SendEmailSection = () => {
|
|
|
|
|
const { data: codici, isLoading: loading } =
|
|
|
|
|
api.annunci.getOnline_AnnuncioIdCodice.useQuery();
|
|
|
|
|
const [selectedAnnunci, setSelectedAnnunci] = useState<
|
|
|
|
|
{ value: AnnunciId; label: string }[]
|
|
|
|
|
>([]);
|
|
|
|
|
const [email, setEmail] = useState<string | undefined>(undefined);
|
|
|
|
|
|
|
|
|
|
const { mutate } = api.comunicazioni.sendAnnunciEmail.useMutation({
|
|
|
|
|
onSuccess: () => {
|
2026-01-27 16:47:02 +01:00
|
|
|
// setSelectedAnnunci([]);
|
|
|
|
|
// setEmail("");
|
2026-01-27 16:30:19 +01:00
|
|
|
toast.success("Email inviata con successo");
|
|
|
|
|
},
|
|
|
|
|
onError: (error) => {
|
|
|
|
|
console.error(error);
|
|
|
|
|
toast.error(`Errore durante l'invio dell'email: ${error.message}`);
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="space-y-4 rounded-lg border p-4">
|
|
|
|
|
<h4 className="font-semibold text-lg">
|
|
|
|
|
Invia email con annunci selezionati
|
|
|
|
|
</h4>
|
|
|
|
|
|
|
|
|
|
<div className="flex max-w-xl flex-col gap-2">
|
|
|
|
|
<Label className="font-medium" htmlFor="email-to">
|
|
|
|
|
Indirizzo email destinatario
|
|
|
|
|
</Label>
|
|
|
|
|
<Input
|
|
|
|
|
id="email-to"
|
|
|
|
|
onChange={(e) => setEmail(e.target.value)}
|
|
|
|
|
placeholder="Inserisci l'indirizzo email"
|
|
|
|
|
type="email"
|
|
|
|
|
value={email || ""}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex max-w-xl flex-col gap-2">
|
|
|
|
|
{loading ? (
|
|
|
|
|
<LoadingPage />
|
|
|
|
|
) : (
|
|
|
|
|
<div className="flex max-w-xl flex-col">
|
|
|
|
|
<Label className="font-medium" htmlFor="select-annuncio">
|
|
|
|
|
Seleziona gli annunci da inviare
|
|
|
|
|
</Label>
|
|
|
|
|
<MultiSelect
|
|
|
|
|
defaultValue={undefined}
|
|
|
|
|
elementId="select-annuncio"
|
|
|
|
|
elementName="annuncio"
|
|
|
|
|
isMulti={true}
|
|
|
|
|
onValueChange={(value) => {
|
|
|
|
|
setSelectedAnnunci(
|
|
|
|
|
value.map((v) => ({
|
|
|
|
|
label: v.label,
|
|
|
|
|
value: parseInt(v.value) as AnnunciId,
|
|
|
|
|
})),
|
|
|
|
|
);
|
|
|
|
|
}}
|
|
|
|
|
options={
|
|
|
|
|
codici?.map((cod) => ({
|
|
|
|
|
label: cod.codice,
|
|
|
|
|
value: cod.id.toString(),
|
|
|
|
|
})) || []
|
|
|
|
|
}
|
|
|
|
|
placeholder=""
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
<Button
|
|
|
|
|
aria-label="Cancel Add Annuncio"
|
|
|
|
|
disabled={!selectedAnnunci.length || !email}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
if (!selectedAnnunci.length || !email) return;
|
|
|
|
|
mutate({
|
|
|
|
|
annunci: selectedAnnunci.map((annuncio) => annuncio.value),
|
|
|
|
|
to: email,
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
type="button"
|
|
|
|
|
>
|
|
|
|
|
Invia
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|