Skip to content

Commit b085f99

Browse files
authored
Merge pull request #175 from map-of-pi/configured-the-search-integration
Approved (1) after addtl. adjustments.
2 parents be7af06 + 6ddfee9 commit b085f99

File tree

6 files changed

+106
-104
lines changed

6 files changed

+106
-104
lines changed

package-lock.json

+12-32
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"leaflet-geosearch": "^3.11.1",
3535
"loglevel": "^1.9.1",
3636
"next": "^14.2.4",
37-
"next-intl": "^3.17.2",
37+
"next-intl": "^3.19.1",
3838
"next-logger": "^4.0.0",
3939
"next-themes": "^0.3.0",
4040
"ngx-logger": "^5.0.12",

src/app/[locale]/page.tsx

+10-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export default function Index() {
3939
const [mapCenter, setMapCenter] = useState<{ lat: number; lng: number }>({ lat: 0, lng: 0 });
4040
const [zoomLevel, setZoomLevel] = useState(2);
4141
const [locationError, setLocationError] = useState<string | null>(null);
42+
const [searchQuery, setSearchQuery] = useState<string>('');
43+
const [searchResults, setSearchResults] = useState<any[]>([]);
4244

4345
// Default map center (example: New York City)
4446
const defaultMapCenter = { lat: 20, lng: -74.0060 };
@@ -73,10 +75,16 @@ export default function Index() {
7375
}
7476
};
7577

78+
// handle search query update from SearchBar and associated results
79+
const handleSearch = (query: string, results: any[]) => {
80+
setSearchQuery(query);
81+
setSearchResults(results);
82+
}
83+
7684
return (
7785
<>
78-
<DynamicMap center={[mapCenter.lat, mapCenter.lng]} zoom={zoomLevel} />
79-
<SearchBar page={'default'} />
86+
<DynamicMap center={[mapCenter.lat, mapCenter.lng]} zoom={zoomLevel} searchQuery={searchQuery} searchResults={searchResults || []} />
87+
<SearchBar page={'default'} onSearch={handleSearch} />
8088
<div className="absolute bottom-8 z-10 flex justify-between gap-[22px] px-6 right-0 left-0 m-auto">
8189
<Link href="/seller/registration">
8290
<Button

src/components/shared/SearchBar/SearchBar.tsx

+37-55
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,87 @@
1-
'use client'
1+
'use client';
22

33
import './SearchBar.scss';
44

55
import { useTranslations } from 'next-intl';
6-
76
import { useState, useRef, ChangeEvent, FormEvent } from 'react';
8-
9-
import { FormControl } from '@mui/material';
7+
import { FormControl, TextField } from '@mui/material';
108
import SearchIcon from '@mui/icons-material/Search';
11-
import Snackbar from '@mui/material/Snackbar';
12-
import TextField from '@mui/material/TextField';
9+
import { fetchSellers } from '@/services/sellerApi';
1310

1411
import logger from '../../../../logger.config.mjs';
1512

1613
interface searchBarProps {
17-
onSearch?:(query:string) => void;
18-
page: 'map_center' | 'default';
14+
onSearch?: (query: string, results: any[]) => void;
15+
page: 'map_center' | 'default';
1916
}
2017

2118
const SearchBar: React.FC<searchBarProps> = ({ onSearch, page }) => {
2219
const t = useTranslations();
20+
2321
const [searchBarValue, setSearchBarValue] = useState('');
24-
const [message, setMessage] = useState('');
22+
const [loading, setLoading] = useState(false);
23+
24+
const inputRef = useRef<HTMLInputElement>(null);
2525

26-
// function to get the placeholder text based on the screen
2726
const getPlaceholderText = (page: 'map_center' | 'default'): string => {
28-
switch (page) {
29-
case 'map_center':
30-
return t('SHARED.MAP_CENTER.SEARCH_BAR_PLACEHOLDER');
31-
default:
32-
return t('HOME.SEARCH_BAR_PLACEHOLDER');
33-
}
27+
return page === 'map_center'
28+
? t('SHARED.MAP_CENTER.SEARCH_BAR_PLACEHOLDER')
29+
: t('HOME.SEARCH_BAR_PLACEHOLDER');
3430
};
31+
3532
const placeholder = getPlaceholderText(page);
3633

3734
const handleSearchBarChange = (event: ChangeEvent<HTMLInputElement>) => {
3835
logger.debug(`Search bar value changed: ${event.target.value}`);
3936
setSearchBarValue(event.target.value);
4037
};
41-
42-
const inputRef = useRef<HTMLInputElement>(null);
4338

4439
const fetchSearchResults = async (query: string): Promise<any[]> => {
45-
logger.debug(`Fetching search results for query: "${query}"`);
46-
// fetch logic to be defined here
47-
// For now, it returns an empty array
48-
return new Promise((resolve) => resolve([]));
40+
setLoading(true);
41+
try {
42+
logger.debug(`Fetching search results for query: "${query}"`);
43+
const data = await fetchSellers(undefined, undefined, query);
44+
return data || []; // Return response.data or empty array if undefined
45+
} catch (error) {
46+
logger.error(`Error fetching search results: ${error}`);
47+
return [];
48+
} finally {
49+
setLoading(false);
50+
}
4951
};
5052

51-
const setSearchQuery = (query: string) => {
52-
// setSearchQuery logic here
53-
};
54-
5553
const handleSubmitSearch = async (event: FormEvent) => {
5654
event.preventDefault();
57-
const query = searchBarValue;
58-
if (query) {
59-
logger.info(`Search query submitted: ${query}`);
60-
61-
if (onSearch) {
62-
onSearch(query);
63-
} else {
64-
// Default search handling
65-
const searchResults = await fetchSearchResults(query);
66-
setSearchQuery(query);
67-
logger.info(`Your search found ${searchResults.length} shops`);
68-
}
69-
} else {
70-
logger.warn('Search query is empty');
55+
const query = searchBarValue.trim();
56+
logger.debug(`Search query submitted: ${query}`);
57+
const results = await fetchSearchResults(query);
58+
if (onSearch) {
59+
onSearch(query, results); // notify parent of the search query to update map
7160
}
7261
};
7362

7463
return (
7564
<div className="w-[90%] m-auto left-0 right-0 max-w-[504px] fixed top-[120px] z-10 flex">
76-
<Snackbar
77-
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
78-
open={!!message}
79-
message={message}
80-
autoHideDuration={6000}
81-
onClose={() => setMessage('')}
82-
/>
8365
<div className="w-[100%] m-auto flex items-center">
8466
<form className="w-full flex items-center gap-2 justify-between" onSubmit={handleSubmitSearch}>
8567
<FormControl className="flex-grow mr-3">
86-
<TextField
87-
id="search-input"
88-
type="text"
68+
<TextField
69+
id="search-input"
70+
type="text"
8971
variant="outlined"
9072
color="success"
9173
className="bg-white hover:bg-gray-100 w-full rounded"
92-
label={ placeholder }
93-
value={searchBarValue}
74+
label={placeholder}
75+
value={searchBarValue}
9476
onChange={handleSearchBarChange}
9577
ref={inputRef}
9678
/>
9779
</FormControl>
9880
<button
9981
aria-label="search"
100-
className="bg-primary rounded h-full w-15 p-[15.5px] flex items-center justify-center hover:bg-gray-600"
101-
// onClick={handleSubmitSearch} style={{backgroundColor: 'red'}}
102-
>
82+
type="submit"
83+
className="bg-primary rounded h-full w-15 p-[15.5px] flex items-center justify-center hover:bg-gray-600"
84+
>
10385
<SearchIcon className="text-[#ffc153]" />
10486
</button>
10587
</form>

src/components/shared/map/Map.tsx

+32-9
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ const sanitizeCoordinates = (lat: number, lng: number) => {
2020
return { lat: sanitizedLat, lng: sanitizedLng };
2121
};
2222

23-
// Function to fetch seller coordinates based on origin and radius
24-
const fetchSellerCoordinates = async (origin: LatLngTuple, radius: number): Promise<ISeller[]> => {
23+
// Function to fetch seller coordinates based on origin, radius, and optional search query
24+
const fetchSellerCoordinates = async (origin: LatLngTuple, radius: number, searchQuery?: string): Promise<ISeller[]> => {
2525
const { lat, lng } = sanitizeCoordinates(origin[0], origin[1]);
2626
const formattedOrigin = toLatLngLiteral([lat, lng]);
2727

2828
try {
29-
const sellersData = await fetchSellers(formattedOrigin, radius);
30-
const sellersWithCoordinates = sellersData.map((seller: any) => {
29+
const sellersData = await fetchSellers(formattedOrigin, radius, searchQuery);
30+
const sellersWithCoordinates = sellersData?.map((seller: any) => {
3131
const [lng, lat] = seller.sell_map_center.coordinates;
3232
return {
3333
...seller,
@@ -53,7 +53,7 @@ const removeDuplicates = (sellers: ISeller[]): ISeller[] => {
5353
return Object.values(uniqueSellers);
5454
};
5555

56-
const Map = ({ center, zoom }: { center: LatLngExpression, zoom: number }) => {
56+
const Map = ({ center, zoom, searchQuery, searchResults }: { center: LatLngExpression, zoom: number, searchQuery: string, searchResults: ISeller[] }) => {
5757
const t = useTranslations();
5858

5959
const customIcon = L.icon({
@@ -72,7 +72,7 @@ const Map = ({ center, zoom }: { center: LatLngExpression, zoom: number }) => {
7272
const [locationError, setLocationError] = useState(false);
7373
const [isLocationAvailable, setIsLocationAvailable] = useState(false);
7474
const [initialLocationSet, setInitialLocationSet] = useState(false);
75-
75+
7676
// Fetch initial seller coordinates when component mounts
7777
useEffect(() => {
7878
logger.info('Component mounted, fetching initial coordinates..');
@@ -87,6 +87,28 @@ const Map = ({ center, zoom }: { center: LatLngExpression, zoom: number }) => {
8787
}
8888
}, [center]);
8989

90+
useEffect(() => {
91+
if (searchQuery) {
92+
setLoading(true);
93+
94+
const sellersWithCoordinates = searchResults
95+
.map((seller: any) => {
96+
const [lng, lat] = seller.sell_map_center.coordinates;
97+
return {
98+
...seller,
99+
coordinates: [lat, lng] as LatLngTuple
100+
};
101+
});
102+
103+
// Remove duplicates
104+
const uniqueSellers = removeDuplicates(sellersWithCoordinates);
105+
106+
// Update the sellers state
107+
setSellers(uniqueSellers);
108+
setLoading(false);
109+
}
110+
}, [searchQuery, searchResults]);
111+
90112
// Log sellers array for debugging
91113
useEffect(() => {
92114
logger.debug('Sellers Array:', { sellers });
@@ -99,7 +121,7 @@ const Map = ({ center, zoom }: { center: LatLngExpression, zoom: number }) => {
99121
try {
100122
const originLiteral = toLatLngLiteral(origin);
101123
const originLatLngTuple: LatLngTuple = [originLiteral.lat, originLiteral.lng];
102-
let sellersData = await fetchSellerCoordinates(originLatLngTuple, radius);
124+
let sellersData = await fetchSellerCoordinates(originLatLngTuple, radius, searchQuery);
103125
sellersData = removeDuplicates(sellersData);
104126
setSellers(sellersData);
105127
} catch (error) {
@@ -110,7 +132,7 @@ const Map = ({ center, zoom }: { center: LatLngExpression, zoom: number }) => {
110132
}
111133
};
112134

113-
// Function to handle map interactions (zoom and move)
135+
// Function to handle map interactions (zoom and move); lazy-loading implementation
114136
const handleMapInteraction = async (newBounds: L.LatLngBounds, mapInstance: L.Map) => {
115137
const newCenter = newBounds.getCenter();
116138
const newRadius = calculateRadius(newBounds, mapInstance);
@@ -121,7 +143,7 @@ const Map = ({ center, zoom }: { center: LatLngExpression, zoom: number }) => {
121143
setError(null);
122144

123145
try {
124-
let additionalSellers = await fetchSellerCoordinates([newCenter.lat, newCenter.lng], largerRadius);
146+
let additionalSellers = await fetchSellerCoordinates([newCenter.lat, newCenter.lng], largerRadius, searchQuery);
125147
additionalSellers = removeDuplicates(additionalSellers);
126148

127149
logger.info('Fetched additional sellers:', { additionalSellers });
@@ -196,6 +218,7 @@ const Map = ({ center, zoom }: { center: LatLngExpression, zoom: number }) => {
196218
setPosition(e.latlng);
197219
setLocationError(false);
198220
if (!initialLocationSet) {
221+
console.log('in location');
199222
map.setView(e.latlng, zoom, { animate: false });
200223
setInitialLocationSet(true);
201224
}

0 commit comments

Comments
 (0)