Files
hamedandClaude Opus 4.8 69e591f03e fix(dashboard): appointment detail fields + sidebar hydration
- Appointment detail (DetailLg/DetailSm) read the real response shape:
  date/time from slot_start, specialty from doctor.specialties[0].name,
  phone from address.telephone.
- Sidebar Head reads userInfo (cookie) after mount to avoid an SSR/client
  hydration mismatch on the user's name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 12:01:43 +03:30

125 lines
4.9 KiB
JavaScript

import RoutingC from "@/components/icons/RoutingC";
import { Button } from "@mui/material";
import React, { useRef } from "react";
import ButtonData from "./ButtonData";
import TextLoading from "@/app/component/loading/Text";
import { convertTimestampToJalali, convertTimestampToTime } from "@/helper";
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
function DetailSm({ appointmentData, loading }) {
const detailsRef = useRef(null);
const handleDownloadPDF = async () => {
if (!detailsRef.current) return;
try {
const canvas = await html2canvas(detailsRef.current, {
scale: 2,
useCORS: true,
logging: false,
backgroundColor: '#ffffff',
});
const imgData = canvas.toDataURL("image/png");
const pdf = new jsPDF({
orientation: "portrait",
unit: "mm",
format: "a4",
});
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = pdf.internal.pageSize.getHeight();
const imgWidth = pdfWidth * 0.9; // 90% of page width
const imgHeight = (canvas.height * imgWidth) / canvas.width;
// Center horizontally and vertically
const xPosition = (pdfWidth - imgWidth) / 2;
const yPosition = (pdfHeight - imgHeight) / 2;
pdf.addImage(imgData, "PNG", xPosition, yPosition, imgWidth, imgHeight);
pdf.save(`appointment_${appointmentData?.uuid || Date.now()}.pdf`);
} catch (error) {
console.error("Error generating PDF:", error);
}
};
return (
<div ref={detailsRef} className="mt-[20px] block md:hidden">
<div className="flex items-center justify-start gap-[8px]">
<div className="flex flex-col justify-center items-start gap-[8px]">
<TextLoading loading={loading} width={60} height={14}>
<p className="text-[#616161] text-[14px] font-medium">
{appointmentData?.doctor?.name}
</p>
</TextLoading>
<TextLoading loading={loading} width={70} height={14}>
<p className="text-[#7E7E7E] text-[14px] font-normal">
{appointmentData?.doctor?.specialties?.[0]?.name}
</p>
</TextLoading>
</div>
</div>
<ul className="flex w-full flex-col items-start justify-start mt-[16px]">
<li className="flex items-center w-full justify-between">
<TextLoading loading={loading} width={70} height={16}>
<p className="text-[#7E7E7E] text-[16px] font-normal">
تاریخ نوبت:
</p>
</TextLoading>
<TextLoading loading={loading} width={55} height={16}>
<p className="text-[#525252] text-[16px] font-medium">
{convertTimestampToJalali(appointmentData?.slot_start)}
</p>
</TextLoading>
</li>
<span className="block w-full h-px bg-[#EFEFEF] mt-[12px] mb-[16px]"></span>
<li className="flex flex-wrap items-center w-full justify-between">
<TextLoading loading={loading} width={80} height={16}>
<p className="text-[#7E7E7E] text-[16px] font-normal">ساعت نوبت:</p>
</TextLoading>
<TextLoading loading={loading} width={60} height={16}>
<p className="text-[#525252] text-[16px] font-medium">
{convertTimestampToTime(appointmentData?.slot_start)}
</p>
</TextLoading>
</li>
<span className="block w-full h-px bg-[#EFEFEF] mt-[12px] mb-[16px]"></span>
<li className="flex flex-wrap gap-x-[12px] gap-y-[12px] items-center w-full justify-between">
<TextLoading loading={loading} width={200} height={16}>
<p className="text-[#7E7E7E] text-[14px] font-normal">
آدرس:<span className="text-[#616161]">{appointmentData?.address?.address}</span>
</p>
</TextLoading>
<TextLoading loading={loading} width={130} height={40}>
<Button
className="!py-[8px] !border-[#EFEFEF] !px-[12px] !gap-[8px]"
variant="outlined"
onClick={() => {
const map = appointmentData?.address?.map;
if (map?.latitude && map?.longitude) {
window.open(`https://www.google.com/maps/dir/?api=1&destination=${map.latitude},${map.longitude}`, '_blank');
}
}}
>
<RoutingC />
<p className="text-[#5559CE] text-[14px] font-medium">
مسیریابی آدرس
</p>
</Button>
</TextLoading>
</li>
<TextLoading loading={loading} width={100} height={18}>
<p className="text-[#7E7E7E] text-[14px] font-normal mt-[12px]">
تلفن: <span className="text-[#616161]">{appointmentData?.address?.telephone}</span>
</p>
</TextLoading>
</ul>
<ButtonData loading={loading} onDownload={handleDownloadPDF} />
</div>
);
}
export default DetailSm;