feat(gps): кнопка «Названия» для слоя объектов (по умолчанию скрыты); подписи сокращены до «объект · заказчик» (≤40 символов)
This commit is contained in:
@@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from 'react';
|
|||||||
import { Card } from '@/components/ui/card';
|
import { Card } from '@/components/ui/card';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { X, Route, Ruler, MapPinPlus } from 'lucide-react';
|
import { X, Route, Ruler, MapPinPlus, Tag } from 'lucide-react';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||||
import { useLocation } from 'wouter';
|
import { useLocation } from 'wouter';
|
||||||
@@ -132,6 +132,9 @@ export function GpsMapTab({ onShowRoute }: { onShowRoute: (assetId: number) => v
|
|||||||
// === Слой задач формы: выбранная форма + её geo-поле → задачи на карте ===
|
// === Слой задач формы: выбранная форма + её geo-поле → задачи на карте ===
|
||||||
const [, setLocation] = useLocation();
|
const [, setLocation] = useLocation();
|
||||||
const [tasksLayer, setTasksLayer] = useState(false);
|
const [tasksLayer, setTasksLayer] = useState(false);
|
||||||
|
// Отображение названий объектов на карте (по умолчанию скрыты — длинные
|
||||||
|
// заголовки перекрывают друг друга; включаем кнопкой «Названия»)
|
||||||
|
const [showLabels, setShowLabels] = useState(false);
|
||||||
const [mapFormId, setMapFormId] = useState<number | null>(null);
|
const [mapFormId, setMapFormId] = useState<number | null>(null);
|
||||||
const [mapFieldId, setMapFieldId] = useState<number | null>(null);
|
const [mapFieldId, setMapFieldId] = useState<number | null>(null);
|
||||||
const [createAt, setCreateAt] = useState<{ lat: number; lng: number } | null>(null);
|
const [createAt, setCreateAt] = useState<{ lat: number; lng: number } | null>(null);
|
||||||
@@ -183,6 +186,15 @@ export function GpsMapTab({ onShowRoute }: { onShowRoute: (assetId: number) => v
|
|||||||
return { lat, lng };
|
return { lat, lng };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Короткое название для подписи: «объект · заказчик» (первая и последняя
|
||||||
|
// части заголовка через «;»), длину ограничиваем, иначе подписи перекрывают карту
|
||||||
|
const shortTitle = (title: string): string => {
|
||||||
|
const parts = title.split(';').map((x) => x.trim()).filter(Boolean);
|
||||||
|
let text = parts.length > 1 ? `${parts[0]} · ${parts[parts.length - 1]}` : (parts[0] ?? title);
|
||||||
|
if (text.length > 40) text = `${text.slice(0, 39)}…`;
|
||||||
|
return text;
|
||||||
|
};
|
||||||
|
|
||||||
const taskMarkers: GpsMapMarker[] = useMemo(() => {
|
const taskMarkers: GpsMapMarker[] = useMemo(() => {
|
||||||
if (!tasksLayer || mapFieldId === null) return [];
|
if (!tasksLayer || mapFieldId === null) return [];
|
||||||
const markers: GpsMapMarker[] = [];
|
const markers: GpsMapMarker[] = [];
|
||||||
@@ -195,14 +207,15 @@ export function GpsMapTab({ onShowRoute }: { onShowRoute: (assetId: number) => v
|
|||||||
lng: geo.lng,
|
lng: geo.lng,
|
||||||
kind: 'dot',
|
kind: 'dot',
|
||||||
color: '#8b5cf6',
|
color: '#8b5cf6',
|
||||||
label: t.title,
|
// Подпись — только при включённом режиме «Названия»
|
||||||
|
label: showLabels ? shortTitle(t.title) : undefined,
|
||||||
noCluster: true,
|
noCluster: true,
|
||||||
zIndex: 40,
|
zIndex: 40,
|
||||||
onClick: rulerMode ? undefined : () => setLocation(`/forms/${mapFormId}/tasks/${t.id}`),
|
onClick: rulerMode ? undefined : () => setLocation(`/forms/${mapFormId}/tasks/${t.id}`),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return markers;
|
return markers;
|
||||||
}, [tasksLayer, mapFieldId, tasksData, rulerMode, setLocation, mapFormId]);
|
}, [tasksLayer, mapFieldId, tasksData, rulerMode, setLocation, mapFormId, showLabels]);
|
||||||
|
|
||||||
// Правый клик по карте — создать объект выбранной формы с этими координатами
|
// Правый клик по карте — создать объект выбранной формы с этими координатами
|
||||||
const handleMapContextMenu = (lat: number, lng: number) => {
|
const handleMapContextMenu = (lat: number, lng: number) => {
|
||||||
@@ -339,6 +352,15 @@ export function GpsMapTab({ onShowRoute }: { onShowRoute: (assetId: number) => v
|
|||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
)}
|
)}
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant={showLabels ? 'default' : 'outline'}
|
||||||
|
className="h-7 text-xs"
|
||||||
|
onClick={() => setShowLabels((v) => !v)}
|
||||||
|
>
|
||||||
|
<Tag className="w-3.5 h-3.5 mr-1" />
|
||||||
|
Названия
|
||||||
|
</Button>
|
||||||
<span className="text-xs text-muted-foreground">
|
<span className="text-xs text-muted-foreground">
|
||||||
Правый клик по карте — новый объект здесь
|
Правый клик по карте — новый объект здесь
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user