diff --git a/components/DvpnMap.js b/components/DvpnMap.js new file mode 100644 index 0000000..ab9852b --- /dev/null +++ b/components/DvpnMap.js @@ -0,0 +1,123 @@ +import dynamic from 'next/dynamic'; +import { useEffect, useState } from 'react'; +import 'leaflet/dist/leaflet.css'; +import L from 'leaflet'; + +// 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 }); + +// Define a custom animated icon +const animatedIcon = L.divIcon({ + className: 'custom-animated-icon', + html: ` +
+ `, + iconSize: [20, 20], + iconAnchor: [10, 10], + popupAnchor: [0, -10], +}); + +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]; + } + }); + setOffsets(offsetMap); + }, [nodes]); + + if (!isClient) { + return null; + } + + return ( +
+ + + {/* */} + {/* */} + {nodes.map((node, index) => { + const [lat, lon] = node.ipinfolocation.split(',').map(Number); + const key = `${lat},${lon}`; + const offset = offsets[key] || [0, 0]; + return ( + + +
+

{node.name}

+

Country: {node.ipinfocountry}

+

City: {node.ipinfocity}

+

Node Name: {node.nodename}

+

Download Speed: {node.downloadSpeed} Mbps

+

Upload Speed: {node.uploadSpeed} Mbps

+
+
+
+ ); + })} +
+ +
+ ); +}; + +export default DvpnMap; diff --git a/components/DwifiMap.js b/components/DwifiMap.js new file mode 100644 index 0000000..217e52b --- /dev/null +++ b/components/DwifiMap.js @@ -0,0 +1,124 @@ +import { useState, useEffect, useRef } from 'react'; +import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet'; +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], + shadowUrl: 'https://unpkg.com/leaflet@1.7.1/dist/images/marker-shadow.png', + shadowSize: [41, 41], +}); + +export default function DwifiMap() { + const [nodes, setNodes] = useState([]); + const socketRef = useRef(null); // Use ref to maintain WebSocket across renders + + useEffect(() => { + const socket = new WebSocket('wss://dev.gateway.erebrus.io/api/v1.0/nodedwifi/stream'); + + socket.onopen = function () { + console.log('WebSocket is open now.'); + }; + + socket.onmessage = function (event) { + console.log('Received:', event.data); + }; + + socket.onerror = function (event) { + console.error('WebSocket error:', event); + }; + + socket.onclose = function (event) { + console.log('WebSocket is closed now.', event); + }; + + return () => { + socket.close(); + }; + }, []); + + useEffect(() => { + function connectWebSocket() { + // Initialize the WebSocket connection + socketRef.current = new WebSocket('wss://dev.gateway.erebrus.io/api/v1.0/nodedwifi/stream'); + + // Handle the WebSocket connection opening + socketRef.current.onopen = function () { + console.log('WebSocket is open now.'); + }; + + // Handle incoming WebSocket messages + socketRef.current.onmessage = function (event) { + const newNode = JSON.parse(event.data); + setNodes((prevNodes) => { + const existingIndex = prevNodes.findIndex((node) => node.id === newNode.id); + if (existingIndex !== -1) { + return prevNodes.map((node) => (node.id === newNode.id ? newNode : node)); + } else { + return [...prevNodes, newNode]; + } + }); + }; + + // Handle WebSocket errors + socketRef.current.onerror = function (event) { + console.error('WebSocket error:', event); + }; + + // Handle WebSocket closure + socketRef.current.onclose = function () { + console.log('WebSocket is closed. Attempting to reconnect...'); + setTimeout(connectWebSocket, 5000); // Attempt to reconnect after 5 seconds + }; + } + + // Establish WebSocket connection + connectWebSocket(); + + // Cleanup function + return () => { + console.log('Cleaning up WebSocket connection...'); + if (socketRef.current) { + socketRef.current.close(); + } + }; + }, []); // Empty dependency array ensures this runs once + + return ( +
+ + + {nodes.map((node) => { + const [lat, lon] = node.co_ordinates.split(',').map(Number); + return ( + + +
+
Address: {node.location}
+

Gateway: {node.gateway}

+

Price per Minute: {node.price_per_min}

+

Wallet Address: {node.wallet_address}

+

Chain Name: {node.chain_name}

+
+
+
+ ); + })} +
+
+ ); +} diff --git a/package.json b/package.json index 5766f36..4460e56 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "file-saver": "^2.0.5", "framer-motion": "^8.0.2", "js-cookie": "^3.0.5", + "leaflet": "^1.9.4", "mapbox-gl": "^3.5.2", "next": "13.1.1", "nft.storage": "^7.1.1", @@ -68,6 +69,7 @@ "react-google-recaptcha": "^2.1.0", "react-icons": "^4.7.1", "react-intersection-observer": "^9.13.0", + "react-leaflet": "^4.2.1", "react-mapbox-gl": "^5.1.1", "react-responsive-carousel": "^3.2.23", "react-toastify": "^9.1.1", diff --git a/pages/dwifi.tsx b/pages/dwifi.tsx index c7a091f..25c4a70 100644 --- a/pages/dwifi.tsx +++ b/pages/dwifi.tsx @@ -2,6 +2,10 @@ import React, { useEffect, useState} from "react"; import Link from "next/link"; import NodeDwifiStream from "../components/nodedataDwifi"; import { motion } from "framer-motion"; +import dynamic from 'next/dynamic'; + +const DwifiMap = dynamic(() => import('../components/DwifiMap'), { ssr: false }); + const Dwifi = () => { @@ -45,7 +49,17 @@ const Dwifi = () => { +
+ +
+
+
+ +
+
+ + {/* */} ) diff --git a/pages/explorer.js b/pages/explorer.js index bc6f0bd..893f4c4 100644 --- a/pages/explorer.js +++ b/pages/explorer.js @@ -1,10 +1,27 @@ import React, { useEffect, useState} from "react"; import Link from "next/link"; import NodesData from "../components/NodesData"; +import dynamic from 'next/dynamic'; +// import Dvpn Map from "../components/DvpnMap" import { motion } from "framer-motion"; +const DvpnMap = dynamic(() => import('../components/DvpnMap'), { ssr: false }); + + const Explorer = () => { + const [nodes, setNodes] = useState([]); + const [activeMap, setActiveMap] = useState('pin'); + + useEffect(() => { + async function fetchNodes() { + const response = await fetch('https://gateway.erebrus.io/api/v1.0/nodes/all'); + const data = await response.json(); + setNodes(data.payload); + } + fetchNodes(); + }, []); + return (
{
- {/* */} +
+ +
+
+
+ +
+ + + ) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7d52fff..bc1bfa4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -152,6 +152,9 @@ importers: js-cookie: specifier: ^3.0.5 version: 3.0.5 + leaflet: + specifier: ^1.9.4 + version: 1.9.4 mapbox-gl: specifier: ^3.5.2 version: 3.5.2 @@ -185,6 +188,9 @@ importers: react-intersection-observer: specifier: ^9.13.0 version: 9.13.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react-leaflet: + specifier: ^4.2.1 + version: 4.2.1(leaflet@1.9.4)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react-mapbox-gl: specifier: ^5.1.1 version: 5.1.1(mapbox-gl@3.5.2)(prop-types@15.8.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -2747,6 +2753,13 @@ packages: peerDependencies: react: '*' + '@react-leaflet/core@2.1.0': + resolution: {integrity: sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==} + peerDependencies: + leaflet: ^1.9.0 + react: ^18.0.0 + react-dom: ^18.0.0 + '@react-native-async-storage/async-storage@1.23.1': resolution: {integrity: sha512-Qd2kQ3yi6Y3+AcUlrHxSLlnBvpdCEMVGFlVBneVOjaFaPU61g1huc38g339ysXspwY1QZA2aNhrk/KlHGO+ewA==} peerDependencies: @@ -7424,6 +7437,9 @@ packages: resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} engines: {node: '>=0.10'} + leaflet@1.9.4: + resolution: {integrity: sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==} + leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -9131,6 +9147,13 @@ packages: react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + react-leaflet@4.2.1: + resolution: {integrity: sha512-p9chkvhcKrWn/H/1FFeVSqLdReGwn2qmiobOQGO3BifX+/vV/39qhY8dGqbdcPh1e6jxh/QHriLXr7a4eLFK4Q==} + peerDependencies: + leaflet: ^1.9.0 + react: ^18.0.0 + react-dom: ^18.0.0 + react-lifecycles-compat@3.0.4: resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} @@ -14975,6 +14998,12 @@ snapshots: dependencies: react: 18.2.0 + '@react-leaflet/core@2.1.0(leaflet@1.9.4)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + leaflet: 1.9.4 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + '@react-native-async-storage/async-storage@1.23.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.47)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))': dependencies: merge-options: 3.0.4 @@ -20123,8 +20152,8 @@ snapshots: '@typescript-eslint/parser': 5.62.0(eslint@8.30.0)(typescript@5.3.3) eslint: 8.30.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.30.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.0(eslint@8.30.0)(typescript@5.3.3))(eslint@8.30.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.0(eslint@8.30.0)(typescript@5.3.3))(eslint@8.30.0))(eslint@8.30.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.0(eslint@8.30.0)(typescript@5.3.3))(eslint@8.30.0))(eslint@8.30.0))(eslint@8.30.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.30.0) eslint-plugin-react: 7.33.2(eslint@8.30.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.30.0) @@ -20142,13 +20171,13 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.30.0): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.0(eslint@8.30.0)(typescript@5.3.3))(eslint@8.30.0))(eslint@8.30.0): dependencies: debug: 4.3.4 enhanced-resolve: 5.15.0 eslint: 8.30.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.30.0))(eslint@8.30.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.0(eslint@8.30.0)(typescript@5.3.3))(eslint@8.30.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.0(eslint@8.30.0)(typescript@5.3.3))(eslint@8.30.0))(eslint@8.30.0))(eslint@8.30.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.0(eslint@8.30.0)(typescript@5.3.3))(eslint@8.30.0))(eslint@8.30.0))(eslint@8.30.0) fast-glob: 3.3.2 get-tsconfig: 4.7.2 is-core-module: 2.13.1 @@ -20159,28 +20188,18 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.30.0))(eslint@8.30.0): + eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.0(eslint@8.30.0)(typescript@5.3.3))(eslint@8.30.0))(eslint@8.30.0))(eslint@8.30.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 5.62.0(eslint@8.30.0)(typescript@5.3.3) eslint: 8.30.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.30.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.0(eslint@8.30.0)(typescript@5.3.3))(eslint@8.30.0))(eslint@8.30.0) transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@6.19.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@8.30.0): - dependencies: - debug: 3.2.7 - optionalDependencies: - '@typescript-eslint/parser': 6.19.0(eslint@8.30.0)(typescript@5.3.3) - eslint: 8.30.0 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color - - eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.0(eslint@8.30.0)(typescript@5.3.3))(eslint@8.30.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.0(eslint@8.30.0)(typescript@5.3.3))(eslint@8.30.0))(eslint@8.30.0))(eslint@8.30.0): dependencies: array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 @@ -20190,7 +20209,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.30.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@8.30.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.62.0(eslint@8.30.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.0(eslint@8.30.0)(typescript@5.3.3))(eslint@8.30.0))(eslint@8.30.0))(eslint@8.30.0) hasown: 2.0.0 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -20201,7 +20220,7 @@ snapshots: semver: 6.3.1 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 6.19.0(eslint@8.30.0)(typescript@5.3.3) + '@typescript-eslint/parser': 5.62.0(eslint@8.30.0)(typescript@5.3.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -22255,6 +22274,8 @@ snapshots: dependencies: language-subtag-registry: 0.3.22 + leaflet@1.9.4: {} + leven@3.1.0: {} levn@0.3.0: @@ -24291,6 +24312,13 @@ snapshots: react-is@18.2.0: {} + react-leaflet@4.2.1(leaflet@1.9.4)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@react-leaflet/core': 2.1.0(leaflet@1.9.4)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + leaflet: 1.9.4 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-lifecycles-compat@3.0.4: {} react-mapbox-gl@5.1.1(mapbox-gl@3.5.2)(prop-types@15.8.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0):