Skip to content

Commit

Permalink
Countries fix
Browse files Browse the repository at this point in the history
  • Loading branch information
AKATWIJUKA-ELIA committed Mar 4, 2025
1 parent 479cc56 commit e40e68e
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 64 deletions.
19 changes: 8 additions & 11 deletions src/netmanager-app/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,14 @@
.country-scroll-bar {
overflow-x: auto;
overflow-y: hidden;
overflow-x:auto;
cursor: pointer;

/* Hide the scrollbar by default */
&::-webkit-scrollbar {
height: 4px;
display: none;
}

/* // Show the scrollbar when the element is focused */
&:hover::-webkit-scrollbar {
height: 4px;
display: block;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React from 'react';
import ChevronDownIcon from '@/icons/Common/chevron_downIcon';
import PropTypes from 'prop-types';
import Spinner from '../Spinner';

/**
* TabButtons Component
*
* A versatile button component that can display icons, text, and handle dropdowns.
* It also supports loading and disabled states.
*
* @param {object} props - Component props
* @returns {JSX.Element} Rendered component
*/
const TabButtons = ({
type = 'button',
Icon,
btnText,
btnStyle = 'border-grey-750 px-4 py-2 bg-white',
dropdown = false,
onClick,
id,
tabRef,
isField = true,
isLoading = false,
disabled = false,
}) => {
return (
<button
ref={tabRef}
id={id}
type={type}
onClick={onClick}
disabled={disabled || isLoading}
aria-disabled={disabled || isLoading}
className={`transition transform active:scale-95 border rounded-xl shadow-sm flex items-center justify-between cursor-pointer ${
disabled || isLoading ? 'opacity-50 cursor-not-allowed' : ''
} ${btnStyle}`}
>
{/* Loading Spinner */}
{isLoading ? (
<Spinner width={20} height={20} />
) : (
Icon && (
<span className="p-[2px] md:p-0">
{typeof Icon === 'function' ? <Icon /> : Icon}
</span>
)
)}

{/* Button Text */}
{btnText && (
<span
className={`text-sm text-start w-full px-2 font-medium capitalize ${
Icon && isField ? 'hidden md:inline-block' : ''
}`}
>
{btnText}
</span>
)}

{/* Dropdown Icon */}
{dropdown && <ChevronDownIcon />}
</button>
);
};

TabButtons.propTypes = {
type: PropTypes.string,
Icon: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
btnText: PropTypes.string,
isField: PropTypes.bool,
btnStyle: PropTypes.string,
dropdown: PropTypes.bool,
onClick: PropTypes.func,
id: PropTypes.string,
tabRef: PropTypes.oneOfType([
PropTypes.func,
PropTypes.shape({ current: PropTypes.any }),
]),
isLoading: PropTypes.bool,
disabled: PropTypes.bool,
};

export default TabButtons;
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from 'react';

const Button = ({
onClick,
className = '',
path,
children,
dataTestId,
disabled = false,
type = 'button',
variant = 'filled',
color,
bgColor,
Icon,
paddingStyles = 'py-2 px-4 shadow-sm',
...rest
}) => {
// Determine styles based on the variant
const variantStyles = {
filled: {
backgroundColor: bgColor || 'bg-blue-600',
textColor: color || 'text-white',
border: '',
},
outlined: {
backgroundColor: bgColor || 'bg-white',
textColor: color || 'text-black',
border: 'border b-secondary-neutral-light-100',
},
text: {
backgroundColor: 'bg-transparent',
textColor: color || 'text-secondary-neutral-light-600',
border: '',
},
disabled: {
backgroundColor: 'bg-secondary-neutral-light-100',
textColor: 'text-secondary-neutral-light-600',
border: '',
},
primaryText: {
backgroundColor: 'bg-transparent',
textColor: color || 'text-blue-600',
border: '',
},
};

const { backgroundColor, textColor, border } =
variantStyles[variant] || variantStyles.filled;

// Combine all styles into a button class
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' : ''}`;

// Render tag if `path` is provided
if (path) {
return (
<a href={path} className={buttonClass} data-testid={dataTestId} {...rest}>
{Icon && <Icon className="w-4 h-4 mr-2" />}
{children}
</a>
);
}

// Render button element if `path` is not provided
return (
<button
onClick={onClick}
className={buttonClass}
data-testid={dataTestId}
type={type}
disabled={disabled}
{...rest}
>
{Icon && <Icon className="w-4 h-4 mr-2" />} {/* Icon before text */}
{children}
</button>
);
};

export default Button;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useCallback, useMemo } from 'react';
import { useDispatch } from 'react-redux';
// import Button from '@material-ui/core/Button';
import Button from './Button'
// import {
// setLocation,
// addSuggestedSites,
Expand Down Expand Up @@ -49,12 +49,12 @@ const CountryList = ({
if (!sortedData.length) {
return (
<div className="flex gap-2 ml-2 animate-pulse mb-2">
{Array.from({ length: 4 }).map((_, index) => (

<div
key={index}
className="bg-secondary-neutral-dark-50 px-4 py-[14px] w-28 h-9 rounded-full dark:bg-gray-700"
/>
))}
>
loading countries
</div>
</div>
);
}
Expand All @@ -72,32 +72,31 @@ const CountryList = ({
}

return (
<Button
key={index}
type="button"
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 ${
selectedCountry?.country === country.country
? 'border-2 border-blue-400'
: ''
}`}
variant="outline"
onClick={() => handleClick(country)}
>
<img
src={`https://flagsapi.com/${country.code.toUpperCase()}/flat/64.png`}
alt={country.country}
width={20}
height={20}
onError={(e) => {
// Fallback in case the flag image fails to load
e.target.onerror = null; // Prevent infinite loop
e.target.src = '/path-to-default-flag-image.png'; // Provide default flag image path
}}
/>
<span className="text-sm text-secondary-neutral-light-600 font-medium">
{country.country}
</span>
</Button>
<button
key={index}
type="button"
className={`flex items-center justify-center cursor-pointer rounded-full bg-gray-100 hover:bg-gray-200 py-[6px] px-[10px] gap-2 ${
selectedCountry?.country === country.country ? 'border-2 border-blue-400' : ''
}`}
variant="outline"
onClick={() => handleClick(country)}
>
<img
src={`https://flagsapi.com/${country.code.toUpperCase()}/flat/64.png`}
alt={country.country}
width={20}
height={20}
className="w-5 h-5 object-contain" // Ensures proper scaling
onError={(e) => {
e.target.onerror = null;
e.target.src = '/path-to-default-flag-image.png';
}}
/>
<span className="text-sm text-gray-500 font-medium">
{country.country}
</span>
</button>

);
})}
</div>
Expand Down
39 changes: 17 additions & 22 deletions src/netmanager-app/components/NetManagerMap/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import LayerIcon from "@/public/icons/map/layerIcon";
import RefreshIcon from "@/public/icons/map/refreshIcon";
import ShareIcon from "@/public/icons/map/ShareIcon";
import LayerModel from './components/LayerModal';
import { Import, LoaderCircle } from 'lucide-react';
import { Import, LoaderCircle, Loader2 } from 'lucide-react';
import { useAppSelector } from '@/core/redux/hooks';
import CountryList from './components/CountryList'
import { Button } from '../ui/button';
import allCountries from './data/countries.json'
import { any } from 'zod';
import { useGrids } from '@/core/hooks/useGrids';
import { useSites } from '@/core/hooks/useSites';


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

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

// Set site details when grid data summary changes
useEffect(() => {

if (activeNetwork && Array.isArray(grids) && grids.length > 0) {
const newSiteDetails = grids.flatMap(
(grid) => grid.sites || [],
);
console.log("Site Details : ",newSiteDetails)
setSiteDetails(newSiteDetails);
}{
console.error("No Site Details ")
}
}, [grids, activeNetwork]);

useEffect(() => {
if (Array.isArray(sites) && sites.length > 0) {
setSiteDetails(sites);
// const newSiteDetails = sites.flatMap(
// (grid) => grid.sites || [],
// );

}
}, [sites]);

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

}


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

</div>

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

0 comments on commit e40e68e

Please sign in to comment.