Load data from JSON files
Load region and system data from JSON files, and use the security parameter to color the systems.
This commit is contained in:
@@ -1,10 +1,17 @@
|
||||
|
||||
import React, { useState, useRef, useCallback } from 'react';
|
||||
import React, { useState, useRef, useCallback, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { MapNode } from './MapNode';
|
||||
import { Connection } from './Connection';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ArrowLeft } from 'lucide-react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
interface System {
|
||||
solarSystemName: string;
|
||||
x: string;
|
||||
y: string;
|
||||
security: number;
|
||||
}
|
||||
|
||||
interface Position {
|
||||
x: number;
|
||||
@@ -12,22 +19,44 @@ interface Position {
|
||||
}
|
||||
|
||||
interface RegionMapProps {
|
||||
regionData: {
|
||||
name: string;
|
||||
systems: Array<{ id: string; name: string }>;
|
||||
nodePositions: Record<string, Position>;
|
||||
connections: Array<{ from: string; to: string }>;
|
||||
};
|
||||
regionName: string;
|
||||
}
|
||||
|
||||
export const RegionMap: React.FC<RegionMapProps> = ({ regionData }) => {
|
||||
const fetchRegionData = async (regionName: string): Promise<System[]> => {
|
||||
const response = await fetch(`/${regionName}.json`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch ${regionName} data`);
|
||||
}
|
||||
return response.json();
|
||||
};
|
||||
|
||||
export const RegionMap: React.FC<RegionMapProps> = ({ regionName }) => {
|
||||
const navigate = useNavigate();
|
||||
const [draggedNode, setDraggedNode] = useState<string | null>(null);
|
||||
const [nodePositions, setNodePositions] = useState<Record<string, Position>>(regionData.nodePositions);
|
||||
const [nodePositions, setNodePositions] = useState<Record<string, Position>>({});
|
||||
const svgRef = useRef<SVGSVGElement>(null);
|
||||
|
||||
const handleSystemClick = (systemId: string) => {
|
||||
navigate(`/systems/${systemId}`);
|
||||
const { data: systems, isLoading, error } = useQuery({
|
||||
queryKey: ['region', regionName],
|
||||
queryFn: () => fetchRegionData(regionName),
|
||||
});
|
||||
|
||||
// Initialize node positions when data is loaded
|
||||
useEffect(() => {
|
||||
if (systems) {
|
||||
const positions: Record<string, Position> = {};
|
||||
systems.forEach(system => {
|
||||
positions[system.solarSystemName] = {
|
||||
x: parseInt(system.x),
|
||||
y: parseInt(system.y)
|
||||
};
|
||||
});
|
||||
setNodePositions(positions);
|
||||
}
|
||||
}, [systems]);
|
||||
|
||||
const handleSystemClick = (systemName: string) => {
|
||||
navigate(`/systems/${systemName}`);
|
||||
};
|
||||
|
||||
const handleMouseDown = useCallback((nodeId: string) => {
|
||||
@@ -51,6 +80,22 @@ export const RegionMap: React.FC<RegionMapProps> = ({ regionData }) => {
|
||||
setDraggedNode(null);
|
||||
}, []);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="w-full h-screen bg-gradient-to-br from-slate-900 via-cyan-900 to-slate-900 flex items-center justify-center">
|
||||
<div className="text-white text-xl">Loading {regionName} data...</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="w-full h-screen bg-gradient-to-br from-slate-900 via-cyan-900 to-slate-900 flex items-center justify-center">
|
||||
<div className="text-red-400 text-xl">Error loading {regionName} data</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full h-screen bg-gradient-to-br from-slate-900 via-cyan-900 to-slate-900 overflow-hidden relative">
|
||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,_var(--tw-gradient-stops))] from-cyan-900/20 via-slate-900/40 to-black"></div>
|
||||
@@ -66,7 +111,7 @@ export const RegionMap: React.FC<RegionMapProps> = ({ regionData }) => {
|
||||
Back to Galaxy
|
||||
</Button>
|
||||
<div>
|
||||
<h1 className="text-4xl font-bold text-white">{regionData.name} Region</h1>
|
||||
<h1 className="text-4xl font-bold text-white">{regionName} Region</h1>
|
||||
<p className="text-cyan-200">Explore the systems within this region</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -92,26 +137,18 @@ export const RegionMap: React.FC<RegionMapProps> = ({ regionData }) => {
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
{/* Render connections first (behind nodes) */}
|
||||
{regionData.connections.map((connection, index) => (
|
||||
<Connection
|
||||
key={index}
|
||||
from={nodePositions[connection.from]}
|
||||
to={nodePositions[connection.to]}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Render systems */}
|
||||
{regionData.systems.map((system) => (
|
||||
{systems?.map((system) => (
|
||||
<MapNode
|
||||
key={system.id}
|
||||
id={system.id}
|
||||
name={system.name}
|
||||
position={nodePositions[system.id]}
|
||||
onClick={() => handleSystemClick(system.id)}
|
||||
onMouseDown={() => handleMouseDown(system.id)}
|
||||
isDragging={draggedNode === system.id}
|
||||
key={system.solarSystemName}
|
||||
id={system.solarSystemName}
|
||||
name={system.solarSystemName}
|
||||
position={nodePositions[system.solarSystemName] || { x: 0, y: 0 }}
|
||||
onClick={() => handleSystemClick(system.solarSystemName)}
|
||||
onMouseDown={() => handleMouseDown(system.solarSystemName)}
|
||||
isDragging={draggedNode === system.solarSystemName}
|
||||
type="system"
|
||||
security={system.security}
|
||||
/>
|
||||
))}
|
||||
</svg>
|
||||
|
Reference in New Issue
Block a user