sc/full-world-wrap #6
@@ -49,6 +49,7 @@ const APP = () => {
|
|||||||
const [lineOfSightData, setLineOfSightData] = useState(null);
|
const [lineOfSightData, setLineOfSightData] = useState(null);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [isPlaying, setIsPlaying] = useState(false);
|
const [isPlaying, setIsPlaying] = useState(false);
|
||||||
|
const [apiError, setApiError] = useState(null);
|
||||||
const [flightSpeed, setFlightSpeed] = useState(1.0);
|
const [flightSpeed, setFlightSpeed] = useState(1.0);
|
||||||
const [mapStyle, setMapStyle] = useState('basic');
|
const [mapStyle, setMapStyle] = useState('basic');
|
||||||
const [mapProjection, setMapProjection] = useState('globe');
|
const [mapProjection, setMapProjection] = useState('globe');
|
||||||
@@ -382,6 +383,7 @@ const APP = () => {
|
|||||||
setIsLocked(false);
|
setIsLocked(false);
|
||||||
setLineOfSightData(null);
|
setLineOfSightData(null);
|
||||||
setSelectedCity(null);
|
setSelectedCity(null);
|
||||||
|
setApiError(null);
|
||||||
syncCitiesToMap([]);
|
syncCitiesToMap([]);
|
||||||
if (mapRef.current) {
|
if (mapRef.current) {
|
||||||
const map = mapRef.current;
|
const map = mapRef.current;
|
||||||
@@ -733,6 +735,7 @@ const APP = () => {
|
|||||||
const handleShowLineOfSight = async () => {
|
const handleShowLineOfSight = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setSelectedCity(null);
|
setSelectedCity(null);
|
||||||
|
setApiError(null);
|
||||||
try {
|
try {
|
||||||
const response = await apiService.getLineOfSight(
|
const response = await apiService.getLineOfSight(
|
||||||
selectedPoint.lat,
|
selectedPoint.lat,
|
||||||
@@ -748,6 +751,7 @@ const APP = () => {
|
|||||||
renderLineOnMap(response.data.data);
|
renderLineOnMap(response.data.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching line of sight:', error);
|
console.error('Error fetching line of sight:', error);
|
||||||
|
setApiError('Failed to fetch route. Please try again.');
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
// Reset flight progress for a new line calculation
|
// Reset flight progress for a new line calculation
|
||||||
@@ -840,6 +844,12 @@ const APP = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{apiError && (
|
||||||
|
<div className="error-banner">
|
||||||
|
⚠️ {apiError}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{!isLocked ? (
|
{!isLocked ? (
|
||||||
<button className="action-btn" onClick={handleShowLineOfSight} disabled={loading}>
|
<button className="action-btn" onClick={handleShowLineOfSight} disabled={loading}>
|
||||||
{loading ? 'Calculating...' : '📡 Show Line of Sight'}
|
{loading ? 'Calculating...' : '📡 Show Line of Sight'}
|
||||||
|
|||||||
@@ -464,6 +464,19 @@
|
|||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error-banner {
|
||||||
|
background: #fdecea;
|
||||||
|
color: #d32f2f;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border-radius: 6px;
|
||||||
|
border-left: 4px solid #d32f2f;
|
||||||
|
font-size: 13px;
|
||||||
|
margin: 10px 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.fly-controls {
|
.fly-controls {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
|||||||
Reference in New Issue
Block a user