change design and data list in doctor-item & handle component appointment in doctor-item & handle functionality date-picker & fix bug appointment page & add req get appointment list
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
import AppointmentPage from "@/components/appointment";
|
||||
import { getStateInfo } from "@/lib/getStateInfo";
|
||||
import axios from "axios";
|
||||
|
||||
async function Appointment({ params: { slug } }) {
|
||||
const { matchedCity } = getStateInfo();
|
||||
|
||||
let apt = null;
|
||||
try {
|
||||
const response = await axios.get(
|
||||
"https://back-dev.clinic-pro.ir/api/v1/appointment-slots"
|
||||
);
|
||||
apt = response.data.data;
|
||||
} catch (error) {
|
||||
// console.error("problem with req:", error.message);
|
||||
}
|
||||
|
||||
return <AppointmentPage slug={slug} matchedCity={matchedCity} />;
|
||||
}
|
||||
|
||||
export default Appointment;
|
||||
@@ -1,10 +0,0 @@
|
||||
import BookingPage from "@/components/booking";
|
||||
import { getStateInfo } from "@/lib/getStateInfo";
|
||||
|
||||
function Booking({ params: { slug } }) {
|
||||
const { matchedCity } = getStateInfo();
|
||||
|
||||
return <BookingPage slug={slug} matchedCity={matchedCity} />;
|
||||
}
|
||||
|
||||
export default Booking;
|
||||
@@ -0,0 +1,18 @@
|
||||
import { CircularProgress } from "@mui/material";
|
||||
import React from "react";
|
||||
|
||||
function LoadingComponent({ children, loading }) {
|
||||
return (
|
||||
<div className="relative">
|
||||
{loading ? (
|
||||
<div className="absolute min-h-[80px] mt-[160px] w-full h-full flex items-center justify-center">
|
||||
<CircularProgress />
|
||||
</div>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default LoadingComponent;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Skeleton } from "@mui/material";
|
||||
import React from "react";
|
||||
|
||||
function LoadingDate({ loading }) {
|
||||
if (loading) {
|
||||
return (
|
||||
<Skeleton
|
||||
variant="rectangular"
|
||||
className="!w-[300px] !rounded-[6px] !absolute !top-0 !right-1/2 !translate-x-1/2 !z-10"
|
||||
height={352}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default LoadingDate;
|
||||
@@ -1,22 +0,0 @@
|
||||
import { Button } from "@mui/material";
|
||||
import Image from "next/image";
|
||||
|
||||
function NextIconDatePicker({ nextIconDatePicker }) {
|
||||
return (
|
||||
<Button
|
||||
className="!min-w-0 !p-0 !rounded-full"
|
||||
ref={nextIconDatePicker}
|
||||
onClick={(e) => e.preventDefault()}
|
||||
>
|
||||
<Image
|
||||
src="/assets/icons/arrow-right.svg"
|
||||
className="icon-left-datepicker"
|
||||
alt="arrow"
|
||||
height={24}
|
||||
width={24}
|
||||
/>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
export default NextIconDatePicker;
|
||||
@@ -1,22 +0,0 @@
|
||||
import { Button } from "@mui/material";
|
||||
import Image from "next/image";
|
||||
|
||||
function PrevIconDatePicker({ prevIconDatePicker }) {
|
||||
return (
|
||||
<Button
|
||||
className="!min-w-0 !p-0 !rounded-full !rotate-180"
|
||||
ref={prevIconDatePicker}
|
||||
onClick={(e) => e.preventDefault()}
|
||||
>
|
||||
<Image
|
||||
src="/assets/icons/arrow-right.svg"
|
||||
className="icon-left-datepicker"
|
||||
alt="arrow"
|
||||
height={24}
|
||||
width={24}
|
||||
/>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
export default PrevIconDatePicker;
|
||||
@@ -0,0 +1,41 @@
|
||||
import React from "react";
|
||||
import { DatePicker } from "jalaali-react-date-picker";
|
||||
import { nextIconData, prevIconData } from "./dataIcon";
|
||||
import LoadingDate from "../LoadingDate";
|
||||
import Image from "next/image";
|
||||
|
||||
function FirstDatePicker({
|
||||
startDate,
|
||||
loading,
|
||||
handleDisableDate,
|
||||
nextIconDatePickerF,
|
||||
prevIconDatePickerF,
|
||||
prevIconDatePickerS,
|
||||
handleStartDateChange,
|
||||
}) {
|
||||
return (
|
||||
<div className="w-full first md:w-1/2 lg:w-full xl:w-1/2 relative flex justify-center">
|
||||
<DatePicker
|
||||
value={startDate}
|
||||
className={`w-full ${loading ? "opacity-0" : "opacity-100"}`}
|
||||
timePicker={false}
|
||||
nextIcon={
|
||||
<Image {...nextIconData} ref={nextIconDatePickerF} id="nextIconF" />
|
||||
}
|
||||
prevIcon={
|
||||
<Image
|
||||
{...prevIconData}
|
||||
ref={prevIconDatePickerF}
|
||||
onClick={() => prevIconDatePickerS.current.click()}
|
||||
/>
|
||||
}
|
||||
isFirst={true}
|
||||
onChange={handleStartDateChange}
|
||||
disabledDates={(e) => handleDisableDate(e)}
|
||||
/>
|
||||
<LoadingDate loading={loading} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default FirstDatePicker;
|
||||
@@ -0,0 +1,42 @@
|
||||
import React from "react";
|
||||
import { DatePicker } from "jalaali-react-date-picker";
|
||||
import { nextIconData, prevIconData } from "./dataIcon";
|
||||
import LoadingDate from "../LoadingDate";
|
||||
import Image from "next/image";
|
||||
|
||||
function SecondDatePicker({
|
||||
endDate,
|
||||
loading,
|
||||
handleDisableDate,
|
||||
nextIconDatePickerF,
|
||||
nextIconDatePickerS,
|
||||
prevIconDatePickerS,
|
||||
handleEndDateChange,
|
||||
}) {
|
||||
return (
|
||||
<div className="w-1/2 second hidden md:flex lg:hidden xl:flex">
|
||||
<div className="w-full relative flex justify-center">
|
||||
<DatePicker
|
||||
value={endDate}
|
||||
timePicker={false}
|
||||
className={`w-full ${loading ? "opacity-0" : "opacity-100"}`}
|
||||
nextIcon={
|
||||
<Image
|
||||
{...nextIconData}
|
||||
ref={nextIconDatePickerS}
|
||||
onClick={() => !loading && nextIconDatePickerF.current.click()}
|
||||
/>
|
||||
}
|
||||
prevIcon={
|
||||
<Image {...prevIconData} ref={prevIconDatePickerS} id="prevIconS" />
|
||||
}
|
||||
onChange={handleEndDateChange}
|
||||
disabledDates={(e) => handleDisableDate(e)}
|
||||
/>
|
||||
<LoadingDate loading={loading} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SecondDatePicker;
|
||||
@@ -0,0 +1,16 @@
|
||||
export const fixedIconData = {
|
||||
src: "/assets/icons/arrow-right.svg",
|
||||
alt: "arrow",
|
||||
height: 24,
|
||||
width: 24,
|
||||
};
|
||||
|
||||
export const nextIconData = {
|
||||
...fixedIconData,
|
||||
className: "icon-left-datepicker cursor-pointer",
|
||||
};
|
||||
|
||||
export const prevIconData = {
|
||||
...fixedIconData,
|
||||
className: "icon-left-datepicker cursor-pointer rotate-180",
|
||||
};
|
||||
@@ -1,20 +1,20 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { DatePicker as DatePickerJalali } from "jalaali-react-date-picker";
|
||||
import { Skeleton } from "@mui/material";
|
||||
import NextIconDatePicker from "./NextIconDatePicker";
|
||||
import PrevIconDatePicker from "./PrevIconDatePicker";
|
||||
import FirstDatePicker from "./date/FirstDatePicker";
|
||||
import SecondDatePicker from "./date/SecondDatePicker";
|
||||
|
||||
function DatePicker({ date, updateDate }) {
|
||||
const nextIconDatePicker = useRef();
|
||||
const prevIconDatePicker = useRef();
|
||||
const nextIconDatePickerF = useRef();
|
||||
const prevIconDatePickerF = useRef();
|
||||
const nextIconDatePickerS = useRef();
|
||||
const prevIconDatePickerS = useRef();
|
||||
|
||||
const [startDate, setStartDate] = useState(null);
|
||||
const [endDate, setEndDate] = useState();
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const handleStartDateChange = (date) => {
|
||||
const handleStartDateChange = (date, e) => {
|
||||
if (date) {
|
||||
setStartDate(date);
|
||||
setEndDate(null);
|
||||
@@ -34,64 +34,34 @@ function DatePicker({ date, updateDate }) {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (nextIconDatePicker.current) {
|
||||
nextIconDatePicker.current.click();
|
||||
if (nextIconDatePickerS.current) {
|
||||
nextIconDatePickerS.current.click();
|
||||
console.log(nextIconDatePickerS.current);
|
||||
|
||||
setLoading(false);
|
||||
}
|
||||
}, [nextIconDatePicker]);
|
||||
}, [nextIconDatePickerS]);
|
||||
|
||||
return (
|
||||
<div className="flex items-start custom-datepicker justify-evenly w-full">
|
||||
<div className="w-full md:w-1/2 lg:w-full xl:w-1/2 relative flex justify-center">
|
||||
<DatePickerJalali
|
||||
value={startDate}
|
||||
className={`w-full ${loading ? "opacity-0" : "opacity-100"}`}
|
||||
timePicker={false}
|
||||
nextIcon={
|
||||
<div className="flex md:hidden lg:flex xl:hidden">
|
||||
<NextIconDatePicker nextIconDatePicker={nextIconDatePicker} />
|
||||
</div>
|
||||
}
|
||||
prevIcon={
|
||||
<PrevIconDatePicker prevIconDatePicker={prevIconDatePicker} />
|
||||
}
|
||||
onChange={handleStartDateChange}
|
||||
disabledDates={(e) => handleDisableDate(e)}
|
||||
/>
|
||||
{loading && (
|
||||
<Skeleton
|
||||
variant="rectangular"
|
||||
className="!w-[300px] !rounded-[6px] !absolute !top-0 !right-1/2 !translate-x-1/2 !z-10"
|
||||
height={352}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="w-1/2 hidden md:flex lg:hidden xl:flex">
|
||||
<div className="w-full relative flex justify-center">
|
||||
<DatePickerJalali
|
||||
value={endDate}
|
||||
timePicker={false}
|
||||
className={`w-full ${loading ? "opacity-0" : "opacity-100"}`}
|
||||
nextIcon={
|
||||
<NextIconDatePicker nextIconDatePicker={nextIconDatePicker} />
|
||||
}
|
||||
prevIcon={
|
||||
<div className="flex md:hidden lg:flex xl:hidden">
|
||||
<PrevIconDatePicker prevIconDatePicker={prevIconDatePicker} />
|
||||
</div>
|
||||
}
|
||||
onChange={handleEndDateChange}
|
||||
disabledDates={(e) => handleDisableDate(e)}
|
||||
/>
|
||||
{loading && (
|
||||
<Skeleton
|
||||
variant="rectangular"
|
||||
className="!w-[300px] !rounded-[6px] !absolute !top-0 !right-1/2 !translate-x-1/2 !z-10"
|
||||
height={352}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="datePickerApt flex items-start custom-datepicker justify-evenly w-full">
|
||||
<FirstDatePicker
|
||||
loading={loading}
|
||||
startDate={startDate}
|
||||
handleDisableDate={handleDisableDate}
|
||||
nextIconDatePickerF={nextIconDatePickerF}
|
||||
prevIconDatePickerF={prevIconDatePickerF}
|
||||
prevIconDatePickerS={prevIconDatePickerS}
|
||||
handleStartDateChange={handleStartDateChange}
|
||||
/>
|
||||
<SecondDatePicker
|
||||
loading={loading}
|
||||
endDate={endDate}
|
||||
handleDisableDate={handleDisableDate}
|
||||
nextIconDatePickerF={nextIconDatePickerF}
|
||||
nextIconDatePickerS={nextIconDatePickerS}
|
||||
prevIconDatePickerS={prevIconDatePickerS}
|
||||
handleEndDateChange={handleEndDateChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,28 +3,30 @@ import { Button } from "@mui/material";
|
||||
function Hours({ doctor, hour, setHour, value, nameHours }) {
|
||||
return (
|
||||
<ul className="grid grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-x-[16px] gap-y-[12px] sm:gap-y-[16px] md:gap-y-[20px] lg:gap-y-[24px] mt-[24px] mb-[40px]">
|
||||
{doctor[nameHours[value]].map((item, idx) => (
|
||||
<li key={idx}>
|
||||
<Button
|
||||
onClick={() => setHour(idx)}
|
||||
disabled={!item.active}
|
||||
className={`
|
||||
{doctor &&
|
||||
nameHours &&
|
||||
doctor[nameHours[value]]?.map((item, idx) => (
|
||||
<li key={idx}>
|
||||
<Button
|
||||
onClick={() => setHour(idx)}
|
||||
disabled={!item.active}
|
||||
className={`
|
||||
!w-full !rounded-[8px] !bg-[#EFEFEF] !flex !justify-center !items-center !py-[10px] !px-[14px] !h-[40px] md:!h-[42px] lg:!h-[44px]
|
||||
${idx === hour ? "!bg-[#F79463] " : ""}
|
||||
`}
|
||||
>
|
||||
<p
|
||||
className={`
|
||||
>
|
||||
<p
|
||||
className={`
|
||||
text-[16px] font-semibold text-[#525252]
|
||||
${item.active ? "text-[#525252]" : "text-[#D7D7D7]"}
|
||||
${idx === hour ? "!text-[#FAFAFA] " : ""}
|
||||
`}
|
||||
>
|
||||
{item.hour}
|
||||
</p>
|
||||
</Button>
|
||||
</li>
|
||||
))}
|
||||
>
|
||||
{item.hour}
|
||||
</p>
|
||||
</Button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,9 +2,8 @@ import Content from "@/components/dashboard/Content";
|
||||
import { defineAbilitiesFor } from "@/lib/ability";
|
||||
import { getUser } from "@/lib/auth";
|
||||
import { getStateInfo } from "@/lib/getStateInfo";
|
||||
import { fetchReq } from "@/lib/req";
|
||||
import { removeToken } from "@/utils";
|
||||
import { cookies, headers } from "next/headers";
|
||||
import { cookies } from "next/headers";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default async function Dashboard({ searchParams }) {
|
||||
|
||||
@@ -3,14 +3,26 @@ import Layout from "@/components/layout/StLayout";
|
||||
import axios from "axios";
|
||||
|
||||
async function Doctor({ params: { slug } }) {
|
||||
const response = await axios.get(
|
||||
`https://back-dev.clinic-pro.ir/api/v1/doctor/${slug}`
|
||||
);
|
||||
const doctor = response.data;
|
||||
let doctors = null;
|
||||
let doctor = null;
|
||||
try {
|
||||
const resDoctors = await axios.get(
|
||||
"https://back-dev.clinic-pro.ir/api/v1/doctors?active=1"
|
||||
);
|
||||
const resDoctor = await axios.get(
|
||||
`https://back-dev.clinic-pro.ir/api/v1/doctor/${slug}`
|
||||
);
|
||||
|
||||
doctor = resDoctor.data;
|
||||
doctors = resDoctors.data.data;
|
||||
} catch (error) {
|
||||
// console.error("problem with req:", error.message);
|
||||
// return redirect("/unauthorized");
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<DoctorPage doctor={doctor} />
|
||||
<DoctorPage doctor={doctor} doctors={doctors} />
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
+1
-2
@@ -11,10 +11,9 @@ async function Doctors({ searchParams }) {
|
||||
const response = await axios.get(
|
||||
"https://back-dev.clinic-pro.ir/api/v1/doctors"
|
||||
);
|
||||
doctors = response.data.$data;
|
||||
doctors = response.data.data;
|
||||
} catch (error) {
|
||||
// console.error("problem with req:", error.message);
|
||||
// return redirect("/unauthorized");
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -885,3 +885,56 @@ html {
|
||||
.spin {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
/* date picker appointment */
|
||||
|
||||
.datePickerApt
|
||||
.first
|
||||
.panel-header-wrapper
|
||||
.center:first-child
|
||||
.iconItem:first-child,
|
||||
.datePickerApt
|
||||
.first
|
||||
.panel-header-wrapper
|
||||
.center:last-child
|
||||
.iconItem:last-child,
|
||||
.datePickerApt
|
||||
.second
|
||||
.panel-header-wrapper
|
||||
.center:first-child
|
||||
.iconItem:first-child,
|
||||
.datePickerApt
|
||||
.second
|
||||
.panel-header-wrapper
|
||||
.center:last-child
|
||||
.iconItem:last-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.datePickerApt #nextIconF,
|
||||
.datePickerApt #prevIconS {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.datePickerApt #nextIconF,
|
||||
.datePickerApt #prevIconS {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.datePickerApt #nextIconF,
|
||||
.datePickerApt #prevIconS {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
.datePickerApt #nextIconF,
|
||||
.datePickerApt #prevIconS {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* end of date picker appointment */
|
||||
|
||||
Reference in New Issue
Block a user