diff --git a/package-lock.json b/package-lock.json
index 080a04a..6b671cb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,8 +15,8 @@
"@sentry/react": "^8.31.0",
"@tanstack/react-query": "^5.51.15",
"@tanstack/react-router": "^1.58.7",
- "chart.js": "^4.4.4",
"echarts": "^5.5.1",
+ "dotted-map": "^2.2.3",
"idb-keyval": "^6.2.1",
"lucide-react": "^0.445.0",
"react": "^18.3.1",
@@ -1606,6 +1606,37 @@
"url": "https://github.com/sponsors/tannerlinsley"
}
},
+ "node_modules/@turf/boolean-point-in-polygon": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-6.5.0.tgz",
+ "integrity": "sha512-DtSuVFB26SI+hj0SjrvXowGTUCHlgevPAIsukssW6BG5MlNSBQAo70wpICBNJL6RjukXg8d2eXaAWuD/CqL00A==",
+ "dependencies": {
+ "@turf/helpers": "^6.5.0",
+ "@turf/invariant": "^6.5.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/turf"
+ }
+ },
+ "node_modules/@turf/helpers": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-6.5.0.tgz",
+ "integrity": "sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw==",
+ "funding": {
+ "url": "https://opencollective.com/turf"
+ }
+ },
+ "node_modules/@turf/invariant": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-6.5.0.tgz",
+ "integrity": "sha512-Wv8PRNCtPD31UVbdJE/KVAWKe7l6US+lJItRR/HOEW3eh+U/JwRCSUl/KZ7bmjM/C+zLNoreM2TU6OoLACs4eg==",
+ "dependencies": {
+ "@turf/helpers": "^6.5.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/turf"
+ }
+ },
"node_modules/@types/babel__core": {
"version": "7.20.5",
"dev": true,
@@ -2259,6 +2290,15 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
},
+ "node_modules/dotted-map": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/dotted-map/-/dotted-map-2.2.3.tgz",
+ "integrity": "sha512-8hyOOHHLLVCcCisM3yb9hqp+3bJ7TSMcr1SfrUw8Wxp5UMqih35jIvUyagweCooJbz/EH1nC9GGuPysh7+YlAg==",
+ "dependencies": {
+ "@turf/boolean-point-in-polygon": "^6.0.1",
+ "proj4": "^2.6.1"
+ }
+ },
"node_modules/escalade": {
"version": "3.2.0",
"dev": true,
@@ -2988,6 +3028,11 @@
"node": ">= 8"
}
},
+ "node_modules/mgrs": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mgrs/-/mgrs-1.0.0.tgz",
+ "integrity": "sha512-awNbTOqCxK1DBGjalK3xqWIstBZgN6fxsMSiXLs9/spqWkF2pAhb2rrYCFSsr1/tT7PhcDGjZndG8SWYn0byYA=="
+ },
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
@@ -3238,6 +3283,15 @@
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
+ "node_modules/proj4": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/proj4/-/proj4-2.12.1.tgz",
+ "integrity": "sha512-vmhP3hmstjXjzFwg8QXJwpoj4n7GVrXk3ZW3DzNK/Ur4cuwXq7ZiMXaWYvLYLQbX8n4MXgbwTr4lthOUZltBpA==",
+ "dependencies": {
+ "mgrs": "1.0.0",
+ "wkt-parser": "^1.3.3"
+ }
+ },
"node_modules/punycode": {
"version": "2.3.1",
"dev": true,
@@ -4552,6 +4606,11 @@
"node": ">= 8"
}
},
+ "node_modules/wkt-parser": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.3.3.tgz",
+ "integrity": "sha512-ZnV3yH8/k58ZPACOXeiHaMuXIiaTk1t0hSUVisbO0t4RjA5wPpUytcxeyiN2h+LZRrmuHIh/1UlrR9e7DHDvTw=="
+ },
"node_modules/word-wrap": {
"version": "1.2.5",
"dev": true,
@@ -4603,4 +4662,4 @@
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
}
}
-}
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index a72c073..8586625 100644
--- a/package.json
+++ b/package.json
@@ -30,8 +30,8 @@
"@sentry/react": "^8.31.0",
"@tanstack/react-query": "^5.51.15",
"@tanstack/react-router": "^1.58.7",
- "chart.js": "^4.4.4",
"echarts": "^5.5.1",
+ "dotted-map": "^2.2.3",
"idb-keyval": "^6.2.1",
"lucide-react": "^0.445.0",
"react": "^18.3.1",
diff --git a/src/components/Peers/PeerCountryCell.css b/src/components/Peers/PeerCountryCell.css
new file mode 100644
index 0000000..ac159a5
--- /dev/null
+++ b/src/components/Peers/PeerCountryCell.css
@@ -0,0 +1,5 @@
+.peerCountry {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+}
diff --git a/src/components/Peers/PeerCountryCell.tsx b/src/components/Peers/PeerCountryCell.tsx
new file mode 100644
index 0000000..1edb332
--- /dev/null
+++ b/src/components/Peers/PeerCountryCell.tsx
@@ -0,0 +1,73 @@
+import { Cell } from "@codex-storage/marketplace-ui-components";
+import { PeerPin } from "./types";
+import { countriesCoordinates } from "./countries";
+import { useQuery } from "@tanstack/react-query";
+import "./PeerCountryCell.css";
+
+export type Props = {
+ address: string;
+ onPinAdd: (pin: PeerPin) => void;
+};
+
+const getFlagEmoji = (countryCode: string) => {
+ const codePoints = countryCode
+ .toUpperCase()
+ .split("")
+ .map((char) => 127397 + char.charCodeAt(0));
+ return String.fromCodePoint(...codePoints);
+};
+
+export function PeerCountryCell({ address, onPinAdd }: Props) {
+ const { data } = useQuery({
+ queryFn: () => {
+ const [ip] = address.split(":");
+
+ return fetch(import.meta.env.VITE_GEO_IP_URL + "/" + ip)
+ .then((res) => res.json())
+ .then((json) => {
+ const coordinate = countriesCoordinates.find(
+ (c) => c.iso === json.country
+ );
+
+ if (coordinate) {
+ onPinAdd({
+ lat: parseFloat(coordinate.lat),
+ lng: parseFloat(coordinate.lng),
+ });
+ }
+
+ return coordinate;
+ });
+ },
+ queryKey: [address],
+
+ // Enable only when the address exists
+ enabled: !!address,
+
+ // No need to retry because if the connection to the node
+ // is back again, all the queries will be invalidated.
+ retry: false,
+
+ // We can cache the data at Infinity because the relation between
+ // country and ip is fixed
+ staleTime: Infinity,
+
+ // Don't expect something new when coming back to the UI
+ refetchOnWindowFocus: false,
+ });
+
+ return (
+ |
+
+ {data ? (
+ <>
+ {!!data && getFlagEmoji(data.iso)}
+ {data?.name}
+ >
+ ) : (
+ {address}
+ )}
+
+ |
+ );
+}
diff --git a/src/components/Peers/countries.ts b/src/components/Peers/countries.ts
new file mode 100644
index 0000000..00151b8
--- /dev/null
+++ b/src/components/Peers/countries.ts
@@ -0,0 +1,1557 @@
+export const countriesCoordinates = [
+ {
+ "iso": "AF",
+ "lat": "33",
+ "lng": "65",
+ "name": "Afghanistan"
+ },
+ {
+ "iso": "AX",
+ "lat": "60.116667",
+ "lng": "19.9",
+ "name": "Åland Islands"
+ },
+ {
+ "iso": "AL",
+ "lat": "41",
+ "lng": "20",
+ "name": "Albania"
+ },
+ {
+ "iso": "DZ",
+ "lat": "28",
+ "lng": "3",
+ "name": "Algeria"
+ },
+ {
+ "iso": "AS",
+ "lat": "-14.3333",
+ "lng": "-170",
+ "name": "American Samoa"
+ },
+ {
+ "iso": "AD",
+ "lat": "42.5",
+ "lng": "1.6",
+ "name": "Andorra"
+ },
+ {
+ "iso": "AO",
+ "lat": "-12.5",
+ "lng": "18.5",
+ "name": "Angola"
+ },
+ {
+ "iso": "AI",
+ "lat": "18.25",
+ "lng": "-63.1667",
+ "name": "Anguilla"
+ },
+ {
+ "iso": "AQ",
+ "lat": "-90",
+ "lng": "0",
+ "name": "Antarctica"
+ },
+ {
+ "iso": "AG",
+ "lat": "17.05",
+ "lng": "-61.8",
+ "name": "Antigua and Barbuda"
+ },
+ {
+ "iso": "AR",
+ "lat": "-34",
+ "lng": "-64",
+ "name": "Argentina"
+ },
+ {
+ "iso": "AM",
+ "lat": "40",
+ "lng": "45",
+ "name": "Armenia"
+ },
+ {
+ "iso": "AW",
+ "lat": "12.5",
+ "lng": "-69.9667",
+ "name": "Aruba"
+ },
+ {
+ "iso": "AU",
+ "lat": "-27",
+ "lng": "133",
+ "name": "Australia"
+ },
+ {
+ "iso": "AT",
+ "lat": "47.3333",
+ "lng": "13.3333",
+ "name": "Austria"
+ },
+ {
+ "iso": "AZ",
+ "lat": "40.5",
+ "lng": "47.5",
+ "name": "Azerbaijan"
+ },
+ {
+ "iso": "BS",
+ "lat": "24.25",
+ "lng": "-76",
+ "name": "Bahamas"
+ },
+ {
+ "iso": "BH",
+ "lat": "26",
+ "lng": "50.55",
+ "name": "Bahrain"
+ },
+ {
+ "iso": "BD",
+ "lat": "24",
+ "lng": "90",
+ "name": "Bangladesh"
+ },
+ {
+ "iso": "BB",
+ "lat": "13.1667",
+ "lng": "-59.5333",
+ "name": "Barbados"
+ },
+ {
+ "iso": "BY",
+ "lat": "53",
+ "lng": "28",
+ "name": "Belarus"
+ },
+ {
+ "iso": "BE",
+ "lat": "50.8333",
+ "lng": "4",
+ "name": "Belgium"
+ },
+ {
+ "iso": "BZ",
+ "lat": "17.25",
+ "lng": "-88.75",
+ "name": "Belize"
+ },
+ {
+ "iso": "BJ",
+ "lat": "9.5",
+ "lng": "2.25",
+ "name": "Benin"
+ },
+ {
+ "iso": "BM",
+ "lat": "32.3333",
+ "lng": "-64.75",
+ "name": "Bermuda"
+ },
+ {
+ "iso": "BT",
+ "lat": "27.5",
+ "lng": "90.5",
+ "name": "Bhutan"
+ },
+ {
+ "iso": "Plurinational State of",
+ "lat": "68",
+ "lng": "-17"
+ },
+ {
+ "iso": "BO",
+ "lat": "-17",
+ "lng": "-65",
+ "name": "Bolivia, Plurinational State of"
+ },
+ {
+ "iso": "Sint Eustatius and Saba",
+ "lat": "535",
+ "lng": "12.183333"
+ },
+ {
+ "iso": "BA",
+ "lat": "44",
+ "lng": "18",
+ "name": "Bosnia and Herzegovina"
+ },
+ {
+ "iso": "BW",
+ "lat": "-22",
+ "lng": "24",
+ "name": "Botswana"
+ },
+ {
+ "iso": "BV",
+ "lat": "-54.4333",
+ "lng": "3.4",
+ "name": "Bouvet Island"
+ },
+ {
+ "iso": "BR",
+ "lat": "-10",
+ "lng": "-55",
+ "name": "Brazil"
+ },
+ {
+ "iso": "IO",
+ "lat": "-6",
+ "lng": "71.5",
+ "name": "British Indian Ocean Territory"
+ },
+ {
+ "iso": "BN",
+ "lat": "4.5",
+ "lng": "114.6667",
+ "name": "Brunei Darussalam"
+ },
+ {
+ "iso": "BN",
+ "lat": "4.5",
+ "lng": "114.6667",
+ "name": "Brunei Darussalam"
+ },
+ {
+ "iso": "BG",
+ "lat": "43",
+ "lng": "25",
+ "name": "Bulgaria"
+ },
+ {
+ "iso": "BF",
+ "lat": "13",
+ "lng": "-2",
+ "name": "Burkina Faso"
+ },
+ {
+ "iso": "MM",
+ "lat": "22",
+ "lng": "98",
+ "name": "Myanmar"
+ },
+ {
+ "iso": "BI",
+ "lat": "-3.5",
+ "lng": "30",
+ "name": "Burundi"
+ },
+ {
+ "iso": "KH",
+ "lat": "13",
+ "lng": "105",
+ "name": "Cambodia"
+ },
+ {
+ "iso": "CM",
+ "lat": "6",
+ "lng": "12",
+ "name": "Cameroon"
+ },
+ {
+ "iso": "CA",
+ "lat": "60",
+ "lng": "-95",
+ "name": "Canada"
+ },
+ {
+ "iso": "CV",
+ "lat": "16",
+ "lng": "-24",
+ "name": "Cape Verde"
+ },
+ {
+ "iso": "KY",
+ "lat": "19.5",
+ "lng": "-80.5",
+ "name": "Cayman Islands"
+ },
+ {
+ "iso": "CF",
+ "lat": "7",
+ "lng": "21",
+ "name": "Central African Republic"
+ },
+ {
+ "iso": "TD",
+ "lat": "15",
+ "lng": "19",
+ "name": "Chad"
+ },
+ {
+ "iso": "CL",
+ "lat": "-30",
+ "lng": "-71",
+ "name": "Chile"
+ },
+ {
+ "iso": "CN",
+ "lat": "35",
+ "lng": "105",
+ "name": "China"
+ },
+ {
+ "iso": "CX",
+ "lat": "-10.5",
+ "lng": "105.6667",
+ "name": "Christmas Island"
+ },
+ {
+ "iso": "CC",
+ "lat": "-12.5",
+ "lng": "96.8333",
+ "name": "Cocos (Keeling) Islands"
+ },
+ {
+ "iso": "CO",
+ "lat": "4",
+ "lng": "-72",
+ "name": "Colombia"
+ },
+ {
+ "iso": "KM",
+ "lat": "-12.1667",
+ "lng": "44.25",
+ "name": "Comoros"
+ },
+ {
+ "iso": "the Democratic Republic of the",
+ "lat": "180",
+ "lng": "0"
+ },
+ {
+ "iso": "CG",
+ "lat": "-1",
+ "lng": "15",
+ "name": "Congo"
+ },
+ {
+ "iso": "CK",
+ "lat": "-21.2333",
+ "lng": "-159.7667",
+ "name": "Cook Islands"
+ },
+ {
+ "iso": "CR",
+ "lat": "10",
+ "lng": "-84",
+ "name": "Costa Rica"
+ },
+ {
+ "iso": "CI",
+ "lat": "8",
+ "lng": "-5",
+ "name": "Côte d'Ivoire"
+ },
+ {
+ "iso": "HR",
+ "lat": "45.1667",
+ "lng": "15.5",
+ "name": "Croatia"
+ },
+ {
+ "iso": "CU",
+ "lat": "21.5",
+ "lng": "-80",
+ "name": "Cuba"
+ },
+ {
+ "iso": "CW",
+ "lat": "12.166667",
+ "lng": "-68.966667",
+ "name": "Curaçao"
+ },
+ {
+ "iso": "CY",
+ "lat": "35",
+ "lng": "33",
+ "name": "Cyprus"
+ },
+ {
+ "iso": "CZ",
+ "lat": "49.75",
+ "lng": "15.5",
+ "name": "Czech Republic"
+ },
+ {
+ "iso": "DK",
+ "lat": "56",
+ "lng": "10",
+ "name": "Denmark"
+ },
+ {
+ "iso": "DJ",
+ "lat": "11.5",
+ "lng": "43",
+ "name": "Djibouti"
+ },
+ {
+ "iso": "DM",
+ "lat": "15.4167",
+ "lng": "-61.3333",
+ "name": "Dominica"
+ },
+ {
+ "iso": "DO",
+ "lat": "19",
+ "lng": "-70.6667",
+ "name": "Dominican Republic"
+ },
+ {
+ "iso": "EC",
+ "lat": "-2",
+ "lng": "-77.5",
+ "name": "Ecuador"
+ },
+ {
+ "iso": "EG",
+ "lat": "27",
+ "lng": "30",
+ "name": "Egypt"
+ },
+ {
+ "iso": "SV",
+ "lat": "13.8333",
+ "lng": "-88.9167",
+ "name": "El Salvador"
+ },
+ {
+ "iso": "GQ",
+ "lat": "2",
+ "lng": "10",
+ "name": "Equatorial Guinea"
+ },
+ {
+ "iso": "ER",
+ "lat": "15",
+ "lng": "39",
+ "name": "Eritrea"
+ },
+ {
+ "iso": "EE",
+ "lat": "59",
+ "lng": "26",
+ "name": "Estonia"
+ },
+ {
+ "iso": "ET",
+ "lat": "8",
+ "lng": "38",
+ "name": "Ethiopia"
+ },
+ {
+ "iso": "FK",
+ "lat": "-51.75",
+ "lng": "-59",
+ "name": "Falkland Islands (Malvinas)"
+ },
+ {
+ "iso": "FO",
+ "lat": "62",
+ "lng": "-7",
+ "name": "Faroe Islands"
+ },
+ {
+ "iso": "FJ",
+ "lat": "-18",
+ "lng": "175",
+ "name": "Fiji"
+ },
+ {
+ "iso": "FI",
+ "lat": "64",
+ "lng": "26",
+ "name": "Finland"
+ },
+ {
+ "iso": "FR",
+ "lat": "46",
+ "lng": "2",
+ "name": "France"
+ },
+ {
+ "iso": "GF",
+ "lat": "4",
+ "lng": "-53",
+ "name": "French Guiana"
+ },
+ {
+ "iso": "PF",
+ "lat": "-15",
+ "lng": "-140",
+ "name": "French Polynesia"
+ },
+ {
+ "iso": "TF",
+ "lat": "-43",
+ "lng": "67",
+ "name": "French Southern Territories"
+ },
+ {
+ "iso": "GA",
+ "lat": "-1",
+ "lng": "11.75",
+ "name": "Gabon"
+ },
+ {
+ "iso": "GM",
+ "lat": "13.4667",
+ "lng": "-16.5667",
+ "name": "Gambia"
+ },
+ {
+ "iso": "GE",
+ "lat": "42",
+ "lng": "43.5",
+ "name": "Georgia"
+ },
+ {
+ "iso": "DE",
+ "lat": "51",
+ "lng": "9",
+ "name": "Germany"
+ },
+ {
+ "iso": "GH",
+ "lat": "8",
+ "lng": "-2",
+ "name": "Ghana"
+ },
+ {
+ "iso": "GI",
+ "lat": "36.1833",
+ "lng": "-5.3667",
+ "name": "Gibraltar"
+ },
+ {
+ "iso": "GR",
+ "lat": "39",
+ "lng": "22",
+ "name": "Greece"
+ },
+ {
+ "iso": "GL",
+ "lat": "72",
+ "lng": "-40",
+ "name": "Greenland"
+ },
+ {
+ "iso": "GD",
+ "lat": "12.1167",
+ "lng": "-61.6667",
+ "name": "Grenada"
+ },
+ {
+ "iso": "GP",
+ "lat": "16.25",
+ "lng": "-61.5833",
+ "name": "Guadeloupe"
+ },
+ {
+ "iso": "GU",
+ "lat": "13.4667",
+ "lng": "144.7833",
+ "name": "Guam"
+ },
+ {
+ "iso": "GT",
+ "lat": "15.5",
+ "lng": "-90.25",
+ "name": "Guatemala"
+ },
+ {
+ "iso": "GG",
+ "lat": "49.5",
+ "lng": "-2.56",
+ "name": "Guernsey"
+ },
+ {
+ "iso": "GW",
+ "lat": "12",
+ "lng": "-15",
+ "name": "Guinea-Bissau"
+ },
+ {
+ "iso": "GN",
+ "lat": "11",
+ "lng": "-10",
+ "name": "Guinea"
+ },
+ {
+ "iso": "GY",
+ "lat": "5",
+ "lng": "-59",
+ "name": "Guyana"
+ },
+ {
+ "iso": "HT",
+ "lat": "19",
+ "lng": "-72.4167",
+ "name": "Haiti"
+ },
+ {
+ "iso": "HM",
+ "lat": "-53.1",
+ "lng": "72.5167",
+ "name": "Heard Island and McDonald Islands"
+ },
+ {
+ "iso": "VA",
+ "lat": "41.9",
+ "lng": "12.45",
+ "name": "Holy See (Vatican City State)"
+ },
+ {
+ "iso": "HN",
+ "lat": "15",
+ "lng": "-86.5",
+ "name": "Honduras"
+ },
+ {
+ "iso": "HK",
+ "lat": "22.25",
+ "lng": "114.1667",
+ "name": "Hong Kong"
+ },
+ {
+ "iso": "HU",
+ "lat": "47",
+ "lng": "20",
+ "name": "Hungary"
+ },
+ {
+ "iso": "IS",
+ "lat": "65",
+ "lng": "-18",
+ "name": "Iceland"
+ },
+ {
+ "iso": "IN",
+ "lat": "20",
+ "lng": "77",
+ "name": "India"
+ },
+ {
+ "iso": "ID",
+ "lat": "-5",
+ "lng": "120",
+ "name": "Indonesia"
+ },
+ {
+ "iso": "Islamic Republic of",
+ "lat": "364",
+ "lng": "32"
+ },
+ {
+ "iso": "IQ",
+ "lat": "33",
+ "lng": "44",
+ "name": "Iraq"
+ },
+ {
+ "iso": "IE",
+ "lat": "53",
+ "lng": "-8",
+ "name": "Ireland"
+ },
+ {
+ "iso": "IM",
+ "lat": "54.23",
+ "lng": "-4.55",
+ "name": "Isle of Man"
+ },
+ {
+ "iso": "IL",
+ "lat": "31.5",
+ "lng": "34.75",
+ "name": "Israel"
+ },
+ {
+ "iso": "IT",
+ "lat": "42.8333",
+ "lng": "12.8333",
+ "name": "Italy"
+ },
+ {
+ "iso": "CI",
+ "lat": "8",
+ "lng": "-5",
+ "name": "Côte d'Ivoire"
+ },
+ {
+ "iso": "JM",
+ "lat": "18.25",
+ "lng": "-77.5",
+ "name": "Jamaica"
+ },
+ {
+ "iso": "JP",
+ "lat": "36",
+ "lng": "138",
+ "name": "Japan"
+ },
+ {
+ "iso": "JE",
+ "lat": "49.21",
+ "lng": "-2.13",
+ "name": "Jersey"
+ },
+ {
+ "iso": "JO",
+ "lat": "31",
+ "lng": "36",
+ "name": "Jordan"
+ },
+ {
+ "iso": "KZ",
+ "lat": "48",
+ "lng": "68",
+ "name": "Kazakhstan"
+ },
+ {
+ "iso": "KE",
+ "lat": "1",
+ "lng": "38",
+ "name": "Kenya"
+ },
+ {
+ "iso": "KI",
+ "lat": "1.4167",
+ "lng": "173",
+ "name": "Kiribati"
+ },
+ {
+ "iso": "Democratic People's Republic of",
+ "lat": "408",
+ "lng": "40"
+ },
+ {
+ "iso": "Republic of",
+ "lat": "410",
+ "lng": "37"
+ },
+ {
+ "iso": "XK",
+ "lat": "42.583333",
+ "lng": "21"
+ },
+ {
+ "iso": "KW",
+ "lat": "29.3375",
+ "lng": "47.6581",
+ "name": "Kuwait"
+ },
+ {
+ "iso": "KG",
+ "lat": "41",
+ "lng": "75",
+ "name": "Kyrgyzstan"
+ },
+ {
+ "iso": "LA",
+ "lat": "18",
+ "lng": "105",
+ "name": "Lao People's Democratic Republic"
+ },
+ {
+ "iso": "LV",
+ "lat": "57",
+ "lng": "25",
+ "name": "Latvia"
+ },
+ {
+ "iso": "LB",
+ "lat": "33.8333",
+ "lng": "35.8333",
+ "name": "Lebanon"
+ },
+ {
+ "iso": "LS",
+ "lat": "-29.5",
+ "lng": "28.5",
+ "name": "Lesotho"
+ },
+ {
+ "iso": "LR",
+ "lat": "6.5",
+ "lng": "-9.5",
+ "name": "Liberia"
+ },
+ {
+ "iso": "LY",
+ "lat": "25",
+ "lng": "17",
+ "name": "Libya"
+ },
+ {
+ "iso": "LY",
+ "lat": "25",
+ "lng": "17",
+ "name": "Libya"
+ },
+ {
+ "iso": "LI",
+ "lat": "47.1667",
+ "lng": "9.5333",
+ "name": "Liechtenstein"
+ },
+ {
+ "iso": "LT",
+ "lat": "56",
+ "lng": "24",
+ "name": "Lithuania"
+ },
+ {
+ "iso": "LU",
+ "lat": "49.75",
+ "lng": "6.1667",
+ "name": "Luxembourg"
+ },
+ {
+ "iso": "MO",
+ "lat": "22.1667",
+ "lng": "113.55",
+ "name": "Macao"
+ },
+ {
+ "iso": "the former Yugoslav Republic of",
+ "lat": "807",
+ "lng": "41.8333"
+ },
+ {
+ "iso": "MG",
+ "lat": "-20",
+ "lng": "47",
+ "name": "Madagascar"
+ },
+ {
+ "iso": "MW",
+ "lat": "-13.5",
+ "lng": "34",
+ "name": "Malawi"
+ },
+ {
+ "iso": "MY",
+ "lat": "2.5",
+ "lng": "112.5",
+ "name": "Malaysia"
+ },
+ {
+ "iso": "MV",
+ "lat": "3.25",
+ "lng": "73",
+ "name": "Maldives"
+ },
+ {
+ "iso": "ML",
+ "lat": "17",
+ "lng": "-4",
+ "name": "Mali"
+ },
+ {
+ "iso": "MT",
+ "lat": "35.8333",
+ "lng": "14.5833",
+ "name": "Malta"
+ },
+ {
+ "iso": "MH",
+ "lat": "9",
+ "lng": "168",
+ "name": "Marshall Islands"
+ },
+ {
+ "iso": "MQ",
+ "lat": "14.6667",
+ "lng": "-61",
+ "name": "Martinique"
+ },
+ {
+ "iso": "MR",
+ "lat": "20",
+ "lng": "-12",
+ "name": "Mauritania"
+ },
+ {
+ "iso": "MU",
+ "lat": "-20.2833",
+ "lng": "57.55",
+ "name": "Mauritius"
+ },
+ {
+ "iso": "YT",
+ "lat": "-12.8333",
+ "lng": "45.1667",
+ "name": "Mayotte"
+ },
+ {
+ "iso": "MX",
+ "lat": "23",
+ "lng": "-102",
+ "name": "Mexico"
+ },
+ {
+ "iso": "Federated States of",
+ "lat": "583",
+ "lng": "6.9167"
+ },
+ {
+ "iso": "Republic of",
+ "lat": "498",
+ "lng": "47"
+ },
+ {
+ "iso": "MC",
+ "lat": "43.7333",
+ "lng": "7.4",
+ "name": "Monaco"
+ },
+ {
+ "iso": "MN",
+ "lat": "46",
+ "lng": "105",
+ "name": "Mongolia"
+ },
+ {
+ "iso": "ME",
+ "lat": "42",
+ "lng": "19",
+ "name": "Montenegro"
+ },
+ {
+ "iso": "MS",
+ "lat": "16.75",
+ "lng": "-62.2",
+ "name": "Montserrat"
+ },
+ {
+ "iso": "MA",
+ "lat": "32",
+ "lng": "-5",
+ "name": "Morocco"
+ },
+ {
+ "iso": "MZ",
+ "lat": "-18.25",
+ "lng": "35",
+ "name": "Mozambique"
+ },
+ {
+ "iso": "MM",
+ "lat": "22",
+ "lng": "98",
+ "name": "Myanmar"
+ },
+ {
+ "iso": "NA",
+ "lat": "-22",
+ "lng": "17",
+ "name": "Namibia"
+ },
+ {
+ "iso": "NR",
+ "lat": "-0.5333",
+ "lng": "166.9167",
+ "name": "Nauru"
+ },
+ {
+ "iso": "NP",
+ "lat": "28",
+ "lng": "84",
+ "name": "Nepal"
+ },
+ {
+ "iso": "AN",
+ "lat": "12.25",
+ "lng": "-68.75"
+ },
+ {
+ "iso": "NL",
+ "lat": "52.5",
+ "lng": "5.75",
+ "name": "Netherlands"
+ },
+ {
+ "iso": "NC",
+ "lat": "-21.5",
+ "lng": "165.5",
+ "name": "New Caledonia"
+ },
+ {
+ "iso": "NZ",
+ "lat": "-41",
+ "lng": "174",
+ "name": "New Zealand"
+ },
+ {
+ "iso": "NI",
+ "lat": "13",
+ "lng": "-85",
+ "name": "Nicaragua"
+ },
+ {
+ "iso": "NE",
+ "lat": "16",
+ "lng": "8",
+ "name": "Niger"
+ },
+ {
+ "iso": "NG",
+ "lat": "10",
+ "lng": "8",
+ "name": "Nigeria"
+ },
+ {
+ "iso": "NU",
+ "lat": "-19.0333",
+ "lng": "-169.8667",
+ "name": "Niue"
+ },
+ {
+ "iso": "NF",
+ "lat": "-29.0333",
+ "lng": "167.95",
+ "name": "Norfolk Island"
+ },
+ {
+ "iso": "MP",
+ "lat": "15.2",
+ "lng": "145.75",
+ "name": "Northern Mariana Islands"
+ },
+ {
+ "iso": "NO",
+ "lat": "62",
+ "lng": "10",
+ "name": "Norway"
+ },
+ {
+ "iso": "OM",
+ "lat": "21",
+ "lng": "57",
+ "name": "Oman"
+ },
+ {
+ "iso": "PK",
+ "lat": "30",
+ "lng": "70",
+ "name": "Pakistan"
+ },
+ {
+ "iso": "PW",
+ "lat": "7.5",
+ "lng": "134.5",
+ "name": "Palau"
+ },
+ {
+ "iso": "Occupied",
+ "lat": "275",
+ "lng": "32"
+ },
+ {
+ "iso": "PA",
+ "lat": "9",
+ "lng": "-80",
+ "name": "Panama"
+ },
+ {
+ "iso": "PG",
+ "lat": "-6",
+ "lng": "147",
+ "name": "Papua New Guinea"
+ },
+ {
+ "iso": "PY",
+ "lat": "-23",
+ "lng": "-58",
+ "name": "Paraguay"
+ },
+ {
+ "iso": "PE",
+ "lat": "-10",
+ "lng": "-76",
+ "name": "Peru"
+ },
+ {
+ "iso": "PH",
+ "lat": "13",
+ "lng": "122",
+ "name": "Philippines"
+ },
+ {
+ "iso": "PN",
+ "lat": "-24.7",
+ "lng": "-127.4",
+ "name": "Pitcairn"
+ },
+ {
+ "iso": "PL",
+ "lat": "52",
+ "lng": "20",
+ "name": "Poland"
+ },
+ {
+ "iso": "PT",
+ "lat": "39.5",
+ "lng": "-8",
+ "name": "Portugal"
+ },
+ {
+ "iso": "PR",
+ "lat": "18.25",
+ "lng": "-66.5",
+ "name": "Puerto Rico"
+ },
+ {
+ "iso": "QA",
+ "lat": "25.5",
+ "lng": "51.25",
+ "name": "Qatar"
+ },
+ {
+ "iso": "RE",
+ "lat": "-21.1",
+ "lng": "55.6",
+ "name": "Réunion"
+ },
+ {
+ "iso": "RO",
+ "lat": "46",
+ "lng": "25",
+ "name": "Romania"
+ },
+ {
+ "iso": "RU",
+ "lat": "60",
+ "lng": "100",
+ "name": "Russian Federation"
+ },
+ {
+ "iso": "RU",
+ "lat": "60",
+ "lng": "100",
+ "name": "Russian Federation"
+ },
+ {
+ "iso": "RW",
+ "lat": "-2",
+ "lng": "30",
+ "name": "Rwanda"
+ },
+ {
+ "iso": "BL",
+ "lat": "17.897728",
+ "lng": "-62.834244",
+ "name": "Saint Barthélemy"
+ },
+ {
+ "iso": "Ascension and Tristan da Cunha",
+ "lat": "654",
+ "lng": "-15.9333"
+ },
+ {
+ "iso": "KN",
+ "lat": "17.3333",
+ "lng": "-62.75",
+ "name": "Saint Kitts and Nevis"
+ },
+ {
+ "iso": "LC",
+ "lat": "13.8833",
+ "lng": "-61.1333",
+ "name": "Saint Lucia"
+ },
+ {
+ "iso": "MF",
+ "lat": "18.075278",
+ "lng": "-63.06",
+ "name": "Saint Martin (French part)"
+ },
+ {
+ "iso": "PM",
+ "lat": "46.8333",
+ "lng": "-56.3333",
+ "name": "Saint Pierre and Miquelon"
+ },
+ {
+ "iso": "VC",
+ "lat": "13.25",
+ "lng": "-61.2",
+ "name": "Saint Vincent and the Grenadines"
+ },
+ {
+ "iso": "VC",
+ "lat": "13.25",
+ "lng": "-61.2",
+ "name": "Saint Vincent and the Grenadines"
+ },
+ {
+ "iso": "WS",
+ "lat": "-13.5833",
+ "lng": "-172.3333",
+ "name": "Samoa"
+ },
+ {
+ "iso": "SM",
+ "lat": "43.7667",
+ "lng": "12.4167",
+ "name": "San Marino"
+ },
+ {
+ "iso": "ST",
+ "lat": "1",
+ "lng": "7",
+ "name": "Sao Tome and Principe"
+ },
+ {
+ "iso": "SA",
+ "lat": "25",
+ "lng": "45",
+ "name": "Saudi Arabia"
+ },
+ {
+ "iso": "SN",
+ "lat": "14",
+ "lng": "-14",
+ "name": "Senegal"
+ },
+ {
+ "iso": "RS",
+ "lat": "44",
+ "lng": "21",
+ "name": "Serbia"
+ },
+ {
+ "iso": "SC",
+ "lat": "-4.5833",
+ "lng": "55.6667",
+ "name": "Seychelles"
+ },
+ {
+ "iso": "SL",
+ "lat": "8.5",
+ "lng": "-11.5",
+ "name": "Sierra Leone"
+ },
+ {
+ "iso": "SG",
+ "lat": "1.3667",
+ "lng": "103.8",
+ "name": "Singapore"
+ },
+ {
+ "iso": "SX",
+ "lat": "18.033333",
+ "lng": "-63.05",
+ "name": "Sint Maarten (Dutch part)"
+ },
+ {
+ "iso": "SK",
+ "lat": "48.6667",
+ "lng": "19.5",
+ "name": "Slovakia"
+ },
+ {
+ "iso": "SI",
+ "lat": "46",
+ "lng": "15",
+ "name": "Slovenia"
+ },
+ {
+ "iso": "SB",
+ "lat": "-8",
+ "lng": "159",
+ "name": "Solomon Islands"
+ },
+ {
+ "iso": "SO",
+ "lat": "10",
+ "lng": "49",
+ "name": "Somalia"
+ },
+ {
+ "iso": "ZA",
+ "lat": "-29",
+ "lng": "24",
+ "name": "South Africa"
+ },
+ {
+ "iso": "GS",
+ "lat": "-54.5",
+ "lng": "-37",
+ "name": "South Georgia and the South Sandwich Islands"
+ },
+ {
+ "iso": "KR",
+ "lat": "37",
+ "lng": "127.5",
+ "name": "Korea, Republic of"
+ },
+ {
+ "iso": "SS",
+ "lat": "8",
+ "lng": "30",
+ "name": "South Sudan"
+ },
+ {
+ "iso": "ES",
+ "lat": "40",
+ "lng": "-4",
+ "name": "Spain"
+ },
+ {
+ "iso": "LK",
+ "lat": "7",
+ "lng": "81",
+ "name": "Sri Lanka"
+ },
+ {
+ "iso": "VC",
+ "lat": "13.25",
+ "lng": "-61.2",
+ "name": "Saint Vincent and the Grenadines"
+ },
+ {
+ "iso": "SD",
+ "lat": "15",
+ "lng": "30",
+ "name": "Sudan"
+ },
+ {
+ "iso": "SR",
+ "lat": "4",
+ "lng": "-56",
+ "name": "Suriname"
+ },
+ {
+ "iso": "SJ",
+ "lat": "78",
+ "lng": "20",
+ "name": "Svalbard and Jan Mayen"
+ },
+ {
+ "iso": "SZ",
+ "lat": "-26.5",
+ "lng": "31.5",
+ "name": "Swaziland"
+ },
+ {
+ "iso": "SE",
+ "lat": "62",
+ "lng": "15",
+ "name": "Sweden"
+ },
+ {
+ "iso": "CH",
+ "lat": "47",
+ "lng": "8",
+ "name": "Switzerland"
+ },
+ {
+ "iso": "SY",
+ "lat": "35",
+ "lng": "38",
+ "name": "Syrian Arab Republic"
+ },
+ {
+ "iso": "TW",
+ "lat": "23.5",
+ "lng": "121",
+ "name": "Taiwan, Province of China"
+ },
+ {
+ "iso": "TJ",
+ "lat": "39",
+ "lng": "71",
+ "name": "Tajikistan"
+ },
+ {
+ "iso": "United Republic of",
+ "lat": "834",
+ "lng": "-6"
+ },
+ {
+ "iso": "TH",
+ "lat": "15",
+ "lng": "100",
+ "name": "Thailand"
+ },
+ {
+ "iso": "TL",
+ "lat": "-8.55",
+ "lng": "125.5167",
+ "name": "Timor-Leste"
+ },
+ {
+ "iso": "TG",
+ "lat": "8",
+ "lng": "1.1667",
+ "name": "Togo"
+ },
+ {
+ "iso": "TK",
+ "lat": "-9",
+ "lng": "-172",
+ "name": "Tokelau"
+ },
+ {
+ "iso": "TO",
+ "lat": "-20",
+ "lng": "-175",
+ "name": "Tonga"
+ },
+ {
+ "iso": "TT",
+ "lat": "11",
+ "lng": "-61",
+ "name": "Trinidad and Tobago"
+ },
+ {
+ "iso": "TN",
+ "lat": "34",
+ "lng": "9",
+ "name": "Tunisia"
+ },
+ {
+ "iso": "TR",
+ "lat": "39",
+ "lng": "35",
+ "name": "Turkey"
+ },
+ {
+ "iso": "TM",
+ "lat": "40",
+ "lng": "60",
+ "name": "Turkmenistan"
+ },
+ {
+ "iso": "TC",
+ "lat": "21.75",
+ "lng": "-71.5833",
+ "name": "Turks and Caicos Islands"
+ },
+ {
+ "iso": "TV",
+ "lat": "-8",
+ "lng": "178",
+ "name": "Tuvalu"
+ },
+ {
+ "iso": "UG",
+ "lat": "1",
+ "lng": "32",
+ "name": "Uganda"
+ },
+ {
+ "iso": "UA",
+ "lat": "49",
+ "lng": "32",
+ "name": "Ukraine"
+ },
+ {
+ "iso": "AE",
+ "lat": "24",
+ "lng": "54",
+ "name": "United Arab Emirates"
+ },
+ {
+ "iso": "GB",
+ "lat": "54",
+ "lng": "-2",
+ "name": "United Kingdom"
+ },
+ {
+ "iso": "UM",
+ "lat": "19.2833",
+ "lng": "166.6",
+ "name": "United States Minor Outlying Islands"
+ },
+ {
+ "iso": "US",
+ "lat": "38",
+ "lng": "-97",
+ "name": "United States"
+ },
+ {
+ "iso": "UY",
+ "lat": "-33",
+ "lng": "-56",
+ "name": "Uruguay"
+ },
+ {
+ "iso": "UZ",
+ "lat": "41",
+ "lng": "64",
+ "name": "Uzbekistan"
+ },
+ {
+ "iso": "VU",
+ "lat": "-16",
+ "lng": "167",
+ "name": "Vanuatu"
+ },
+ {
+ "iso": "Bolivarian Republic of",
+ "lat": "862",
+ "lng": "8"
+ },
+ {
+ "iso": "VE",
+ "lat": "8",
+ "lng": "-66",
+ "name": "Venezuela, Bolivarian Republic of"
+ },
+ {
+ "iso": "VN",
+ "lat": "16",
+ "lng": "106",
+ "name": "Viet Nam"
+ },
+ {
+ "iso": "VN",
+ "lat": "16",
+ "lng": "106",
+ "name": "Viet Nam"
+ },
+ {
+ "iso": "British",
+ "lat": "92",
+ "lng": "18.5"
+ },
+ {
+ "iso": "U.S.",
+ "lat": "850",
+ "lng": "18.3333"
+ },
+ {
+ "iso": "WF",
+ "lat": "-13.3",
+ "lng": "-176.2",
+ "name": "Wallis and Futuna"
+ },
+ {
+ "iso": "EH",
+ "lat": "24.5",
+ "lng": "-13",
+ "name": "Western Sahara"
+ },
+ {
+ "iso": "YE",
+ "lat": "15",
+ "lng": "48",
+ "name": "Yemen"
+ },
+ {
+ "iso": "ZM",
+ "lat": "-15",
+ "lng": "30",
+ "name": "Zambia"
+ },
+ {
+ "iso": "ZW",
+ "lat": "-20",
+ "lng": "30",
+ "name": "Zimbabwe"
+ }
+]
\ No newline at end of file
diff --git a/src/components/Peers/types.ts b/src/components/Peers/types.ts
new file mode 100644
index 0000000..a3e1bea
--- /dev/null
+++ b/src/components/Peers/types.ts
@@ -0,0 +1,4 @@
+export type PeerPin = {
+ lat: number;
+ lng: number;
+};
\ No newline at end of file
diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts
index 2484188..3441411 100644
--- a/src/routeTree.gen.ts
+++ b/src/routeTree.gen.ts
@@ -17,6 +17,7 @@ import { Route as DashboardIndexImport } from './routes/dashboard/index'
import { Route as DashboardSettingsImport } from './routes/dashboard/settings'
import { Route as DashboardRequestsImport } from './routes/dashboard/requests'
import { Route as DashboardPurchasesImport } from './routes/dashboard/purchases'
+import { Route as DashboardPeersImport } from './routes/dashboard/peers'
import { Route as DashboardHelpImport } from './routes/dashboard/help'
import { Route as DashboardFavoritesImport } from './routes/dashboard/favorites'
import { Route as DashboardDisclaimerImport } from './routes/dashboard/disclaimer'
@@ -55,6 +56,11 @@ const DashboardPurchasesRoute = DashboardPurchasesImport.update({
getParentRoute: () => DashboardRoute,
} as any)
+const DashboardPeersRoute = DashboardPeersImport.update({
+ path: '/peers',
+ getParentRoute: () => DashboardRoute,
+} as any)
+
const DashboardHelpRoute = DashboardHelpImport.update({
path: '/help',
getParentRoute: () => DashboardRoute,
@@ -133,6 +139,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof DashboardHelpImport
parentRoute: typeof DashboardImport
}
+ '/dashboard/peers': {
+ id: '/dashboard/peers'
+ path: '/peers'
+ fullPath: '/dashboard/peers'
+ preLoaderRoute: typeof DashboardPeersImport
+ parentRoute: typeof DashboardImport
+ }
'/dashboard/purchases': {
id: '/dashboard/purchases'
path: '/purchases'
@@ -172,6 +185,7 @@ interface DashboardRouteChildren {
DashboardDisclaimerRoute: typeof DashboardDisclaimerRoute
DashboardFavoritesRoute: typeof DashboardFavoritesRoute
DashboardHelpRoute: typeof DashboardHelpRoute
+ DashboardPeersRoute: typeof DashboardPeersRoute
DashboardPurchasesRoute: typeof DashboardPurchasesRoute
DashboardRequestsRoute: typeof DashboardRequestsRoute
DashboardSettingsRoute: typeof DashboardSettingsRoute
@@ -184,6 +198,7 @@ const DashboardRouteChildren: DashboardRouteChildren = {
DashboardDisclaimerRoute: DashboardDisclaimerRoute,
DashboardFavoritesRoute: DashboardFavoritesRoute,
DashboardHelpRoute: DashboardHelpRoute,
+ DashboardPeersRoute: DashboardPeersRoute,
DashboardPurchasesRoute: DashboardPurchasesRoute,
DashboardRequestsRoute: DashboardRequestsRoute,
DashboardSettingsRoute: DashboardSettingsRoute,
@@ -202,6 +217,7 @@ export interface FileRoutesByFullPath {
'/dashboard/disclaimer': typeof DashboardDisclaimerRoute
'/dashboard/favorites': typeof DashboardFavoritesRoute
'/dashboard/help': typeof DashboardHelpRoute
+ '/dashboard/peers': typeof DashboardPeersRoute
'/dashboard/purchases': typeof DashboardPurchasesRoute
'/dashboard/requests': typeof DashboardRequestsRoute
'/dashboard/settings': typeof DashboardSettingsRoute
@@ -215,6 +231,7 @@ export interface FileRoutesByTo {
'/dashboard/disclaimer': typeof DashboardDisclaimerRoute
'/dashboard/favorites': typeof DashboardFavoritesRoute
'/dashboard/help': typeof DashboardHelpRoute
+ '/dashboard/peers': typeof DashboardPeersRoute
'/dashboard/purchases': typeof DashboardPurchasesRoute
'/dashboard/requests': typeof DashboardRequestsRoute
'/dashboard/settings': typeof DashboardSettingsRoute
@@ -230,6 +247,7 @@ export interface FileRoutesById {
'/dashboard/disclaimer': typeof DashboardDisclaimerRoute
'/dashboard/favorites': typeof DashboardFavoritesRoute
'/dashboard/help': typeof DashboardHelpRoute
+ '/dashboard/peers': typeof DashboardPeersRoute
'/dashboard/purchases': typeof DashboardPurchasesRoute
'/dashboard/requests': typeof DashboardRequestsRoute
'/dashboard/settings': typeof DashboardSettingsRoute
@@ -246,6 +264,7 @@ export interface FileRouteTypes {
| '/dashboard/disclaimer'
| '/dashboard/favorites'
| '/dashboard/help'
+ | '/dashboard/peers'
| '/dashboard/purchases'
| '/dashboard/requests'
| '/dashboard/settings'
@@ -258,6 +277,7 @@ export interface FileRouteTypes {
| '/dashboard/disclaimer'
| '/dashboard/favorites'
| '/dashboard/help'
+ | '/dashboard/peers'
| '/dashboard/purchases'
| '/dashboard/requests'
| '/dashboard/settings'
@@ -271,6 +291,7 @@ export interface FileRouteTypes {
| '/dashboard/disclaimer'
| '/dashboard/favorites'
| '/dashboard/help'
+ | '/dashboard/peers'
| '/dashboard/purchases'
| '/dashboard/requests'
| '/dashboard/settings'
@@ -315,6 +336,7 @@ export const routeTree = rootRoute
"/dashboard/disclaimer",
"/dashboard/favorites",
"/dashboard/help",
+ "/dashboard/peers",
"/dashboard/purchases",
"/dashboard/requests",
"/dashboard/settings",
@@ -341,6 +363,10 @@ export const routeTree = rootRoute
"filePath": "dashboard/help.tsx",
"parent": "/dashboard"
},
+ "/dashboard/peers": {
+ "filePath": "dashboard/peers.tsx",
+ "parent": "/dashboard"
+ },
"/dashboard/purchases": {
"filePath": "dashboard/purchases.tsx",
"parent": "/dashboard"
diff --git a/src/routes/dashboard.tsx b/src/routes/dashboard.tsx
index c50f33a..fea649d 100644
--- a/src/routes/dashboard.tsx
+++ b/src/routes/dashboard.tsx
@@ -12,6 +12,7 @@ import {
Settings,
HelpCircle,
TriangleAlert,
+ Earth,
} from "lucide-react";
import { ICON_SIZE } from "../utils/constants";
import { NodeIndicator } from "../components/NodeIndicator/NodeIndicator";
@@ -87,6 +88,15 @@ const Layout = () => {
),
},
+ {
+ type: "menu-item",
+ Component: (p: MenuItemComponentProps) => (
+
+
+ Peers
+
+ ),
+ },
{
type: "menu-item",
Component: (p: MenuItemComponentProps) => (
diff --git a/src/routes/dashboard/peers.css b/src/routes/dashboard/peers.css
new file mode 100644
index 0000000..7f308ee
--- /dev/null
+++ b/src/routes/dashboard/peers.css
@@ -0,0 +1,41 @@
+.peers-map {
+ max-width: 1000px;
+ width: 100%;
+}
+
+.peers-table {
+ margin-top: 1rem;
+ width: calc(100% - 4rem);
+ max-width: calc(1000px - 4rem);
+}
+
+.peers {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding-bottom: 4rem;
+ padding-left: 2rem;
+ padding-right: 2rem;
+}
+
+.peers circle[fill="#d6ff79"] {
+ /* fill: yellow; */
+ animation: dash 3s linear infinite;
+ stroke: white;
+ stroke-width: 0.6px;
+ stroke-dasharray: 0.3;
+}
+
+@keyframes dash {
+ from {
+ stroke-dashoffset: 2;
+ }
+ to {
+ stroke-dashoffset: 0;
+ }
+}
+@keyframes circleAn {
+ to {
+ /* stroke-dashoffset: 100px; */
+ }
+}
diff --git a/src/routes/dashboard/peers.tsx b/src/routes/dashboard/peers.tsx
new file mode 100644
index 0000000..6682e60
--- /dev/null
+++ b/src/routes/dashboard/peers.tsx
@@ -0,0 +1,102 @@
+import { Cell, Row, Table } from "@codex-storage/marketplace-ui-components";
+import { createFileRoute } from "@tanstack/react-router";
+import { getMapJSON } from "dotted-map";
+import DottedMap from "dotted-map/without-countries";
+import { Promises } from "../../utils/promises";
+import { useQuery } from "@tanstack/react-query";
+import { PeerCountryCell } from "../../components/Peers/PeerCountryCell";
+import { useCallback, useState } from "react";
+import { PeerPin } from "../../components/Peers/types";
+import "./peers.css";
+import { CodexSdk } from "../../sdk/codex";
+
+// This function accepts the same arguments as DottedMap in the example above.
+const mapJsonString = getMapJSON({ height: 60, grid: "diagonal" });
+
+export const Route = createFileRoute("/dashboard/peers")({
+ component: () => {
+ const [pins, setPins] = useState<[PeerPin, number][]>([]);
+ const { data } = useQuery({
+ queryFn: () =>
+ CodexSdk.debug.info().then((s) => Promises.rejectOnError(s)),
+ queryKey: ["debug"],
+
+ // No need to retry because if the connection to the node
+ // is back again, all the queries will be invalidated.
+ retry: false,
+
+ // The client node should be local, so display the cache value while
+ // making a background request looks good.
+ staleTime: 0,
+
+ // Refreshing when focus returns can be useful if a user comes back
+ // to the UI after performing an operation in the terminal.
+ refetchOnWindowFocus: true,
+
+ // Throw the error to the error boundary
+ throwOnError: true,
+ });
+
+ const onPinAdd = useCallback((pin: PeerPin) => {
+ setPins((val) => {
+ const [, quantity = 0] =
+ val.find(([p]) => p.lat === pin.lat && p.lng == pin.lng) || [];
+ return [...val, [pin, quantity + 1]];
+ });
+ }, []);
+
+ // It’s safe to re-create the map at each render, because of the
+ // pre-computation it’s super fast ⚡️
+ const map = new DottedMap({ map: JSON.parse(mapJsonString) });
+
+ pins.map(([pin, quantity]) =>
+ map.addPin({
+ lat: pin.lat,
+ lng: pin.lng,
+ svgOptions: { color: "#d6ff79", radius: 0.8 * quantity },
+ })
+ );
+
+ const svgMap = map.getSVG({
+ radius: 0.42,
+ color: "#423B38",
+ shape: "circle",
+ backgroundColor: "#020300",
+ });
+
+ const headers = ["Country", "PeerId", "Active"];
+
+ const rows =
+ ((data as any)?.table?.nodes || []).map((node: any) => (
+ ,
+ | {node.peerId} | ,
+
+ {node.seen ? (
+
+ ) : (
+
+ )}
+ | ,
+ ]}>
+ )) || [];
+
+ return (
+
+ {/*
}`})
*/}
+
+
+
+
+
+ );
+ },
+});