A10-A16: datetime-local time parsing, step heading, gps_error state, unified leaflet 1.9.4 icons, drop debug log, dashboard error surfacing, isMobile on resize
This commit is contained in:
+12
-2
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { BrowserRouter as Router, Routes, Route, Navigate, useLocation } from "react-router-dom";
|
||||
import AdminDashboard from "./pages/AdminDashboard";
|
||||
import MobileFormPage from "./pages/MobileFormPage";
|
||||
@@ -27,7 +27,17 @@ function ThemeProvider({ children }) {
|
||||
}
|
||||
|
||||
function App() {
|
||||
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent) || window.innerWidth < 768;
|
||||
const [isMobile, setIsMobile] = useState(
|
||||
() => /iPhone|iPad|iPod|Android/i.test(navigator.userAgent) || window.innerWidth < 768
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const onResize = () => setIsMobile(
|
||||
/iPhone|iPad|iPod|Android/i.test(navigator.userAgent) || window.innerWidth < 768
|
||||
);
|
||||
window.addEventListener('resize', onResize);
|
||||
return () => window.removeEventListener('resize', onResize);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Router>
|
||||
|
||||
@@ -116,7 +116,6 @@ const CaseForm = ({ isMobile = false }) => {
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
console.log("Case created:", result);
|
||||
|
||||
// Перенаправляем на страницу анализа с ID карточки
|
||||
window.location.href = `/analysis/${result.id}`;
|
||||
|
||||
@@ -27,23 +27,23 @@ const Step4Environment = ({ data, updateData }) => {
|
||||
|
||||
const handleGetLocation = () => {
|
||||
if (!navigator.geolocation) {
|
||||
alert("Геолокация не поддерживается вашим браузером");
|
||||
updateData({ gps_error: 'Геолокация не поддерживается вашим браузером' });
|
||||
return;
|
||||
}
|
||||
|
||||
updateData({ gps_loading: true });
|
||||
updateData({ gps_loading: true, gps_error: null });
|
||||
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(position) => {
|
||||
updateData({
|
||||
tnp_lat: position.coords.latitude.toFixed(6),
|
||||
tnp_lon: position.coords.longitude.toFixed(6),
|
||||
gps_loading: false
|
||||
gps_loading: false,
|
||||
gps_error: null
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
alert("Ошибка получения координат: " + error.message);
|
||||
updateData({ gps_loading: false });
|
||||
updateData({ gps_error: 'Ошибка получения координат: ' + error.message, gps_loading: false });
|
||||
},
|
||||
{
|
||||
enableHighAccuracy: true,
|
||||
@@ -55,7 +55,7 @@ const Step4Environment = ({ data, updateData }) => {
|
||||
|
||||
return (
|
||||
<div className="form-step">
|
||||
<h2>Шаг 5: Среда и местность</h2>
|
||||
<h2>Среда и местность</h2>
|
||||
|
||||
{/* Сезон определяется автоматически, показываем только для информации */}
|
||||
{data.season && (
|
||||
|
||||
@@ -6,9 +6,9 @@ import L from 'leaflet';
|
||||
// Fix default marker icon issue with webpack
|
||||
delete L.Icon.Default.prototype._getIconUrl;
|
||||
L.Icon.Default.mergeOptions({
|
||||
iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon-2x.png',
|
||||
iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png',
|
||||
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png',
|
||||
iconRetinaUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png',
|
||||
iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png',
|
||||
shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',
|
||||
});
|
||||
|
||||
const SearchMap = ({ tnpLat, tnpLon, maxDistance, zones }) => {
|
||||
@@ -183,8 +183,8 @@ const SearchMap = ({ tnpLat, tnpLon, maxDistance, zones }) => {
|
||||
<Marker
|
||||
position={tnpPosition}
|
||||
icon={L.icon({
|
||||
iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png',
|
||||
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png',
|
||||
iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png',
|
||||
shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41],
|
||||
popupAnchor: [1, -34],
|
||||
|
||||
@@ -110,6 +110,7 @@ function AdminDashboard() {
|
||||
} catch (err) {
|
||||
if (err.name !== 'AbortError') {
|
||||
setDashboard(null);
|
||||
setError(err.message || 'Ошибка загрузки дашборда');
|
||||
}
|
||||
} finally {
|
||||
setDashboardLoading(false);
|
||||
|
||||
@@ -41,7 +41,10 @@ const AnalysisResult = () => {
|
||||
|
||||
const getTimeOfDay = (lostTime) => {
|
||||
if (!lostTime) return 'день';
|
||||
const hour = parseInt(lostTime.split(':')[0]);
|
||||
// Значение может прийти как "YYYY-MM-DDTHH:MM" (input type="datetime-local")
|
||||
// или как "HH:MM" — берём часы из обоих форматов.
|
||||
const timePart = lostTime.includes('T') ? lostTime.split('T')[1] : lostTime;
|
||||
const hour = parseInt(timePart.split(':')[0]);
|
||||
if (hour >= 6 && hour < 18) return 'день';
|
||||
if (hour >= 18 && hour < 22) return 'сумерки';
|
||||
return 'ночь';
|
||||
|
||||
Reference in New Issue
Block a user