Kapcsolat hozzáadása koordinátával a terepbejárás térképen.
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 6s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 6s
This commit is contained in:
@@ -1,6 +1 @@
|
|||||||
enum MapEditTool {
|
enum MapEditTool { none, point, line, polygon, contact }
|
||||||
none,
|
|
||||||
point,
|
|
||||||
line,
|
|
||||||
polygon,
|
|
||||||
}
|
|
||||||
|
|||||||
+34
-3
@@ -14,8 +14,17 @@ class Contact {
|
|||||||
final String email;
|
final String email;
|
||||||
final String note;
|
final String note;
|
||||||
final String? createdBy;
|
final String? createdBy;
|
||||||
|
|
||||||
final DateTime? updatedAt;
|
final DateTime? updatedAt;
|
||||||
|
|
||||||
|
/// Opcionális helyszín — WGS84 (lat/lon) és EOV (eovY/eovX) is tárolva,
|
||||||
|
/// akárcsak a többi geometria-típusnál. Csak akkor van kitöltve, ha a
|
||||||
|
/// térképi "Kapcsolat" eszközzel vették fel, vagy utólag hozzárendelték.
|
||||||
|
final double? lat;
|
||||||
|
final double? lon;
|
||||||
|
final double? eovY;
|
||||||
|
final double? eovX;
|
||||||
|
|
||||||
const Contact({
|
const Contact({
|
||||||
this.id,
|
this.id,
|
||||||
required this.projectId,
|
required this.projectId,
|
||||||
@@ -26,15 +35,25 @@ class Contact {
|
|||||||
this.note = '',
|
this.note = '',
|
||||||
this.createdBy,
|
this.createdBy,
|
||||||
this.updatedAt,
|
this.updatedAt,
|
||||||
|
this.lat,
|
||||||
|
this.lon,
|
||||||
|
this.eovY,
|
||||||
|
this.eovX,
|
||||||
});
|
});
|
||||||
|
|
||||||
Contact copyWith({
|
bool get hasLocation => lat != null && lon != null;
|
||||||
String? name,
|
|
||||||
|
Contact copyWith(
|
||||||
|
{String? name,
|
||||||
String? address,
|
String? address,
|
||||||
String? phone,
|
String? phone,
|
||||||
String? email,
|
String? email,
|
||||||
String? note,
|
String? note,
|
||||||
}) =>
|
double? lat,
|
||||||
|
double? lon,
|
||||||
|
double? eovY,
|
||||||
|
double? eovX,
|
||||||
|
bool clearLocation = false}) =>
|
||||||
Contact(
|
Contact(
|
||||||
id: id,
|
id: id,
|
||||||
projectId: projectId,
|
projectId: projectId,
|
||||||
@@ -45,6 +64,10 @@ class Contact {
|
|||||||
note: note ?? this.note,
|
note: note ?? this.note,
|
||||||
createdBy: createdBy,
|
createdBy: createdBy,
|
||||||
updatedAt: updatedAt,
|
updatedAt: updatedAt,
|
||||||
|
lat: clearLocation ? null : (lat ?? this.lat),
|
||||||
|
lon: clearLocation ? null : (lon ?? this.lon),
|
||||||
|
eovX: clearLocation ? null : (eovX ?? this.eovX),
|
||||||
|
eovY: clearLocation ? null : (eovY ?? this.eovY),
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Beszúráshoz/frissítéshez — az id-t csak akkor küldjük, ha van
|
/// Beszúráshoz/frissítéshez — az id-t csak akkor küldjük, ha van
|
||||||
@@ -58,6 +81,10 @@ class Contact {
|
|||||||
'phone': phone.trim(),
|
'phone': phone.trim(),
|
||||||
'email': email.trim(),
|
'email': email.trim(),
|
||||||
'note': note.trim(),
|
'note': note.trim(),
|
||||||
|
'lat': lat,
|
||||||
|
'lon': lon,
|
||||||
|
'eov_y': eovY,
|
||||||
|
'eov_x': eovX,
|
||||||
};
|
};
|
||||||
|
|
||||||
factory Contact.fromMap(Map<String, dynamic> m) => Contact(
|
factory Contact.fromMap(Map<String, dynamic> m) => Contact(
|
||||||
@@ -72,5 +99,9 @@ class Contact {
|
|||||||
updatedAt: m['updated_at'] != null
|
updatedAt: m['updated_at'] != null
|
||||||
? DateTime.tryParse(m['updated_at'] as String)
|
? DateTime.tryParse(m['updated_at'] as String)
|
||||||
: null,
|
: null,
|
||||||
|
lat: (m['lat'] as num?)?.toDouble(),
|
||||||
|
lon: (m['lon'] as num?)?.toDouble(),
|
||||||
|
eovY: (m['eov_y'] as num?)?.toDouble(),
|
||||||
|
eovX: (m['eov_x'] as num?)?.toDouble(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ class _ContactEditViewState extends State<ContactEditView> {
|
|||||||
late final TextEditingController _note;
|
late final TextEditingController _note;
|
||||||
|
|
||||||
bool _saving = false;
|
bool _saving = false;
|
||||||
|
late double? _lat;
|
||||||
|
late double? _lon;
|
||||||
|
late double? _eovY;
|
||||||
|
late double? _eovX;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -43,6 +47,10 @@ class _ContactEditViewState extends State<ContactEditView> {
|
|||||||
_phone = TextEditingController(text: _original?.phone ?? '');
|
_phone = TextEditingController(text: _original?.phone ?? '');
|
||||||
_email = TextEditingController(text: _original?.email ?? '');
|
_email = TextEditingController(text: _original?.email ?? '');
|
||||||
_note = TextEditingController(text: _original?.note ?? '');
|
_note = TextEditingController(text: _original?.note ?? '');
|
||||||
|
_lat = _original?.lat;
|
||||||
|
_lon = _original?.lon;
|
||||||
|
_eovY = _original?.eovY;
|
||||||
|
_eovX = _original?.eovX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -69,7 +77,13 @@ class _ContactEditViewState extends State<ContactEditView> {
|
|||||||
phone: _phone.text,
|
phone: _phone.text,
|
||||||
email: _email.text,
|
email: _email.text,
|
||||||
note: _note.text,
|
note: _note.text,
|
||||||
|
lat: _lat,
|
||||||
|
lon: _lon,
|
||||||
|
eovY: _eovY,
|
||||||
|
eovX: _eovX,
|
||||||
|
clearLocation: _lat == null,
|
||||||
);
|
);
|
||||||
|
|
||||||
final queued = await ContactService.to.save(contact);
|
final queued = await ContactService.to.save(contact);
|
||||||
Get.back(result: queued); // a lista frissítéshez visszakapja
|
Get.back(result: queued); // a lista frissítéshez visszakapja
|
||||||
if (Get.isRegistered<ContactsController>()) {
|
if (Get.isRegistered<ContactsController>()) {
|
||||||
@@ -182,6 +196,27 @@ class _ContactEditViewState extends State<ContactEditView> {
|
|||||||
alignLabelWithHint: true,
|
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),
|
const SizedBox(height: 24),
|
||||||
FilledButton.icon(
|
FilledButton.icon(
|
||||||
onPressed: _saving ? null : _save,
|
onPressed: _saving ? null : _save,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'dart:math';
|
|||||||
//import 'dart:math' as math;
|
//import 'dart:math' as math;
|
||||||
|
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_map/flutter_map.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/enums/note_type.dart';
|
||||||
import 'package:terepi_seged/eov/convert_coordinate.dart';
|
import 'package:terepi_seged/eov/convert_coordinate.dart';
|
||||||
import 'package:terepi_seged/eov/eov.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/measured_point.dart';
|
||||||
import 'package:terepi_seged/models/note_item.dart';
|
import 'package:terepi_seged/models/note_item.dart';
|
||||||
import 'package:terepi_seged/models/point_to_measure.dart';
|
import 'package:terepi_seged/models/point_to_measure.dart';
|
||||||
import 'package:terepi_seged/models/point_with_description_model.dart';
|
import 'package:terepi_seged/models/point_with_description_model.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.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/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/controllers/ntrip_settings_controller.dart';
|
||||||
import 'package:terepi_seged/pages/ntrip_settings/presentation/views/ntrip_settings_sheet.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/pages/tracking/presentation/controllers/tracking_controller.dart';
|
||||||
import 'package:terepi_seged/services/app_database.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/coord_converter_service.dart';
|
||||||
import 'package:terepi_seged/services/device_identity_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_connection.dart';
|
||||||
import 'package:terepi_seged/services/gnss/gnss_device_service.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/gnss/gnss_service.dart';
|
||||||
import 'package:terepi_seged/services/ntrip_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/project_service.dart';
|
||||||
import 'package:terepi_seged/services/stakeout_service.dart';
|
import 'package:terepi_seged/services/stakeout_service.dart';
|
||||||
import 'package:terepi_seged/widgets/map/all_layer_overlay.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.point:
|
||||||
|
case MapEditTool.contact:
|
||||||
case MapEditTool.none:
|
case MapEditTool.none:
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -300,10 +306,14 @@ class MapSurveyController extends GetxController implements StyleEditable {
|
|||||||
|
|
||||||
gpsHeightController.text = '1.8';
|
gpsHeightController.text = '1.8';
|
||||||
|
|
||||||
ever(ProjectService.to.activeProject, (_) => _loadNoteItems());
|
ever(ProjectService.to.activeProject, (_) {
|
||||||
|
_loadNoteItems();
|
||||||
|
_loadContactMarkers();
|
||||||
|
});
|
||||||
|
|
||||||
await _loadNoteItems();
|
await _loadNoteItems();
|
||||||
await _loadMeasurePoints();
|
await _loadMeasurePoints();
|
||||||
|
await _loadContactMarkers();
|
||||||
|
|
||||||
_subscribeToTeamPosition();
|
_subscribeToTeamPosition();
|
||||||
}
|
}
|
||||||
@@ -1088,6 +1098,8 @@ class MapSurveyController extends GetxController implements StyleEditable {
|
|||||||
return Icons.polyline_outlined;
|
return Icons.polyline_outlined;
|
||||||
case MapEditTool.polygon:
|
case MapEditTool.polygon:
|
||||||
return Icons.border_outer_outlined;
|
return Icons.border_outer_outlined;
|
||||||
|
case MapEditTool.contact:
|
||||||
|
return Icons.person_pin_circle_outlined;
|
||||||
case MapEditTool.none:
|
case MapEditTool.none:
|
||||||
return Icons.edit_location_alt_outlined;
|
return Icons.edit_location_alt_outlined;
|
||||||
}
|
}
|
||||||
@@ -1101,6 +1113,8 @@ class MapSurveyController extends GetxController implements StyleEditable {
|
|||||||
return 'Vonal rögzítése';
|
return 'Vonal rögzítése';
|
||||||
case MapEditTool.polygon:
|
case MapEditTool.polygon:
|
||||||
return 'Terület rögzítése';
|
return 'Terület rögzítése';
|
||||||
|
case MapEditTool.contact:
|
||||||
|
return 'Kapcsolat hozzáadása';
|
||||||
case MapEditTool.none:
|
case MapEditTool.none:
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -1114,6 +1128,8 @@ class MapSurveyController extends GetxController implements StyleEditable {
|
|||||||
return 'Hosszan nyomj a térképre a töréspontokhoz';
|
return 'Hosszan nyomj a térképre a töréspontokhoz';
|
||||||
case MapEditTool.polygon:
|
case MapEditTool.polygon:
|
||||||
return 'Hosszan nyomj a térképre a sarokpontokhoz.';
|
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:
|
case MapEditTool.none:
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -1127,6 +1143,8 @@ class MapSurveyController extends GetxController implements StyleEditable {
|
|||||||
return editorPointCount >= 2;
|
return editorPointCount >= 2;
|
||||||
case MapEditTool.polygon:
|
case MapEditTool.polygon:
|
||||||
return editorPointCount >= 3;
|
return editorPointCount >= 3;
|
||||||
|
case MapEditTool.contact:
|
||||||
|
return false;
|
||||||
case MapEditTool.none:
|
case MapEditTool.none:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1140,6 +1158,8 @@ class MapSurveyController extends GetxController implements StyleEditable {
|
|||||||
return 'Kész';
|
return 'Kész';
|
||||||
case MapEditTool.polygon:
|
case MapEditTool.polygon:
|
||||||
return 'Lezárás';
|
return 'Lezárás';
|
||||||
|
case MapEditTool.contact:
|
||||||
|
return 'Kész';
|
||||||
case MapEditTool.none:
|
case MapEditTool.none:
|
||||||
return 'Kész';
|
return 'Kész';
|
||||||
}
|
}
|
||||||
@@ -1150,6 +1170,16 @@ class MapSurveyController extends GetxController implements StyleEditable {
|
|||||||
activeEditLabel.value = '';
|
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() {
|
void startLineTool() {
|
||||||
polygonEditorController.clear();
|
polygonEditorController.clear();
|
||||||
polygonEditorController.setMode(PolygonEditorMode.line);
|
polygonEditorController.setMode(PolygonEditorMode.line);
|
||||||
@@ -1207,6 +1237,87 @@ class MapSurveyController extends GetxController implements StyleEditable {
|
|||||||
//draftPoints.clear();
|
//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) {
|
Marker _markerFromNoteItem(NoteItem item) {
|
||||||
return Marker(
|
return Marker(
|
||||||
key: ValueKey('note_point_${item.id}'),
|
key: ValueKey('note_point_${item.id}'),
|
||||||
@@ -1730,6 +1841,7 @@ class MapSurveyController extends GetxController implements StyleEditable {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MapEditTool.point:
|
case MapEditTool.point:
|
||||||
|
case MapEditTool.contact:
|
||||||
case MapEditTool.none:
|
case MapEditTool.none:
|
||||||
draftLengthMeters.value = 0.0;
|
draftLengthMeters.value = 0.0;
|
||||||
draftAreaSquareMeters.value = 0.0;
|
draftAreaSquareMeters.value = 0.0;
|
||||||
|
|||||||
@@ -64,6 +64,10 @@ class MapSurveyView extends GetView<MapSurveyController> {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (controller.activeEditTool.value == MapEditTool.contact) {
|
||||||
|
controller.saveContactAtPoint(point);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (controller.activeEditTool.value == MapEditTool.line ||
|
if (controller.activeEditTool.value == MapEditTool.line ||
|
||||||
controller.activeEditTool.value == MapEditTool.polygon) {
|
controller.activeEditTool.value == MapEditTool.polygon) {
|
||||||
controller.polygonEditorController.addPoint(point);
|
controller.polygonEditorController.addPoint(point);
|
||||||
@@ -142,6 +146,13 @@ class MapSurveyView extends GetView<MapSurveyController> {
|
|||||||
|
|
||||||
return MarkerLayer(markers: [...controller.pointNotes]);
|
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(() {
|
Obx(() {
|
||||||
// Vonalak - terepbejárás
|
// Vonalak - terepbejárás
|
||||||
if (controller.mode.value != MapSurveyMode.fieldWalk) {
|
if (controller.mode.value != MapSurveyMode.fieldWalk) {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class AppDatabase {
|
|||||||
final path = p.join(dbDir.path, 'terepi_seged.db');
|
final path = p.join(dbDir.path, 'terepi_seged.db');
|
||||||
|
|
||||||
return openDatabase(path,
|
return openDatabase(path,
|
||||||
version: 6,
|
version: 7,
|
||||||
onConfigure: (db) => db.execute('PRAGMA foreign_keys = ON'),
|
onConfigure: (db) => db.execute('PRAGMA foreign_keys = ON'),
|
||||||
onCreate: _onCreate,
|
onCreate: _onCreate,
|
||||||
onUpgrade: _onUpgrade);
|
onUpgrade: _onUpgrade);
|
||||||
@@ -271,7 +271,9 @@ class AppDatabase {
|
|||||||
|
|
||||||
await _createStakeoutTable(db);
|
await _createStakeoutTable(db);
|
||||||
await _createContactsOutbox(db);
|
await _createContactsOutbox(db);
|
||||||
|
|
||||||
await _addAppInstanceIdColumns(db);
|
await _addAppInstanceIdColumns(db);
|
||||||
|
await _addContactLocationColumns(db);
|
||||||
|
|
||||||
await _createVibratorNavTables(db);
|
await _createVibratorNavTables(db);
|
||||||
|
|
||||||
@@ -312,6 +314,7 @@ class AppDatabase {
|
|||||||
|
|
||||||
await _addAppInstanceIdColumns(db);
|
await _addAppInstanceIdColumns(db);
|
||||||
await _createVibratorNavTables(db);
|
await _createVibratorNavTables(db);
|
||||||
|
await _addContactLocationColumns(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _migrateToV4(Database db) async {
|
Future<void> _migrateToV4(Database db) async {
|
||||||
@@ -1327,6 +1330,10 @@ class AppDatabase {
|
|||||||
phone TEXT NOT NULL DEFAULT '',
|
phone TEXT NOT NULL DEFAULT '',
|
||||||
email TEXT NOT NULL DEFAULT '',
|
email TEXT NOT NULL DEFAULT '',
|
||||||
note TEXT NOT NULL DEFAULT '',
|
note TEXT NOT NULL DEFAULT '',
|
||||||
|
lat REAL,
|
||||||
|
lon REAL,
|
||||||
|
eov_y REAL,
|
||||||
|
eov_x REAL,
|
||||||
created_at TEXT NOT NULL
|
created_at TEXT NOT NULL
|
||||||
)
|
)
|
||||||
''');
|
''');
|
||||||
@@ -1334,6 +1341,14 @@ class AppDatabase {
|
|||||||
'ON contacts_outbox(project_id)');
|
'ON contacts_outbox(project_id)');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Idempotens oszlop-pótlás, ha a contacts_outbox már létezik (korábbi
|
||||||
|
/// telepítéseknél) — ugyanaz a minta, mint az app_instance_id-nél.
|
||||||
|
Future<void> _addContactLocationColumns(Database db) async {
|
||||||
|
for (final col in ['lat', 'lon', 'eov_y', 'eov_x']) {
|
||||||
|
await _tryExec(db, 'ALTER TABLE contacts_outbox ADD COLUMN $col REAL');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> insertPendingContact(Map<String, dynamic> row) async {
|
Future<void> insertPendingContact(Map<String, dynamic> row) async {
|
||||||
final db = await database;
|
final db = await database;
|
||||||
await db.insert('contacts_outbox', row);
|
await db.insert('contacts_outbox', row);
|
||||||
|
|||||||
@@ -108,6 +108,10 @@ class ContactService extends GetxService {
|
|||||||
'phone': c.phone.trim(),
|
'phone': c.phone.trim(),
|
||||||
'email': c.email.trim(),
|
'email': c.email.trim(),
|
||||||
'note': c.note.trim(),
|
'note': c.note.trim(),
|
||||||
|
'lat': c.lat,
|
||||||
|
'lon': c.lon,
|
||||||
|
'eov_y': c.eovY,
|
||||||
|
'eov_x': c.eovX,
|
||||||
'created_at': DateTime.now().toIso8601String(),
|
'created_at': DateTime.now().toIso8601String(),
|
||||||
});
|
});
|
||||||
return true; // várólistán
|
return true; // várólistán
|
||||||
@@ -160,6 +164,10 @@ class ContactService extends GetxService {
|
|||||||
'phone': m['phone'],
|
'phone': m['phone'],
|
||||||
'email': m['email'],
|
'email': m['email'],
|
||||||
'note': m['note'],
|
'note': m['note'],
|
||||||
|
'lat': m['lat'],
|
||||||
|
'lon': m['lon'],
|
||||||
|
'eov_y': m['eov_y'],
|
||||||
|
'eov_x': m['eov_x'],
|
||||||
}, onConflict: 'client_uuid', ignoreDuplicates: true);
|
}, onConflict: 'client_uuid', ignoreDuplicates: true);
|
||||||
|
|
||||||
// Sikeres felküldés → a lokális példány törölhető.
|
// Sikeres felküldés → a lokális példány törölhető.
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class LabelFieldState extends State<LabelField> {
|
|||||||
MapEditTool.point => 'Pont neve...',
|
MapEditTool.point => 'Pont neve...',
|
||||||
MapEditTool.line => 'Vonal neve...',
|
MapEditTool.line => 'Vonal neve...',
|
||||||
MapEditTool.polygon => 'Terület neve...',
|
MapEditTool.polygon => 'Terület neve...',
|
||||||
|
MapEditTool.contact => 'Felirat ...',
|
||||||
MapEditTool.none => 'Felirat...',
|
MapEditTool.none => 'Felirat...',
|
||||||
};
|
};
|
||||||
return Column(
|
return Column(
|
||||||
|
|||||||
@@ -116,6 +116,8 @@ class LineOrPolygonDrawingContent extends StatelessWidget {
|
|||||||
return 'min. 3';
|
return 'min. 3';
|
||||||
case MapEditTool.point:
|
case MapEditTool.point:
|
||||||
return '1 pont';
|
return '1 pont';
|
||||||
|
case MapEditTool.contact:
|
||||||
|
return '';
|
||||||
case MapEditTool.none:
|
case MapEditTool.none:
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:terepi_seged/enums/map_edit_tool.dart';
|
import 'package:terepi_seged/enums/map_edit_tool.dart';
|
||||||
import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart';
|
import 'package:terepi_seged/pages/map_survey/presentations/controllers/map_survey_controller.dart';
|
||||||
|
import 'package:terepi_seged/services/permission_service.dart';
|
||||||
|
|
||||||
import 'map_toolbar_action.dart';
|
import 'map_toolbar_action.dart';
|
||||||
import 'map_toolbar_divider.dart';
|
import 'map_toolbar_divider.dart';
|
||||||
@@ -65,6 +66,13 @@ class MapEditCompactToolbar extends StatelessWidget {
|
|||||||
selected: activeTool == MapEditTool.polygon,
|
selected: activeTool == MapEditTool.polygon,
|
||||||
onTap: controller.startPolygonTool,
|
onTap: controller.startPolygonTool,
|
||||||
),
|
),
|
||||||
|
if (PermissionService.to.canContacts)
|
||||||
|
ToolbarAction(
|
||||||
|
icon: Icons.person_pin_circle_outlined,
|
||||||
|
label: 'Kapcsolat',
|
||||||
|
selected: activeTool == MapEditTool.contact,
|
||||||
|
onTap: controller.startContactTool,
|
||||||
|
),
|
||||||
const ToolbarDivider(),
|
const ToolbarDivider(),
|
||||||
ToolbarAction(
|
ToolbarAction(
|
||||||
icon: Icons.list_alt_outlined,
|
icon: Icons.list_alt_outlined,
|
||||||
@@ -72,12 +80,12 @@ class MapEditCompactToolbar extends StatelessWidget {
|
|||||||
selected: false,
|
selected: false,
|
||||||
onTap: () {},
|
onTap: () {},
|
||||||
),
|
),
|
||||||
ToolbarAction(
|
// ToolbarAction(
|
||||||
icon: Icons.layers_outlined,
|
// icon: Icons.layers_outlined,
|
||||||
label: 'Rétegek',
|
// label: 'Rétegek',
|
||||||
selected: false,
|
// selected: false,
|
||||||
onTap: () {},
|
// onTap: () {},
|
||||||
),
|
// ),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user