fix(doctor): unwrap double-nested API response and guard empty sections
The GET /api/v1/doctor/{uuid} response is double-nested
({ success, data: { data: {...} } }), but the page only unwrapped one
level, leaving every field (name, specialties, expertise, address)
undefined — so خدمات / موقعیت مکانی / نظرات rendered empty or broken.
- Extract the doctor object with res.data?.data?.data in both
generateMetadata and the page.
- Hide the خدمات block when expertise is empty (no fabricated data).
- Render the location map iframe and routing buttons only when the
address has real latitude/longitude (was building q=null,null).
- Fix the comments list rendering a stray 0 on empty arrays.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -11,8 +11,7 @@ function Comment({ comments }) {
|
|||||||
false && "w-full"
|
false && "w-full"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{comments &&
|
{comments?.length > 0 &&
|
||||||
comments.length &&
|
|
||||||
comments.map((item, idx) => (
|
comments.map((item, idx) => (
|
||||||
<ItemUser
|
<ItemUser
|
||||||
key={idx}
|
key={idx}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export async function generateMetadata({ params }) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await axiosInstance.get(`${API_URL}/api/v1/doctor/${slug}`);
|
const res = await axiosInstance.get(`${API_URL}/api/v1/doctor/${slug}`);
|
||||||
const doctor = res.data;
|
const doctor = res.data?.data?.data;
|
||||||
if (!doctor) return {};
|
if (!doctor) return {};
|
||||||
|
|
||||||
const specialtyNames = doctor.specialties?.map((s) => s.name).join(" و ") || "";
|
const specialtyNames = doctor.specialties?.map((s) => s.name).join(" و ") || "";
|
||||||
@@ -49,7 +49,7 @@ async function Doctor({ params }) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const resDoctor = await axiosInstance.get(`${API_URL}/api/v1/doctor/${slug}`);
|
const resDoctor = await axiosInstance.get(`${API_URL}/api/v1/doctor/${slug}`);
|
||||||
doctor = resDoctor.data;
|
doctor = resDoctor.data?.data?.data;
|
||||||
if (doctor) {
|
if (doctor) {
|
||||||
const resComments = await axiosInstance.get(
|
const resComments = await axiosInstance.get(
|
||||||
`${API_URL}/api/v1/clinicpro/comments/${doctor.id}`
|
`${API_URL}/api/v1/clinicpro/comments/${doctor.id}`
|
||||||
|
|||||||
@@ -39,23 +39,25 @@ function AboutDcotor({ doctor }) {
|
|||||||
</Button>
|
</Button>
|
||||||
</MultilineLoading>
|
</MultilineLoading>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-[12px] lg:mt-[8px] mb-6 md:mb-7 lg:mb-8">
|
{doctor?.expertise?.length > 0 && (
|
||||||
<p className="text-[#525252] text-[14px] md:text-[16px] font-bold">
|
<div className="mt-[12px] lg:mt-[8px] mb-6 md:mb-7 lg:mb-8">
|
||||||
خدمات
|
<p className="text-[#525252] text-[14px] md:text-[16px] font-bold">
|
||||||
</p>
|
خدمات
|
||||||
<ul className="flex flex-col mt-[12px] sm:flex-row gap-y-[16px] items-start sm:items-center justify-start gap-4 flex-wrap">
|
</p>
|
||||||
{doctor?.expertise?.map((item, idx) => (
|
<ul className="flex flex-col mt-[12px] sm:flex-row gap-y-[16px] items-start sm:items-center justify-start gap-4 flex-wrap">
|
||||||
<li key={idx} className="flex items-center justify-start gap-1">
|
{doctor.expertise.map((item, idx) => (
|
||||||
<span className="w-2 h-2 bg-[#F17732] rounded-full"></span>
|
<li key={idx} className="flex items-center justify-start gap-1">
|
||||||
<TextLoading width={70} height={18}>
|
<span className="w-2 h-2 bg-[#F17732] rounded-full"></span>
|
||||||
<h4 className="text-[#616161] text-[16px] font-normal text-nowrap">
|
<TextLoading width={70} height={18}>
|
||||||
{item.name}
|
<h4 className="text-[#616161] text-[16px] font-normal text-nowrap">
|
||||||
</h4>
|
{item.name}
|
||||||
</TextLoading>
|
</h4>
|
||||||
</li>
|
</TextLoading>
|
||||||
))}
|
</li>
|
||||||
</ul>
|
))}
|
||||||
</div>
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,35 @@ function Item({ data }) {
|
|||||||
<p className="text-[#525252] text-[16px] font-normal">
|
<p className="text-[#525252] text-[16px] font-normal">
|
||||||
تلفن: {data.telephone}
|
تلفن: {data.telephone}
|
||||||
</p>
|
</p>
|
||||||
|
{data?.map?.latitude && data?.map?.longitude && (
|
||||||
|
<ModalOpenLocation
|
||||||
|
open={open}
|
||||||
|
data={data}
|
||||||
|
setOpen={setOpen}
|
||||||
|
handleClose={handleClose}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
className="!hidden md:!flex !gap-[8px] !py-[8px] !px-[12px]"
|
||||||
|
onClick={handleOpen}
|
||||||
|
variant="outlined"
|
||||||
|
>
|
||||||
|
<RoutingC />
|
||||||
|
مسیریابی
|
||||||
|
</Button>
|
||||||
|
</ModalOpenLocation>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{data?.map?.latitude && data?.map?.longitude && (
|
||||||
|
<div className="w-full relative h-[219px] sm:h-[302px] md:h-[385px] lg:h-[470px] mt-[24px]">
|
||||||
|
<iframe
|
||||||
|
src={`https://maps.google.com/maps?q=${data.map.latitude},${data.map.longitude}&z=14&output=embed`}
|
||||||
|
className="w-full rounded-lg mt-4 h-full"
|
||||||
|
referrerPolicy="no-referrer-when-downgrade"
|
||||||
|
allowFullScreen=""
|
||||||
|
loading="lazy"
|
||||||
|
></iframe>
|
||||||
|
|
||||||
<ModalOpenLocation
|
<ModalOpenLocation
|
||||||
open={open}
|
open={open}
|
||||||
data={data}
|
data={data}
|
||||||
@@ -56,41 +85,16 @@ function Item({ data }) {
|
|||||||
handleClose={handleClose}
|
handleClose={handleClose}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
className="!hidden md:!flex !gap-[8px] !py-[8px] !px-[12px]"
|
className="!flex md:!hidden !p-2 !absolute !left-3 !bottom-3 !rounded-[4px] !border !border-[#5559CE] !py-2 !px-3
|
||||||
|
!bg-[#5559CE] !shadow-[0px_1px_24.8px_0px_rgba(69,_69,_69,_0.54)] !gap-[8px] !text-[#FAFAFA] !text-[14px] !font-medium"
|
||||||
onClick={handleOpen}
|
onClick={handleOpen}
|
||||||
variant="outlined"
|
|
||||||
>
|
>
|
||||||
<RoutingC />
|
<RoutingWhiteC />
|
||||||
مسیریابی
|
مسیریابی
|
||||||
</Button>
|
</Button>
|
||||||
</ModalOpenLocation>
|
</ModalOpenLocation>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
<div className="w-full relative h-[219px] sm:h-[302px] md:h-[385px] lg:h-[470px] mt-[24px]">
|
|
||||||
<iframe
|
|
||||||
src={`https://maps.google.com/maps?q=${data.map.latitude},${data.map.longitude}&z=14&output=embed`}
|
|
||||||
className="w-full rounded-lg mt-4 h-full"
|
|
||||||
referrerPolicy="no-referrer-when-downgrade"
|
|
||||||
allowFullScreen=""
|
|
||||||
loading="lazy"
|
|
||||||
></iframe>
|
|
||||||
|
|
||||||
<ModalOpenLocation
|
|
||||||
open={open}
|
|
||||||
data={data}
|
|
||||||
setOpen={setOpen}
|
|
||||||
handleClose={handleClose}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
className="!flex md:!hidden !p-2 !absolute !left-3 !bottom-3 !rounded-[4px] !border !border-[#5559CE] !py-2 !px-3
|
|
||||||
!bg-[#5559CE] !shadow-[0px_1px_24.8px_0px_rgba(69,_69,_69,_0.54)] !gap-[8px] !text-[#FAFAFA] !text-[14px] !font-medium"
|
|
||||||
onClick={handleOpen}
|
|
||||||
>
|
|
||||||
<RoutingWhiteC />
|
|
||||||
مسیریابی
|
|
||||||
</Button>
|
|
||||||
</ModalOpenLocation>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user