change design poster and text head && design modal filter & data for filter and doctors & handle functionality filter, set in url, read from url and change state
This commit is contained in:
@@ -13,13 +13,13 @@ import PointD from "@/components/icons/PointD";
|
||||
|
||||
function ItemDoctor({ doctor, loading, setDoctors }) {
|
||||
const handleLoading = () => {
|
||||
setDoctors((prevDoctors) =>
|
||||
prevDoctors.map((item) =>
|
||||
item.id === doctor.id
|
||||
? { ...item, loading: true }
|
||||
: { ...item, loading: false }
|
||||
)
|
||||
);
|
||||
// setDoctors((prevDoctors) =>
|
||||
// prevDoctors.map((item) =>
|
||||
// item.id === doctor.id
|
||||
// ? { ...item, loading: true }
|
||||
// : { ...item, loading: false }
|
||||
// )
|
||||
// );
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
import { useState } from "react";
|
||||
import ItemUser from "./ItemUser";
|
||||
|
||||
function Comment({ data, comments }) {
|
||||
const [list, setList] = useState(data?.comments);
|
||||
function Comment({ comments }) {
|
||||
const [update, setUpdate] = useState(false);
|
||||
|
||||
return (
|
||||
|
||||
@@ -3,6 +3,7 @@ import { TextField } from "@mui/material";
|
||||
function Field({
|
||||
type,
|
||||
name,
|
||||
error,
|
||||
title,
|
||||
props,
|
||||
value,
|
||||
@@ -31,7 +32,9 @@ function Field({
|
||||
"& .MuiInputBase-input": { padding: "12.5px 14px" },
|
||||
"& .MuiInputBase-root": { borderRadius: "6px !important" },
|
||||
"& .MuiOutlinedInput-notchedOutline": {
|
||||
border: "1px solid #E9ECEF !important",
|
||||
border: error
|
||||
? "1px solid red !important"
|
||||
: "1px solid #E9ECEF !important",
|
||||
},
|
||||
".Mui-focused": {
|
||||
"& .MuiOutlinedInput-notchedOutline": {
|
||||
|
||||
@@ -2,33 +2,35 @@ import CloseModalD from "@/components/icons/CloseModalD";
|
||||
import Image from "next/image";
|
||||
|
||||
function Content({ data, onClose }) {
|
||||
console.log(data);
|
||||
|
||||
const { latitude, longitude } = data && data.map;
|
||||
|
||||
const maps = [
|
||||
{
|
||||
src: "/assets/images/snapp.png",
|
||||
name: "snapp",
|
||||
url: `https://snapp.ir/route?lat=${latitude}&lng=${longitude}`,
|
||||
url: `https://snapp.ir/route?lat=${"latitude"}&lng=${"longitude"}`,
|
||||
},
|
||||
{
|
||||
src: "/assets/images/tapsi.png",
|
||||
name: "tapsi",
|
||||
url: `https://tapsi.ir/route?lat=${latitude}&lng=${longitude}`,
|
||||
url: `https://tapsi.ir/route?lat=${"latitude"}&lng=${"longitude"}`,
|
||||
},
|
||||
{
|
||||
src: "/assets/images/maps.png",
|
||||
name: "maps",
|
||||
url: `https://www.google.com/maps/dir/?api=1&destination=${latitude},${longitude}`,
|
||||
url: `https://www.google.com/maps/dir/?api=1&destination=${"latitude"},${"longitude"}`,
|
||||
},
|
||||
{
|
||||
src: "/assets/images/balad.png",
|
||||
name: "balad",
|
||||
url: `https://balad.ir/map?lat=${latitude}&lng=${longitude}`,
|
||||
url: `https://balad.ir/map?lat=${"latitude"}&lng=${"longitude"}`,
|
||||
},
|
||||
{
|
||||
src: "/assets/images/waze.png",
|
||||
name: "waze",
|
||||
url: `https://waze.com/ul?ll=${latitude},${longitude}&navigate=yes`,
|
||||
url: `https://waze.com/ul?ll=${"latitude"},${"longitude"}&navigate=yes`,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -61,7 +63,7 @@ function Content({ data, onClose }) {
|
||||
height={40}
|
||||
width={40}
|
||||
/>
|
||||
<p className="text-[#3B3B3B] font-normal text-[14px]">
|
||||
<p className="text-[#3B3B3B] text-center font-normal text-[14px]">
|
||||
{item.name}
|
||||
</p>
|
||||
</a>
|
||||
|
||||
@@ -5,6 +5,8 @@ import { styleDefault } from "@/mui";
|
||||
import Content from "./Content";
|
||||
|
||||
function ModalOpenLocation({ open, data, setOpen, handleClose, children }) {
|
||||
console.log(data);
|
||||
|
||||
const toggleDrawer = (newOpen) => () => {
|
||||
setOpen(newOpen);
|
||||
};
|
||||
|
||||
@@ -1,55 +1,95 @@
|
||||
"use client";
|
||||
import CustomLoading from "@/app/component/loading/Custom";
|
||||
import ArrowLeftList from "@/components/icons/ArrowLeftList";
|
||||
import { Button } from "@mui/material";
|
||||
import Image from "next/image";
|
||||
import { useRef } from "react";
|
||||
import { useRef, useEffect, useState } from "react";
|
||||
|
||||
function ListBime({ data }) {
|
||||
const list = useRef();
|
||||
const [showArrows, setShowArrows] = useState(false);
|
||||
const [itemWidth, setItemWidth] = useState(156);
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.list_bime?.length > 4) {
|
||||
setShowArrows(true);
|
||||
} else {
|
||||
setShowArrows(false);
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
if (window.innerWidth < 640) {
|
||||
setItemWidth(window.innerWidth / 2.5);
|
||||
} else if (window.innerWidth < 1024) {
|
||||
setItemWidth(window.innerWidth / 3.5);
|
||||
} else {
|
||||
setItemWidth(156);
|
||||
}
|
||||
};
|
||||
|
||||
handleResize();
|
||||
window.addEventListener("resize", handleResize);
|
||||
return () => window.removeEventListener("resize", handleResize);
|
||||
}, []);
|
||||
|
||||
const handleScroll = (type) => {
|
||||
if (!list.current) return;
|
||||
list.current.scrollBy({
|
||||
left: type === "left" ? -200 : 200,
|
||||
left: type === "left" ? -itemWidth : itemWidth,
|
||||
behavior: "smooth",
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full relative">
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => handleScroll("right")}
|
||||
className="!border-[#EFEFEF] !hidden md:!flex !bg-[#FFF] !absolute !right-[-24px] !top-1/2 !-translate-y-1/2 !rounded-full !min-w-fit !p-0 !w-[48px] !h-[48px] !z-20 !rotate-180"
|
||||
>
|
||||
<ArrowLeftList />
|
||||
</Button>
|
||||
<div className="relative w-[calc(100%_-_48px)] mx-auto">
|
||||
{showArrows && (
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => handleScroll("right")}
|
||||
className="!border-[#EFEFEF] md:!flex !bg-[#FFF] !absolute !right-[-24px] !top-1/2 !-translate-y-1/2 !rounded-full !min-w-fit !p-0 !w-[48px] !h-[48px] !z-20 !rotate-180"
|
||||
>
|
||||
<ArrowLeftList />
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<ul
|
||||
ref={list}
|
||||
className="flex overflow-auto hidden-scroll mt-[8px] items-center justify-start xl:justify-center gap-[8px] sm:gap-[13px] md:gap-[19px] lg:gap-[24px]"
|
||||
className={`flex mt-[8px] items-center justify-start xl:justify-center gap-[8px] sm:gap-[13px] md:gap-[19px] lg:gap-[24px] ${
|
||||
showArrows ? "overflow-x-auto hidden-scroll" : "overflow-visible"
|
||||
}`}
|
||||
>
|
||||
{data?.list_bime?.map((item, idx) => (
|
||||
<CustomLoading key={idx} width={156} height={110}>
|
||||
<li className="p-[16px] min-w-[156px] w-full border border-[#EFEFEF] flex flex-col items-center justify-center gap-[20px]">
|
||||
<CustomLoading key={idx} width={itemWidth} height={110}>
|
||||
<li
|
||||
className="p-[16px] border border-[#EFEFEF] h-[175px] flex flex-col items-center justify-center gap-[20px]"
|
||||
style={{ minWidth: itemWidth }}
|
||||
>
|
||||
<Image
|
||||
src={item.logo && item.logo[0]?.url || ""}
|
||||
src={item.logo?.[0]?.url || ""}
|
||||
height={92}
|
||||
width={92}
|
||||
alt="bime"
|
||||
className="object-contain"
|
||||
/>
|
||||
<h3 className="text-[#525252] text-[16px] font-medium">
|
||||
<h3 className="text-[#525252] text-[16px] font-medium text-center">
|
||||
{item.name}
|
||||
</h3>
|
||||
</li>
|
||||
</CustomLoading>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
{showArrows && (
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => handleScroll("left")}
|
||||
className="!border-[#EFEFEF] !hidden md:!flex !bg-[#FFF] !absolute !left-[-24px] !top-1/2 !-translate-y-1/2 !rounded-full !min-w-fit !p-0 !w-[48px] !h-[48px] !z-20"
|
||||
className="!border-[#EFEFEF] md:!flex !bg-[#FFF] !absolute !left-[-24px] !top-1/2 !-translate-y-1/2 !rounded-full !min-w-fit !p-0 !w-[48px] !h-[48px] !z-20"
|
||||
>
|
||||
<ArrowLeftList />
|
||||
</Button>
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,10 +7,7 @@ function Detail({ data }) {
|
||||
head="روزهای کاری: "
|
||||
detail={`ساعت کاری: ${data.hours_of_work}`}
|
||||
/>
|
||||
<ContentDetail
|
||||
head="تلفن: "
|
||||
detail={`${data.phone_number_1} ${data.phone_number_2}`}
|
||||
/>
|
||||
<ContentDetail head="تلفن: " detail={`${data.phone_number}`} />
|
||||
<ContentDetail head="ایمیل:" detail={data.email} />
|
||||
<ContentDetail head="آدرس: " detail={data.location} />
|
||||
</ul>
|
||||
|
||||
@@ -15,14 +15,15 @@ function Contact({ data }) {
|
||||
return (
|
||||
<div
|
||||
className="
|
||||
opacity-page border border-[#EFEFEF] rounded-[16px]
|
||||
py-[12px] sm:py-[18px] md:py-[25px] lg:py-[32px]
|
||||
px-[12px] sm:px-[30px] md:px-[47px] lg:px-[64px]
|
||||
"
|
||||
opacity-page border border-[#EFEFEF] rounded-[16px]
|
||||
py-[12px] sm:py-[18px] md:py-[25px] lg:py-[32px]
|
||||
px-[12px] sm:px-[30px] md:px-[47px] lg:px-[64px]
|
||||
"
|
||||
>
|
||||
<div className="flex items-end justify-between">
|
||||
<Detail data={data} />
|
||||
<ModalOpenLocation
|
||||
data={data}
|
||||
open={open}
|
||||
setOpen={setOpen}
|
||||
handleClose={handleClose}
|
||||
@@ -40,11 +41,12 @@ function Contact({ data }) {
|
||||
<div className="w-full relative h-[460px] mt-[24px]">
|
||||
<CustomLoading width="full" height={400}>
|
||||
<iframe
|
||||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d83998.96777841153!2d2.264635095144491!3d48.85882549249809!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x47e66e1f06e2b70f%3A0x40b82c3688c9460!2sParis%2C%20France!5e0!3m2!1sen!2snl!4v1723498499341!5m2!1sen!2snl"
|
||||
src={`https://maps.google.com/maps?q=${data.map.latitude},${data.map.longitude}&z=14&output=embed`}
|
||||
className="w-full h-full rounded-lg"
|
||||
loading="lazy"
|
||||
></iframe>
|
||||
<ModalOpenLocation
|
||||
data={data}
|
||||
open={open}
|
||||
setOpen={setOpen}
|
||||
handleClose={handleClose}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
import { useState } from "react";
|
||||
import SearchBar from "./search";
|
||||
import SortList from "./sortlist";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import specialties from "@/data/specialties.json";
|
||||
import { QueryForDoctorsFilter } from "@/helper";
|
||||
|
||||
function Head() {
|
||||
const searchParams = useSearchParams();
|
||||
const [page, setPage] = useState(1);
|
||||
const [doctors, setDoctors] = useState();
|
||||
const router = useRouter();
|
||||
|
||||
const fieldName = searchParams.get("specialty");
|
||||
|
||||
const setDataInURL = (newFilter) => {
|
||||
const query = QueryForDoctorsFilter(newFilter);
|
||||
|
||||
const searchParams = new URLSearchParams(query).toString();
|
||||
router.push(`?${searchParams}`);
|
||||
};
|
||||
|
||||
const findItem = (key, name) =>
|
||||
specialties.find((item) => item[key] === name);
|
||||
const isParent =
|
||||
findItem("name", fieldName) && findItem("name", fieldName).parent;
|
||||
|
||||
const valCategory = isParent
|
||||
? findItem("id", isParent)
|
||||
: findItem("name", fieldName);
|
||||
const valSpecialty = isParent && findItem("name", fieldName);
|
||||
|
||||
const defaultFilter = {
|
||||
category: valCategory,
|
||||
specialty: valSpecialty,
|
||||
active: searchParams.get("active") || 0,
|
||||
gender: searchParams.get("gender") || "هر دو",
|
||||
degree: searchParams.get("degree") || "همه موارد",
|
||||
sort: (searchParams.get("sort") && Number(searchParams.get("sort"))) || "",
|
||||
name:
|
||||
searchParams.get("name") || valSpecialty?.name || valCategory?.name || "",
|
||||
};
|
||||
const [filter, setFilter] = useState(defaultFilter);
|
||||
|
||||
const updateData = (name, value, isReq) => {
|
||||
const newFilter = { ...filter, [name]: value };
|
||||
setDataInURL(newFilter);
|
||||
setFilter(newFilter);
|
||||
isReq && sendReq(newFilter);
|
||||
};
|
||||
|
||||
const sendReq = (newFilter) => {
|
||||
// const data = newFilter || filter;
|
||||
// const params = QueryForDoctorsReq(data);
|
||||
// let filteredName = params;
|
||||
// if (
|
||||
// data?.name === data.specialty?.name ||
|
||||
// data?.name === data.category?.name
|
||||
// ) {
|
||||
// filteredName.name = "";
|
||||
// delete filteredName.name;
|
||||
// }
|
||||
// filteredName.page = 1;
|
||||
// filteredName.limit = 12;
|
||||
// setPage(1);
|
||||
// return request
|
||||
// .getDoctors(filteredName)
|
||||
// .then((res) => {
|
||||
// setDoctors(res.data);
|
||||
// return res;
|
||||
// })
|
||||
// .catch((err) => {
|
||||
// throw err;
|
||||
// });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col lg:flex-row items-start lg:items-center justify-center gap-[24px] lg:gap-[32px] w-full">
|
||||
<SearchBar
|
||||
filter={filter}
|
||||
sendReq={sendReq}
|
||||
setFilter={setFilter}
|
||||
updateData={updateData}
|
||||
setDataInURL={setDataInURL}
|
||||
/>
|
||||
<SortList
|
||||
filter={filter}
|
||||
sendReq={sendReq}
|
||||
setFilter={setFilter}
|
||||
updateData={updateData}
|
||||
setDataInURL={setDataInURL}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Head;
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Button } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
|
||||
function ButtonApply({ sendReq, setOpen }) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleClick = () => {
|
||||
setLoading(false);
|
||||
setOpen(false);
|
||||
|
||||
// setLoading(true);
|
||||
|
||||
// sendReq().finally(() => {
|
||||
// setOpen(false);
|
||||
// setLoading(false);
|
||||
// });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex justify-end w-full">
|
||||
<Button
|
||||
loading={loading}
|
||||
variant="contained"
|
||||
onClick={handleClick}
|
||||
className="!px-3 !py-2 !text-[16px] !font-medium"
|
||||
>
|
||||
اعمال تغییرات
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ButtonApply;
|
||||
@@ -0,0 +1,34 @@
|
||||
import specialties from "@/data/specialties.json";
|
||||
import Form from "./form";
|
||||
|
||||
function Content({ filter, setFilter, updateData, setDataInURL }) {
|
||||
const changeSpecialty = (name, value) => {
|
||||
const newFilter = { ...filter, [name]: value };
|
||||
|
||||
if (name === "category") {
|
||||
const childrenList = specialties.filter((item) => item.parent);
|
||||
const filteredChildrenList = childrenList.filter(
|
||||
(item) => item.parent === value.id
|
||||
);
|
||||
const firstChildren = filteredChildrenList[0];
|
||||
|
||||
newFilter.specialty = firstChildren || "";
|
||||
}
|
||||
|
||||
setFilter(newFilter);
|
||||
setDataInURL(newFilter);
|
||||
return newFilter;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mt-[50px] px-[0px] md:px-[19px] lg:px-[38px] mb-[32px]">
|
||||
<Form
|
||||
filter={filter}
|
||||
updateData={updateData}
|
||||
changeSpecialty={changeSpecialty}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Content;
|
||||
@@ -0,0 +1,58 @@
|
||||
import CloseOrangeModal from "@/components/icons/CloseOrangeModal";
|
||||
import { Button, CircularProgress } from "@mui/material";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { clearFilterParams } from "@/helper";
|
||||
import { useState } from "react";
|
||||
|
||||
function DeleteAllButton({ filter, sendReq, setFilter, handleClose }) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const router = useRouter();
|
||||
|
||||
const resetFilter = () => {
|
||||
setLoading(true);
|
||||
clearFilterParams(router, [
|
||||
"category",
|
||||
"specialty",
|
||||
"active",
|
||||
"gender",
|
||||
"degree",
|
||||
]);
|
||||
|
||||
const newFilter = {
|
||||
...filter,
|
||||
...{
|
||||
category: undefined,
|
||||
specialty: undefined,
|
||||
active: 0,
|
||||
gender: "هر دو",
|
||||
degree: "همه موارد",
|
||||
},
|
||||
};
|
||||
sendReq(newFilter).finally(() => {
|
||||
setLoading(false);
|
||||
handleClose();
|
||||
setFilter(newFilter);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex justify-between w-full">
|
||||
<p className="text-[#3B3B3B] text-[20px] font-bold">فیلترها</p>
|
||||
<Button
|
||||
variant="text"
|
||||
disabled={loading}
|
||||
onClick={resetFilter}
|
||||
className="cursor-pointer !py-0 !px-2 flex items-center justify-center gap-1"
|
||||
>
|
||||
{loading ? (
|
||||
<CircularProgress className="!max-w-[17px] !max-h-[17px] !w-[17px] !h-[17px] !text-[#F17732]" />
|
||||
) : (
|
||||
<CloseOrangeModal />
|
||||
)}
|
||||
<p className="text-[#F17732] text-[14px] font-normal">حذف همه</p>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default DeleteAllButton;
|
||||
@@ -0,0 +1,58 @@
|
||||
"use client";
|
||||
|
||||
import { styleDefault } from "@/mui";
|
||||
import { Modal } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import Content from "./Content";
|
||||
import ButtonApply from "./ButtonApply";
|
||||
import DeleteAllButton from "./DeleteAllButton";
|
||||
|
||||
function FilterModal({
|
||||
filter,
|
||||
sendReq,
|
||||
children,
|
||||
setFilter,
|
||||
updateData,
|
||||
setDataInURL,
|
||||
}) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleOpen = () => setOpen(true);
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Button Modal */}
|
||||
<div onClick={handleOpen}>{children}</div>
|
||||
|
||||
{/* Content Modal */}
|
||||
<Modal open={open} onClose={handleClose} className="w-full">
|
||||
<div
|
||||
style={styleDefault}
|
||||
className="!px-[16px] !overflow-auto md:!min-w-[580px] md:!px-[24px] lg:!px-[32px] !py-[24px] !bg-[#FFF] !rounded-[8px] !shadow-[0px_1px_24.8px_0px_rgba(204,_204,_204,_0.18)]
|
||||
!w-full md:!w-fit !h-full md:!h-fit !flex !flex-col !justify-between !max-h-screen md:!max-h-[calc(100%_-_32px)]"
|
||||
>
|
||||
<div>
|
||||
<DeleteAllButton
|
||||
filter={filter}
|
||||
sendReq={sendReq}
|
||||
setFilter={setFilter}
|
||||
handleClose={handleClose}
|
||||
/>
|
||||
<Content
|
||||
filter={filter}
|
||||
setFilter={setFilter}
|
||||
updateData={updateData}
|
||||
setDataInURL={setDataInURL}
|
||||
/>
|
||||
</div>
|
||||
<ButtonApply sendReq={sendReq} setOpen={setOpen} />
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default FilterModal;
|
||||
@@ -0,0 +1,82 @@
|
||||
import BottomSelect from "@/components/icons/BottomSelect";
|
||||
import { Autocomplete, Button, TextField } from "@mui/material";
|
||||
import { styleTextSelectRight } from "@/mui";
|
||||
|
||||
function CateSelector({ name, list, value, isError, updateData, label }) {
|
||||
return (
|
||||
<Autocomplete
|
||||
disablePortal
|
||||
value={value || null}
|
||||
options={list}
|
||||
getOptionLabel={(option) => option?.name}
|
||||
className="!w-full !rounded-lg auto-complete-selector"
|
||||
onChange={(_, newValue) => updateData(name, newValue)}
|
||||
sx={{
|
||||
...styleTextSelectRight,
|
||||
// Hide Icon Number
|
||||
"& input::-webkit-outer-spin-button, & input::-webkit-inner-spin-button":
|
||||
{
|
||||
display: "none",
|
||||
},
|
||||
"& input[type=number]": {
|
||||
MozAppearance: "textfield",
|
||||
},
|
||||
"& .MuiInputBase-input": { padding: "12.5px 14px !important" },
|
||||
"& .MuiInputBase-root": {
|
||||
borderRadius: 2,
|
||||
padding: "0 !important",
|
||||
height: {
|
||||
xs: "43px !important",
|
||||
sm: "43px !important",
|
||||
md: "46px !important",
|
||||
lg: "48px !important",
|
||||
},
|
||||
},
|
||||
"& .MuiOutlinedInput-notchedOutline": {
|
||||
border: "1px solid #D7D7D7",
|
||||
},
|
||||
"& .MuiInput-underline:hover:not(.Mui-disabled):before, .MuiOutlinedInput-notchedOutline":
|
||||
{
|
||||
borderColor: "#D7D7D7 !important",
|
||||
},
|
||||
"& .muirtl-1kiro5a-MuiInputBase-root-MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline":
|
||||
{
|
||||
border: "1px solid #5559CE !important",
|
||||
},
|
||||
"& .MuiOutlinedInput-notchedOutline": {
|
||||
border: isError ? "1px solid red !important" : "",
|
||||
},
|
||||
}}
|
||||
renderOption={(props, option) => (
|
||||
<Button
|
||||
fullWidth
|
||||
{...props}
|
||||
key={option.id || props.id}
|
||||
className="!flex !justify-start !p-[8px] !text-start !text-[#A1A1A1] hover:dark:!bg-[#35343D] !bg-[#FFF] dark:!bg-[#1F1D2B]"
|
||||
>
|
||||
{option.name}
|
||||
</Button>
|
||||
)}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
fullWidth
|
||||
{...params}
|
||||
InputProps={{
|
||||
...params.InputProps,
|
||||
endAdornment: (
|
||||
<div className="absolute left-4">
|
||||
<BottomSelect />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
placeholder={label}
|
||||
sx={{
|
||||
borderRadius: "8px",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default CateSelector;
|
||||
@@ -0,0 +1,19 @@
|
||||
import Radios from "./Radios";
|
||||
|
||||
function RadioContent({ group, text, value, updateData, name }) {
|
||||
return (
|
||||
<div>
|
||||
<p className="text-[16px] font-medium text-[#3B3B3B]">{text}</p>
|
||||
<div className="mt-[16px]">
|
||||
<Radios
|
||||
updateData={updateData}
|
||||
group={group}
|
||||
value={value}
|
||||
name={name}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default RadioContent;
|
||||
@@ -0,0 +1,29 @@
|
||||
import { FormControlLabel, Radio, RadioGroup } from "@mui/material";
|
||||
|
||||
function Radios({ group, value, updateData, name }) {
|
||||
return (
|
||||
<RadioGroup
|
||||
value={value}
|
||||
className="radio-mui"
|
||||
onChange={(e) => updateData(name, e.target.value)}
|
||||
sx={{
|
||||
"& .MuiFormControlLabel-root": {
|
||||
marginRight: "0 !important",
|
||||
transform: "translateX(9px)",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{group.map((item, idx) => (
|
||||
<FormControlLabel
|
||||
control={<Radio className="!ml-2" />}
|
||||
className="!text-[#525252]"
|
||||
label={item}
|
||||
value={item}
|
||||
key={idx}
|
||||
/>
|
||||
))}
|
||||
</RadioGroup>
|
||||
);
|
||||
}
|
||||
|
||||
export default Radios;
|
||||
@@ -0,0 +1,30 @@
|
||||
import { FormControlLabel, Switch } from "@mui/material";
|
||||
|
||||
function SwitchContent({ filter, updateData }) {
|
||||
return (
|
||||
<div className="flex items-center justify-start gap-[12px]">
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={filter.active}
|
||||
onChange={(event) =>
|
||||
updateData("active", event.target.checked ? 1 : 0)
|
||||
}
|
||||
/>
|
||||
}
|
||||
sx={{
|
||||
".MuiFormControlLabel-label": {
|
||||
color: "#3B3B3B",
|
||||
fontSize: "16px",
|
||||
fontWeight: 500,
|
||||
},
|
||||
marginLeft: "0 !important",
|
||||
}}
|
||||
label="فقط پزشکان دارای نوبت"
|
||||
labelPlacement="start"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SwitchContent;
|
||||
@@ -0,0 +1,55 @@
|
||||
import SwitchContent from "./SwitchContent";
|
||||
import RadioContent from "./RadioContent";
|
||||
import { filterList } from "@/helper";
|
||||
import CateSelector from "./CateSelector";
|
||||
|
||||
const gender = ["زن", "مرد", "هر دو"];
|
||||
const degree = ["پزشک عمومی", "پزشک متخصص", "پزشک فوق تخصص", "همه موارد"];
|
||||
|
||||
function Form({ filter, changeSpecialty, updateData }) {
|
||||
const { parentList, childrenList } = filterList(filter);
|
||||
|
||||
return (
|
||||
<>
|
||||
<CateSelector
|
||||
name="category"
|
||||
list={parentList}
|
||||
label="دسته بندی"
|
||||
value={filter.category}
|
||||
updateData={changeSpecialty}
|
||||
/>
|
||||
<div
|
||||
className={`${!!childrenList.length ? "max-h-32 mt-[24px]" : "max-h-0 mt-0"} overflow-hidden transition-all duration-500`}
|
||||
>
|
||||
<CateSelector
|
||||
name="specialty"
|
||||
list={childrenList}
|
||||
updateData={updateData}
|
||||
value={filter.specialty}
|
||||
label="تخصص"
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-[40px] mb-[32px]">
|
||||
<RadioContent
|
||||
updateData={updateData}
|
||||
value={filter.gender}
|
||||
text="جنسیت پزشک"
|
||||
group={gender}
|
||||
name="gender"
|
||||
/>
|
||||
<span className="block mt-[16px] mb-[24px] w-full h-px bg-[#EFEFEF]"></span>
|
||||
<RadioContent
|
||||
updateData={updateData}
|
||||
value={filter.degree}
|
||||
text="درجه علمی"
|
||||
group={degree}
|
||||
name="degree"
|
||||
/>
|
||||
<span className="block mt-[16px] mb-[24px] w-full h-px bg-[#EFEFEF]"></span>
|
||||
<SwitchContent filter={filter} updateData={updateData} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default Form;
|
||||
@@ -0,0 +1,106 @@
|
||||
import { Autocomplete, TextField } from "@mui/material";
|
||||
import { useRef, useState, useEffect } from "react";
|
||||
|
||||
function AutoComplete({
|
||||
data,
|
||||
noneBg,
|
||||
clearText,
|
||||
inputValue,
|
||||
placeholder,
|
||||
handleSearch,
|
||||
setInputValue,
|
||||
setSelectedOption,
|
||||
debounce = 500,
|
||||
}) {
|
||||
const typingTimeoutRef = useRef(null);
|
||||
const [localInput, setLocalInput] = useState(inputValue || "");
|
||||
|
||||
useEffect(() => {
|
||||
setLocalInput(inputValue || "");
|
||||
}, [inputValue]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onInputChange = (_, newInputValue) => {
|
||||
setLocalInput(newInputValue);
|
||||
|
||||
if (setInputValue) setInputValue(newInputValue);
|
||||
|
||||
if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current);
|
||||
typingTimeoutRef.current = setTimeout(() => {
|
||||
handleSearch(newInputValue);
|
||||
}, debounce);
|
||||
};
|
||||
|
||||
const onChange = (_, newValue) => {
|
||||
if (typingTimeoutRef.current) {
|
||||
clearTimeout(typingTimeoutRef.current);
|
||||
typingTimeoutRef.current = null;
|
||||
}
|
||||
|
||||
const val = newValue
|
||||
? typeof newValue === "string"
|
||||
? newValue
|
||||
: newValue.name
|
||||
: "";
|
||||
setLocalInput(val);
|
||||
setSelectedOption && setSelectedOption(newValue);
|
||||
handleSearch(val);
|
||||
if (setInputValue) setInputValue(val);
|
||||
};
|
||||
|
||||
return (
|
||||
<Autocomplete
|
||||
freeSolo
|
||||
options={data}
|
||||
getOptionLabel={(option) =>
|
||||
typeof option === "string" ? option : option.name
|
||||
}
|
||||
disableClearable
|
||||
inputValue={localInput}
|
||||
className="!w-full"
|
||||
onInputChange={onInputChange}
|
||||
onChange={onChange}
|
||||
renderOption={(props, option) => (
|
||||
<li {...props} key={option.id}>
|
||||
{option.name}
|
||||
</li>
|
||||
)}
|
||||
sx={{
|
||||
"& .MuiAutocomplete-input": {
|
||||
background: noneBg ? "" : "#ffffff !important",
|
||||
},
|
||||
}}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
variant="standard"
|
||||
placeholder={placeholder}
|
||||
dir="rtl"
|
||||
InputProps={{
|
||||
...params.InputProps,
|
||||
disableUnderline: true,
|
||||
style: { height: "100%" },
|
||||
}}
|
||||
sx={{
|
||||
background: "transparent !important",
|
||||
"& .MuiInputBase-input": {
|
||||
background: "#FAFAFA",
|
||||
color: "#6C757D",
|
||||
padding: "0 16px",
|
||||
fontSize: "14px",
|
||||
fontFamily: "inherit",
|
||||
},
|
||||
}}
|
||||
className="!shadow-none !w-full !px-5 !h-full !text-[14px] md:!text-[16px] !min-w-[50%] !rounded-0 !font-normal"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default AutoComplete;
|
||||
@@ -0,0 +1,82 @@
|
||||
import { clearFilterParams } from "@/helper";
|
||||
import { useRouter } from "next/navigation";
|
||||
import specialties from "@/data/specialties.json";
|
||||
import AutoComplete from "./AutoComplete";
|
||||
|
||||
function SearchField({ filter, setFilter, setDataInURL }) {
|
||||
const router = useRouter();
|
||||
|
||||
const clearText = () => {
|
||||
clearFilterParams(router, ["name", "category", "specialty"]);
|
||||
const newFilter = {
|
||||
...filter,
|
||||
...{
|
||||
name: "",
|
||||
category: undefined,
|
||||
specialty: undefined,
|
||||
},
|
||||
};
|
||||
setFilter(newFilter);
|
||||
};
|
||||
|
||||
const handleSearch = (e) => {
|
||||
const findName = specialties.find((item) => item.name === e);
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
let dataUrl = {};
|
||||
|
||||
if (findName) {
|
||||
let newFilter = { ...filter };
|
||||
if (findName.parent) {
|
||||
const itemParent = specialties.find(
|
||||
(item) => item.id === findName.parent
|
||||
);
|
||||
dataUrl.specialty = findName.name;
|
||||
newFilter.category = itemParent;
|
||||
newFilter.specialty = findName;
|
||||
} else {
|
||||
dataUrl.specialty = findName.name;
|
||||
newFilter.category = findName;
|
||||
newFilter.specialty = "";
|
||||
}
|
||||
|
||||
searchParams.delete("name");
|
||||
Object.entries(dataUrl).forEach(([key, value]) => {
|
||||
if (value) {
|
||||
searchParams.set(key, value);
|
||||
}
|
||||
});
|
||||
router.push(`?${searchParams.toString()}`);
|
||||
newFilter.name = e;
|
||||
setFilter(newFilter);
|
||||
} else {
|
||||
let newFilter = filter;
|
||||
|
||||
if (
|
||||
filter.name === filter.specialty?.name ||
|
||||
filter.name === filter.category?.name
|
||||
) {
|
||||
searchParams.delete("specialty");
|
||||
newFilter.specialty = "";
|
||||
newFilter.category = "";
|
||||
router.push(`?${searchParams.toString()}`);
|
||||
}
|
||||
newFilter.name = e;
|
||||
setFilter(newFilter);
|
||||
setDataInURL(newFilter);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="!min-w-[50%] !w-full">
|
||||
<AutoComplete
|
||||
data={specialties}
|
||||
clearText={clearText}
|
||||
inputValue={filter.name}
|
||||
handleSearch={handleSearch}
|
||||
placeholder="جستجوی نام پزشک، تخصص، بیماری ..."
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SearchField;
|
||||
@@ -0,0 +1,55 @@
|
||||
import { Button } from "@mui/material";
|
||||
import SearchD from "@/components/icons/SearchD";
|
||||
import { useState } from "react";
|
||||
import specialties from "@/data/specialties.json";
|
||||
|
||||
function SendReq({ filter, setFilter, setDataInURL, sendReq }) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
// const checkName = () => {
|
||||
// let newFilter = filter;
|
||||
// const specialtyItem =
|
||||
// filter.name &&
|
||||
// specialties.find((item) => item.name.includes(filter.name));
|
||||
|
||||
// if (specialtyItem) {
|
||||
// if (specialtyItem.parent) {
|
||||
// newFilter.specialty = specialtyItem;
|
||||
// newFilter.category = specialties.find(
|
||||
// (item) => item.id === specialtyItem.parent
|
||||
// );
|
||||
// } else {
|
||||
// newFilter.specialty = specialtyItem;
|
||||
// }
|
||||
// }
|
||||
|
||||
// return newFilter;
|
||||
// };
|
||||
|
||||
const filterData = () => {
|
||||
setLoading(false);
|
||||
|
||||
// setLoading(true);
|
||||
// // const newFilter = checkName();
|
||||
// // setFilter(filter);
|
||||
// // setDataInURL(filter);
|
||||
|
||||
// sendReq(filter).finally(() => {
|
||||
// setLoading(false);
|
||||
// });
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
loading={loading}
|
||||
onClick={filterData}
|
||||
className="!flex !m-1 !rounded-[4px] !w-[36px] sm:!w-[42px] md:!w-[49px] lg:!w-[56px] !min-w-[36px] sm:!min-w-[42px] md:!min-w-[49px] lg:!min-w-[56px]
|
||||
!gap-2.5 !p-2.5 md:!p-4 !h-[calc(100%_-_8px)]"
|
||||
>
|
||||
<div className="w-[24px] h-[24px] min-w-[24px] min-h-[24px]">
|
||||
{!loading && <SearchD />}
|
||||
</div>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
export default SendReq;
|
||||
@@ -0,0 +1,54 @@
|
||||
import { Button, ButtonGroup } from "@mui/material";
|
||||
import SettingD from "@/components/icons/SettingD";
|
||||
import ArrowBottomD from "@/components/icons/ArrowBottomD";
|
||||
import SendReq from "./SendReq";
|
||||
import SearchField from "./SearchField";
|
||||
import FilterModal from "../modal/FilterModal";
|
||||
|
||||
function SearchBar({ filter, sendReq, setFilter, updateData, setDataInURL }) {
|
||||
return (
|
||||
<ButtonGroup
|
||||
variant="contained"
|
||||
className="!bg-[#FFF] !w-full lg:!w-[60%] lg:!max-w-[734px] !rounded-lg !overflow-hidden
|
||||
flex items-center !shadow-[0px_1px_24.8px_0px_rgba(204,_204,_204,_0.18)]
|
||||
!h-[44px] sm:!h-[50px] md:!h-[57px] lg:!h-[64px]"
|
||||
>
|
||||
<FilterModal
|
||||
filter={filter}
|
||||
sendReq={sendReq}
|
||||
setFilter={setFilter}
|
||||
updateData={updateData}
|
||||
setDataInURL={setDataInURL}
|
||||
>
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="contained"
|
||||
className="!border-none !hidden lg:!flex !max-h-full !min-w-fit !h-[64px] !px-2 !bg-[#F8F8FF] !rounded-l-none"
|
||||
>
|
||||
<div className="min-w-[20px] min-h-[20px]">
|
||||
<SettingD />
|
||||
</div>
|
||||
<p className="text-[#616161] text-[14px] md:text-[16px] font-medium mx-2">
|
||||
فیلترها
|
||||
</p>
|
||||
<div className="w-[20px] md:w-[22px] lg:w-[24px] h-[20px] md:h-[22px] lg:h-[24px]">
|
||||
<ArrowBottomD />
|
||||
</div>
|
||||
</Button>
|
||||
</FilterModal>
|
||||
<SearchField
|
||||
filter={filter}
|
||||
setFilter={setFilter}
|
||||
setDataInURL={setDataInURL}
|
||||
/>
|
||||
<SendReq
|
||||
filter={filter}
|
||||
sendReq={sendReq}
|
||||
setFilter={setFilter}
|
||||
setDataInURL={setDataInURL}
|
||||
/>
|
||||
</ButtonGroup>
|
||||
);
|
||||
}
|
||||
|
||||
export default SearchBar;
|
||||
@@ -0,0 +1,25 @@
|
||||
import ArrowBottomD from "@/components/icons/ArrowBottomD";
|
||||
import SettingD from "@/components/icons/SettingD";
|
||||
import { Button } from "@mui/material";
|
||||
|
||||
function FilterBtn() {
|
||||
return (
|
||||
<Button
|
||||
className="!flex lg:!hidden !h-[44px] sm:!h-[50px] md:!h-[57px] lg:!h-[64px] !p-2.5 !bg-transparent !shadow-none !border !border-solid !border-[#EFEFEF]"
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
>
|
||||
<div className="min-w-[20px] min-h-[20px]">
|
||||
<SettingD />
|
||||
</div>
|
||||
<p className="text-[#616161] text-[14px] md:text-[16px] font-medium mx-2">
|
||||
فیلترها
|
||||
</p>
|
||||
<div className="w-[20px] md:w-[22px] lg:w-[24px] h-[20px] md:h-[22px] lg:h-[24px]">
|
||||
<ArrowBottomD />
|
||||
</div>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
export default FilterBtn;
|
||||
@@ -0,0 +1,88 @@
|
||||
import { MenuItem, Select, SvgIcon } from "@mui/material";
|
||||
import SortD from "@/components/icons/SortD";
|
||||
import StarDI from "@/components/icons/StarDI";
|
||||
import ArrowBottomD from "@/components/icons/ArrowBottomD";
|
||||
|
||||
const listSort = [
|
||||
{ label: 3, id: 3 },
|
||||
{ label: 4, id: 4 },
|
||||
{ label: 5, id: 5 },
|
||||
];
|
||||
|
||||
function SelectSort({ filter, updateData }) {
|
||||
const handleClick = (e) => {
|
||||
updateData("sort", Number(e.target.value), true);
|
||||
};
|
||||
|
||||
return (
|
||||
<Select
|
||||
displayEmpty
|
||||
value={filter.sort}
|
||||
onChange={handleClick}
|
||||
className="!w-[198px] !max-w-[305px] lg:!w-full text-[14px] md:text-[16px] !bg-transparent lg:!bg-[#FFF] !h-[44px] sm:!h-[50px] md:!h-[57px] lg:!h-[64px]"
|
||||
renderValue={(value) => {
|
||||
return (
|
||||
<div className="w-[20px] flex gap-[4px] md:gap-[8px] md:w-[22px] lg:w-[24px] h-[20px] md:h-[22px] lg:h-[24px]">
|
||||
<SvgIcon color="primary">
|
||||
<SortD />
|
||||
</SvgIcon>
|
||||
{value ? (
|
||||
<ul className="flex items-center justify-start gap-1">
|
||||
{Array(filter.sort)
|
||||
.fill({})
|
||||
.map((_, idx) => (
|
||||
<li key={idx}>
|
||||
<StarDI />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
"مرتب سازی"
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
IconComponent={() => (
|
||||
<div
|
||||
className="mx-3
|
||||
min-w-[20px] md:min-w-[22px] lg:min-w-[24px] min-h-[20px] md:min-h-[22px] lg:min-h-[24px]
|
||||
max-w-[20px] md:max-w-[22px] lg:max-w-[24px] max-h-[20px] md:max-h-[22px] lg:max-h-[24px]
|
||||
w-[20px] md:w-[22px] lg:w-[24px] h-[20px] md:h-[22px] lg:h-[24px]
|
||||
"
|
||||
>
|
||||
<ArrowBottomD />
|
||||
</div>
|
||||
)}
|
||||
sx={{
|
||||
"& .MuiSelect-select ": {
|
||||
paddingRight: "12px !important",
|
||||
},
|
||||
"& .MuiOutlinedInput-notchedOutline ": {
|
||||
borderColor: "#EFEFEF !important",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{listSort.map((item, idx) => (
|
||||
<MenuItem
|
||||
key={idx}
|
||||
value={item.label}
|
||||
name={item.label}
|
||||
className="!flex !flex-col !items-start !w-full hover:!bg-transparent"
|
||||
>
|
||||
<div
|
||||
value={item.id}
|
||||
className="!p-2 !mr-2 !w-[calc(100%_-_16px)] flex items-center justify-start"
|
||||
>
|
||||
{Array(item.label)
|
||||
.fill({})
|
||||
.map((_, idx) => (
|
||||
<StarDI key={idx} />
|
||||
))}
|
||||
</div>
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
|
||||
export default SelectSort;
|
||||
@@ -0,0 +1,24 @@
|
||||
"use client";
|
||||
|
||||
import FilterModal from "../modal/FilterModal";
|
||||
import FilterBtn from "./FilterBtn";
|
||||
import SelectSort from "./SelectSort";
|
||||
|
||||
function SortList({ filter, sendReq, setFilter, updateData, setDataInURL }) {
|
||||
return (
|
||||
<div className="flex flex-wrap items-center lg:!w-[25%] gap-[20px] gap-y-[12px] lg:gap-0">
|
||||
<FilterModal
|
||||
filter={filter}
|
||||
sendReq={sendReq}
|
||||
setFilter={setFilter}
|
||||
updateData={updateData}
|
||||
setDataInURL={setDataInURL}
|
||||
>
|
||||
<FilterBtn />
|
||||
</FilterModal>
|
||||
<SelectSort filter={filter} updateData={updateData} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SortList;
|
||||
@@ -1,9 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import SmSearch from "@/components/searchHead/smSearch";
|
||||
import List from "./List";
|
||||
import { useState } from "react";
|
||||
import { searchOnList } from "@/helper";
|
||||
import { useState } from "react";
|
||||
import List from "./List";
|
||||
import Head from "./head";
|
||||
|
||||
function Doctors({ doctors }) {
|
||||
const [filteredSpecialties, setFilteredSpecialties] = useState(doctors);
|
||||
@@ -13,13 +13,15 @@ function Doctors({ doctors }) {
|
||||
|
||||
return (
|
||||
<div className="opacity-page">
|
||||
<div className="flex justify-center">
|
||||
{/* <div className="flex justify-center">
|
||||
<SmSearch
|
||||
data={doctors}
|
||||
handleSearch={handleSearch}
|
||||
placeholder="جستجوی پزشک یا تخصص"
|
||||
/>
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
<Head />
|
||||
<List doctors={filteredSpecialties} />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -10,8 +10,8 @@ import Tabs from "@/app/component/Tabs";
|
||||
const listTab = ["درباره کلینیک", "اطلاعات تماس", "پزشک ها"];
|
||||
|
||||
function ClinicPage({ data, doctors }) {
|
||||
const [value, setValue] = useState(0);
|
||||
const handleChange = (event, newValue) => setValue(newValue);
|
||||
const [value, setValue] = useState(2);
|
||||
const handleChange = (_, newValue) => setValue(newValue);
|
||||
|
||||
const Components = [
|
||||
<About data={data} />,
|
||||
|
||||
@@ -34,8 +34,8 @@ function Share({ data }) {
|
||||
<Box
|
||||
sx={styleDefault}
|
||||
className="!pt-[12px] md:!pt-[14px] lg:!py-[16px] !overflow-hidden
|
||||
!px-[12px] sm:!px-[16px] md:!px-[20px] lg:!px-[24px]
|
||||
!pb-[12px] sm:!pb-[16px] lg:!pb-[20px] !rounded-[8px]"
|
||||
!px-[12px] sm:!px-[16px] md:!px-[20px] lg:!px-[24px]
|
||||
!pb-[12px] sm:!pb-[16px] lg:!pb-[20px] !rounded-[8px]"
|
||||
>
|
||||
<div className="flex items-center justify-between w-full">
|
||||
<p className="text-[#3B3B3B] text-[14px] sm:text-[16px] md:text-[18px] lg:text-[20px] font-medium">
|
||||
|
||||
@@ -21,7 +21,7 @@ function Comments({ doctor, comments }) {
|
||||
<ModalAnswer doctor={doctor} />
|
||||
</div>
|
||||
<Chart comments={comments} doctor={doctor} />
|
||||
<Comment data={doctor} comments={comments} />
|
||||
<Comment comments={comments} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -41,12 +41,9 @@ function ModalAnswer({ doctor }) {
|
||||
rate: newRate,
|
||||
});
|
||||
}
|
||||
const data = res.response?.data;
|
||||
// setComment();
|
||||
})
|
||||
.catch((err) => {
|
||||
const data = err.response?.data;
|
||||
// setComment();
|
||||
.catch(() => {
|
||||
//
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -1,45 +1,70 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import Field from "@/app/component/fields/Field";
|
||||
import { Button } from "@mui/material";
|
||||
import { request } from "@/services/response";
|
||||
import ArrowLeftD from "@/components/icons/ArrowLeftD";
|
||||
|
||||
function Form({ doctor, changeData, setOpen, comment, loading, setLoading }) {
|
||||
console.log(comment.rate);
|
||||
|
||||
function Form({
|
||||
doctor,
|
||||
setOpen,
|
||||
comment,
|
||||
loading,
|
||||
changeData,
|
||||
setComment,
|
||||
setLoading,
|
||||
}) {
|
||||
const [isError, setIsError] = useState(false);
|
||||
|
||||
const sendReq = () => {
|
||||
setLoading(true);
|
||||
if (comment?.detail?.comment) {
|
||||
setLoading(true);
|
||||
|
||||
request
|
||||
.postDoctorComment(comment.detail)
|
||||
.then((res) => {
|
||||
let newComment = comment.rate;
|
||||
newComment = {
|
||||
doctor_id: doctor?.id,
|
||||
accuracy_of_diagnosis: newComment[1].progress,
|
||||
doctor_expertise: newComment[4].progress,
|
||||
doctor_behavior: newComment[2].progress,
|
||||
clinic_cleanliness: newComment[3].progress,
|
||||
waiting_time_at_clinic: newComment[0].progress,
|
||||
};
|
||||
|
||||
request[comment.defaultRate ? "patchDoctorRate" : "postDoctorRate"](
|
||||
newComment,
|
||||
comment.uuid
|
||||
)
|
||||
.then((res) => {
|
||||
setLoading(false);
|
||||
setOpen(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoading(false);
|
||||
setOpen(false);
|
||||
request
|
||||
.postDoctorComment(comment.detail)
|
||||
.then(() => {
|
||||
let newComment = comment.rate;
|
||||
newComment = {
|
||||
doctor_id: doctor?.id,
|
||||
accuracy_of_diagnosis: newComment[1].progress,
|
||||
doctor_expertise: newComment[4].progress,
|
||||
doctor_behavior: newComment[2].progress,
|
||||
clinic_cleanliness: newComment[3].progress,
|
||||
waiting_time_at_clinic: newComment[0].progress,
|
||||
};
|
||||
setComment({
|
||||
...comment,
|
||||
detail: {
|
||||
...comment.detail,
|
||||
comment: "",
|
||||
},
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoading(false);
|
||||
setOpen(false);
|
||||
});
|
||||
|
||||
request[comment.defaultRate ? "patchDoctorRate" : "postDoctorRate"](
|
||||
newComment,
|
||||
comment.uuid
|
||||
)
|
||||
.then(() => {
|
||||
setLoading(false);
|
||||
setOpen(false);
|
||||
})
|
||||
.catch(() => {
|
||||
setLoading(false);
|
||||
setOpen(false);
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
setLoading(false);
|
||||
setOpen(false);
|
||||
});
|
||||
} else {
|
||||
setIsError(true);
|
||||
}
|
||||
};
|
||||
|
||||
const handleChange = (_, val) => {
|
||||
if (val && isError) setIsError(false);
|
||||
else if (!val && !isError) setIsError(true);
|
||||
changeData("detail", "comment", val);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -47,8 +72,9 @@ function Form({ doctor, changeData, setOpen, comment, loading, setLoading }) {
|
||||
<p className="text-[#495057] text-[16px] font-bold">متن نظر</p>
|
||||
<Field
|
||||
type="number"
|
||||
error={isError}
|
||||
multiline={true}
|
||||
handleChange={(_, val) => changeData("detail", "comment", val)}
|
||||
handleChange={handleChange}
|
||||
title="نظر خود را بنویسید..."
|
||||
/>
|
||||
<Button
|
||||
|
||||
@@ -63,6 +63,7 @@ function Content({
|
||||
comment={comment}
|
||||
loading={loading}
|
||||
setOpen={setOpen}
|
||||
setComment={setComment}
|
||||
changeData={changeData}
|
||||
setLoading={setLoading}
|
||||
/>
|
||||
|
||||
@@ -12,7 +12,9 @@ function Poster({ data }) {
|
||||
<div>
|
||||
<div className="flex items-center justify-start gap-[5px]">
|
||||
<Image src={Logo} width={30} height={30} alt="logo" />
|
||||
<p className="text-[#E7EEF6] text-[16px] font-bold">nobat724.com</p>
|
||||
<p className="text-[#E7EEF6] text-[16px] font-bold !-translate-y-1">
|
||||
nobat724.com
|
||||
</p>
|
||||
</div>
|
||||
<p className="mt-[40px] text-[#E7EEF6] text-[20px] font-bold text-right">
|
||||
{data?.name}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[
|
||||
{
|
||||
"name": "clinic_cleanliness",
|
||||
"name": "waiting_time_at_clinic",
|
||||
"label": "زمان انتظار در مطب",
|
||||
"progress": 70
|
||||
},
|
||||
|
||||
@@ -6,7 +6,7 @@ export function getStateInfoClient() {
|
||||
if (typeof window === "undefined")
|
||||
return { matchedCity: null, matchedState: null, fullUrl: "" };
|
||||
|
||||
const fullUrl = window.location.href; // کل URL
|
||||
const fullUrl = window.location.href;
|
||||
const host = window.location.host || "";
|
||||
const subdomain = host.split(".")[0];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user