fix filter gender, req and set new data when delete all filters, show date time with timestamp in doctors list, fix send data in home page list specialty, change data of params for request to doctors in doctors page
This commit is contained in:
@@ -10,6 +10,9 @@ import Link from "next/link";
|
||||
import CustomLoading from "./loading/Custom";
|
||||
import TextLoading from "./loading/Text";
|
||||
import CircularLoading from "./loading/Circular";
|
||||
import moment from "moment-jalaali";
|
||||
|
||||
moment.loadPersian({ dialect: "persian-modern" });
|
||||
|
||||
function ItemDoctor({ doctor }) {
|
||||
return (
|
||||
@@ -78,7 +81,7 @@ function ItemDoctor({ doctor }) {
|
||||
}`}
|
||||
>
|
||||
{Number(doctor?.active)
|
||||
? `اولین نوبت آزاد: ${Number(doctor?.active)}`
|
||||
? `اولین نوبت آزاد: ${moment(doctor?.free_turn * 1000)?.format("dddd jD jMMMM")}`
|
||||
: "نوبت ندارد"}
|
||||
</p>
|
||||
</CustomLoading>
|
||||
|
||||
@@ -21,8 +21,6 @@ function Content({
|
||||
const handleClick = () => {
|
||||
setLoading(true);
|
||||
sendReq().finally(() => {
|
||||
console.log("asd");
|
||||
|
||||
setLoading(false);
|
||||
handleClose();
|
||||
});
|
||||
|
||||
+5
-20
@@ -1,39 +1,24 @@
|
||||
import DoctorsPage from "@/components/doctors";
|
||||
import Layout from "@/components/layout/StLayout";
|
||||
import { buildDoctorParams } from "@/helper";
|
||||
import { getStateInfo } from "@/lib/getStateInfo";
|
||||
import axios from "axios";
|
||||
|
||||
// Data
|
||||
import states from "@/data/state.json";
|
||||
import cities from "@/data/city.json";
|
||||
|
||||
async function Doctors({ searchParams }) {
|
||||
const { matchedCity, matchedState } = getStateInfo();
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||
|
||||
let doctors = null;
|
||||
try {
|
||||
const params = {};
|
||||
const state = searchParams.state;
|
||||
const city = searchParams.city;
|
||||
console.log(state);
|
||||
console.log(city);
|
||||
|
||||
if (matchedCity)
|
||||
params.city = city
|
||||
? cities.find((item) => item.name === city)?.id
|
||||
: matchedCity?.id || null;
|
||||
if (matchedState)
|
||||
params.state = state
|
||||
? states.find((item) => item.name === state)?.id
|
||||
: matchedState?.id || null;
|
||||
if (searchParams.search) params.name = searchParams.search;
|
||||
const params = buildDoctorParams(searchParams);
|
||||
|
||||
const response = await axios.get(`${API_URL}/api/v1/doctors`, {
|
||||
params,
|
||||
});
|
||||
doctors = response.data.data;
|
||||
} catch (error) {}
|
||||
} catch (error) {
|
||||
console.error("Error fetching doctors:", error);
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import React from 'react'
|
||||
|
||||
function Content() {
|
||||
return (
|
||||
<div>Content</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Content
|
||||
@@ -0,0 +1,34 @@
|
||||
import LocationD from "../../icons/LocationD";
|
||||
import { Button } from "@mui/material";
|
||||
import ModalSearchCity from "@/app/component/modalSearchCity";
|
||||
import { useState } from "react";
|
||||
|
||||
function FilterLocate({ filter, sendReq, setFilter, setDataInURL }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<ModalSearchCity
|
||||
open={open}
|
||||
filter={filter}
|
||||
sendReq={sendReq}
|
||||
setOpen={setOpen}
|
||||
setFilter={setFilter}
|
||||
setDataInURL={setDataInURL}
|
||||
>
|
||||
<Button
|
||||
className="!flex !ml-auto !w-fit !px-3 !py-1 !items-center !justify-start !gap-2 !cursor-pointer"
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
<LocationD />
|
||||
<h1 className="text-[#525252] text-[16px] font-semibold">
|
||||
{" "}
|
||||
{filter?.state?.name || "استان"}
|
||||
{" / "}
|
||||
{filter?.city?.name || "شهر"}
|
||||
</h1>
|
||||
</Button>
|
||||
</ModalSearchCity>
|
||||
);
|
||||
}
|
||||
|
||||
export default FilterLocate;
|
||||
@@ -2,38 +2,26 @@ import { useState } from "react";
|
||||
|
||||
import SearchBar from "../search";
|
||||
import SortList from "../sortlist";
|
||||
import { Button } from "@mui/material";
|
||||
import { useParams, useRouter, useSearchParams } from "next/navigation";
|
||||
import LocationD from "../../icons/LocationD";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import specialties from "@/data/specialties.json";
|
||||
import ModalSearchCity from "@/app/component/modalSearchCity";
|
||||
|
||||
// Data
|
||||
import states from "@/data/state.json";
|
||||
import cities from "@/data/city.json";
|
||||
import { QueryForDoctorsFilter, QueryForDoctorsReq } from "@/helper";
|
||||
import { request } from "@/services/response";
|
||||
import FilterLocate from "./FilterLocate";
|
||||
|
||||
function Head({ matchedCity, matchedState, setDoctors }) {
|
||||
const params = useParams();
|
||||
const searchParams = useSearchParams();
|
||||
const router = useRouter();
|
||||
const fieldName = searchParams.get("specialty");
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const findItem = (key, name) =>
|
||||
specialties.find((item) => item[key] === name);
|
||||
const isParent =
|
||||
findItem("name", fieldName) && findItem("name", fieldName).parent;
|
||||
|
||||
const defaultData = {
|
||||
category: isParent ? findItem("id", isParent) : findItem("name", fieldName),
|
||||
specialties: isParent && findItem("name", fieldName),
|
||||
turn: params && params.hasOwnProperty("turn") ? JSON.parse(params.turn) : 1,
|
||||
gender: params.gender || "هر دو",
|
||||
degree: params.degree || "همه موارد",
|
||||
};
|
||||
|
||||
const selectedState = searchParams.get("state") || matchedState?.name;
|
||||
const selectedCity =
|
||||
searchParams.get("city") ||
|
||||
@@ -51,7 +39,6 @@ function Head({ matchedCity, matchedState, setDoctors }) {
|
||||
name: searchParams.get("name") || "",
|
||||
};
|
||||
|
||||
const [data, setData] = useState(defaultData);
|
||||
const [filter, setFilter] = useState(defaultFilter);
|
||||
|
||||
const setDataInURL = (newFilter) => {
|
||||
@@ -83,27 +70,12 @@ function Head({ matchedCity, matchedState, setDoctors }) {
|
||||
|
||||
return (
|
||||
<div className="flex justify-center gap-[16px] sm:gap-[19px] md:gap-[22px] lg:gap-[24px] flex-col items-center mt-0 md:mt-[40px] lg:mt-[90px]">
|
||||
<ModalSearchCity
|
||||
open={open}
|
||||
<FilterLocate
|
||||
filter={filter}
|
||||
sendReq={sendReq}
|
||||
setOpen={setOpen}
|
||||
setFilter={setFilter}
|
||||
setDataInURL={setDataInURL}
|
||||
>
|
||||
<Button
|
||||
className="!flex !ml-auto !w-fit !px-3 !py-1 !items-center !justify-start !gap-2 !cursor-pointer"
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
<LocationD />
|
||||
<h1 className="text-[#525252] text-[16px] font-semibold">
|
||||
{" "}
|
||||
{filter?.state?.name || "استان"}
|
||||
{" / "}
|
||||
{filter?.city?.name || "شهر"}
|
||||
</h1>
|
||||
</Button>
|
||||
</ModalSearchCity>
|
||||
/>
|
||||
<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}
|
||||
@@ -113,10 +85,11 @@ function Head({ matchedCity, matchedState, setDoctors }) {
|
||||
setDataInURL={setDataInURL}
|
||||
/>
|
||||
<SortList
|
||||
data={data}
|
||||
filter={filter}
|
||||
setData={setData}
|
||||
sendReq={sendReq}
|
||||
setFilter={setFilter}
|
||||
updateData={updateData}
|
||||
setDataInURL={setDataInURL}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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;
|
||||
@@ -1,13 +1,11 @@
|
||||
"use client";
|
||||
|
||||
import CloseOrangeModal from "@/components/icons/CloseOrangeModal";
|
||||
import { styleDefault } from "@/mui";
|
||||
import { Button, Modal } from "@mui/material";
|
||||
import { Modal } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import Content from "./Content";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { clearFilterParams } from "@/helper";
|
||||
import ButtonApply from "./ButtonApply";
|
||||
import DeleteAllButton from "./DeleteAllButton";
|
||||
|
||||
function FilterModal({
|
||||
filter,
|
||||
@@ -17,7 +15,6 @@ function FilterModal({
|
||||
updateData,
|
||||
setDataInURL,
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleOpen = () => setOpen(true);
|
||||
@@ -25,30 +22,6 @@ function FilterModal({
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const resetFilter = () => {
|
||||
clearFilterParams(router, [
|
||||
"category",
|
||||
"specialty",
|
||||
"active",
|
||||
"gender",
|
||||
"degree",
|
||||
]);
|
||||
|
||||
const newFilter = {
|
||||
category: undefined,
|
||||
specialty: undefined,
|
||||
active: 0,
|
||||
gender: "هر دو",
|
||||
degree: "همه موارد",
|
||||
};
|
||||
setFilter({
|
||||
...filter,
|
||||
...newFilter,
|
||||
});
|
||||
|
||||
handleClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Button Modal */}
|
||||
@@ -62,19 +35,12 @@ function FilterModal({
|
||||
!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>
|
||||
<div className="flex justify-between w-full">
|
||||
<p className="text-[#3B3B3B] text-[20px] font-bold">فیلترها</p>
|
||||
<Button
|
||||
className="cursor-pointer !p-0 flex items-center justify-center gap-1"
|
||||
onClick={resetFilter}
|
||||
variant="text"
|
||||
>
|
||||
<CloseOrangeModal />
|
||||
<p className="text-[#F17732] text-[14px] font-normal">
|
||||
حذف همه
|
||||
</p>
|
||||
</Button>
|
||||
</div>
|
||||
<DeleteAllButton
|
||||
filter={filter}
|
||||
sendReq={sendReq}
|
||||
setFilter={setFilter}
|
||||
handleClose={handleClose}
|
||||
/>
|
||||
<Content
|
||||
filter={filter}
|
||||
setFilter={setFilter}
|
||||
|
||||
@@ -4,10 +4,22 @@ import FilterModal from "../modal/FilterModal";
|
||||
import FilterBtn from "./FilterBtn";
|
||||
import SelectSort from "./SelectSort";
|
||||
|
||||
function SortList({ data, filter, setData, updateData }) {
|
||||
function SortList({
|
||||
filter,
|
||||
updateData,
|
||||
sendReq,
|
||||
setFilter,
|
||||
setDataInURL,
|
||||
}) {
|
||||
return (
|
||||
<div className="flex flex-wrap items-center lg:!w-[25%] gap-[20px] gap-y-[12px] lg:gap-0">
|
||||
<FilterModal data={data} setData={setData}>
|
||||
<FilterModal
|
||||
filter={filter}
|
||||
sendReq={sendReq}
|
||||
setFilter={setFilter}
|
||||
updateData={updateData}
|
||||
setDataInURL={setDataInURL}
|
||||
>
|
||||
<FilterBtn />
|
||||
</FilterModal>
|
||||
<SelectSort filter={filter} updateData={updateData} />
|
||||
|
||||
@@ -17,7 +17,7 @@ function FrequentSearches() {
|
||||
href={{
|
||||
pathname: "/doctors",
|
||||
query: {
|
||||
field: item.id,
|
||||
specialty: item.name,
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
||||
+96
-3
@@ -1,8 +1,12 @@
|
||||
import { toast } from "react-toastify";
|
||||
import specialties from "@/data/specialties.json";
|
||||
import Cookies from "js-cookie";
|
||||
import moment from "moment-jalaali";
|
||||
|
||||
// Data
|
||||
import specialties from "@/data/specialties.json";
|
||||
import states from "@/data/state.json";
|
||||
import cities from "@/data/city.json";
|
||||
|
||||
export const numberToArStyle = (num) => num?.toLocaleString("ar-AE") || "";
|
||||
|
||||
export const isActiveURL = (link, name) => link === name;
|
||||
@@ -329,9 +333,25 @@ export const QueryForDoctorsReq = (newFilter) => {
|
||||
if (newFilter.state?.id) params.state = newFilter.state.id;
|
||||
|
||||
if (newFilter.degree && newFilter.degree !== "همه موارد")
|
||||
params.degree = newFilter.degree;
|
||||
switch (newFilter.degree) {
|
||||
case "کارشناس":
|
||||
params.degree = "expert";
|
||||
break;
|
||||
case "پزشک عمومی":
|
||||
params.degree = "general";
|
||||
break;
|
||||
case "پزشک متخصص":
|
||||
params.degree = "specialist";
|
||||
break;
|
||||
case "پزشک فوق تخصص":
|
||||
params.degree = "subspecialistplus";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (newFilter.gender && newFilter.gender !== "هر دو")
|
||||
params.gender = newFilter.gender;
|
||||
params.gender = newFilter.gender === "مرد" ? "man" : "woman";
|
||||
|
||||
if (newFilter.name) params.name = newFilter.name;
|
||||
|
||||
@@ -342,3 +362,76 @@ export const QueryForDoctorsReq = (newFilter) => {
|
||||
|
||||
return params;
|
||||
};
|
||||
|
||||
export const buildDoctorParams = (searchParams) => {
|
||||
const params = {};
|
||||
|
||||
// 🔹 active
|
||||
if (searchParams.active && Number(searchParams.active) === 1) {
|
||||
params.active = 1;
|
||||
}
|
||||
|
||||
// 🔹 specialty (find by name in specialties.json)
|
||||
if (searchParams.specialty) {
|
||||
const spec = specialties.find((s) => s.name === searchParams.specialty);
|
||||
if (spec) {
|
||||
params.specialty = spec.id;
|
||||
}
|
||||
}
|
||||
|
||||
// 🔹 city (find by name in city.json)
|
||||
if (searchParams.city) {
|
||||
const cityObj = cities.find((c) => c.name === searchParams.city);
|
||||
if (cityObj) {
|
||||
params.city = cityObj.id;
|
||||
}
|
||||
}
|
||||
|
||||
// 🔹 state (find by name in state.json)
|
||||
if (searchParams.state) {
|
||||
const stateObj = states.find((s) => s.name === searchParams.state);
|
||||
if (stateObj) {
|
||||
params.state = stateObj.id;
|
||||
}
|
||||
}
|
||||
|
||||
// 🔹 degree → convert fa → en
|
||||
if (searchParams.degree) {
|
||||
switch (searchParams.degree) {
|
||||
case "کارشناس":
|
||||
params.degree = "expert";
|
||||
break;
|
||||
case "پزشک عمومی":
|
||||
params.degree = "general";
|
||||
break;
|
||||
case "پزشک متخصص":
|
||||
params.degree = "specialist";
|
||||
break;
|
||||
case "پزشک فوق تخصص":
|
||||
params.degree = "subspecialistplus";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 🔹 gender
|
||||
if (searchParams.gender) {
|
||||
if (searchParams.gender === "مرد") params.gender = "man";
|
||||
if (searchParams.gender === "زن") params.gender = "woman";
|
||||
}
|
||||
|
||||
// 🔹 name
|
||||
if (searchParams.name) {
|
||||
params.name = searchParams.name;
|
||||
}
|
||||
|
||||
// 🔹 sort (3 = ASC, 4|5 = DESC)
|
||||
if (searchParams.sort) {
|
||||
const sortNum = Number(searchParams.sort);
|
||||
if (sortNum === 3) params.sort = "ASC";
|
||||
else if ([4, 5].includes(sortNum)) params.sort = "DESC";
|
||||
}
|
||||
|
||||
return params;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user