Skip to content

Commit

Permalink
Merge pull request #10 from mohammad00alavi/branch-10_search_autocomp…
Browse files Browse the repository at this point in the history
…lete

Branch 10 search autocomplete
  • Loading branch information
mohammad00alavi authored Sep 6, 2023
2 parents 0e63933 + d273de4 commit 5ae98d7
Show file tree
Hide file tree
Showing 22 changed files with 344 additions and 58 deletions.
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
NEXT_PUBLIC_WEATHER_API_KEY=c140b0fcb1cd436a9f3f757823397c1d
NEXT_PUBLIC_UNSPLASH_API_KEY=M4KxGszn25i0ppP2jAfck3-YgWxt-0OdlZfgmfIZGrk
NEXT_PUBLIC_UNSPLASH_API_KEY=M4KxGszn25i0ppP2jAfck3-YgWxt-0OdlZfgmfIZGrk
NEXT_PUBLIC_GOOGLE_API_KEY=AIzaSyB8-GYZov3FeO9z1B_y3LH7J_d_2k95Q7Q
23 changes: 23 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@
"postcss": "8.4.26",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-google-autocomplete": "^2.7.3",
"react-plotly.js": "^2.6.0",
"tailwindcss": "3.3.3",
"typescript": "5.1.6"
},
"devDependencies": {
"@types/googlemaps": "^3.43.3"
}
}
45 changes: 0 additions & 45 deletions src/components/CityInput/CityInput.tsx

This file was deleted.

27 changes: 27 additions & 0 deletions src/components/Search/SeachModalList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from "react";
import { SearchModalItem } from "./SearchModalItem";

export interface SeachModalListProps {
itemList: google.maps.places.AutocompletePrediction[];
searchClickHandler: () => void;
}

const SeachModalList = ({
itemList,
searchClickHandler,
}: SeachModalListProps) => {
return (
<ul className="bg-gray-500">
{itemList?.map((item) => (
<SearchModalItem
href={item.structured_formatting.main_text}
key={item.place_id}
clickHandler={searchClickHandler}
text={item.description}
/>
))}
</ul>
);
};

export default SeachModalList;
15 changes: 15 additions & 0 deletions src/components/Search/SearchCity.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";
import { SearchFormProps } from "@/types/SearchFormProps";
import SearchModalContainer from "./SearchModalContainer";
import SearchForm from "./SearchForm";

const SearchCity: React.FC<SearchFormProps> = ({ onTestSubmit }) => {
return (
<div className="w-full m-auto absolute z-50">
<SearchForm onTestSubmit={onTestSubmit} />
<SearchModalContainer />
</div>
);
};

export default SearchCity;
45 changes: 45 additions & 0 deletions src/components/Search/SearchForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useSearch } from "@/hooks/useSearch";
import { SearchFormProps } from "@/types/SearchFormProps";
import { useRouter } from "next/router";
import React from "react";

const SearchForm = ({ onTestSubmit }: SearchFormProps) => {
const { handleInputChange, inputText, setInputText } = useSearch();
const router = useRouter();

const onSubmitHandler = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
// Only for passing the test
if (onTestSubmit) {
onTestSubmit({
city: inputText.toLowerCase(),
});
}
router.push(`/${inputText.toLowerCase()}`, undefined, {
shallow: false,
});
setInputText("");
};
return (
<form
onSubmit={onSubmitHandler}
className="flex flex-row justify-between w-full relative opacity-40"
>
<input
aria-label="search"
className="py-4 px-4 outline-none w-full"
type="text"
value={inputText}
onChange={handleInputChange}
required
placeholder="Enter city name here... :)"
/>

<button className="py-2 px-4 bg-white" type="submit">
Search
</button>
</form>
);
};

export default SearchForm;
27 changes: 27 additions & 0 deletions src/components/Search/SearchModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from "react";
import SeachModalList, { SeachModalListProps } from "./SeachModalList";

interface SearchModalProps extends SeachModalListProps {
closeModalHandler: () => void;
}

const SearchModal = ({
itemList,
searchClickHandler,
closeModalHandler,
}: SearchModalProps) => {
return (
<div className="relative">
<SeachModalList
itemList={itemList}
searchClickHandler={searchClickHandler}
/>
<div
className="absolute w-full h-screen bg-transparent z-50"
onClick={closeModalHandler}
/>
</div>
);
};

export default SearchModal;
32 changes: 32 additions & 0 deletions src/components/Search/SearchModalContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from "react";
import SearchModal from "./SearchModal";
import { useSearch } from "@/hooks/useSearch";

const SearchModalContainer = () => {
const {
inputText,
setInputText,
isModalOpen,
setIsModalOpen,
predictions: uniquePredictions,
isPlacePredictionsLoading,
} = useSearch();

return (
<>
{inputText &&
isModalOpen &&
(isPlacePredictionsLoading ? (
<p className="text-white p-4 bg-gray-500">loading...</p>
) : (
<SearchModal
closeModalHandler={() => setIsModalOpen(false)}
itemList={uniquePredictions}
searchClickHandler={() => setInputText("")}
/>
))}
</>
);
};

export default SearchModalContainer;
26 changes: 26 additions & 0 deletions src/components/Search/SearchModalItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Link from "next/link";
import React from "react";

interface SearchModalItemProps {
href: string;
clickHandler: () => void;
text: string;
}

export const SearchModalItem = ({
href,
clickHandler,
text,
}: SearchModalItemProps) => {
return (
<Link
href={`/${href.toLowerCase()}`}
className="text-white"
onClick={clickHandler}
>
<li className="text-white p-4 lg:p-2 border-b-[1px] border-gray-400">
{text}
</li>
</Link>
);
};
36 changes: 36 additions & 0 deletions src/context/SearchContext/Provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { usePlacePredictions } from "@/hooks/usePlacePredictions";
import React, { createContext } from "react";

interface Props {
children: React.ReactNode;
}

export const SearchContext = createContext({});
const Provider = ({ children }: Props) => {
const {
inputText,
setInputText,
isModalOpen,
setIsModalOpen,
predictions: uniquePredictions,
isPlacePredictionsLoading,
handleInputChange,
} = usePlacePredictions();
return (
<SearchContext.Provider
value={{
inputText,
setInputText,
isModalOpen,
setIsModalOpen,
predictions: uniquePredictions,
isPlacePredictionsLoading,
handleInputChange,
}}
>
{children}
</SearchContext.Provider>
);
};

export default Provider;
7 changes: 5 additions & 2 deletions src/elements/CityElement/CityElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import Layout from "@/components/Layout/Layout";
import DateAndLocation from "./DateAndLocation";
import TempContainer from "./TempContainer";
import CityTemplate from "./CityTemplate";
import CityInput from "@/components/CityInput/CityInput";
import SearchCity from "@/components/Search/SearchCity";
import CustomHead from "@/components/CustomHead/CustomHead";
import SearchProvider from "@/context/SearchContext/Provider";

interface CityElementProps {
pageProps: PagePropsTypes;
Expand All @@ -22,7 +23,9 @@ const CityElement: React.FC<CityElementProps> = ({ pageProps }) => {
/>
<Provider<PagePropsTypes> appProps={pageProps}>
<Layout>
<CityInput />
<SearchProvider>
<SearchCity />
</SearchProvider>
<CityTemplate>
<DateAndLocation />
<TempContainer />
Expand Down
2 changes: 1 addition & 1 deletion src/elements/CityElement/CityTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const CityTemplate: React.FC<ComponentWithChildren> = ({ children }) => {
}}
>
<div className="absolute inset-0 bg-teal-950 opacity-80 z-10" />
<div className="w-full h-full flex flex-col justify-between z-50">
<div className="w-full h-full flex flex-col justify-between z-10">
{children}
</div>
</div>
Expand Down
7 changes: 5 additions & 2 deletions src/elements/HomeElement/HomeElement.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import CityInput from "@/components/CityInput/CityInput";
import SearchCity from "@/components/Search/SearchCity";
import Layout from "@/components/Layout/Layout";
import HomeTemplate from "./HomeTemplate";
import Heading from "@/components/Heading/Heading";
import AppInfo from "@/components/AppInfo/AppInfo";
import CustomHead from "@/components/CustomHead/CustomHead";
import Board from "./Board";
import SearchProvider from "@/context/SearchContext/Provider";

const HomeElement = () => {
return (
<>
<CustomHead title="Weather App" description="The Weather App" />
<Layout>
<CityInput />
<SearchProvider>
<SearchCity />
</SearchProvider>
<HomeTemplate>
<Board />
<AppInfo />
Expand Down
Loading

0 comments on commit 5ae98d7

Please sign in to comment.