modal search and default valud of province and city and handle search && show searched state in clinics page

This commit is contained in:
Ehsan
2025-05-15 00:16:09 +03:30
parent feba3c4a64
commit 60fe4c8040
12 changed files with 66 additions and 36 deletions
+4 -1
View File
@@ -1,10 +1,13 @@
import ClinicsPage from "@/components/clinics"; import ClinicsPage from "@/components/clinics";
import Layout from "@/components/layout/StLayout"; import Layout from "@/components/layout/StLayout";
import { getStateInfo } from "@/lib/getStateInfo";
function Clinics() { function Clinics() {
const { matchedCity, matchedState } = getStateInfo();
return ( return (
<Layout name='/clinics'> <Layout name='/clinics'>
<ClinicsPage /> <ClinicsPage matchedCity={matchedCity} matchedState={matchedState} />
</Layout> </Layout>
); );
} }
-1
View File
@@ -20,7 +20,6 @@ function ModalSearchCity({ children, selected, state, setSelected, open, setOpen
const handleClose = () => setOpen(false); const handleClose = () => setOpen(false);
useEffect(() => { useEffect(() => {
if (provinceSelected) { if (provinceSelected) {
const selectedState = states.find( const selectedState = states.find(
(state) => state.label === provinceSelected (state) => state.label === provinceSelected
+3 -6
View File
@@ -1,4 +1,3 @@
"use client";
import { Button, ButtonGroup, TextField } from "@mui/material"; import { Button, ButtonGroup, TextField } from "@mui/material";
import SearchD from "@/components/icons/SearchD"; import SearchD from "@/components/icons/SearchD";
@@ -6,11 +5,7 @@ import ModalSearchCity from "@/app/component/modalSearchCity";
import { useState } from "react"; import { useState } from "react";
import ButtonFilter from "@/app/component/modalSearchCity/ButtonFilter"; import ButtonFilter from "@/app/component/modalSearchCity/ButtonFilter";
function SearchBar() { function SearchBar({ selected, setSelected, state, handleSearch }) {
const [selected, setSelected] = useState({
province: "",
city: "",
});
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
return ( return (
@@ -23,6 +18,7 @@ function SearchBar() {
> >
<ModalSearchCity <ModalSearchCity
open={open} open={open}
state={state}
setOpen={setOpen} setOpen={setOpen}
selected={selected} selected={selected}
setSelected={setSelected} setSelected={setSelected}
@@ -31,6 +27,7 @@ function SearchBar() {
</ModalSearchCity> </ModalSearchCity>
<TextField <TextField
variant="standard" variant="standard"
onChange={e => handleSearch(e.target.value)}
InputProps={{ InputProps={{
disableUnderline: true, disableUnderline: true,
}} }}
+22 -3
View File
@@ -3,11 +3,19 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import List from "./list"; import List from "./list";
import { searchOnList } from "@/helper";
import SearchBar from "./head/SearchBar"; import SearchBar from "./head/SearchBar";
import clinics from "@/data/clinics.json";
import HeadPageList from "@/app/component/head"; import HeadPageList from "@/app/component/head";
function ClinicsPage() { function ClinicsPage({ matchedCity, matchedState }) {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [filteredClinics, setFilteredClinics] = useState(clinics)
const [selected, setSelected] = useState({
province: matchedState?.name || "",
city: matchedCity?.name || "",
});
useEffect(() => { useEffect(() => {
setTimeout(() => { setTimeout(() => {
@@ -15,15 +23,26 @@ function ClinicsPage() {
}, 2000); }, 2000);
}, []); }, []);
const handleSearch = text => {
setFilteredClinics(
searchOnList(clinics, text, 'title')
);
}
return ( return (
<div> <div>
<HeadPageList <HeadPageList
title="لیست کلینیک ها و درمانگاه های تخصصی" title="لیست کلینیک ها و درمانگاه های تخصصی"
detail="در قسمت زیر می توانید کلینیک مورد نظر خود را جستجو نمایید" detail="در قسمت زیر می توانید کلینیک مورد نظر خود را جستجو نمایید"
> >
<SearchBar /> <SearchBar
selected={selected}
setSelected={setSelected}
state={matchedState?.name}
handleSearch={handleSearch}
/>
</HeadPageList> </HeadPageList>
<List loading={loading} /> <List loading={loading} selected={selected} clinics={filteredClinics} />
</div> </div>
); );
} }
+8 -5
View File
@@ -1,16 +1,18 @@
import Pageguide from "@/app/component/Pageguide"; import Pageguide from "@/app/component/Pageguide";
import clinics from "@/data/clinics.json";
import ItemClinic from "./ItemClinic"; import ItemClinic from "./ItemClinic";
import Pagination from "@/app/component/Pagination"; import Pagination from "@/app/component/Pagination";
import { useProvince } from "@/context/ProvinceProvider";
function List({ loading }) { function List({ loading, selected, clinics }) {
const { isProvinceInclude } = useProvince(); const listPage = ["کلینیک ها", selected?.city || ""];
const listPage = ["کلینیک ها", isProvinceInclude?.name || ""];
return ( return (
<div className="padding-responsive pt-[20px]"> <div className="padding-responsive pt-[20px]">
<Pageguide list={listPage} /> <Pageguide list={listPage} />
{clinics.length === 0 ? (
<div className="text-center py-10 text-gray-500">
کلینیکی با این عنوان یافت نشد!
</div>
) : (
<ul <ul
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-[24px] className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-[24px]
gap-y-[16px] sm:gap-y-[24px] md:gap-y-[32px] lg:gap-y-[40px] mt-6" gap-y-[16px] sm:gap-y-[24px] md:gap-y-[32px] lg:gap-y-[40px] mt-6"
@@ -19,6 +21,7 @@ function List({ loading }) {
<ItemClinic data={item} key={item.id} loading={loading} /> <ItemClinic data={item} key={item.id} loading={loading} />
))} ))}
</ul> </ul>
)}
<div className="mt-[48px] flex justify-center"> <div className="mt-[48px] flex justify-center">
<Pagination /> <Pagination />
</div> </div>
+5 -1
View File
@@ -12,11 +12,15 @@ function TextHeader() {
</h1> </h1>
<h2 <h2
className="text-[#525252] text-center mt-2.5 font-kalame text-[16px] sm:text-[25px] md:text-[31px] lg:text-[36px] className="text-[#525252] text-center mt-2.5 font-kalame text-[16px] sm:text-[25px] md:text-[31px] lg:text-[36px]
font-bold flex items-center gap-1 sm:gap-2" font-bold flex items-center gap-0.5 sm:gap-1 md:gap-2"
> >
<div className="max-w-[18px] sm:max-w-[22px]">
<BText /> <BText />
</div>
{matchedCity?.slogan} {matchedCity?.slogan}
<div className="max-w-[18px] sm:max-w-[22px]">
<AText /> <AText />
</div>
</h2> </h2>
</div> </div>
) )
+1 -2
View File
@@ -1,5 +1,4 @@
import { Button, ButtonGroup, TextField } from "@mui/material"; import { ButtonGroup } from "@mui/material";
import SearchD from "@/components/icons/SearchD";
import Fields from "./Fields"; import Fields from "./Fields";
import { getStateInfo } from "@/lib/getStateInfo"; import { getStateInfo } from "@/lib/getStateInfo";
+1
View File
@@ -6,6 +6,7 @@ function AText() {
height="25" height="25"
viewBox="0 0 24 25" viewBox="0 0 24 25"
fill="none" fill="none"
className="w-full"
> >
<g clipPath="url(#clip0_209_1147)"> <g clipPath="url(#clip0_209_1147)">
<path <path
+1 -1
View File
@@ -6,7 +6,7 @@ function BText() {
height="25" height="25"
viewBox="0 0 24 25" viewBox="0 0 24 25"
fill="none" fill="none"
className="rotate-180" className="rotate-180 w-full"
> >
<g clipPath="url(#clip0_209_1152)"> <g clipPath="url(#clip0_209_1152)">
<path <path
+1 -1
View File
@@ -52,7 +52,7 @@ function Footer({ matchedCity }) {
transition-all duration-300 hover:duration-300 rounded-[8px] border-solid border border-[#EFEFEF] bg-[#F7F7F7] hover:bg-none hover:border-[#FDBD9F]" transition-all duration-300 hover:duration-300 rounded-[8px] border-solid border border-[#EFEFEF] bg-[#F7F7F7] hover:bg-none hover:border-[#FDBD9F]"
> >
{item.icon} {item.icon}
<p className="text-[#2F2F2F] text-center text-[16px] font-medium"> <p className="text-[#2F2F2F] text-center text-[12px] sm:text-[14px] md:text-[16px] font-medium">
{item.text} {item.text}
</p> </p>
</div> </div>
+3 -5
View File
@@ -5,17 +5,15 @@ import List from "./list";
import SmSearch from "../searchHead/SmSearch"; import SmSearch from "../searchHead/SmSearch";
import HeadPageList from "@/app/component/head"; import HeadPageList from "@/app/component/head";
import specialtiesData from "@/data/specialties.json"; import specialtiesData from "@/data/specialties.json";
import { searchOnList } from "@/helper";
function SpecialtiesPage() { function SpecialtiesPage() {
const [filteredSpecialties, setFilteredSpecialties] = useState(specialtiesData); const [filteredSpecialties, setFilteredSpecialties] = useState(specialtiesData);
const searchHandler = (e) => { const searchHandler = (e) => {
const value = e.target.value
setFilteredSpecialties( setFilteredSpecialties(
specialtiesData.filter(item => searchOnList(specialtiesData, e.target.value, 'name')
item.name.toLowerCase().includes(value) );
)
)
}; };
return ( return (
+8 -1
View File
@@ -9,7 +9,6 @@ export const convertToJalali = (date) => {
const currentDate = date; const currentDate = date;
const jalaliDate = moment(currentDate).format("jYYYY/jM/jD"); const jalaliDate = moment(currentDate).format("jYYYY/jM/jD");
const jalaliYear = moment(jalaliDate, "jYYYY/jM/jD").jYear(); const jalaliYear = moment(jalaliDate, "jYYYY/jM/jD").jYear();
const jalaliMonth = moment(jalaliDate, "jYYYY/jM/jD").jMonth() + 1; const jalaliMonth = moment(jalaliDate, "jYYYY/jM/jD").jMonth() + 1;
const jalaliDay = moment(jalaliDate, "jYYYY/jM/jD").jDate(); const jalaliDay = moment(jalaliDate, "jYYYY/jM/jD").jDate();
@@ -131,3 +130,11 @@ export function validatePhoneNumber(input) {
return { valid: true, text: null }; return { valid: true, text: null };
} }
export const searchOnList = (list, value, name) => {
let newList = list;
newList = list.filter(item =>
item[name].toLowerCase().includes(value)
)
return newList;
}