feat: add admin statistics API endpoint and GeoMap component for scan visualization.
This commit is contained in:
parent
509e5a51a7
commit
57d6e3a449
|
|
@ -2,6 +2,8 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||||
import { cookies } from 'next/headers';
|
import { cookies } from 'next/headers';
|
||||||
import { db } from '@/lib/db';
|
import { db } from '@/lib/db';
|
||||||
|
|
||||||
|
export const dynamic = 'force-dynamic';
|
||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
// Check newsletter-admin cookie authentication
|
// Check newsletter-admin cookie authentication
|
||||||
|
|
|
||||||
|
|
@ -81,37 +81,37 @@ const countryNameToCode: Record<string, string> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// ISO Alpha-2 to ISO Alpha-3 mapping (for matching with TopoJSON)
|
// ISO Alpha-2 to ISO Alpha-3 mapping (for matching with TopoJSON)
|
||||||
const alpha2ToAlpha3: Record<string, string> = {
|
const alpha2ToNumeric: Record<string, string> = {
|
||||||
'US': 'USA',
|
'US': '840',
|
||||||
'DE': 'DEU',
|
'DE': '276',
|
||||||
'GB': 'GBR',
|
'GB': '826',
|
||||||
'FR': 'FRA',
|
'FR': '250',
|
||||||
'CA': 'CAN',
|
'CA': '124',
|
||||||
'AU': 'AUS',
|
'AU': '036',
|
||||||
'JP': 'JPN',
|
'JP': '392',
|
||||||
'CN': 'CHN',
|
'CN': '156',
|
||||||
'IN': 'IND',
|
'IN': '356',
|
||||||
'BR': 'BRA',
|
'BR': '076',
|
||||||
'ES': 'ESP',
|
'ES': '724',
|
||||||
'IT': 'ITA',
|
'IT': '380',
|
||||||
'NL': 'NLD',
|
'NL': '528',
|
||||||
'CH': 'CHE',
|
'CH': '756',
|
||||||
'AT': 'AUT',
|
'AT': '040',
|
||||||
'PL': 'POL',
|
'PL': '616',
|
||||||
'SE': 'SWE',
|
'SE': '752',
|
||||||
'NO': 'NOR',
|
'NO': '578',
|
||||||
'DK': 'DNK',
|
'DK': '208',
|
||||||
'FI': 'FIN',
|
'FI': '246',
|
||||||
'BE': 'BEL',
|
'BE': '056',
|
||||||
'PT': 'PRT',
|
'PT': '620',
|
||||||
'IE': 'IRL',
|
'IE': '372',
|
||||||
'MX': 'MEX',
|
'MX': '484',
|
||||||
'AR': 'ARG',
|
'AR': '032',
|
||||||
'KR': 'KOR',
|
'KR': '410',
|
||||||
'SG': 'SGP',
|
'SG': '702',
|
||||||
'NZ': 'NZL',
|
'NZ': '554',
|
||||||
'RU': 'RUS',
|
'RU': '643',
|
||||||
'ZA': 'ZAF',
|
'ZA': '710',
|
||||||
};
|
};
|
||||||
|
|
||||||
interface CountryStat {
|
interface CountryStat {
|
||||||
|
|
@ -132,9 +132,9 @@ const GeoMap: React.FC<GeoMapProps> = ({ countryStats, totalScans }) => {
|
||||||
|
|
||||||
countryStats.forEach((stat) => {
|
countryStats.forEach((stat) => {
|
||||||
const alpha2 = countryNameToCode[stat.country] || stat.country;
|
const alpha2 = countryNameToCode[stat.country] || stat.country;
|
||||||
const alpha3 = alpha2ToAlpha3[alpha2];
|
const numericCode = alpha2ToNumeric[alpha2];
|
||||||
if (alpha3) {
|
if (numericCode) {
|
||||||
countryData[alpha3] = stat.count;
|
countryData[numericCode] = stat.count;
|
||||||
if (stat.count > maxCount) maxCount = stat.count;
|
if (stat.count > maxCount) maxCount = stat.count;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -158,8 +158,9 @@ const GeoMap: React.FC<GeoMapProps> = ({ countryStats, totalScans }) => {
|
||||||
<Geographies geography={geoUrl}>
|
<Geographies geography={geoUrl}>
|
||||||
{({ geographies }) =>
|
{({ geographies }) =>
|
||||||
geographies.map((geo) => {
|
geographies.map((geo) => {
|
||||||
const isoCode = geo.properties.ISO_A3 || geo.id;
|
// geo.id is the numeric ISO code as a string (e.g., "840" for US)
|
||||||
const scanCount = countryData[isoCode] || 0;
|
const geoId = geo.id;
|
||||||
|
const scanCount = countryData[geoId] || 0;
|
||||||
const fillColor = scanCount > 0 ? colorScale(scanCount) : '#F1F5F9';
|
const fillColor = scanCount > 0 ? colorScale(scanCount) : '#F1F5F9';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue