Kapcsolat hozzáadása koordinátával a terepbejárás térképen.
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 6s

This commit is contained in:
2026-08-06 16:14:30 +02:00
parent 7f514da38f
commit 950c2f48f1
10 changed files with 239 additions and 21 deletions
@@ -33,6 +33,10 @@ class _ContactEditViewState extends State<ContactEditView> {
late final TextEditingController _note;
bool _saving = false;
late double? _lat;
late double? _lon;
late double? _eovY;
late double? _eovX;
@override
void initState() {
@@ -43,6 +47,10 @@ class _ContactEditViewState extends State<ContactEditView> {
_phone = TextEditingController(text: _original?.phone ?? '');
_email = TextEditingController(text: _original?.email ?? '');
_note = TextEditingController(text: _original?.note ?? '');
_lat = _original?.lat;
_lon = _original?.lon;
_eovY = _original?.eovY;
_eovX = _original?.eovX;
}
@override
@@ -69,7 +77,13 @@ class _ContactEditViewState extends State<ContactEditView> {
phone: _phone.text,
email: _email.text,
note: _note.text,
lat: _lat,
lon: _lon,
eovY: _eovY,
eovX: _eovX,
clearLocation: _lat == null,
);
final queued = await ContactService.to.save(contact);
Get.back(result: queued); // a lista frissítéshez visszakapja
if (Get.isRegistered<ContactsController>()) {
@@ -182,6 +196,27 @@ class _ContactEditViewState extends State<ContactEditView> {
alignLabelWithHint: true,
),
),
const SizedBox(height: 12),
if (_lat != null && _lon != null)
Card(
color: Colors.indigo.withOpacity(0.06),
child: ListTile(
leading: const Icon(Icons.location_on, color: Colors.indigo),
title: Text(
'${_lat!.toStringAsFixed(6)}, ${_lon!.toStringAsFixed(6)}'),
subtitle: const Text('Helyszín rögzítve'),
trailing: IconButton(
icon: const Icon(Icons.close),
tooltip: 'Helyszín törlése',
onPressed: () => setState(() {
_lat = null;
_lon = null;
_eovY = null;
_eovX = null;
}),
),
),
),
const SizedBox(height: 24),
FilledButton.icon(
onPressed: _saving ? null : _save,
@@ -5,6 +5,7 @@ import 'dart:math';
//import 'dart:math' as math;
import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_map/flutter_map.dart';
@@ -31,22 +32,26 @@ import 'package:terepi_seged/enums/map_survey_mode.dart';
import 'package:terepi_seged/enums/note_type.dart';
import 'package:terepi_seged/eov/convert_coordinate.dart';
import 'package:terepi_seged/eov/eov.dart';
import 'package:terepi_seged/models/contact.dart';
import 'package:terepi_seged/models/measured_point.dart';
import 'package:terepi_seged/models/note_item.dart';
import 'package:terepi_seged/models/point_to_measure.dart';
import 'package:terepi_seged/models/point_with_description_model.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:terepi_seged/pages/contacts/presentation/views/contact_edit_view.dart';
import 'package:terepi_seged/pages/map_survey/presentations/views/measured_points_table_dialog.dart';
import 'package:terepi_seged/pages/ntrip_settings/presentation/controllers/ntrip_settings_controller.dart';
import 'package:terepi_seged/pages/ntrip_settings/presentation/views/ntrip_settings_sheet.dart';
import 'package:terepi_seged/pages/tracking/presentation/controllers/tracking_controller.dart';
import 'package:terepi_seged/services/app_database.dart';
import 'package:terepi_seged/services/contact_service.dart';
import 'package:terepi_seged/services/coord_converter_service.dart';
import 'package:terepi_seged/services/device_identity_service.dart';
import 'package:terepi_seged/services/gnss/gnss_connection.dart';
import 'package:terepi_seged/services/gnss/gnss_device_service.dart';
import 'package:terepi_seged/services/gnss/gnss_service.dart';
import 'package:terepi_seged/services/ntrip_service.dart';
import 'package:terepi_seged/services/permission_service.dart';
import 'package:terepi_seged/services/project_service.dart';
import 'package:terepi_seged/services/stakeout_service.dart';
import 'package:terepi_seged/widgets/map/all_layer_overlay.dart';
@@ -237,6 +242,7 @@ class MapSurveyController extends GetxController implements StyleEditable {
);
case MapEditTool.point:
case MapEditTool.contact:
case MapEditTool.none:
return '';
}
@@ -300,10 +306,14 @@ class MapSurveyController extends GetxController implements StyleEditable {
gpsHeightController.text = '1.8';
ever(ProjectService.to.activeProject, (_) => _loadNoteItems());
ever(ProjectService.to.activeProject, (_) {
_loadNoteItems();
_loadContactMarkers();
});
await _loadNoteItems();
await _loadMeasurePoints();
await _loadContactMarkers();
_subscribeToTeamPosition();
}
@@ -1088,6 +1098,8 @@ class MapSurveyController extends GetxController implements StyleEditable {
return Icons.polyline_outlined;
case MapEditTool.polygon:
return Icons.border_outer_outlined;
case MapEditTool.contact:
return Icons.person_pin_circle_outlined;
case MapEditTool.none:
return Icons.edit_location_alt_outlined;
}
@@ -1101,6 +1113,8 @@ class MapSurveyController extends GetxController implements StyleEditable {
return 'Vonal rögzítése';
case MapEditTool.polygon:
return 'Terület rögzítése';
case MapEditTool.contact:
return 'Kapcsolat hozzáadása';
case MapEditTool.none:
return '';
}
@@ -1114,6 +1128,8 @@ class MapSurveyController extends GetxController implements StyleEditable {
return 'Hosszan nyomj a térképre a töréspontokhoz';
case MapEditTool.polygon:
return 'Hosszan nyomj a térképre a sarokpontokhoz.';
case MapEditTool.contact:
return 'Hosszan nyomj a térképre a kapcsolat helyéhez.';
case MapEditTool.none:
return '';
}
@@ -1127,6 +1143,8 @@ class MapSurveyController extends GetxController implements StyleEditable {
return editorPointCount >= 2;
case MapEditTool.polygon:
return editorPointCount >= 3;
case MapEditTool.contact:
return false;
case MapEditTool.none:
return false;
}
@@ -1140,6 +1158,8 @@ class MapSurveyController extends GetxController implements StyleEditable {
return 'Kész';
case MapEditTool.polygon:
return 'Lezárás';
case MapEditTool.contact:
return 'Kész';
case MapEditTool.none:
return 'Kész';
}
@@ -1150,6 +1170,16 @@ class MapSurveyController extends GetxController implements StyleEditable {
activeEditLabel.value = '';
}
void startContactTool() {
if (!PermissionService.to.canContacts) {
Get.snackbar(
'Nincs jogosultság', 'Kapcsolatok kezeléséhez jogosultság szükséges.',
snackPosition: SnackPosition.BOTTOM);
return;
}
activeEditTool.value = MapEditTool.contact;
}
void startLineTool() {
polygonEditorController.clear();
polygonEditorController.setMode(PolygonEditorMode.line);
@@ -1207,6 +1237,87 @@ class MapSurveyController extends GetxController implements StyleEditable {
//draftPoints.clear();
}
// ── Kapcsolatok a térképen ──────────────────────────────────────────
final contactMarkers = <Marker>[].obs;
Future<void> saveContactAtPoint(LatLng point) async {
activeEditTool.value = MapEditTool.none;
if (!PermissionService.to.canContacts) return;
final projectId = ProjectService.to.activeProject.value?.uuid;
if (projectId == null) return;
final eov = CoordConverterService.to.wgsToEovPoint(
point.longitude,
point.latitude,
);
final draft = Contact(
projectId: projectId,
name: '',
lat: point.latitude,
lon: point.longitude,
eovY: eov.x,
eovX: eov.y,
);
final result =
await Get.to(() => const ContactEditView(), arguments: draft);
if (result != null) {
await _loadContactMarkers();
}
}
Future<void> _loadContactMarkers() async {
if (!PermissionService.to.canContacts) {
contactMarkers.clear();
return;
}
final projectId = ProjectService.to.activeProject.value?.uuid;
if (projectId == null) {
contactMarkers.clear();
return;
}
try {
final all = await ContactService.to.listMerged(projectId);
contactMarkers.value = all
.where((c) => c.contact.hasLocation)
.map(_markerFromContact)
.toList();
} catch (_) {
// Offline/hiba: a meglévő jelölők maradnak, nem törli ki csendben.
}
}
Marker _markerFromContact(ContactWithState c) {
return Marker(
key: ValueKey('contact_${c.contact.id ?? c.localUuid}'),
point: LatLng(c.contact.lat!, c.contact.lon!),
width: 34,
height: 34,
child: GestureDetector(
onTap: () async {
final result =
await Get.to(() => const ContactEditView(), arguments: c.contact);
if (result != null) await _loadContactMarkers();
},
child: Container(
decoration: BoxDecoration(
color: c.isPending ? Colors.orange : Colors.indigo,
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 2),
boxShadow: const [
BoxShadow(color: Colors.black26, blurRadius: 4),
],
),
child: const Icon(Icons.person, color: Colors.white, size: 20),
),
),
);
}
Marker _markerFromNoteItem(NoteItem item) {
return Marker(
key: ValueKey('note_point_${item.id}'),
@@ -1730,6 +1841,7 @@ class MapSurveyController extends GetxController implements StyleEditable {
break;
case MapEditTool.point:
case MapEditTool.contact:
case MapEditTool.none:
draftLengthMeters.value = 0.0;
draftAreaSquareMeters.value = 0.0;
@@ -64,6 +64,10 @@ class MapSurveyView extends GetView<MapSurveyController> {
}
return;
}
if (controller.activeEditTool.value == MapEditTool.contact) {
controller.saveContactAtPoint(point);
return;
}
if (controller.activeEditTool.value == MapEditTool.line ||
controller.activeEditTool.value == MapEditTool.polygon) {
controller.polygonEditorController.addPoint(point);
@@ -142,6 +146,13 @@ class MapSurveyView extends GetView<MapSurveyController> {
return MarkerLayer(markers: [...controller.pointNotes]);
}),
Obx(() {
// Kapcsolatok - terepi bejárás
if (controller.mode.value != MapSurveyMode.fieldWalk) {
return const SizedBox.shrink();
}
return MarkerLayer(markers: [...controller.contactMarkers]);
}),
Obx(() {
// Vonalak - terepbejárás
if (controller.mode.value != MapSurveyMode.fieldWalk) {