From b10fa6259ea8aa9adf2d41e1cc0949dfa433b254 Mon Sep 17 00:00:00 2001 From: ehsan Date: Mon, 29 Sep 2025 00:36:55 +0330 Subject: [PATCH] fix bug modal search location in home && send request after click on continue for update list clinics && change style on hover text of specialties and service in clinics page && add loading for list of clinics && fix bug page doctor item && link footer to clinic-pro --- app/component/ItemDoctor.js | 14 ++- app/globals.css | 4 + .../clinic/components/about/Services.js | 12 +-- .../clinic/components/about/Specialties.js | 34 +++---- .../clinic/components/about/TextDetail.js | 6 +- components/clinic/components/about/index.js | 1 - components/clinics/head/FilterButton.js | 26 ++---- components/clinics/head/SearchBar.js | 31 +++++-- .../clinics/head/filter/AutoComplete.js | 93 +++++++++++++++++++ .../clinics/head/filter/ButtonFilter.js | 35 +++++++ components/clinics/head/filter/Content.js | 87 +++++++++++++++++ components/clinics/head/filter/index.js | 85 +++++++++++++++++ components/clinics/list/ItemClinic.js | 22 ++++- components/clinics/list/index.js | 7 +- .../doctor/detailDoctor/cards/AboutDcotor.js | 2 +- .../cards/comments/chart/index.js | 11 ++- components/doctors/listDoctors/index.js | 1 - components/home/search/modal/Content.js | 24 +++-- components/home/search/modal/index.js | 25 ++--- components/layout/footer/index.js | 27 ++++-- helper/index.js | 8 ++ 21 files changed, 448 insertions(+), 107 deletions(-) create mode 100644 components/clinics/head/filter/AutoComplete.js create mode 100644 components/clinics/head/filter/ButtonFilter.js create mode 100644 components/clinics/head/filter/Content.js create mode 100644 components/clinics/head/filter/index.js diff --git a/app/component/ItemDoctor.js b/app/component/ItemDoctor.js index 0fb4f66..2bdf619 100644 --- a/app/component/ItemDoctor.js +++ b/app/component/ItemDoctor.js @@ -1,22 +1,20 @@ import Image from "next/image"; import { Button } from "@mui/material"; +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"; // Icons import ArrowLeftD from "@/components/icons/ArrowLeftD"; import ClockD from "@/components/icons/ClockD"; import LikeD from "@/components/icons/LikeD"; import PointD from "@/components/icons/PointD"; -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"; -import { useState } from "react"; moment.loadPersian({ dialect: "persian-modern" }); -function ItemDoctor({ doctor, doctors, setDoctors }) { - const [loading, setLoading] = useState(false); +function ItemDoctor({ doctor, setDoctors }) { const handleLoading = () => { setDoctors((prevDoctors) => prevDoctors.map((item) => diff --git a/app/globals.css b/app/globals.css index 8913e3e..73db557 100644 --- a/app/globals.css +++ b/app/globals.css @@ -942,3 +942,7 @@ html { } /* end of date picker appointment */ + +.hover-item-clinic:hover h3 { + color: #f17732; +} diff --git a/components/clinic/components/about/Services.js b/components/clinic/components/about/Services.js index 73ea949..97aeade 100644 --- a/components/clinic/components/about/Services.js +++ b/components/clinic/components/about/Services.js @@ -10,17 +10,15 @@ function Services({ data }) { gap-y-[24px] sm:gap-y-[30px] md:gap-y-[35px] lg:gap-y-[40px]" > {data?.services?.map((item, idx) => ( -
  • +
  • -

    +

    {item.name}

    diff --git a/components/clinic/components/about/Specialties.js b/components/clinic/components/about/Specialties.js index 365cb08..9ea0dbc 100644 --- a/components/clinic/components/about/Specialties.js +++ b/components/clinic/components/about/Specialties.js @@ -9,23 +9,23 @@ function Specialties({ data }) { gap-x-[40px] sm:gap-x-[48px] md:gap-x-[56px] lg:gap-x-[64px] gap-y-[24px] sm:gap-y-[30px] md:gap-y-[35px] lg:gap-y-[40px]" > - {data && data.specialties && data?.specialties?.map((item, idx) => ( -
  • -
    - -
    - -

    - {item.name} -

    -
    -
  • - ))} + {data && + data.specialties && + data?.specialties?.map((item) => ( +
  • +
    + +
    + +

    + {item.name} +

    +
    +
  • + ))} ); } diff --git a/components/clinic/components/about/TextDetail.js b/components/clinic/components/about/TextDetail.js index 81fdae1..34465ca 100644 --- a/components/clinic/components/about/TextDetail.js +++ b/components/clinic/components/about/TextDetail.js @@ -11,13 +11,13 @@ function TextDetail({ data }) {

    180 && isMore - ? "after:bg-transparent max-h-screen" + ? "after:bg-transparent max-h-screen after:absolute" : data?.caption?.length > 180 && - "after:bg-[linear-gradient(transparent,#FAFAFA)] max-h-[200px]" + "after:bg-[linear-gradient(transparent,#FAFAFA)] max-h-[200px] after:absolute" } `} dangerouslySetInnerHTML={{ __html: data?.caption }} diff --git a/components/clinic/components/about/index.js b/components/clinic/components/about/index.js index 3f3255d..1d863bb 100644 --- a/components/clinic/components/about/index.js +++ b/components/clinic/components/about/index.js @@ -6,7 +6,6 @@ import ContentDetail from "./ContentDetail"; import TextDetail from "./TextDetail"; function About({ data }) { - console.log(data); return (

    diff --git a/components/clinics/head/FilterButton.js b/components/clinics/head/FilterButton.js index 8029178..45d7f24 100644 --- a/components/clinics/head/FilterButton.js +++ b/components/clinics/head/FilterButton.js @@ -1,32 +1,18 @@ -import SearchD from "@/components/icons/SearchD"; -import { QueryForClinicsFilter } from "@/helper"; -import { request } from "@/services/response"; -import { Button } from "@mui/material"; import { useState } from "react"; +import { Button } from "@mui/material"; +import SearchD from "@/components/icons/SearchD"; -function FilterButton({ selected, setFilteredClinics }) { +function FilterButton({ filterData }) { const [loading, setLoading] = useState(false); - const filterData = () => { + const sendReq = () => { setLoading(true); - const params = QueryForClinicsFilter(selected); - - request - .getClinicList(params) - .then((res) => { - if (res.data) setFilteredClinics(res.data); - }) - .catch((err) => { - console.log(err); - }) - .finally(() => { - setLoading(false); - }); + filterData().finally(() => setLoading(false)); }; return ( + )} + renderInput={(params) => ( + + +
    + ), + }} + placeholder={label} + sx={{ + borderRadius: "8px", + }} + /> + )} + /> + ); +} + +export default AutoComplete; diff --git a/components/clinics/head/filter/ButtonFilter.js b/components/clinics/head/filter/ButtonFilter.js new file mode 100644 index 0000000..2ebe2e9 --- /dev/null +++ b/components/clinics/head/filter/ButtonFilter.js @@ -0,0 +1,35 @@ +// Icons +import ArrowBottomH from "@/components/icons/ArrowBottomH"; +import Location from "@/components/icons/Location"; +import { Button } from "@mui/material"; + +function ButtonFilter({ selected, setOpen }) { + const handleOpen = () => setOpen(true); + + return ( +
    + +
    + ); +} + +export default ButtonFilter; diff --git a/components/clinics/head/filter/Content.js b/components/clinics/head/filter/Content.js new file mode 100644 index 0000000..5a14757 --- /dev/null +++ b/components/clinics/head/filter/Content.js @@ -0,0 +1,87 @@ +import { Button } from "@mui/material"; + +// Icon +import CloseModalD from "@/components/icons/CloseModalD"; +import ArrowLeftM from "@/components/icons/ArrowLeftM"; +import AutoComplete from "./AutoComplete"; +import { useState } from "react"; + +function Content({ + state, + states, + selected, + updateData, + filterData, + handleClose, + filteredCities, + handleSearch, +}) { + const [loading, setLoading] = useState(false); + const listboxProps = { + style: { + maxHeight: 200, + overflow: "auto", + }, + }; + + const handleFilter = () => { + handleSearch && handleSearch(""); + setLoading(true); + filterData().finally(() => { + handleClose(); + setLoading(false); + }); + }; + + return ( +
    +
    +
    + +
    +
    +
    +

    + شهر یا استان مورد نظر را انتخاب نمایید: +

    +
    + + +
    +
    + +
    +
    +
    + ); +} + +export default Content; diff --git a/components/clinics/head/filter/index.js b/components/clinics/head/filter/index.js new file mode 100644 index 0000000..7a4bdf0 --- /dev/null +++ b/components/clinics/head/filter/index.js @@ -0,0 +1,85 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { Modal, Box } from "@mui/material"; +import { styleDefault } from "@/mui"; + +// Data +import states from "@/data/state.json"; +import cities from "@/data/city.json"; +import Content from "./Content"; +import { useRouter } from "next/navigation"; + +function ModalSearchCity({ + open, + state, + setOpen, + children, + selected, + filterData, + setSelected, + handleSearch, +}) { + const provinceSelected = selected?.province?.name; + const router = useRouter(); + const [filteredCities, setFilteredCities] = useState([]); + + const handleClose = () => setOpen(false); + + useEffect(() => { + if (provinceSelected) { + const selectedState = states.find( + (state) => state.name === provinceSelected + ); + if (selectedState) { + const stateId = selectedState.id; + const filteredCities = cities.filter( + (city) => city.province_id === stateId + ); + setFilteredCities(filteredCities); + } + } else { + setFilteredCities([]); + } + }, [provinceSelected]); + + const updateData = (name, event) => { + const searchParams = new URLSearchParams(window.location.search); + + if (name === "province") { + setSelected({ ...selected, province: event, city: "" }); + searchParams.set("state", event?.name); + searchParams.delete("city", selected.city?.name); + } else { + setSelected({ ...selected, [name]: event }); + searchParams.set("city", event?.name); + searchParams.set("state", selected.province?.name); + } + router.push(`?${searchParams.toString()}`); + }; + + return ( + <> + {/* Button Modal */} + {children} + + {/* Content Modal */} + + + + + + + ); +} + +export default ModalSearchCity; diff --git a/components/clinics/list/ItemClinic.js b/components/clinics/list/ItemClinic.js index 53a4e02..efe62a2 100644 --- a/components/clinics/list/ItemClinic.js +++ b/components/clinics/list/ItemClinic.js @@ -7,7 +7,17 @@ import { Button } from "@mui/material"; import Image from "next/image"; import Link from "next/link"; -function ItemClinic({ data, loading }) { +function ItemClinic({ setFilteredClinics, data, loading }) { + const handleLoading = () => { + setFilteredClinics((prevClinics) => + prevClinics.map((item) => + item.id === data.id + ? { ...item, loading: true } + : { ...item, loading: false } + ) + ); + }; + return (
  • @@ -54,8 +64,14 @@ function ItemClinic({ data, loading }) { {/* Arrow */} -
  • diff --git a/components/clinics/list/index.js b/components/clinics/list/index.js index 4c84446..2db3518 100644 --- a/components/clinics/list/index.js +++ b/components/clinics/list/index.js @@ -40,7 +40,12 @@ function List({ limit, selected, clinics, pages, setFilteredClinics }) { gap-y-[16px] sm:gap-y-[24px] md:gap-y-[32px] lg:gap-y-[40px] mt-6" > {clinics.map((item) => ( - + ))} ) : ( diff --git a/components/doctor/detailDoctor/cards/AboutDcotor.js b/components/doctor/detailDoctor/cards/AboutDcotor.js index 3287974..11c7c1e 100644 --- a/components/doctor/detailDoctor/cards/AboutDcotor.js +++ b/components/doctor/detailDoctor/cards/AboutDcotor.js @@ -43,7 +43,7 @@ function AboutDcotor({ doctor }) {

    تخصص ها

    -
      +
        {doctor?.expertise?.map((item, idx) => (
      • diff --git a/components/doctor/detailDoctor/cards/comments/chart/index.js b/components/doctor/detailDoctor/cards/comments/chart/index.js index 2310a73..4c7faf8 100644 --- a/components/doctor/detailDoctor/cards/comments/chart/index.js +++ b/components/doctor/detailDoctor/cards/comments/chart/index.js @@ -53,11 +53,12 @@ function Chart({ comments, doctor }) {
          - {Object.values(doctor?.average_rate?.averages).map((item, idx) => ( - - - - ))} + {doctor?.average_rate?.averages && + Object.values(doctor?.average_rate?.averages).map((item, idx) => ( + + + + ))}
        diff --git a/components/doctors/listDoctors/index.js b/components/doctors/listDoctors/index.js index bbc50ca..77f95e6 100644 --- a/components/doctors/listDoctors/index.js +++ b/components/doctors/listDoctors/index.js @@ -12,7 +12,6 @@ function ListDoctors({ doctors, setDoctors }) { ))} diff --git a/components/home/search/modal/Content.js b/components/home/search/modal/Content.js index fc708c2..b9f3788 100644 --- a/components/home/search/modal/Content.js +++ b/components/home/search/modal/Content.js @@ -2,8 +2,8 @@ import { Button } from "@mui/material"; // Icon import CloseModalD from "@/components/icons/CloseModalD"; +import AutoCompleteSelect from "@/app/component/element/AutoCompleteSelect"; import ArrowLeftM from "@/components/icons/ArrowLeftM"; -import AutoComplete from "./AutoComplete"; function Content({ state, @@ -14,6 +14,7 @@ function Content({ filteredCities, handleSearch, }) { + const citySelected = selected.city; const listboxProps = { style: { maxHeight: 200, @@ -38,19 +39,24 @@ function Content({ شهر یا استان مورد نظر را انتخاب نمایید:

        - - item.name === citySelected) && + citySelected + } list={filteredCities} name="city" label="شهر" @@ -74,4 +80,4 @@ function Content({ ); } -export default Content; +export default Content; \ No newline at end of file diff --git a/components/home/search/modal/index.js b/components/home/search/modal/index.js index fe1fffb..80a62b8 100644 --- a/components/home/search/modal/index.js +++ b/components/home/search/modal/index.js @@ -3,12 +3,12 @@ import { useState, useEffect } from "react"; import { Modal, Box } from "@mui/material"; import { styleDefault } from "@/mui"; +import { addLabelToList } from "@/helper"; // Data -import states from "@/data/state.json"; -import cities from "@/data/city.json"; +import statesData from "@/data/state.json"; +import citiesData from "@/data/city.json"; import Content from "./Content"; -import { useRouter } from "next/navigation"; function ModalSearchCity({ open, @@ -16,11 +16,13 @@ function ModalSearchCity({ setOpen, children, selected, - setSelected, handleSearch, + setSelected, }) { - const provinceSelected = selected?.province?.name; - const router = useRouter(); + const provinceSelected = selected.province; + + const states = addLabelToList(statesData); + const cities = addLabelToList(citiesData); const [filteredCities, setFilteredCities] = useState([]); const handleClose = () => setOpen(false); @@ -28,7 +30,7 @@ function ModalSearchCity({ useEffect(() => { if (provinceSelected) { const selectedState = states.find( - (state) => state.name === provinceSelected + (state) => state.label === provinceSelected ); if (selectedState) { const stateId = selectedState.id; @@ -42,19 +44,12 @@ function ModalSearchCity({ } }, [provinceSelected]); - const updateData = (name, event) => { - const searchParams = new URLSearchParams(window.location.search); - + const updateData = (event, name) => { if (name === "province") { setSelected({ ...selected, province: event, city: "" }); - searchParams.set("state", event?.name); - searchParams.set("city", selected.city?.name); } else { setSelected({ ...selected, [name]: event }); - searchParams.set("city", event?.name); - searchParams.set("state", selected.province?.name); } - router.push(`?${searchParams.toString()}`); }; return ( diff --git a/components/layout/footer/index.js b/components/layout/footer/index.js index 612415e..90b6256 100644 --- a/components/layout/footer/index.js +++ b/components/layout/footer/index.js @@ -20,7 +20,11 @@ import { useState } from "react"; const head = [ { icon: , text: "جستجوی پزشک در شهر شما" }, { icon: , text: "نوبت گیری سریع و آسان" }, - { icon: , text: "دشبورد اختصاصی برای پزشکان" }, + { + icon: , + text: "دشبورد اختصاصی برای پزشکان", + link: "https://clinic-pro.ir/", + }, ]; function Footer({ matchedCity }) { @@ -50,16 +54,21 @@ function Footer({ matchedCity }) {
        {head.map((item, idx) => ( -
        !item.link && e.preventDefault} > - {item.icon} -

        - {item.text} -

        -
        +
        + {item.icon} +

        + {item.text} +

        +
        + ))}
        diff --git a/helper/index.js b/helper/index.js index 886619d..4aad278 100644 --- a/helper/index.js +++ b/helper/index.js @@ -355,6 +355,14 @@ export const QueryForDoctorsReq = (newFilter) => { return params; }; +export const addLabelToList = (list) => + list.map((item) => { + return { + ...item, + label: item.name, + }; + }); + export const QueryForClinicsFilter = (searchParams) => { const params = {};