Skip to content

Commit

Permalink
Update index.jsx
Browse files Browse the repository at this point in the history
  • Loading branch information
OchiengPaul442 committed Feb 22, 2024
1 parent d15cea6 commit 1590207
Showing 1 changed file with 202 additions and 129 deletions.
331 changes: 202 additions & 129 deletions platform/src/pages/map/index.jsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,15 @@
import React, { useState, useEffect } from 'react';
import Layout from '@/components/Layout';
import CloseIcon from '@/icons/close_icon';
import LocationIcon from '@/icons/LocationIcon';
import MenuIcon from '@/icons/map/menuIcon';
import AirQoMap from '@/components/Map/AirQoMap';
import { useDispatch, useSelector } from 'react-redux';
import HomeIcon from '@/icons/map/homeIcon';
import { useRouter } from 'next/router';
import { AirQualityLegend } from '@/components/Map/components/Legend';
import allCountries from '@/components/Map/components/countries';
import SearchField from '@/components/Search/SearchField';

const MAP_ACCESS_TOKEN = process.env.NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN;

const countries = [
{
id: 1,
name: 'Uganda',
flag: 'UG',
},
{
id: 2,
name: 'Kenya',
flag: 'KE',
},
{
id: 3,
name: 'Nigeria',
flag: 'NG',
},
{
id: 4,
name: 'Rwanda',
flag: 'RW',
},
{
id: 5,
name: 'Tanzania',
flag: 'TZ',
},
];
import SearchField from '@/components/search/SearchField';
import { getSitesSummary } from '@/lib/store/services/deviceRegistry/GridsSlice';

const TabSelector = ({ selectedTab, setSelectedTab }) => {
return (
Expand All @@ -58,45 +29,66 @@ const TabSelector = ({ selectedTab, setSelectedTab }) => {
}`}>
Sites
</div>
<div
onClick={() => setSelectedTab('airqlouds')}
className={`px-3 py-2 flex justify-center items-center w-full hover:cursor-pointer text-sm font-medium text-secondary-neutral-light-600${
selectedTab === 'airqlouds' ? 'border rounded-md bg-white shadow-sm' : ''
}`}>
AirQlouds
</div>
</div>
</div>
);
};

const filteredCountries = allCountries.filter((country) =>
countries.find((c) => c.name === country.country),
);

const CountryList = ({ selectedCountry, setSelectedCountry }) => (
<div className='flex space-x-4 overflow-x-auto py-4 ml-4'>
{filteredCountries.map((country, index) => (
<div
key={index}
className='flex items-center cursor-pointer rounded-full bg-gray-100 hover:bg-gray-200 p-2 min-w-max space-x-2 m-0'
style={{
backgroundColor: selectedCountry?.country === country.country ? '#77A9FF' : '',
}}
onClick={() => setSelectedCountry(country)}>
<img src={country.flag} alt={country.country} width={20} height={20} />
<span>{country.country}</span>
</div>
))}
</div>
);
const CountryList = ({ data, selectedCountry, setSelectedCountry }) => {
const dispatch = useDispatch();

const sortedData = [...data].sort((a, b) => a.country.localeCompare(b.country));

return (
<div className='flex space-x-4 overflow-x-auto py-4 ml-4 map-scrollbar'>
{sortedData.map((country, index) => (
<div
key={index}
className={`flex items-center cursor-pointer rounded-full bg-gray-100 hover:bg-gray-200 p-2 min-w-max space-x-2 m-0 ${
selectedCountry?.country === country.country ? 'border-2 border-blue-400' : ''
}`}
onClick={() => {
setSelectedCountry(country);
dispatch(
setLocation({
country: country.country,
}),
);
}}>
<img src={country.flag} alt={country.country} width={20} height={20} />
<span>{country.country}</span>
</div>
))}
</div>
);
};

const index = () => {
const dispatch = useDispatch();
const router = useRouter();
const [location, setLocation] = useState();
const [showSideBar, setShowSideBar] = useState(true);
const [selectedTab, setSelectedTab] = useState('locations');
const [selectedSite, setSelectedSite] = useState(null);
const siteData = useSelector((state) => state.grids.sitesSummary);
const [searchResults, setSearchResults] = useState([]);
const [isFocused, setIsFocused] = useState(false);
const [selectedCountry, setSelectedCountry] = useState(null);
// admin check
const isAdmin = false;

// Use destructuring to directly access individual_preferences
const { individual_preferences } = useSelector((state) => state.defaults);

// Use flatMap for more efficient mapping and flattening
const selectedSites = individual_preferences.flatMap((pref) => pref.selected_sites);

// siteDetails
const siteDetails = siteData.sites;

useEffect(() => {
dispatch(getSitesSummary());
}, []);

useEffect(() => {
const handleResize = () => {
Expand Down Expand Up @@ -129,6 +121,10 @@ const index = () => {
setLocation();
};

const handleSearch = (results) => {
setSearchResults(results);
};

const locations = [
{
id: 1,
Expand Down Expand Up @@ -157,96 +153,173 @@ const index = () => {
},
];

// Assuming siteDetails and allCountries are defined
let uniqueCountries = [];
let result = [];

siteDetails.forEach((site) => {
if (!uniqueCountries.includes(site.country)) {
uniqueCountries.push(site.country);
let countryDetails = allCountries.find((data) => data.country === site.country);
if (countryDetails) {
result.push({ ...site, ...countryDetails });
} else {
return;
}
}
});

return (
<Layout noTopNav={false}>
<div className='relative'>
<>
{showSideBar && (
<div className='absolute left-0 top-0 w-[280px] h-full md:w-[400px] bg-white shadow-lg shadow-right space-y-4 z-50 overflow-y-auto'>
<div className='px-4 pt-4'>
<div className='w-full flex justify-between items-center'>
<div>
<div className={!isFocused ? 'space-y-4' : 'hidden'}>
<div className='px-4 pt-4'>
<div className='w-full flex justify-start items-center'>
<label className='font-medium text-xl'>Map</label>
</div>
<button
className='p-2 border rounded-xl hover:bg-gray-100'
onClick={() => setShowSideBar(!showSideBar)}>
<CloseIcon width={15} height={15} fill={'#6F87A1'} />
</button>
<p className='text-gray-500 text-sm font-normal w-auto md:w-[316.681px;] mt-6'>
Navigate, Explore, and Understand Air Quality Data with Precision, Right Down to
Your Neighborhood
</p>
{isAdmin && (
<TabSelector selectedTab={selectedTab} setSelectedTab={handleSelectedTab} />
)}
</div>
<p className='text-gray-500 text-sm font-normal w-auto md:w-[316.681px;] mt-6'>
Navigate, Explore, and Understand Air Quality Data with Precision, Right Down to
Your Neighborhood
</p>
<TabSelector selectedTab={selectedTab} setSelectedTab={handleSelectedTab} />
{isAdmin && <hr />}
</div>
<hr />
<div className='px-4 space-y-4'>
<SearchField />
<div className='flex justify-between items-center'>
<button className='px-4 py-2 rounded-full bg-blue-500 text-white'>All</button>
<CountryList
selectedCountry={selectedCountry}
setSelectedCountry={setSelectedCountry}
/>
</div>
<div className='space-y-2'>
<label className='font-medium text-gray-600 text-sm'>Suggestions</label>
<hr />
{locations.map((location) => (
<div
key={location.id}
className='flex flex-row justify-start items-center mb-0.5 text-sm w-full hover:cursor-pointer hover:bg-blue-100 p-2 rounded-lg'
onClick={() => {
handleLocationSelect();
}}>
<div className='p-2 rounded-full bg-gray-100'>
<LocationIcon />
{selectedTab === 'locations' &&
(!isFocused ? (
<div className='px-4 space-y-4'>
<div onMouseDown={() => setIsFocused(true)}>
<SearchField />
</div>
<div className='flex justify-between items-center'>
<button
onClick={() => {
dispatch(setCenter({ latitude: 16.1532, longitude: 13.1691 }));
dispatch(setZoom(1.5));
setShowSideBar(false);
setSelectedSite(null);
}}
className='px-4 py-2 rounded-full bg-blue-500 text-white'>
All
</button>
<CountryList
data={result}
selectedCountry={selectedCountry}
setSelectedCountry={setSelectedCountry}
/>
</div>
<div className='space-y-2 max-h-[445px] overflow-y-scroll map-scrollbar'>
<label className='font-medium text-gray-600 text-sm'>Suggestions</label>
<hr />
{selectedSites.map((sites) => (
<div
key={sites._id}
className={`flex flex-row justify-start items-center mb-0.5 text-sm w-full hover:cursor-pointer hover:bg-grey-100 p-2 rounded-lg ${
sites._id === selectedSite?._id ? 'bg-blue-100' : ''
}`}
onClick={() => {
handleLocationSelect(sites);
}}>
<div className='p-2 rounded-full bg-gray-100'>
<LocationIcon />
</div>
<div className='ml-3 flex flex-col item-start border-b w-full relative'>
<span className='font-normal text-black capitalize text-lg overflow-ellipsis overflow-hidden w-full'>
{sites.name}
</span>
<span className='font-normal text-gray-500 capitalize text-sm mb-2'>
{sites.region + ',' + sites.country}
</span>
</div>
</div>
))}
<hr />
</div>
</div>
) : (
// Search focused view
<div className='px-4 pt-4'>
<div className='w-full flex justify-start items-center'>
<button
onClick={() => setIsFocused(false)}
className='font-medium text-xl focus:outline-none mb-2'>
Back
</button>
</div>
<SearchField
data={siteDetails}
onSearch={handleSearch}
searchKeys={['city', 'village', 'country']}
/>
{searchResults.length > 0 ? (
<div className='space-y-2 max-h-[445px] overflow-y-scroll mt-4'>
<label className='font-medium text-gray-600 text-sm'>Results</label>
<hr />
{searchResults.map((grid) => (
<div
key={grid._id}
className='flex flex-row justify-start items-center mb-0.5 text-sm w-full hover:cursor-pointer hover:bg-blue-100 p-2 rounded-lg'
onClick={() => {
handleLocationSelect(grid);
}}>
<div className='p-2 rounded-full bg-gray-100'>
<LocationIcon />
</div>
<div className='ml-3 flex flex-col item-start border-b w-full'>
<span className='font-normal text-black capitalize text-lg'>
{grid.name}
</span>
<span className='font-normal text-gray-500 capitalize text-sm mb-2'>
{grid.region + ',' + grid.country}
</span>
</div>
</div>
))}
<hr />
</div>
<div className='ml-3 flex flex-col item-start border-b w-full'>
<span className='font-normal text-black capitalize text-lg'>
{location.name}
</span>
<span className='font-normal text-gray-500 capitalize text-sm mb-2'>
{location.country}
</span>
) : (
<div className='flex justify-center items-center h-80'>
<p className='text-gray-500 text-sm font-normal'>No results found</p>
</div>
</div>
))}
<hr />
</div>
</div>
)}
</div>
))}
</div>
)}
<div
className={`absolute bottom-4 ${
className={`absolute bottom-2 ${
showSideBar ? 'left-[calc(280px+15px)] md:left-[calc(400px+15px)]' : 'left-[15px]'
} z-50`}>
<AirQualityLegend />
</div>
</>
<div className='h-auto w-full relative bg-[#ebe7e1]'>
{!showSideBar && (
<div className='absolute top-4 left-3 z-50 '>
<div className='flex flex-col space-y-4'>
<button
className='inline-flex items-center justify-center w-[50px] h-[50px] mr-2 text-white rounded-full bg-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 shadow-md'
onClick={() => setShowSideBar(!showSideBar)}>
<MenuIcon />
</button>
<button
className='inline-flex items-center justify-center w-[50px] h-[50px] mr-2 text-white rounded-full bg-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 shadow-md'
onClick={() => handleHomeClick()}>
<HomeIcon />
</button>
</div>
<div
className={`absolute top-4 ${
showSideBar ? 'left-[calc(280px+15px)] md:left-[calc(400px+15px)]' : 'left-[15px]'
} z-50`}>
<div className='flex flex-col space-y-4'>
<button
className='inline-flex items-center justify-center w-[50px] h-[50px] mr-2 text-white rounded-full bg-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 shadow-md'
onClick={() => setShowSideBar(!showSideBar)}>
<MenuIcon />
</button>
<button
className='inline-flex items-center justify-center w-[50px] h-[50px] mr-2 text-white rounded-full bg-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 shadow-md'
onClick={() => handleHomeClick()}>
<HomeIcon />
</button>
</div>
)}
<AirQoMap
mapboxApiAccessToken={MAP_ACCESS_TOKEN}
customStyle='flex-grow h-screen w-full relative'
/>
</div>
</div>
</>
<AirQoMap
showSideBar={showSideBar}
mapboxApiAccessToken={process.env.NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN}
customStyle='flex-grow h-screen w-full relative bg-[#e6e4e0]'
/>
</div>
</Layout>
);
Expand Down

0 comments on commit 1590207

Please sign in to comment.