manager-app/lib/Components/geoloc_input_container.dart

222 lines
8.6 KiB
Dart

import 'package:manager_app/l10n/app_localizations.dart';
import 'package:flutter/material.dart';
import 'package:location_picker_flutter_map/location_picker_flutter_map.dart';
import 'package:manager_app/Components/common_loader.dart';
import 'package:manager_app/Components/message_notification.dart';
import 'package:manager_app/constants.dart';
/// Choix d'un point sur une carte.
///
/// Le champ affiche les coordonnées retenues au lieu d'un simple bouton
/// « Changer la localisation » : on voit ce qui est réglé sans ouvrir la carte.
/// Le dialogue reprend la coquille standard, et la carte occupe la hauteur
/// disponible au lieu d'un bloc de 350 px.
class GeolocInputContainer extends StatefulWidget {
final Color color;
final String label;
final LatLong? initialValue;
final ValueChanged<LatLong> onChanged;
final bool isSmall;
final double fontSize;
final double fontSizeText;
const GeolocInputContainer({
Key? key,
this.color = kSecond,
required this.label,
required this.initialValue,
required this.onChanged,
this.isSmall = false,
this.fontSize = 18,
this.fontSizeText = 20,
}) : super(key: key);
@override
State<GeolocInputContainer> createState() => _GeolocInputContainerState();
}
class _GeolocInputContainerState extends State<GeolocInputContainer> {
LatLong? localisation;
@override
Widget build(BuildContext context) {
final l = AppLocalizations.of(context)!;
localisation = widget.initialValue;
final current = localisation;
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(widget.label, style: kLabelField),
const SizedBox(height: kSpace2),
Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(kRadiusInput),
onTap: () => _openPicker(context),
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: kSpace4, vertical: kSpace3),
decoration: BoxDecoration(
color: kSurface2,
border: Border.all(color: kLine),
borderRadius: BorderRadius.circular(kRadiusInput),
),
child: Row(
children: [
const Icon(Icons.place_outlined, size: 15, color: kInk3),
const SizedBox(width: kSpace3),
Expanded(
child: Text(
current == null
? l.noLocationChosen
: "${current.latitude.toStringAsFixed(5)}, ${current.longitude.toStringAsFixed(5)}",
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 13,
color: current == null ? kInk3 : kInk,
fontStyle:
current == null ? FontStyle.italic : FontStyle.normal,
),
),
),
const SizedBox(width: kSpace3),
Text(l.change,
style: const TextStyle(
fontSize: 12.5,
fontWeight: FontWeight.w600,
color: kPrimaryColor)),
],
),
),
),
),
],
);
}
void _openPicker(BuildContext context) {
final size = MediaQuery.of(context).size;
showDialog(
context: context,
builder: (BuildContext context) {
final l = AppLocalizations.of(context)!;
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(kRadiusShell),
side: const BorderSide(color: kLine),
),
clipBehavior: Clip.antiAlias,
insetPadding:
const EdgeInsets.symmetric(horizontal: kSpace7, vertical: kSpace7),
child: SizedBox(
width: size.width * 0.75,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(
kSpace6, kSpace5, kSpace4, kSpace5),
child: Row(
children: [
Expanded(child: Text(widget.label, style: kTitleCard)),
IconButton(
icon: const Icon(Icons.close, size: 20, color: kInk3),
tooltip: l.cancel,
onPressed: () => Navigator.of(context).pop(),
),
],
),
),
const Divider(height: 1, thickness: 1, color: kLineSoft),
Flexible(
child: FlutterLocationPicker(
initZoom: 14,
initPosition: localisation == null
? LatLong(50.429333, 4.891434)
: LatLong(localisation!.latitude, localisation!.longitude),
minZoomLevel: 0,
maxZoomLevel: 17,
markerIcon: const Icon(
Icons.location_pin,
color: kPrimaryColor,
size: 50,
),
loadingWidget: CommonLoader(iconSize: 40.0),
searchBarHintColor: kPrimaryColor,
mapLoadingBackgroundColor: kSurface2,
zoomButtonsBackgroundColor: kPrimaryColor,
zoomButtonsColor: kWhite,
locationButtonBackgroundColor: kPrimaryColor,
locationButtonsColor: kWhite,
countryFilter: "be, fr",
trackMyPosition: false,
searchBarHintText: l.searchLocationHint,
searchBarTextColor: kInk,
searchBarBackgroundColor: kSurface,
showSelectLocationButton: true,
selectLocationButtonText: l.selectThisLocation,
selectedLocationButtonTextstyle:
const TextStyle(fontSize: 14, color: kPrimaryColor),
mapLanguage: 'fr',
onError: (e) => print(e),
selectLocationButtonLeadingIcon:
const Icon(Icons.check, color: kPrimaryColor),
onPicked: (pickedData) {
localisation = pickedData.latLong;
},
showContributorBadgeForOSM: false,
),
),
Container(
padding: const EdgeInsets.all(kSpace4),
decoration: const BoxDecoration(
color: kSurface2,
border: Border(top: BorderSide(color: kLineSoft)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(l.cancel,
style: const TextStyle(fontSize: 13, color: kInk2)),
),
const SizedBox(width: kSpace2),
FilledButton(
onPressed: () {
if (localisation != null) {
widget.onChanged(localisation!);
Navigator.of(context).pop();
} else {
showNotification(kPrimaryColor, kWhite,
l.noLocationChosen, context, null);
}
},
style: FilledButton.styleFrom(
backgroundColor: kPrimaryColor,
padding: const EdgeInsets.symmetric(
horizontal: kSpace5, vertical: kSpace3),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(kRadiusPill)),
),
child: Text(l.validate,
style: const TextStyle(
fontSize: 13, fontWeight: FontWeight.w600)),
),
],
),
),
],
),
),
);
},
);
}
}