Skip to content

Commit e40e68e

Browse files
Countries fix
1 parent 479cc56 commit e40e68e

File tree

5 files changed

+219
-64
lines changed

5 files changed

+219
-64
lines changed

src/netmanager-app/app/globals.css

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,14 @@
7878
.country-scroll-bar {
7979
overflow-x: auto;
8080
overflow-y: hidden;
81+
overflow-x:auto;
8182
cursor: pointer;
82-
83-
/* Hide the scrollbar by default */
84-
&::-webkit-scrollbar {
85-
height: 4px;
86-
display: none;
87-
}
88-
89-
/* // Show the scrollbar when the element is focused */
90-
&:hover::-webkit-scrollbar {
91-
height: 4px;
92-
display: block;
9383
}
84+
.scrollbar-hide::-webkit-scrollbar {
85+
display: none;
9486
}
87+
.scrollbar-hide {
88+
-ms-overflow-style: none;
89+
scrollbar-width: none;
90+
}
91+
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import React from 'react';
2+
import ChevronDownIcon from '@/icons/Common/chevron_downIcon';
3+
import PropTypes from 'prop-types';
4+
import Spinner from '../Spinner';
5+
6+
/**
7+
* TabButtons Component
8+
*
9+
* A versatile button component that can display icons, text, and handle dropdowns.
10+
* It also supports loading and disabled states.
11+
*
12+
* @param {object} props - Component props
13+
* @returns {JSX.Element} Rendered component
14+
*/
15+
const TabButtons = ({
16+
type = 'button',
17+
Icon,
18+
btnText,
19+
btnStyle = 'border-grey-750 px-4 py-2 bg-white',
20+
dropdown = false,
21+
onClick,
22+
id,
23+
tabRef,
24+
isField = true,
25+
isLoading = false,
26+
disabled = false,
27+
}) => {
28+
return (
29+
<button
30+
ref={tabRef}
31+
id={id}
32+
type={type}
33+
onClick={onClick}
34+
disabled={disabled || isLoading}
35+
aria-disabled={disabled || isLoading}
36+
className={`transition transform active:scale-95 border rounded-xl shadow-sm flex items-center justify-between cursor-pointer ${
37+
disabled || isLoading ? 'opacity-50 cursor-not-allowed' : ''
38+
} ${btnStyle}`}
39+
>
40+
{/* Loading Spinner */}
41+
{isLoading ? (
42+
<Spinner width={20} height={20} />
43+
) : (
44+
Icon && (
45+
<span className="p-[2px] md:p-0">
46+
{typeof Icon === 'function' ? <Icon /> : Icon}
47+
</span>
48+
)
49+
)}
50+
51+
{/* Button Text */}
52+
{btnText && (
53+
<span
54+
className={`text-sm text-start w-full px-2 font-medium capitalize ${
55+
Icon && isField ? 'hidden md:inline-block' : ''
56+
}`}
57+
>
58+
{btnText}
59+
</span>
60+
)}
61+
62+
{/* Dropdown Icon */}
63+
{dropdown && <ChevronDownIcon />}
64+
</button>
65+
);
66+
};
67+
68+
TabButtons.propTypes = {
69+
type: PropTypes.string,
70+
Icon: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
71+
btnText: PropTypes.string,
72+
isField: PropTypes.bool,
73+
btnStyle: PropTypes.string,
74+
dropdown: PropTypes.bool,
75+
onClick: PropTypes.func,
76+
id: PropTypes.string,
77+
tabRef: PropTypes.oneOfType([
78+
PropTypes.func,
79+
PropTypes.shape({ current: PropTypes.any }),
80+
]),
81+
isLoading: PropTypes.bool,
82+
disabled: PropTypes.bool,
83+
};
84+
85+
export default TabButtons;
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import React from 'react';
2+
3+
const Button = ({
4+
onClick,
5+
className = '',
6+
path,
7+
children,
8+
dataTestId,
9+
disabled = false,
10+
type = 'button',
11+
variant = 'filled',
12+
color,
13+
bgColor,
14+
Icon,
15+
paddingStyles = 'py-2 px-4 shadow-sm',
16+
...rest
17+
}) => {
18+
// Determine styles based on the variant
19+
const variantStyles = {
20+
filled: {
21+
backgroundColor: bgColor || 'bg-blue-600',
22+
textColor: color || 'text-white',
23+
border: '',
24+
},
25+
outlined: {
26+
backgroundColor: bgColor || 'bg-white',
27+
textColor: color || 'text-black',
28+
border: 'border b-secondary-neutral-light-100',
29+
},
30+
text: {
31+
backgroundColor: 'bg-transparent',
32+
textColor: color || 'text-secondary-neutral-light-600',
33+
border: '',
34+
},
35+
disabled: {
36+
backgroundColor: 'bg-secondary-neutral-light-100',
37+
textColor: 'text-secondary-neutral-light-600',
38+
border: '',
39+
},
40+
primaryText: {
41+
backgroundColor: 'bg-transparent',
42+
textColor: color || 'text-blue-600',
43+
border: '',
44+
},
45+
};
46+
47+
const { backgroundColor, textColor, border } =
48+
variantStyles[variant] || variantStyles.filled;
49+
50+
// Combine all styles into a button class
51+
const buttonClass = `flex justify-center items-center cursor-pointer ${paddingStyles} rounded-xl sm:gap-1 ${className} ${textColor} ${backgroundColor} ${border} transition transform active:scale-95 ${disabled ? 'cursor-not-allowed opacity-50' : ''}`;
52+
53+
// Render tag if `path` is provided
54+
if (path) {
55+
return (
56+
<a href={path} className={buttonClass} data-testid={dataTestId} {...rest}>
57+
{Icon && <Icon className="w-4 h-4 mr-2" />}
58+
{children}
59+
</a>
60+
);
61+
}
62+
63+
// Render button element if `path` is not provided
64+
return (
65+
<button
66+
onClick={onClick}
67+
className={buttonClass}
68+
data-testid={dataTestId}
69+
type={type}
70+
disabled={disabled}
71+
{...rest}
72+
>
73+
{Icon && <Icon className="w-4 h-4 mr-2" />} {/* Icon before text */}
74+
{children}
75+
</button>
76+
);
77+
};
78+
79+
export default Button;

src/netmanager-app/components/NetManagerMap/components/CountryList.jsx

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useCallback, useMemo } from 'react';
22
import { useDispatch } from 'react-redux';
3-
// import Button from '@material-ui/core/Button';
3+
import Button from './Button'
44
// import {
55
// setLocation,
66
// addSuggestedSites,
@@ -49,12 +49,12 @@ const CountryList = ({
4949
if (!sortedData.length) {
5050
return (
5151
<div className="flex gap-2 ml-2 animate-pulse mb-2">
52-
{Array.from({ length: 4 }).map((_, index) => (
52+
5353
<div
54-
key={index}
5554
className="bg-secondary-neutral-dark-50 px-4 py-[14px] w-28 h-9 rounded-full dark:bg-gray-700"
56-
/>
57-
))}
55+
>
56+
loading countries
57+
</div>
5858
</div>
5959
);
6060
}
@@ -72,32 +72,31 @@ const CountryList = ({
7272
}
7373

7474
return (
75-
<Button
76-
key={index}
77-
type="button"
78-
className={`flex items-center cursor-pointer rounded-full bg-gray-100 hover:bg-gray-200 py-[6px] px-[10px] min-w-max space-x-2 m-0 ${
79-
selectedCountry?.country === country.country
80-
? 'border-2 border-blue-400'
81-
: ''
82-
}`}
83-
variant="outline"
84-
onClick={() => handleClick(country)}
85-
>
86-
<img
87-
src={`https://flagsapi.com/${country.code.toUpperCase()}/flat/64.png`}
88-
alt={country.country}
89-
width={20}
90-
height={20}
91-
onError={(e) => {
92-
// Fallback in case the flag image fails to load
93-
e.target.onerror = null; // Prevent infinite loop
94-
e.target.src = '/path-to-default-flag-image.png'; // Provide default flag image path
95-
}}
96-
/>
97-
<span className="text-sm text-secondary-neutral-light-600 font-medium">
98-
{country.country}
99-
</span>
100-
</Button>
75+
<button
76+
key={index}
77+
type="button"
78+
className={`flex items-center justify-center cursor-pointer rounded-full bg-gray-100 hover:bg-gray-200 py-[6px] px-[10px] gap-2 ${
79+
selectedCountry?.country === country.country ? 'border-2 border-blue-400' : ''
80+
}`}
81+
variant="outline"
82+
onClick={() => handleClick(country)}
83+
>
84+
<img
85+
src={`https://flagsapi.com/${country.code.toUpperCase()}/flat/64.png`}
86+
alt={country.country}
87+
width={20}
88+
height={20}
89+
className="w-5 h-5 object-contain" // Ensures proper scaling
90+
onError={(e) => {
91+
e.target.onerror = null;
92+
e.target.src = '/path-to-default-flag-image.png';
93+
}}
94+
/>
95+
<span className="text-sm text-gray-500 font-medium">
96+
{country.country}
97+
</span>
98+
</button>
99+
101100
);
102101
})}
103102
</div>

src/netmanager-app/components/NetManagerMap/page.tsx

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ import LayerIcon from "@/public/icons/map/layerIcon";
1010
import RefreshIcon from "@/public/icons/map/refreshIcon";
1111
import ShareIcon from "@/public/icons/map/ShareIcon";
1212
import LayerModel from './components/LayerModal';
13-
import { Import, LoaderCircle } from 'lucide-react';
13+
import { Import, LoaderCircle, Loader2 } from 'lucide-react';
1414
import { useAppSelector } from '@/core/redux/hooks';
1515
import CountryList from './components/CountryList'
1616
import { Button } from '../ui/button';
1717
import allCountries from './data/countries.json'
1818
import { any } from 'zod';
19-
import { useGrids } from '@/core/hooks/useGrids';
19+
import { useSites } from '@/core/hooks/useSites';
2020

2121

2222
const NetManagerMap = () => {
@@ -42,10 +42,8 @@ const NetManagerMap = () => {
4242
const [siteDetails, setSiteDetails] = useState<any[]>([]);
4343
const activeNetwork = useAppSelector((state) => state.user.activeNetwork);
4444
// const gridsDataSummary = useAppSelector((state) => state.grids) || [];
45-
const { grids, isLoading: isGridsLoading } = useGrids(
46-
activeNetwork?.net_name ?? ""
47-
);
48-
console.log("GridsData Summary: ", grids);
45+
const { sites, isLoading, error } = useSites();
46+
console.log("GridsData Summary: ", sites);
4947

5048
const AirQuality= {
5149
goodair :'/images/map/GoodAir.png',
@@ -58,18 +56,16 @@ const NetManagerMap = () => {
5856
}
5957

6058
// Set site details when grid data summary changes
61-
useEffect(() => {
62-
63-
if (activeNetwork && Array.isArray(grids) && grids.length > 0) {
64-
const newSiteDetails = grids.flatMap(
65-
(grid) => grid.sites || [],
66-
);
67-
console.log("Site Details : ",newSiteDetails)
68-
setSiteDetails(newSiteDetails);
69-
}{
70-
console.error("No Site Details ")
71-
}
72-
}, [grids, activeNetwork]);
59+
60+
useEffect(() => {
61+
if (Array.isArray(sites) && sites.length > 0) {
62+
setSiteDetails(sites);
63+
// const newSiteDetails = sites.flatMap(
64+
// (grid) => grid.sites || [],
65+
// );
66+
67+
}
68+
}, [sites]);
7369

7470
/**
7571
* Initialize Country Data
@@ -344,7 +340,6 @@ const NetManagerMap = () => {
344340
.catch(error => console.error("Error fetching location:", error));
345341

346342
}
347-
348343

349344
return (
350345
<div className="flex flex-col-reverse md:flex md:flex-row min-h-screen md:h-screen -ml-5 ">
@@ -364,11 +359,11 @@ const NetManagerMap = () => {
364359
<div className='flex items-center overflow-hidden px-4 transition-all duration-300 ease-in-out'>
365360
<Button
366361
type="button"
367-
className='py-[6px] px-[10px] border-none rounded-lg text-sm font-medium'
362+
className='flex py-[3px] px-[10px] border-none rounded-lg mb-3 text-sm font-medium'
368363
>
369364
ALL
370365
</Button>
371-
<div className='country-scroll-bar'>
366+
<div className='flex scrollbar-hide overflow-x-auto gap-2 '>
372367
<CountryList
373368
data={countryData}
374369
selectedCountry={selectedCountry}
@@ -410,7 +405,7 @@ const NetManagerMap = () => {
410405

411406
</div>
412407

413-
{ (loading || !airdata) &&(<div className="absolute inset-0 flex items-center justify-center z-[10000]">
408+
{ ( loading || !airdata) &&(<div className="absolute inset-0 flex items-center justify-center z-[10000]">
414409
<div
415410
className={`bg-white w-[64px] h-[64px] flex justify-center items-center rounded-md shadow-md p-3`}
416411
>

0 commit comments

Comments
 (0)