Skip to content

Commit

Permalink
Merge pull request #120 from NetSepio/main
Browse files Browse the repository at this point in the history
Merging main with prod
  • Loading branch information
Rushikeshnimkar authored Aug 29, 2024
2 parents a1268bf + a8bf898 commit f2c2fd4
Show file tree
Hide file tree
Showing 28 changed files with 1,110 additions and 575 deletions.
130 changes: 104 additions & 26 deletions components/DvpnMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,73 +2,115 @@ import dynamic from 'next/dynamic';
import { useEffect, useState } from 'react';
import 'leaflet/dist/leaflet.css';
import L from 'leaflet';
import geojsonData from '../utils/countries.json';

// Dynamically import components with ssr: false
const MapContainer = dynamic(() => import('react-leaflet').then((module) => module.MapContainer), { ssr: false });
const TileLayer = dynamic(() => import('react-leaflet').then((module) => module.TileLayer), { ssr: false });
const Marker = dynamic(() => import('react-leaflet').then((module) => module.Marker), { ssr: false });
const Popup = dynamic(() => import('react-leaflet').then((module) => module.Popup), { ssr: false });
const GeoJSON = dynamic(() => import('react-leaflet').then((module) => module.GeoJSON), { ssr: false });

// Define a custom animated icon
const animatedIcon = L.divIcon({
className: 'custom-animated-icon',
html: `
<div style="
width: 20px;
height: 20px;
background: radial-gradient(circle, blue, white);
background: radial-gradient(circle, #007bff, white);
border-radius: 50%;
animation: pulse 2s infinite;
border: 2px solid white;
animation: pulse 1.5s infinite;
"></div>
`,
iconSize: [20, 20],
iconAnchor: [10, 10],
popupAnchor: [0, -10],
});

const getCircularOffset = (index, total, radius = 0.05) => {
const angle = (index / total) * 2 * Math.PI;
return [Math.cos(angle) * radius, Math.sin(angle) * radius];
};

const DvpnMap = ({ nodes }) => {
const [isClient, setIsClient] = useState(false);
const [offsets, setOffsets] = useState({});

useEffect(() => {
setIsClient(true);

// Initialize offsets
const offsetMap = {};
nodes.forEach((node) => {
const [lat, lon] = node.ipinfolocation.split(',').map(Number);
const key = `${lat},${lon}`;

if (!offsetMap[key]) {
offsetMap[key] = [0, 0];
} else {
// Apply a small offset if multiple markers have the same coordinates
offsetMap[key] = [offsetMap[key][0] + 0.01, offsetMap[key][1] + 0.01];
offsetMap[key] = [];
}
offsetMap[key].push(node);
});
setOffsets(offsetMap);

const finalOffsets = {};
for (const key in offsetMap) {
const nodesAtLocation = offsetMap[key];
nodesAtLocation.forEach((node, index) => {
finalOffsets[node.id] = getCircularOffset(index, nodesAtLocation.length);
});
}

setOffsets(finalOffsets);
}, [nodes]);

if (!isClient) {
return null;
}

const getCountryStyle = (feature) => {
const country = feature.properties.ISO_A2;
const count = nodes.filter(node => node.ipinfocountry === country).length;

return {
fillColor: count > 3 ? '#0e038c' :
count > 2 ? '#1500ff' :
count > 1 ? '#007bff' :
count > 0 ? '#7fd0f5' :
'#f7f7f7',
weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7
};
};

const onEachCountry = (feature, layer) => {
const country = feature.properties.ISO_A2;
const count = nodes.filter(node => node.ipinfocountry === country).length;

if (count > 0) {
layer.bindTooltip(`${feature.properties.ADMIN}: ${count} nodes`, {
permanent: true,
direction: 'center',
className: 'country-tooltip',
});
}
};

return (
<div className="relative h-full w-full p-20 pl-20 pr-20">
<div className="relative h-full w-full p-20 px-15 bg-[#20253A] mb-5">

<MapContainer
center={[20, 0]}
zoom={2}
minZoom={2}
maxZoom={5}
style={{ height: '100%', width: '100%', padding: '20px', }}
// className="leaflet-container"
// maxBounds={[[-90, -180], [90, 180]]}
// maxBoundsViscosity={1.0}
maxZoom={10}
style={{ height: '100%', width: '100%', padding: '20px', borderRadius: '20px', border: '2px solid gray', boxShadow: '0 0px 25px black' }}
>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
/>
{/* <TileLayer
{/* <TileLayer
url="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png" // CartoDB Dark theme URL
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors | Map tiles by <a href="https://carto.com/attributions">CartoDB</a>'
noWrap={true}
Expand All @@ -78,16 +120,18 @@ const DvpnMap = ({ nodes }) => {
attribution='&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> &copy; <a href="http://cartodb.com/attributions">CartoDB</a>'
noWrap={true}
/> */}

<GeoJSON
data={geojsonData}
style={getCountryStyle}
onEachFeature={onEachCountry}
/>

{nodes.map((node, index) => {
const [lat, lon] = node.ipinfolocation.split(',').map(Number);
const key = `${lat},${lon}`;
const offset = offsets[key] || [0, 0];
const [offsetLat, offsetLon] = offsets[node.id] || [0, 0];
return (
<Marker
key={index}
position={[lat + offset[0], lon + offset[1]]}
icon={animatedIcon}
>
<Marker key={index} position={[lat + offsetLat, lon + offsetLon]} icon={animatedIcon}>
<Popup>
<div className="text-blue-800">
<h3 className="text-blue-900 text-lg font-semibold">{node.name}</h3>
Expand All @@ -102,19 +146,53 @@ const DvpnMap = ({ nodes }) => {
);
})}
</MapContainer>

<style jsx>{`
@keyframes pulse {
0% {
transform: scale(1);
transform: scale(0.5);
}
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
transform: scale(0.5);
}
}
.popup-content {
font-family: Arial, sans-serif;
font-size: 14px;
line-height: 1.6;
color: #333;
background-color: #f9f9f9;
border-radius: 8px;
padding: 10px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
}
.popup-title {
margin-top: 0;
font-size: 16px;
font-weight: bold;
color: #FF5F6D;
}
.popup-content p {
margin: 5px 0;
}
.popup-content strong {
color: #333;
}
.country-tooltip {
font-size: 12px;
background-color: #ffffff;
border: 1px solid #dddddd;
border-radius: 4px;
padding: 4px;
}
`}</style>
</div>
);
Expand Down
48 changes: 39 additions & 9 deletions components/DwifiMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,46 @@ import 'leaflet/dist/leaflet.css';
import L from 'leaflet';

// Custom icon
const customIcon = new L.Icon({
iconUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon.png',
iconRetinaUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-icon-2x.png',
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
const customIcon = new L.DivIcon({
html: `<div class="custom-marker">
<span class="anticon anticon-environment">
<svg viewBox="64 64 896 896" focusable="false" class="" data-icon="environment" width="2em" height="2em" fill="currentColor" aria-hidden="true">
<path d="M512 64C324.3 64 176 208.6 176 384c0 237 300.6 526.2 318.7 543.1a31.99 31.99 0 0045.4 0C547.4 910.2 848 621 848 384 848 208.6 699.7 64 512 64zm0 484c-70.7 0-128-57.3-128-128s57.3-128 128-128 128 57.3 128 128-57.3 128-128 128z"></path>
</svg>
</span>
</div>`,
className: 'ant-icon',
iconSize: [25, 41], // Twice the original size
iconAnchor: [12, 25], // Adjust anchor to be at the bottom center of the icon
popupAnchor: [1, -34], // Adjust popup position
shadowUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-shadow.png',
shadowSize: [41, 41],
});


// Add this CSS to handle the animation
const style = document.createElement('style');
style.innerHTML = `
.custom-marker {
animation: pulse 2s infinite;
color: #1E3A8A; /* Dark blue */
}
@keyframes pulse {
0%, 100% {
transform: scale(0.9);
color: #1E3A8A; /* Dark blue */
filter: drop-shadow(0 0 10px rgba(0, 0, 0, 0.5));
}
50% {
transform: scale(1.1);
color: #3B82F6; /* Normal blue */
filter: drop-shadow(0 0 0px rgba(0, 0, 0, 0));
}
}
`;
document.head.appendChild(style);

export default function DwifiMap() {
const [nodes, setNodes] = useState([]);
const socketRef = useRef(null); // Use ref to maintain WebSocket across renders
Expand All @@ -26,7 +56,7 @@ export default function DwifiMap() {
};

socket.onmessage = function (event) {
console.log('Received:', event.data);
console.log('Received:');
};

socket.onerror = function (event) {
Expand Down Expand Up @@ -90,11 +120,11 @@ export default function DwifiMap() {
}, []); // Empty dependency array ensures this runs once

return (
<div className="relative h-full w-full p-20 pl-20 pr-20">
<div className="relative h-full w-full p-20 px-15 bg-[#20253A]">
<MapContainer
center={[20.5937, 78.9629]}
zoom={5}
style={{ height: '100%', width: '100%', padding: '20px', }}
style={{ height: '100%', width: '100%', padding: '20px', borderRadius: '20px', border: '2px solid gray', boxShadow: '0 0px 25px black' }}
maxBounds={[[6, 68], [37, 97]]}
maxBoundsViscosity={1.0}
>
Expand Down
4 changes: 2 additions & 2 deletions components/Mission.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const Mission = () => {
animate={{ y: 0, opacity: 1, transition: { duration: 1 } }}
className="text-black font-bold py-2 px-4 text-center rounded-[8px] text-sm w-auto z-10 bg-[#8EB9FF]"
>
<Link href="/subscription">
<Link href="https://netsepio.com/mission">
Our Mission
</Link>
</motion.div>
Expand All @@ -107,7 +107,7 @@ const Mission = () => {
animate={{ y: 0, opacity: 1, transition: { duration: 1 } }}
className="text-black font-bold py-3 text-center rounded-[50px] lg:w-[25%] md:w-[25%] w-1/2 z-10 bg-button "
>
<Link href="/subscription">
<Link href="https://netsepio.com/mission">
Our mission
</Link>
</motion.div>
Expand Down
Loading

0 comments on commit f2c2fd4

Please sign in to comment.