diff --git a/components/dashboard/Locations.tsx b/components/dashboard/Locations.tsx
index 342ea14..47ac2b7 100644
--- a/components/dashboard/Locations.tsx
+++ b/components/dashboard/Locations.tsx
@@ -3,6 +3,8 @@
import { useState } from 'react'
import { formatNumber } from '@/lib/utils/format'
import * as Flags from 'country-flag-icons/react/3x2'
+// @ts-ignore
+import iso3166 from 'iso-3166-2'
import WorldMap from './WorldMap'
import { Modal } from '@ciphera-net/ui'
@@ -36,6 +38,27 @@ export default function Locations({ countries, cities, regions }: LocationProps)
}
}
+ const getRegionName = (regionCode: string, countryCode: string) => {
+ if (!regionCode || regionCode === 'Unknown' || !countryCode || countryCode === 'Unknown') return 'Unknown'
+
+ try {
+ const countryData = iso3166.data[countryCode]
+ if (!countryData || !countryData.sub) return regionCode
+
+ // ISO 3166-2 structure keys are typically "US-OR"
+ const fullCode = `${countryCode}-${regionCode}`
+ const regionData = countryData.sub[fullCode]
+
+ if (regionData && regionData.name) {
+ return regionData.name
+ }
+
+ return regionCode
+ } catch (e) {
+ return regionCode
+ }
+ }
+
const getData = () => {
switch (activeTab) {
case 'countries': return countries
@@ -103,7 +126,7 @@ export default function Locations({ countries, cities, regions }: LocationProps)
{activeTab === 'countries' ? getCountryName(item.country) :
- activeTab === 'regions' ? (item.region === 'Unknown' ? 'Unknown' : item.region) :
+ activeTab === 'regions' ? getRegionName(item.region, item.country) :
(item.city === 'Unknown' ? 'Unknown' : item.city)}
@@ -137,7 +160,7 @@ export default function Locations({ countries, cities, regions }: LocationProps)
{getFlagComponent(item.country)}
{activeTab === 'countries' ? getCountryName(item.country) :
- activeTab === 'regions' ? (item.region === 'Unknown' ? 'Unknown' : item.region) :
+ activeTab === 'regions' ? getRegionName(item.region, item.country) :
(item.city === 'Unknown' ? 'Unknown' : item.city)}
diff --git a/package-lock.json b/package-lock.json
index 8d0c2f8..bfe52b3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,6 +15,7 @@
"d3-scale": "^4.0.2",
"framer-motion": "^12.23.26",
"i18n-iso-countries": "^7.14.0",
+ "iso-3166-2": "^1.0.0",
"next": "^16.1.1",
"next-themes": "^0.4.6",
"react": "^19.2.3",
@@ -4881,6 +4882,11 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/iso-3166-2": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/iso-3166-2/-/iso-3166-2-1.0.0.tgz",
+ "integrity": "sha512-xLAazfKZzwlsg/Zz/GQGQk3jJez5/2ORrjD3TjSuqz/arMht/xTK49c0GOE3afO/gEd9tHtBVVlfBla01unUng=="
+ },
"node_modules/iterator.prototype": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
diff --git a/package.json b/package.json
index dabc52f..c869e41 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"d3-scale": "^4.0.2",
"framer-motion": "^12.23.26",
"i18n-iso-countries": "^7.14.0",
+ "iso-3166-2": "^1.0.0",
"next": "^16.1.1",
"next-themes": "^0.4.6",
"react": "^19.2.3",