Newer
Older
import { getServerSession } from "next-auth";
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
import { getAnnonceByIdInclude } from "@/lib/services/annonceService";
import Link from "next/link";
import ImageCarrousel from "@/lib/components/annonceComponents/ImageCarrousel";
import AddQuestionButton from "@/lib/components/EditAnnonce/addQuestionButtonComponent";
import AnswerQuestionButton from "@/lib/components/EditAnnonce/answerQuestionButtonComponent";
import RoomComponent from "@/lib/components/annonceComponents/roomComponent";
import BathRoomComponent from "@/lib/components/annonceComponents/bathRoomComponent";
import AeraComponent from "@/lib/components/annonceComponents/aeraComponent";
import FloorComponent from "@/lib/components/annonceComponents/floorComponent";
import YearComponent from "@/lib/components/annonceComponents/yearComponent";
import AvailableComponent from "@/lib/components/annonceComponents/availableComponent";
import Image from "next/image";
Jérémy DEZETREE
a validé
export default async function AnnonceDetail({ params }: { params: { id: string } }) {
Jérémy DEZETREE
a validé
const session = await getServerSession(authOptions);
const annonce = await getAnnonceByIdInclude(Number(params.id));
if (!annonce) return <div className="p-20 text-center">Annonce non trouvée.</div>;
const formattedPrice = new Intl.NumberFormat("fr-FR", {
style: "currency",
currency: "EUR",
minimumFractionDigits: 0,
const imageSrc = annonce.mainImg ? `data:image/jpeg;base64,${annonce.mainImg}` : "/default-image-annonce.jpg";
let imagesSrc = [];
if (annonce.gallery && annonce.gallery.length > 0) {
const autresImagesSrc = annonce.gallery.map((img) => `data:image/jpeg;base64,${img.imageData}`);
imagesSrc = [imageSrc, ...autresImagesSrc];
} else {
imagesSrc = [imageSrc];
}
Jérémy DEZETREE
a validé
return (
<div className="mx-auto flex max-w-[1200px] flex-col px-4 pt-22 md:px-46">
<div className="mb-8 flex items-end justify-between">
<h1 className="font-oswald text-primary text-5xl">{annonce.title}</h1>
{annonce.realeSteateStatus === "AVAILABLE" && (
<p className="font-oswald text-3xl font-extralight tracking-widest text-gray-600">Location</p>
)}
{annonce.realeSteateStatus === "RENTED" && (
<p className="font-oswald text-3xl font-extralight tracking-widest text-gray-600">Loué</p>
)}
{annonce.realeSteateStatus === "FORSALE" && (
<p className="font-oswald text-3xl font-extralight tracking-widest text-gray-600">Achat</p>
)}
{annonce.realeSteateStatus === "SOLD" && (
<p className="font-oswald text-3xl font-extralight tracking-widest text-gray-600">Vendu</p>
)}
</div>
<p className="font-oswald mb-8 text-xl text-red-600">{formattedPrice}</p>
<ImageCarrousel images={imagesSrc} titre={annonce.title} />
<div className="mt-16 flex flex-col flex-wrap items-center justify-center md:flex-row md:items-start md:justify-between">
<div className="w-full md:w-1/2">
<h3 className="font-oswald text-[18px] font-medium">Description de la propriété</h3>
<p className="font-roboto mt-6 mb-12 text-base/8 text-gray-700">{annonce.description}</p>
<div className="grid w-full grid-cols-3 grid-rows-2 place-items-center gap-x-8 gap-y-12">
<div>
<RoomComponent value={annonce.numberOfRooms} size={32} />
<div>
<BathRoomComponent value={annonce.numberOfBathrooms} size={32} />
<div>
<AeraComponent value={annonce.surface} size={32} />
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<div>
<FloorComponent value={annonce.floor} size={32} />
</div>
<div>
<YearComponent value={annonce.yearBuilt} size={32} />
</div>
<div>
<AvailableComponent
value={new Date(annonce.avaibleFrom).toLocaleDateString("fr-FR")}
size={32}
/>
</div>
</div>
</div>
<div className="mt-16 flex h-fit w-fit flex-col bg-[#f3f7fa] px-6 py-8 md:mt-0">
<h2 className="font-oswald text-2xl font-medium">
{annonce.agent.firstName} {annonce.agent.lastName}
</h2>
<p className="font-ligh mt-2 text-lg tracking-widest text-gray-600">{annonce.agent.role}</p>
{/*<Image
src={annonce.agent.}
alt={`${titre} - Image ${currentIndex + 1}`}
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
style={{ objectFit: "cover" }}
className="transition-opacity duration-300 ease-in-out"
priority={currentIndex === 0}
/>*/}
<div className="my-8 h-[244px] w-auto bg-amber-200">photoplaceholder</div>
<p className="font-oswald text-2xl">E-mail</p>
<p className="mt-2 font-light">{annonce.agent.email}</p>
</div>
</div>
<div className="mt-16 w-full">
<h3 className="font-oswald text-[18px] font-medium mb-6">FAQ</h3>
{annonce.questions && annonce.questions.length > 0 ? (
<div className="space-y-6 max-h-[400px] overflow-y-scroll">
{annonce.questions.map((q) => (
<div key={q.id} className="p-4 shadow-sm">
<p className="font-medium text-gray-900">
<span className="text-gray-800">{q.authorName ?? "Utilisateur anonyme"}</span> :
</p>
<p className="mt-1 text-gray-700">{q.content}</p>
<div className="mt-2 border-t border-gray-300 pt-2 text-gray-700">
{q.answer ? (
<div className="pl-10">
<p className="font-semibold">Réponse :</p>
<p>{q.answer}</p>
<p className="text-sm text-gray-500">
— {q.answerAuthorName ?? "Agent"} le{" "}
{q.answeredAt ? new Date(q.answeredAt).toLocaleDateString() : ""}
</p>
</div>
) : (
<>
<p className="text-gray-500 italic">Pas encore de réponse.</p>
{session &&
(session.user?.role === "ADMIN" ||
Number(session.user?.id) === annonce.agent.id) && (
<AnswerQuestionButton questionId={q.id} />
)}
</>
)}
</div>
))}
</div>
) : (
<p className="text-gray-600">Aucune question posée pour le moment.</p>
)}
{session && <AddQuestionButton annonceId={annonce.id} />}
Jérémy DEZETREE
a validé
</div>
);