114 lines
3.2 KiB
Dart
114 lines
3.2 KiB
Dart
// lib/screens/map_screen.dart
|
||
import 'dart:math';
|
||
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter_map/flutter_map.dart';
|
||
import 'package:latlong2/latlong.dart';
|
||
|
||
import '../theme/gradient_scaffold.dart';
|
||
|
||
class MapScreen extends StatefulWidget {
|
||
final Map<String, String> job;
|
||
|
||
const MapScreen({super.key, required this.job});
|
||
|
||
@override
|
||
State<MapScreen> createState() => _MapScreenState();
|
||
}
|
||
|
||
class _MapScreenState extends State<MapScreen> {
|
||
late final MapController _mapController;
|
||
late LatLng _jobPos;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_mapController = MapController();
|
||
_jobPos = _randomLatLngInFrance();
|
||
}
|
||
|
||
LatLng _randomLatLngInFrance() {
|
||
final rng = Random();
|
||
final lat = 43 + rng.nextDouble() * 8; // 43-51 °N
|
||
final lng = -1 + rng.nextDouble() * 8; // -1–7 °E
|
||
return LatLng(lat, lng);
|
||
}
|
||
|
||
void _recenter() {
|
||
_mapController.move(_jobPos, 13);
|
||
}
|
||
|
||
void _faceNorth() {
|
||
_mapController.rotate(0); // 0° = nord en haut
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return GradientScaffold(
|
||
appBar: AppBar(title: Text(widget.job['company'] ?? 'Carte')),
|
||
body: Stack(
|
||
children: [
|
||
FlutterMap(
|
||
mapController: _mapController,
|
||
options: MapOptions(initialCenter: _jobPos, initialZoom: 13),
|
||
children: [
|
||
TileLayer(
|
||
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||
userAgentPackageName: 'fr.allbyte.swipejobs',
|
||
),
|
||
MarkerLayer(
|
||
markers: [
|
||
Marker(
|
||
point: _jobPos,
|
||
width: 40,
|
||
height: 40,
|
||
child: const Icon(
|
||
Icons.location_pin,
|
||
size: 40,
|
||
color: Colors.red,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
],
|
||
),
|
||
Positioned(
|
||
right: 12,
|
||
bottom: 24,
|
||
child: Column(
|
||
children: [
|
||
_roundBtn(Icons.my_location, _recenter, 'Recentrer'),
|
||
const SizedBox(height: 12),
|
||
_roundBtn(Icons.explore, _faceNorth, 'Nord en haut'),
|
||
const SizedBox(height: 12),
|
||
_roundBtn(Icons.zoom_in, () {
|
||
_mapController.move(
|
||
_mapController.camera.center,
|
||
_mapController.camera.zoom + 1,
|
||
);
|
||
}, 'Zoom +'),
|
||
const SizedBox(height: 12),
|
||
_roundBtn(Icons.zoom_out, () {
|
||
_mapController.move(
|
||
_mapController.camera.center,
|
||
_mapController.camera.zoom - 1,
|
||
);
|
||
}, 'Zoom –'),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _roundBtn(IconData icon, VoidCallback onTap, String tooltip) {
|
||
return FloatingActionButton(
|
||
heroTag: tooltip,
|
||
mini: true,
|
||
backgroundColor: const Color(0xFF5B2E74),
|
||
onPressed: onTap,
|
||
child: Icon(icon, color: Colors.white),
|
||
);
|
||
}
|
||
}
|