handle pagination in clinics page & change design login & fix bug filter state & change list most searched in home page & handle error page doctor item & change key url doctors and home page and get data from url & send data with url search to doctors page & show pagination only when list is long

This commit is contained in:
Ehsan
2025-05-18 01:07:22 +03:30
parent 80c7329916
commit 4a57468e26
15 changed files with 55 additions and 59 deletions
+3 -1
View File
@@ -2,13 +2,15 @@ import { Pagination as PaginationMUI } from "@mui/material";
function Pagination({ page, setPage, list, itemsPerPage }) { function Pagination({ page, setPage, list, itemsPerPage }) {
const handleChange = (_, value) => setPage(value); const handleChange = (_, value) => setPage(value);
const count = list && itemsPerPage ? Math.ceil(list.length / itemsPerPage) : 20;
return ( return (
<PaginationMUI <PaginationMUI
count={list && itemsPerPage ? Math.ceil(list.length / itemsPerPage) : 20} count={count}
page={page || 1} page={page || 1}
onChange={setPage && handleChange} onChange={setPage && handleChange}
color="primary" color="primary"
className={count < 2 && '!hidden'}
sx={{ sx={{
"& .mui-8q7g72-MuiButtonBase-root-MuiPaginationItem-root": { "& .mui-8q7g72-MuiButtonBase-root-MuiPaginationItem-root": {
color: "#616161", color: "#616161",
+1 -1
View File
@@ -23,7 +23,7 @@ function Content({
}; };
const handleFilter = () => { const handleFilter = () => {
handleSearch('') handleSearch && handleSearch('');
handleClose(); handleClose();
} }
+1 -1
View File
@@ -23,7 +23,7 @@ function List({ loading, selected, clinics }) {
</ul> </ul>
)} )}
<div className="mt-[48px] flex justify-center"> <div className="mt-[48px] flex justify-center">
<Pagination /> <Pagination list={clinics} itemsPerPage={12} />
</div> </div>
</div> </div>
); );
@@ -54,13 +54,12 @@ function Chart({ doctor, loading }) {
</div> </div>
<div className="flex flex-wrap items-center justify-center gap-[50px]"> <div className="flex flex-wrap items-center justify-center gap-[50px]">
<ul <ul
className={`flex w-full flex-col items-start justify-start gap-1.5 ${ className={`flex w-full flex-col items-start justify-start gap-1.5 ${loading ? "lg:w-full" : "lg:w-fit"
loading ? "lg:w-full" : "lg:w-fit" }`}
}`}
> >
{doctor.progress_detail.map((item, idx) => ( {doctor.progress_detail.map((item, idx) => (
<TextLoading width="full" height={20} loading={loading}> <TextLoading width="full" key={idx} height={20} loading={loading}>
<ProgressDetail data={item} key={idx} /> <ProgressDetail data={item} />
</TextLoading> </TextLoading>
))} ))}
</ul> </ul>
@@ -9,9 +9,9 @@ function Locations({ doctor, loading }) {
</p> </p>
<ul className="flex w-full mt-[24px] flex-col justify-center items-start"> <ul className="flex w-full mt-[24px] flex-col justify-center items-start">
{doctor.locations.map((item, idx) => ( {doctor.locations.map((item, idx) => (
<CustomLoading loading={loading} width="full" height={40}> <CustomLoading key={idx} loading={loading} width="full" height={40}>
<li className="w-full"> <li className="w-full">
<Item key={idx} data={item} /> <Item data={item} />
{doctor.locations.length > idx + 1 && ( {doctor.locations.length > idx + 1 && (
<span className="w-full h-px bg-[#EFEFEF] block my-[12px] md:my-[14px] lg:my-[16px]"></span> <span className="w-full h-px bg-[#EFEFEF] block my-[12px] md:my-[14px] lg:my-[16px]"></span>
)} )}
+2 -2
View File
@@ -20,11 +20,11 @@ function DoctorsPage({ params, matchedCity, matchedState }) {
}); });
const findItem = (name, value) => specialties.find(item => item[name] === value) const findItem = (name, value) => specialties.find(item => item[name] === value)
const itemCategory = findItem('id', params.category); const itemCategory = findItem('id', params.category);
const itemExpertise = findItem('id', params.expertise); const itemSpecialties = findItem('id', params.specialties);
const [data, setData] = useState({ const [data, setData] = useState({
category: itemCategory || "", category: itemCategory || "",
expertise: itemExpertise ? { ...itemExpertise, label: itemExpertise.name } : "", specialties: itemSpecialties ? { ...itemSpecialties, label: itemSpecialties.name } : "",
turn: params && params.hasOwnProperty('turn') ? JSON.parse(params.turn) : 1, turn: params && params.hasOwnProperty('turn') ? JSON.parse(params.turn) : 1,
gender: params.gender || "هر دو", gender: params.gender || "هر دو",
degree: params.degree || "متخصص", degree: params.degree || "متخصص",
+1 -1
View File
@@ -11,7 +11,7 @@ function ListDoctors({ loading }) {
))} ))}
</ul> </ul>
<div className="mt-[56px] flex justify-center"> <div className="mt-[56px] flex justify-center">
<Pagination /> <Pagination list={doctors} itemsPerPage={12} />
</div> </div>
</> </>
); );
+9 -9
View File
@@ -11,22 +11,22 @@ function Content({ data, setData }) {
const router = useRouter(); const router = useRouter();
const { parentList, childrenList } = filterList(data); const { parentList, childrenList } = filterList(data);
const changeUrl = (value, name, removeExpertise) => { const changeUrl = (value, name, removeSpecialties) => {
const current = new URLSearchParams(window.location.search); const current = new URLSearchParams(window.location.search);
current.set(name, value.id || value); current.set(name, value.id || value);
if (removeExpertise) { if (removeSpecialties) {
current.delete('expertise') current.delete('specialties')
}; };
const queryString = current.toString(); const queryString = current.toString();
router.push(`/doctors?${queryString}`) router.push(`/doctors?${queryString}`)
} }
const changeData = (value, name, removeExpertise) => { const changeData = (value, name, removeSpecialties) => {
changeUrl(value, name, removeExpertise); changeUrl(value, name, removeSpecialties);
const newData = data; const newData = data;
newData[name] = value; newData[name] = value;
if (removeExpertise) { if (removeSpecialties) {
newData.expertise = '' newData.specialties = ''
}; };
setData(newData); setData(newData);
} }
@@ -47,8 +47,8 @@ function Content({ data, setData }) {
list={childrenList} list={childrenList}
updateData={changeData} updateData={changeData}
sendAll={true} sendAll={true}
value={data.expertise} value={data.specialties}
name="expertise" name="specialties"
label="تخصص" label="تخصص"
/> />
</div> </div>
+2 -2
View File
@@ -16,10 +16,10 @@ function FilterModal({ data, setData, children }) {
const handleClose = () => setOpen(false); const handleClose = () => setOpen(false);
const deleteData = () => { const deleteData = () => {
clearFilterParams(router, ['turn', 'expertise', 'degree', 'category', 'gender']) clearFilterParams(router, ['turn', 'specialties', 'degree', 'category', 'gender'])
setData({ setData({
category: "", category: "",
expertise: "", specialties: "",
turn: true, turn: true,
gender: "هر دو", gender: "هر دو",
degree: "متخصص", degree: "متخصص",
-17
View File
@@ -1,17 +0,0 @@
const category = [
{ label: "چشم پزشکی 1", id: 10 },
{ label: "چشم پزشکی 2", id: 20 },
{ label: "چشم پزشکی 3", id: 30 },
{ label: "چشم پزشکی 4", id: 40 },
{ label: "چشم پزشکی 5", id: 40 },
];
const expertise = [
{ label: "تخصص 1", id: 10 },
{ label: "تخصص 2", id: 20 },
{ label: "تخصص 3", id: 30 },
{ label: "تخصص 4", id: 40 },
{ label: "تخصص 5", id: 40 },
];
export { category, expertise };
+12 -5
View File
@@ -1,20 +1,27 @@
import { frequentSearches } from "@/constans"; import { frequentSearches } from "@/constans";
import { filterList } from "@/helper";
import { Button } from "@mui/material"; import { Button } from "@mui/material";
import specialties from "@/data/specialties.json";
import Link from "next/link"; import Link from "next/link";
function FrequentSearches() { function FrequentSearches() {
const childrenList = specialties.filter(item => item.parent);
console.log(childrenList);
return ( return (
<div className="flex items-center justify-center gap-[8px] sm:gap-[10px] md:gap-[13px] lg:gap-[16px] w-full lg:w-fit"> <div className="flex items-center justify-center gap-[8px] sm:gap-[10px] md:gap-[13px] lg:gap-[16px] w-full">
<p className="text-[#3B3B3B] text-[14px] md:text-[16px] font-normal text-nowrap"> <p className="text-[#3B3B3B] text-[14px] md:text-[16px] font-normal text-nowrap">
جستجوهای پر تکرار: جستجوهای پر تکرار:
</p> </p>
<div className="overflow-auto hidden-scroll flex justify-start"> <div className="overflow-auto hidden-scroll flex justify-start max-w-[620px]">
<ul className="flex items-center justify-start gap-[14px] pl-[14px]"> <ul className="flex items-center justify-start gap-[14px] pl-[14px]">
{frequentSearches.map((item, idx) => ( {childrenList.map((item, idx) => (
<Link href={{ <Link href={{
pathname: "/doctors", pathname: "/doctors",
query: { query: {
search: item category: item.parent,
specialties: item.id,
}, },
}}> }}>
<li key={idx}> <li key={idx}>
@@ -24,7 +31,7 @@ function FrequentSearches() {
className="!py-[6px] md:!py-[7px] lg:!py-[8px] !px-[12px] sm:!px-[14px] md:!px-[15px] lg:!px-[16px] !text-[12px] lg:!text-[14px] className="!py-[6px] md:!py-[7px] lg:!py-[8px] !px-[12px] sm:!px-[14px] md:!px-[15px] lg:!px-[16px] !text-[12px] lg:!text-[14px]
!rounded-[4px] !shadow-none !font-normal !border !border-solid !border-[#D7D7D7] hover:!bg-[#EFEFEF]" !rounded-[4px] !shadow-none !font-normal !border !border-solid !border-[#D7D7D7] hover:!bg-[#EFEFEF]"
> >
{item} {item.name}
</Button> </Button>
</li> </li>
</Link> </Link>
+8 -6
View File
@@ -11,7 +11,7 @@ import SearchD from "@/components/icons/SearchD";
function Fields({ city, state }) { function Fields({ city, state }) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [selected, setSelected] = useState({ const [data, setData] = useState({
province: state?.name || '', province: state?.name || '',
city: city?.name || '', city: city?.name || '',
}); });
@@ -21,15 +21,16 @@ function Fields({ city, state }) {
<ModalSearchCity <ModalSearchCity
open={open} open={open}
state={state} state={state}
selected={data}
setOpen={setOpen} setOpen={setOpen}
selected={selected} setSelected={setData}
setSelected={setSelected}
> >
<ButtonFilter setOpen={setOpen} selected={selected} /> <ButtonFilter setOpen={setOpen} selected={data} />
</ModalSearchCity> </ModalSearchCity>
<span className="black w-px bg-[#EFEFEF]"></span> <span className="black w-px bg-[#EFEFEF]"></span>
<TextField <TextField
variant="standard" variant="standard"
onChange={e => setData({ ...data, search: e.target.value })}
InputProps={{ InputProps={{
disableUnderline: true, disableUnderline: true,
}} }}
@@ -62,8 +63,9 @@ function Fields({ city, state }) {
href={{ href={{
pathname: "/doctors", pathname: "/doctors",
query: { query: {
province: selected.province, province: data.province,
city: selected.city, city: data.city,
search: data.search
}, },
}} }}
> >
+3 -3
View File
@@ -8,7 +8,7 @@ function LayoutRegister({ children, matchedCity }) {
<div <div
className="flex padding-responsive items-center justify-center pt-[32px] className="flex padding-responsive items-center justify-center pt-[32px]
overflow-auto flex-col h-screen w-full bg-banner-stroke !bg-bottom !bg-no-repeat !bg-cover overflow-auto flex-col h-screen w-full bg-banner-stroke !bg-bottom !bg-no-repeat !bg-cover
!pb-[calc(108px_+_40px)] md:!pb-[calc(111px_+_40px)]" !pb-[60px] md:!pb-[60px]"
> >
<Link href="/"> <Link href="/">
<div className="flex items-center justify-center gap-[5px] sm:mt-0"> <div className="flex items-center justify-center gap-[5px] sm:mt-0">
@@ -22,9 +22,9 @@ function LayoutRegister({ children, matchedCity }) {
</div> </div>
</Link> </Link>
{children} {children}
<div className="fixed bottom-0 left-0 bg-[#FAFAFA] w-full pb-[50px] px-[18px] sm:px-[67px] md:px[117px] lg:px-[166px]"> <div className="fixed bottom-0 left-0 bg-[#FAFAFA] w-full pb-[10px] md:pb-[14px] px-[18px] sm:px-[67px] md:px[117px] lg:px-[166px]">
<div className="bg-border-t-gradient-sign h-px w-full"></div> <div className="bg-border-t-gradient-sign h-px w-full"></div>
<div className="flex items-center justify-center gap-[32px] sm:gap-[40px] md:gap-[48px] lg:gap-[56px] mt-[24px]"> <div className="flex items-center justify-center gap-[32px] sm:gap-[40px] md:gap-[48px] lg:gap-[56px] mt-[10px] md:mt-[14px]">
{about.map((item, idx) => ( {about.map((item, idx) => (
<Link href="/" key={idx}> <Link href="/" key={idx}>
<p <p
+3 -3
View File
@@ -17,8 +17,8 @@ function LogInPage({ setIsSendMsg, setStep, matchedCity }) {
return ( return (
<div <div
className="rounded-[16px] mt-[64px] opacity-page sm:mt-[32px] border border-solid sm:border-[#EFEFEF] bg-transparent sm:bg-[#FFF] className="rounded-[16px] mt-[28px] opacity-page sm:mt-[14px] border border-solid sm:border-[#EFEFEF] bg-transparent sm:bg-[#FFF]
p-0 border-transparent sm:p-[40px] sm:pb-[48px] w-full sm:w-fit sm:min-w-[425px]" p-0 border-transparent sm:p-[40px] sm:pb-[48px] w-full sm:w-fit sm:min-w-[425px] overflow-hidden"
> >
<p className="text-[#525252] text-[18px] font-bold"> <p className="text-[#525252] text-[18px] font-bold">
ورود یا ثبت نام در {matchedCity?.site_name || "نوبت 724"} ورود یا ثبت نام در {matchedCity?.site_name || "نوبت 724"}
@@ -73,7 +73,7 @@ function LogInPage({ setIsSendMsg, setStep, matchedCity }) {
> >
ورود ورود
</Button> </Button>
<p className="text-[#525252] text-[14px] font-normal text-center mt-[49px] sm:mt-[58px] md:mt-[67px] lg:mt-[76px]"> <p className="text-[#525252] text-[14px] font-normal text-center mt-[34px] sm:mt-[36px] md:mt-[38px] lg:mt-[40px]">
<Link href="/"> <Link href="/">
<span className="text-[#F17732] underline">قوانین استفاده</span> <span className="text-[#F17732] underline">قوانین استفاده</span>
</Link>{" "} </Link>{" "}
+4 -1
View File
@@ -168,7 +168,10 @@ export const filterList = (data) => {
const changedParentList = addKeyToList(parentList, 'label', 'name') || []; const changedParentList = addKeyToList(parentList, 'label', 'name') || [];
const changedChildrenList = addKeyToList(childrenList, 'label', 'name') || []; const changedChildrenList = addKeyToList(childrenList, 'label', 'name') || [];
const filteredChildrenList = changedChildrenList.filter(item => item.parent === data.category.id); const filteredChildrenList =
data && data.category ?
changedChildrenList.filter(item => item.parent === data.category.id) :
[];
return { return {
parentList: changedParentList, parentList: changedParentList,