import 'dart:async'; import 'dart:typed_data'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:mapbox_maps_flutter/mapbox_maps_flutter.dart' as mapBox; import 'package:manager_api_new/api.dart'; import 'package:mymuseum_visitapp/Components/video_viewer_youtube.dart'; import 'package:mymuseum_visitapp/Models/agenda.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/constants.dart'; import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; import 'package:url_launcher/url_launcher.dart'; class EventPopup extends StatefulWidget { final EventAgenda eventAgenda; final MapProvider mapProvider; final Uint8List mapIcon; EventPopup({Key? key, required this.eventAgenda, required this.mapProvider, required this.mapIcon}) : super(key: key); @override State createState() => _EventPopupState(); } class _EventPopupState extends State { final DateFormat formatter = DateFormat('dd/MM/yyyy hh:mm'); Completer _controller = Completer(); Set markers = {}; bool init = false; mapBox.MapboxMap? mapboxMap; mapBox.PointAnnotationManager? pointAnnotationManager; Set getMarkers() { markers = {}; if (widget.eventAgenda.address!.lat != null && widget.eventAgenda.address!.lng != null) { markers.add(Marker( draggable: false, markerId: MarkerId(widget.eventAgenda.address!.lat.toString() + widget.eventAgenda.address!.lng.toString()), position: LatLng( double.parse(widget.eventAgenda.address!.lat!.toString()), double.parse(widget.eventAgenda.address!.lng!.toString()), ), icon: BitmapDescriptor.defaultMarker, infoWindow: InfoWindow.noText)); } return markers; } _onMapCreated(mapBox.MapboxMap mapboxMap, Uint8List icon) { this.mapboxMap = mapboxMap; mapboxMap.annotations.createPointAnnotationManager().then((pointAnnotationManager) async { this.pointAnnotationManager = pointAnnotationManager; pointAnnotationManager.createMulti(createPoints(LatLng(double.parse(widget.eventAgenda.address!.lat!.toString()), double.parse(widget.eventAgenda.address!.lng!.toString())), icon)); init = true; }); } createPoints(LatLng position, Uint8List icon) { var options = []; options.add(mapBox.PointAnnotationOptions( geometry: mapBox.Point( coordinates: mapBox.Position( position.longitude, position.latitude, )), // .toJson() iconSize: 1.3, iconOffset: [0.0, 0.0], symbolSortKey: 10, iconColor: 0, iconImage: null, image: icon, //widget.selectedMarkerIcon, )); print(options.length); return options; } Future openEmail(String email) async { final Uri emailLaunchUri = Uri( scheme: 'mailto', path: email, ); try { await launchUrl(emailLaunchUri, mode: LaunchMode.externalApplication); } catch (e) { print('Erreur lors de l\'ouverture de l\'email: $e'); } } Future openPhone(String phone) async { final Uri phoneLaunchUri = Uri( scheme: 'tel', path: phone, ); try { await launchUrl(phoneLaunchUri, mode: LaunchMode.externalApplication); } catch (e) { print('Erreur lors de l\'ouverture de l\'email: $e'); } } @override Widget build(BuildContext context) { final appContext = Provider.of(context); VisitAppContext visitAppContext = appContext.getContext(); var dateToShow = widget.eventAgenda.dateFrom!.isAtSameMomentAs(widget.eventAgenda.dateTo!) ? "${formatter.format(widget.eventAgenda.dateFrom!)}": "${formatter.format(widget.eventAgenda.dateFrom!)} - ${formatter.format(widget.eventAgenda.dateTo!)}"; Size size = MediaQuery.of(context).size; if(!init) { print("getmarkers in build"); getMarkers(); init = true; } return Dialog( insetPadding: const EdgeInsets.all(4.0), shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)) ), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), color: kBackgroundColor, ), height: size.height * 0.92, width: size.width * 0.95, child: Stack( children: [ ClipRRect( borderRadius: BorderRadius.only(topLeft: Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0), topRight: Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), child: Stack( children: [ Container( decoration: BoxDecoration( boxShadow: const [ BoxShadow( color: kMainGrey, spreadRadius: 0.5, blurRadius: 5, offset: Offset(0, 1), // changes position of shadow ), ], gradient: const LinearGradient( begin: Alignment.centerRight, end: Alignment.centerLeft, colors: [ kMainColor0, kMainColor1, kMainColor2, ], ), border: const Border(right: BorderSide(width: 0.05, color: kMainGrey)), color: Colors.grey, image: widget.eventAgenda.image != null ? DecorationImage( fit: BoxFit.cover, opacity: 0.4, image: NetworkImage( widget.eventAgenda.image!, ), ): null ), width: size.width, height: 125, child: Padding( padding: const EdgeInsets.only(left: 10, right: 10, top: 4), child: Center( child: HtmlWidget( '
${widget.eventAgenda.name!}
', textStyle: const TextStyle(fontSize: 20.0, color: Colors.white), customStylesBuilder: (element) { return {'text-align': 'center', 'font-family': "Roboto", '-webkit-line-clamp': "2"}; }, ), ), ), ), ], ), ), Padding( padding: const EdgeInsets.only(top: 125), child: SingleChildScrollView( child: IntrinsicHeight( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0), child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: kSecondColor.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), ), child: Center( child: Wrap( crossAxisAlignment: WrapCrossAlignment.center, spacing: 6.0, children: [ const Icon(Icons.calendar_today_rounded, color: kSecondColor, size: 18), Text( dateToShow, style: const TextStyle( fontSize: 16, color: kSecondColor, fontWeight: FontWeight.w600, ), ), ], ), ), ), ), Padding( padding: const EdgeInsets.all(8), child: Container( constraints: BoxConstraints(minHeight: 250, maxHeight: size.height * 0.38), width: size.width, decoration: BoxDecoration( color: kBackgroundLight, borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)) ), child: Padding( padding: const EdgeInsets.only(left: 20, right: 10, bottom: 10, top: 15), child: Scrollbar( thumbVisibility: true, thickness: 2.0, child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ HtmlWidget( widget.eventAgenda.description!, customStylesBuilder: (element) { return {'text-align': 'left', 'font-family': "Roboto"}; }, textStyle: const TextStyle(fontSize: 15.0), ), widget.eventAgenda.idVideoYoutube != null && widget.eventAgenda.idVideoYoutube!.isNotEmpty ? Padding( padding: const EdgeInsets.all(8.0), child: SizedBox( height: 250, width: 350, child: VideoViewerYoutube(videoUrl: "https://www.youtube.com/watch?v=${widget.eventAgenda.idVideoYoutube}", isAuto: false, webView: true) ), ) : SizedBox(), ], ), ), ), ), ), ), ), Expanded( child: Padding( padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ widget.eventAgenda.address!.lat != null && widget.eventAgenda.address!.lng != null ? SizedBox( width: size.width, height: size.height * 0.2, child: widget.mapProvider == MapProvider.Google ? ClipRRect( borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), child: GoogleMap( mapToolbarEnabled: false, initialCameraPosition: CameraPosition( target: LatLng(double.parse(widget.eventAgenda.address!.lat!.toString()), double.parse(widget.eventAgenda.address!.lng!.toString())), zoom: 14, ), onMapCreated: (GoogleMapController controller) { _controller.complete(controller); }, markers: markers, ), ) : ClipRRect( borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), child: mapBox.MapWidget( key: ValueKey("mapBoxWidget"), styleUri: mapBox.MapboxStyles.STANDARD, onMapCreated: (maBoxMap) { _onMapCreated(maBoxMap, widget.mapIcon); }, cameraOptions: mapBox.CameraOptions( center: mapBox.Point(coordinates: mapBox.Position(double.parse(widget.eventAgenda.address!.lng!.toString()), double.parse(widget.eventAgenda.address!.lat!.toString()))), // .toJson() zoom: 14 ), ), ), ): SizedBox(), widget.eventAgenda.address?.address != null && widget.eventAgenda.address!.address!.isNotEmpty ? GestureDetector( onTap: () async { final query = Uri.encodeComponent(widget.eventAgenda.address!.address!); final googleMapsUrl = Uri.parse("https://www.google.com/maps/search/?api=1&query=$query"); if (await canLaunchUrl(googleMapsUrl)) { await launchUrl(googleMapsUrl, mode: LaunchMode.externalApplication); } else { print("Impossible d'ouvrir Google Maps"); } }, child: Container( width: size.width, height: 60, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.location_on, size: 13, color: kMainColor), Padding( padding: const EdgeInsets.all(4.0), child: SizedBox( width: size.width * 0.7, child: AutoSizeText( textAlign: TextAlign.center, widget.eventAgenda.address!.address!, style: const TextStyle( fontSize: 12, color: kMainColor, //decoration: TextDecoration.underline, ), maxLines: 3, ), ), ) ], ), ), ) : const SizedBox(), widget.eventAgenda.phone != null && widget.eventAgenda.phone!.isNotEmpty ? SizedBox( width: size.width, height: 35, child: InkWell( onTap: () => openPhone(widget.eventAgenda.phone!), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.phone, size: 13, color: kMainColor), Padding( padding: const EdgeInsets.all(4.0), child: Text(widget.eventAgenda.phone!, style: TextStyle(fontSize: 12, color: kMainColor)), ), ], ), ), ) : SizedBox(), widget.eventAgenda.email != null && widget.eventAgenda.email!.isNotEmpty ? SizedBox( width: size.width, height: 35, child: InkWell( onTap: () => openEmail(widget.eventAgenda.email!), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.email, size: 13, color: kMainColor), Padding( padding: const EdgeInsets.all(4.0), child: AutoSizeText( widget.eventAgenda.email!, style: TextStyle(fontSize: 12, color: kMainColor), maxLines: 3 ), ) ], ), ), ) : SizedBox(), widget.eventAgenda.website != null && widget.eventAgenda.website!.isNotEmpty ? GestureDetector( onTap: () async { final url = Uri.parse(widget.eventAgenda.website!); if (await canLaunchUrl(url)) { await launchUrl(url, mode: LaunchMode.externalApplication); } else { // Optionnel : afficher une erreur print('Impossible d\'ouvrir le lien'); } }, child: SizedBox( width: size.width * 0.8, height: 35, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.public, size: 13, color: kMainColor), const SizedBox(width: 4), Flexible( child: AutoSizeText( textAlign: TextAlign.center, widget.eventAgenda.website!, style: const TextStyle( fontSize: 12, color: kMainColor, //decoration: TextDecoration.underline, ), maxLines: 3, overflow: TextOverflow.ellipsis, ), ), ], ), ), ) : const SizedBox(), ], ), ), ) ], ), ), ), ), Positioned( right: 4.5, top: 4.5, child: GestureDetector( onTap: () { setState(() { Navigator.of(context).pop(); }); }, child: Container( width: 50, height: 50, decoration: BoxDecoration( color: kMainColor.withValues(alpha: 0.55), shape: BoxShape.circle, ), child: const Icon( Icons.close, size: 25, color: Colors.white, ), ), ), ), ], ), ), ); } }