191 lines
5.0 KiB
TypeScript
191 lines
5.0 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useRef } from "react";
|
|
|
|
interface CountryData {
|
|
name: string;
|
|
count: number;
|
|
// In a real implementation, we would have coordinates
|
|
x?: number;
|
|
y?: number;
|
|
}
|
|
|
|
interface ObservatoryMapProps {
|
|
countries: CountryData[];
|
|
onCountrySelect: (country: string) => void;
|
|
selectedCountry: string | null;
|
|
}
|
|
|
|
export function ObservatoryMap({
|
|
countries,
|
|
onCountrySelect,
|
|
selectedCountry
|
|
}: ObservatoryMapProps) {
|
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
|
|
// Draw the map and country markers
|
|
useEffect(() => {
|
|
const canvas = canvasRef.current;
|
|
if (!canvas) return;
|
|
|
|
const ctx = canvas.getContext('2d');
|
|
if (!ctx) return;
|
|
|
|
// Set canvas dimensions
|
|
const updateCanvasDimensions = () => {
|
|
const parent = canvas.parentElement;
|
|
if (parent) {
|
|
canvas.width = parent.clientWidth;
|
|
canvas.height = parent.clientHeight;
|
|
}
|
|
};
|
|
|
|
updateCanvasDimensions();
|
|
window.addEventListener('resize', updateCanvasDimensions);
|
|
|
|
// Clear canvas
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
// Draw world map background (simplified)
|
|
ctx.fillStyle = '#f9f9f9';
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
|
|
// Draw grid lines for better visualization
|
|
ctx.strokeStyle = '#e5e5e5';
|
|
ctx.lineWidth = 1;
|
|
|
|
// Horizontal grid lines
|
|
for (let y = 0; y < canvas.height; y += 50) {
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, y);
|
|
ctx.lineTo(canvas.width, y);
|
|
ctx.stroke();
|
|
}
|
|
|
|
// Vertical grid lines
|
|
for (let x = 0; x < canvas.width; x += 50) {
|
|
ctx.beginPath();
|
|
ctx.moveTo(x, 0);
|
|
ctx.lineTo(x, canvas.height);
|
|
ctx.stroke();
|
|
}
|
|
|
|
// Draw country markers at more fixed positions
|
|
countries.forEach((country) => {
|
|
// Position based on country name (simplified)
|
|
let x, y;
|
|
|
|
// Very simple positioning logic
|
|
switch(country.name) {
|
|
case 'Sudan':
|
|
x = canvas.width * 0.55;
|
|
y = canvas.height * 0.45;
|
|
break;
|
|
case 'Ukraine':
|
|
x = canvas.width * 0.65;
|
|
y = canvas.height * 0.25;
|
|
break;
|
|
case 'USA':
|
|
case 'New York':
|
|
x = canvas.width * 0.25;
|
|
y = canvas.height * 0.35;
|
|
break;
|
|
case 'UK':
|
|
x = canvas.width * 0.45;
|
|
y = canvas.height * 0.25;
|
|
break;
|
|
case 'France':
|
|
x = canvas.width * 0.48;
|
|
y = canvas.height * 0.30;
|
|
break;
|
|
case 'China':
|
|
x = canvas.width * 0.75;
|
|
y = canvas.height * 0.35;
|
|
break;
|
|
case 'Russia':
|
|
x = canvas.width * 0.70;
|
|
y = canvas.height * 0.20;
|
|
break;
|
|
case 'India':
|
|
x = canvas.width * 0.70;
|
|
y = canvas.height * 0.40;
|
|
break;
|
|
case 'Brazil':
|
|
x = canvas.width * 0.35;
|
|
y = canvas.height * 0.60;
|
|
break;
|
|
case 'Australia':
|
|
x = canvas.width * 0.80;
|
|
y = canvas.height * 0.65;
|
|
break;
|
|
default:
|
|
// Random position for other countries
|
|
x = 100 + Math.random() * (canvas.width - 200);
|
|
y = 100 + Math.random() * (canvas.height - 200);
|
|
}
|
|
|
|
// Draw marker
|
|
ctx.beginPath();
|
|
ctx.arc(x, y, 6, 0, Math.PI * 2);
|
|
|
|
// Simple color
|
|
ctx.fillStyle = country.name === 'Sudan' ? '#f87171' : '#cbd5e1';
|
|
|
|
ctx.fill();
|
|
|
|
// Draw country name if it's Sudan or selected
|
|
if (country.name === 'Sudan' || country.name === selectedCountry) {
|
|
ctx.fillStyle = '#374151';
|
|
ctx.font = '12px system-ui, sans-serif';
|
|
ctx.fillText(country.name, x + 10, y + 4);
|
|
}
|
|
|
|
// Store coordinates for click detection
|
|
country.x = x;
|
|
country.y = y;
|
|
});
|
|
|
|
// Handle click events
|
|
const handleClick = (e: MouseEvent) => {
|
|
const rect = canvas.getBoundingClientRect();
|
|
const x = e.clientX - rect.left;
|
|
const y = e.clientY - rect.top;
|
|
|
|
// Check if a country marker was clicked
|
|
for (const country of countries) {
|
|
if (country.x && country.y) {
|
|
const distance = Math.sqrt(
|
|
Math.pow(x - country.x, 2) + Math.pow(y - country.y, 2)
|
|
);
|
|
|
|
if (distance <= 8) {
|
|
onCountrySelect(country.name);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
canvas.addEventListener('click', handleClick);
|
|
|
|
// Cleanup
|
|
return () => {
|
|
window.removeEventListener('resize', updateCanvasDimensions);
|
|
canvas.removeEventListener('click', handleClick);
|
|
};
|
|
}, [countries, selectedCountry, onCountrySelect]);
|
|
|
|
return (
|
|
<div className="w-full h-full">
|
|
<canvas
|
|
ref={canvasRef}
|
|
className="w-full h-full"
|
|
/>
|
|
{countries.length === 0 && (
|
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
<p className="text-gray-400 text-center">No countries detected in the news</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|