refactor: update appointment components to fetch and handle doctor data and disabled dates
This commit is contained in:
@@ -2,20 +2,41 @@ import AppointmentPage from "@/components/appointment";
|
|||||||
import { getStateInfo } from "@/lib/getStateInfo";
|
import { getStateInfo } from "@/lib/getStateInfo";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
async function Appointment({ params: { slug } }) {
|
async function Appointment({ params: { doctorId } }) {
|
||||||
const { matchedCity } = getStateInfo();
|
const { matchedCity } = getStateInfo();
|
||||||
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||||
|
|
||||||
let apt = null;
|
let doctor = null;
|
||||||
try {
|
let disabledDates = [];
|
||||||
const response = await axios.get(`${API_URL}/api/v1/appointment-slots`);
|
|
||||||
|
|
||||||
apt = response.data.data;
|
try {
|
||||||
|
// دریافت اطلاعات دکتر با UUID
|
||||||
|
const doctorRes = await axios.get(`${API_URL}/api/v1/doctor/${doctorId}`);
|
||||||
|
doctor = doctorRes.data;
|
||||||
|
|
||||||
|
// دریافت روزهای غیرفعال با استفاده از doctor.id
|
||||||
|
if (doctor && doctor.id) {
|
||||||
|
const disabledDatesRes = await axios.get(
|
||||||
|
`${API_URL}/api/v1/appointment/not-available/${doctor.id}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
disabledDates = disabledDatesRes.data?.data || [];
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// console.error("problem with req:", error.message);
|
console.error("Error fetching appointment data:", error.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <AppointmentPage slug={slug} matchedCity={matchedCity} />;
|
return (
|
||||||
|
<AppointmentPage
|
||||||
|
doctor={doctor}
|
||||||
|
disabledDates={disabledDates}
|
||||||
|
matchedCity={matchedCity}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Appointment;
|
export default Appointment;
|
||||||
|
|||||||
@@ -4,10 +4,9 @@ import { useEffect, useRef, useState } from "react";
|
|||||||
import FirstDatePicker from "./date/FirstDatePicker";
|
import FirstDatePicker from "./date/FirstDatePicker";
|
||||||
import SecondDatePicker from "./date/SecondDatePicker";
|
import SecondDatePicker from "./date/SecondDatePicker";
|
||||||
import { dateToTimestamp } from "@/helper";
|
import { dateToTimestamp } from "@/helper";
|
||||||
import { request } from "@/services/response";
|
|
||||||
import moment from "moment-jalaali";
|
import moment from "moment-jalaali";
|
||||||
|
|
||||||
function DatePicker({ setDate }) {
|
function DatePicker({ setDate, disabledDates = [] }) {
|
||||||
const nextIconDatePickerF = useRef();
|
const nextIconDatePickerF = useRef();
|
||||||
const prevIconDatePickerF = useRef();
|
const prevIconDatePickerF = useRef();
|
||||||
const nextIconDatePickerS = useRef();
|
const nextIconDatePickerS = useRef();
|
||||||
@@ -16,7 +15,6 @@ function DatePicker({ setDate }) {
|
|||||||
const [startDate, setStartDate] = useState(null);
|
const [startDate, setStartDate] = useState(null);
|
||||||
const [endDate, setEndDate] = useState();
|
const [endDate, setEndDate] = useState();
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [disableDates, setDisableDates] = useState([]);
|
|
||||||
|
|
||||||
const handleStartDateChange = (date, e) => {
|
const handleStartDateChange = (date, e) => {
|
||||||
if (date) {
|
if (date) {
|
||||||
@@ -42,7 +40,7 @@ function DatePicker({ setDate }) {
|
|||||||
if (date.isBefore(today)) return true;
|
if (date.isBefore(today)) return true;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
disableDates.some((ts) => date.isSame(moment.unix(ts).startOf("day")))
|
disabledDates.some((ts) => date.isSame(moment.unix(ts).startOf("day")))
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -51,27 +49,22 @@ function DatePicker({ setDate }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
request
|
// تنظیم loading به false بعد از یک تاخیر کوتاه
|
||||||
.getAppointmentNotAvailable(47)
|
setTimeout(() => {
|
||||||
.then((res) => {
|
setLoading(false);
|
||||||
setTimeout(() => {
|
}, 1000);
|
||||||
setLoading(false);
|
|
||||||
}, 1000);
|
|
||||||
setDisableDates(res.data);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
});
|
|
||||||
if (nextIconDatePickerS.current) {
|
if (nextIconDatePickerS.current) {
|
||||||
nextIconDatePickerS.current.click();
|
nextIconDatePickerS.current.click();
|
||||||
}
|
}
|
||||||
}, [nextIconDatePickerS]);
|
}, [nextIconDatePickerS, disabledDates]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="datePickerApt flex items-start custom-datepicker justify-evenly w-full">
|
<div className="datePickerApt flex items-start custom-datepicker justify-evenly w-full">
|
||||||
<FirstDatePicker
|
<FirstDatePicker
|
||||||
loading={loading}
|
loading={loading}
|
||||||
startDate={startDate}
|
startDate={startDate}
|
||||||
disableDates={disableDates}
|
disableDates={disabledDates}
|
||||||
handleDisableDate={handleDisableDate}
|
handleDisableDate={handleDisableDate}
|
||||||
nextIconDatePickerF={nextIconDatePickerF}
|
nextIconDatePickerF={nextIconDatePickerF}
|
||||||
prevIconDatePickerF={prevIconDatePickerF}
|
prevIconDatePickerF={prevIconDatePickerF}
|
||||||
|
|||||||
@@ -18,9 +18,10 @@ function Container({
|
|||||||
matchedCity,
|
matchedCity,
|
||||||
isForAnother,
|
isForAnother,
|
||||||
setIsForAnother,
|
setIsForAnother,
|
||||||
|
disabledDates,
|
||||||
}) {
|
}) {
|
||||||
const elements = [
|
const elements = [
|
||||||
<Date doctor={doctor} setStep={setStep} />,
|
<Date doctor={doctor} setStep={setStep} disabledDates={disabledDates} />,
|
||||||
// <LogInPage setIsSendMsg={false} setStep={setStep} />,
|
// <LogInPage setIsSendMsg={false} setStep={setStep} />,
|
||||||
// <VerificationPage setIsSendMsg={false} link={false} setStep={setStep} />,
|
// <VerificationPage setIsSendMsg={false} link={false} setStep={setStep} />,
|
||||||
<Detail
|
<Detail
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import DatePicker from "@/app/component/date/datePicker";
|
import DatePicker from "@/app/component/date/datePicker";
|
||||||
|
|
||||||
function SelectDatePicker({ setDate }) {
|
function SelectDatePicker({ setDate, disabledDates }) {
|
||||||
return <DatePicker setDate={setDate} />;
|
return <DatePicker setDate={setDate} disabledDates={disabledDates} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SelectDatePicker;
|
export default SelectDatePicker;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import SelectDatePicker from "./SelectDatePicker";
|
import SelectDatePicker from "./SelectDatePicker";
|
||||||
|
|
||||||
function Time({ isStep, setDate }) {
|
function Time({ isStep, setDate, disabledDates }) {
|
||||||
return (
|
return (
|
||||||
<div className="flex relative mt-[24px] flex-col items-start gap-[19px] justify-start">
|
<div className="flex relative mt-[24px] flex-col items-start gap-[19px] justify-start">
|
||||||
<p className="text-[#3B3B3B] text-[14px] md:text-[16px] font-bold">
|
<p className="text-[#3B3B3B] text-[14px] md:text-[16px] font-bold">
|
||||||
1. انتخاب روز
|
1. انتخاب روز
|
||||||
</p>
|
</p>
|
||||||
<SelectDatePicker setDate={setDate} />
|
<SelectDatePicker setDate={setDate} disabledDates={disabledDates} />
|
||||||
{!isStep && (
|
{!isStep && (
|
||||||
<div className="absolute left-0 top-0 w-full h-full bg-[rgba(255,255,255,0.84)]"></div>
|
<div className="absolute left-0 top-0 w-full h-full bg-[rgba(255,255,255,0.84)]"></div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useState } from "react";
|
|||||||
import Hour from "./hour";
|
import Hour from "./hour";
|
||||||
import Time from "./Time";
|
import Time from "./Time";
|
||||||
|
|
||||||
function Date({ doctor, setStep }) {
|
function Date({ doctor, setStep, disabledDates }) {
|
||||||
const [locateVisit, setLocateVisit] = useState(true);
|
const [locateVisit, setLocateVisit] = useState(true);
|
||||||
const [date, setDate] = useState();
|
const [date, setDate] = useState();
|
||||||
|
|
||||||
@@ -16,6 +16,7 @@ function Date({ doctor, setStep }) {
|
|||||||
setDate={setDate}
|
setDate={setDate}
|
||||||
locateVisit={locateVisit}
|
locateVisit={locateVisit}
|
||||||
isStep={doctor?.multiwork ? locateVisit : true}
|
isStep={doctor?.multiwork ? locateVisit : true}
|
||||||
|
disabledDates={disabledDates}
|
||||||
/>
|
/>
|
||||||
<Hour
|
<Hour
|
||||||
isStep={doctor?.multiwork ? locateVisit : true}
|
isStep={doctor?.multiwork ? locateVisit : true}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import doctors from "@/data/doctors.json";
|
|
||||||
import { request } from "@/services/response";
|
import { request } from "@/services/response";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import Container from "./Container";
|
import Container from "./Container";
|
||||||
@@ -13,9 +12,7 @@ const defaultData = {
|
|||||||
basic_insurance: { value: "", isEdit: false },
|
basic_insurance: { value: "", isEdit: false },
|
||||||
};
|
};
|
||||||
|
|
||||||
function AppointmentPage({ slug, matchedCity }) {
|
function AppointmentPage({ doctor, disabledDates, matchedCity }) {
|
||||||
const doctor = doctors.find((item) => item.id === +slug);
|
|
||||||
|
|
||||||
const [step, setStep] = useState(0);
|
const [step, setStep] = useState(0);
|
||||||
const [isForAnother, setIsForAnother] = useState(false);
|
const [isForAnother, setIsForAnother] = useState(false);
|
||||||
|
|
||||||
@@ -78,6 +75,7 @@ function AppointmentPage({ slug, matchedCity }) {
|
|||||||
matchedCity={matchedCity}
|
matchedCity={matchedCity}
|
||||||
isForAnother={isForAnother}
|
isForAnother={isForAnother}
|
||||||
setIsForAnother={setIsForAnother}
|
setIsForAnother={setIsForAnother}
|
||||||
|
disabledDates={disabledDates}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import TickCircleOrange from "@/components/icons/TickCircleOrange";
|
|||||||
import { Button } from "@mui/material";
|
import { Button } from "@mui/material";
|
||||||
|
|
||||||
function Detail({ doctor, step, setStep }) {
|
function Detail({ doctor, step, setStep }) {
|
||||||
|
// دریافت اولین آدرس از لیست
|
||||||
|
const firstAddress = doctor?.address?.[0]?.address || doctor?.location || "آدرس موجود نیست";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="">
|
<div className="">
|
||||||
<ul className="flex flex-col items-start justify-start gap-[24px]">
|
<ul className="flex flex-col items-start justify-start gap-[24px]">
|
||||||
@@ -14,7 +17,7 @@ function Detail({ doctor, step, setStep }) {
|
|||||||
<LocationA />
|
<LocationA />
|
||||||
</div>
|
</div>
|
||||||
<p className="text-[#616161] text-[14px] md:text-[16px] font-normal">
|
<p className="text-[#616161] text-[14px] md:text-[16px] font-normal">
|
||||||
آدرس: {doctor?.location}
|
آدرس: {firstAddress}
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-center justify-between w-full">
|
<li className="flex items-center justify-between w-full">
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
|
|
||||||
function Head({ doctor }) {
|
function Head({ doctor }) {
|
||||||
|
// تبدیل img array به string
|
||||||
|
const doctorImage = doctor?.img?.[0]?.url || "/default-doctor.jpg";
|
||||||
|
|
||||||
|
// تبدیل expertise array به string
|
||||||
|
const expertiseText = doctor?.expertise
|
||||||
|
?.map((exp) => exp.name)
|
||||||
|
.join("، ") || "";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="
|
className="
|
||||||
@@ -16,7 +24,7 @@ function Head({ doctor }) {
|
|||||||
h-[40px] sm:h-[58px] md:h-[77px] lg:h-[95px]
|
h-[40px] sm:h-[58px] md:h-[77px] lg:h-[95px]
|
||||||
"
|
"
|
||||||
alt="profile doctor"
|
alt="profile doctor"
|
||||||
src={doctor?.img}
|
src={doctorImage}
|
||||||
height={95}
|
height={95}
|
||||||
width={95}
|
width={95}
|
||||||
/>
|
/>
|
||||||
@@ -25,7 +33,7 @@ function Head({ doctor }) {
|
|||||||
{doctor?.name}
|
{doctor?.name}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-[#616161] text-[14px] md:text-[16px] font-medium">
|
<p className="text-[#616161] text-[14px] md:text-[16px] font-medium">
|
||||||
تخصص: {doctor?.expertise}
|
تخصص: {expertiseText}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ function Address({ doctor }) {
|
|||||||
<li key={idx}>
|
<li key={idx}>
|
||||||
<div className="flex py-[12px] text-[#616161] text-[14px] items-start justify-start">
|
<div className="flex py-[12px] text-[#616161] text-[14px] items-start justify-start">
|
||||||
<p className="font-bold min-w-[115px]">{`${item.name}: `}</p>
|
<p className="font-bold min-w-[115px]">{`${item.name}: `}</p>
|
||||||
<p className="font-normal">{item.location}</p>
|
<p className="font-normal">{item.address || item.location}</p>
|
||||||
</div>
|
</div>
|
||||||
{doctor.address.length > idx + 1 && (
|
{doctor.address.length > idx + 1 && (
|
||||||
<span className="bg-[#EFEFEF] block h-px w-full"></span>
|
<span className="bg-[#EFEFEF] block h-px w-full"></span>
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
|
|
||||||
function Head({ doctor }) {
|
function Head({ doctor }) {
|
||||||
|
// تبدیل img array به string
|
||||||
|
const doctorImage = doctor?.img?.[0]?.url || "/default-doctor.jpg";
|
||||||
|
|
||||||
|
// تبدیل expertise array به string
|
||||||
|
const expertiseText = doctor?.expertise
|
||||||
|
?.map((exp) => exp.name)
|
||||||
|
.join("، ") || "";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-start gap-[12px]">
|
<div className="flex items-center justify-start gap-[12px]">
|
||||||
<Image
|
<Image
|
||||||
@@ -8,7 +16,7 @@ function Head({ doctor }) {
|
|||||||
w-[48px] sm:w-[51px] md:w-[54px] lg:w-[56px]
|
w-[48px] sm:w-[51px] md:w-[54px] lg:w-[56px]
|
||||||
h-[48px] sm:h-[51px] md:h-[54px] lg:h-[56px]
|
h-[48px] sm:h-[51px] md:h-[54px] lg:h-[56px]
|
||||||
"
|
"
|
||||||
src={doctor?.img}
|
src={doctorImage}
|
||||||
alt="profile"
|
alt="profile"
|
||||||
height={56}
|
height={56}
|
||||||
width={56}
|
width={56}
|
||||||
@@ -18,7 +26,7 @@ function Head({ doctor }) {
|
|||||||
{doctor?.name}
|
{doctor?.name}
|
||||||
</h2>
|
</h2>
|
||||||
<h3 className="text-[#525252] text-[12px] md:text-[14px] font-medium">
|
<h3 className="text-[#525252] text-[12px] md:text-[14px] font-medium">
|
||||||
تخصص: {doctor?.expertise}
|
تخصص: {expertiseText}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user