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:
gpt-engineer-app[bot]
2025-06-13 23:43:25 +00:00
parent 1fdf39d60a
commit 0264ac2f00
11 changed files with 310 additions and 60 deletions

View File

@@ -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>