import 'package:auto_size_text/auto_size_text.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:carousel_slider/carousel_slider.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:manager_api_new/api.dart'; import 'package:mymuseum_visitapp/Components/loading_common.dart'; import 'package:mymuseum_visitapp/Components/show_element_for_resource.dart'; import 'package:mymuseum_visitapp/Helpers/ImageCustomProvider.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:photo_view/photo_view.dart'; import 'package:provider/provider.dart'; import 'package:html/parser.dart' show parse; import '../../../constants.dart'; import 'map_context.dart'; class MarkerViewWidget extends StatefulWidget { const MarkerViewWidget({super.key}); @override _MarkerInfoWidget createState() => _MarkerInfoWidget(); } class _MarkerInfoWidget extends State { CarouselSliderController? sliderController; ValueNotifier currentIndex = ValueNotifier(1); @override void initState() { sliderController = CarouselSliderController(); super.initState(); } @override void dispose() { sliderController = null; super.dispose(); } @override Widget build(BuildContext context) { int breakPointPrice = 50; Size size = MediaQuery.of(context).size; final mapContext = Provider.of(context); final appContext = Provider.of(context); VisitAppContext visitAppContext = appContext.getContext() as VisitAppContext; var language = visitAppContext.language; GeoPointDTO? selectedPoint = mapContext.getSelectedPoint() as GeoPointDTO?; ScrollController scrollDescription = ScrollController(); ScrollController scrollPrice = ScrollController(); var isPointPrice = selectedPoint != null && selectedPoint.prices != null && selectedPoint.prices!.isNotEmpty && selectedPoint.prices!.any((d) => d.language == language) && selectedPoint.prices!.firstWhere((d) => d.language == language).value != null && selectedPoint.prices!.firstWhere((d) => d.language == language).value!.trim().isNotEmpty; Color primaryColor = Color(int.parse(visitAppContext.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16)); Size sizeMarker = Size(size.width * 0.93, size.height * 0.8); return Center( child: Visibility( visible: selectedPoint != null, child: Container( width: sizeMarker.width, height: sizeMarker.height, margin: const EdgeInsets.symmetric(vertical: 3, horizontal: 4), decoration: BoxDecoration( color: kBackgroundColor, // Colors.amberAccent //kBackgroundLight, //shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 10.0), /*boxShadow: [ BoxShadow( color: kBackgroundSecondGrey, spreadRadius: 0.5, blurRadius: 1.1, offset: Offset(0, 1.1), // changes position of shadow ), ],*/ ), child: Stack( children: [ if(selectedPoint != null) 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: selectedPoint.imageUrl != null ? DecorationImage( fit: BoxFit.cover, opacity: 0.4, image: NetworkImage( selectedPoint.imageUrl!, ), ): null ), width: size.width, height: 75, child: Center( child: HtmlWidget( selectedPoint.title!.firstWhere((t) => t.language == language).value!, textStyle: const TextStyle(fontSize: 20.0), customStylesBuilder: (element) { return {'text-align': 'center', 'font-family': "Roboto", '-webkit-line-clamp': "2"}; }, ), ), ), ], ), ), if(selectedPoint != null) Padding( padding: const EdgeInsets.only(top: 75), child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(10.0), child: Column( //mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.all(6), child: Container( height: size.height * 0.4, 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( controller: scrollDescription, thumbVisibility: true, thickness: 2.0, child: SingleChildScrollView( controller: scrollDescription, child: Padding( padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ if(selectedPoint.description!.any((d) => d.language == language) && selectedPoint.description!.firstWhere((d) => d.language == language).value != null && selectedPoint.description!.firstWhere((d) => d.language == language).value!.trim().isNotEmpty) HtmlWidget( selectedPoint.description!.firstWhere((d) => d.language == language).value!, customStylesBuilder: (element) { return {'text-align': 'left', 'font-family': "Roboto"}; }, textStyle: const TextStyle(fontSize: kMenuDescriptionDetailSize), ), ], ), ), ), ), ), ), ), Padding( padding: const EdgeInsets.all(8.0), child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ SizedBox( height: size.height * 0.2, child: CarouselSlider( carouselController: sliderController, options: CarouselOptions( onPageChanged: (int index, CarouselPageChangedReason reason) { currentIndex.value = index + 1; }, height: size.height *0.33, enlargeCenterPage: true, pageSnapping: true, reverse: false, ), items: selectedPoint.contents!.map((ContentDTO i) { return Builder( builder: (BuildContext context) { AppContext appContext = Provider.of(context); var resourcetoShow = getElementForResource(context, appContext, i, true); return resourcetoShow; }, ); }).toList(), ), ), Padding( padding: const EdgeInsets.only(top: 10.0), child: Column( children: [ if(isPointPrice && selectedPoint.prices!.firstWhere((d) => d.language == language).value!.length > breakPointPrice) Padding( padding: const EdgeInsets.only(top: 8.0, bottom: 8.0), child: Container( height: size.height * 0.18, 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( controller: scrollPrice, thumbVisibility: true, thickness: 2.0, child: SingleChildScrollView( controller: scrollPrice, child: Padding( padding: const EdgeInsets.all(8.0), child: Column( //crossAxisAlignment: CrossAxisAlignment.center, //mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Center(child: Padding( padding: const EdgeInsets.all(5.0), child: Icon(Icons.price_change_outlined, color: primaryColor, size: 25), )), HtmlWidget( selectedPoint.prices!.firstWhere((d) => d.language == language).value!, customStylesBuilder: (element) { return {'text-align': 'left', 'font-family': "Roboto"}; }, textStyle: const TextStyle(fontSize: kMenuDescriptionDetailSize), ), ], ), ), ), ), ), ), ), if(isPointPrice && selectedPoint.prices!.firstWhere((d) => d.language == language).value!.length <= breakPointPrice) Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Icon(Icons.price_change_outlined, color: primaryColor, size: 13), Padding( padding: const EdgeInsets.all(4.0), child: HtmlWidget( selectedPoint.prices!.firstWhere((d) => d.language == language).value!, customStylesBuilder: (element) { return {'text-align': 'left', 'font-family': "Roboto"}; }, textStyle: const TextStyle(fontSize: 12), ), ) ], ), selectedPoint.phone != null && selectedPoint.phone!.isNotEmpty && selectedPoint.phone!.any((d) => d.language == language) && selectedPoint.phone!.firstWhere((d) => d.language == language).value != null && selectedPoint.phone!.firstWhere((d) => d.language == language).value!.trim().isNotEmpty ? Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.phone, color: primaryColor, size: 13), Padding( padding: const EdgeInsets.all(4.0), child: Text(parse(selectedPoint.phone!.firstWhere((p) => p.language == language).value!).documentElement!.text, style: const TextStyle(fontSize: 18)), ) ], ): const SizedBox(), selectedPoint.email != null && selectedPoint.email!.isNotEmpty && selectedPoint.email!.any((d) => d.language == language) && selectedPoint.email!.firstWhere((d) => d.language == language).value != null && selectedPoint.email!.firstWhere((d) => d.language == language).value!.trim().isNotEmpty ? Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.email, color: primaryColor, size: 13), Padding( padding: const EdgeInsets.all(4.0), child: AutoSizeText(parse(selectedPoint.email!.firstWhere((p) => p.language == language).value!).documentElement!.text, style: const TextStyle(fontSize: 18), maxLines: 3), ) ], ): const SizedBox(), selectedPoint.site != null && selectedPoint.site!.isNotEmpty && selectedPoint.site!.any((d) => d.language == language) && selectedPoint.site!.firstWhere((d) => d.language == language).value != null && selectedPoint.site!.firstWhere((d) => d.language == language).value!.trim().isNotEmpty ? Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.public, color: primaryColor, size: 13), Padding( padding: const EdgeInsets.all(4.0), child: AutoSizeText(parse(selectedPoint.site!.firstWhere((p) => p.language == language).value!).documentElement!.text, style: const TextStyle(fontSize: 18), maxLines: 3), ) ], ): const SizedBox(), ], ), ), ], ), ) ], ), ), ), ), /*Align( alignment: Alignment.topCenter, child: Padding( padding: const EdgeInsets.only(top: 20), child: HtmlWidget( (mapContext.getSelectedMarker() as MapMarker).title!, customStylesBuilder: (element) { return {'text-align': 'center'}; }, textStyle: TextStyle(fontWeight: FontWeight.w500, fontSize: kIsWeb ? kWebTitleSize : kTitleSize) ), ), ), Padding( padding: const EdgeInsets.only(top: 75), child: Center( child: Stack( children: [ Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ if((mapContext.getSelectedMarker() as MapMarker).contents != null && (mapContext.getSelectedMarker() as MapMarker).contents!.length > 0) Stack( children: [ Container( //color: Colors.green, child: CarouselSlider( carouselController: sliderController, options: CarouselOptions( onPageChanged: (int index, CarouselPageChangedReason reason) { currentIndex.value = index + 1; }, height: size.height *0.35, enlargeCenterPage: true, pageSnapping: true, reverse: false, ), items: (mapContext.getSelectedMarker() as MapMarker).contents!.map((ContentGeoPoint i) { return Builder( builder: (BuildContext context) { AppContext appContext = Provider.of(context); var resourcetoShow = getElementForResource(context, appContext, i); return Padding( padding: const EdgeInsets.all(8.0), child: resourcetoShow, ); }, ); }).toList(), ), ), Positioned( bottom: 0, child: Container( //color: Colors.red, height: 25, width: sizeMarker.width, //color: Colors.amber, child: Padding( padding: const EdgeInsets.only(top: 0), child: Align( alignment: Alignment.bottomCenter, child: ValueListenableBuilder( valueListenable: currentIndex, builder: (context, value, _) { return Text( value.toString()+'/'+(mapContext.getSelectedMarker() as MapMarker).contents!.length.toString(), style: TextStyle(fontSize: 15, fontWeight: FontWeight.w500), ); } ) ), ), ), ), ], ), // Description Container( height: (mapContext.getSelectedMarker() as MapMarker).contents != null && (mapContext.getSelectedMarker() as MapMarker).contents!.length > 0 ? size.height *0.3 : size.height *0.6, width: MediaQuery.of(context).size.width *0.4, decoration: BoxDecoration( color: kBackgroundColor, shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(tabletAppContext.configuration!.roundedValue?.toDouble() ?? 10.0), boxShadow: [ BoxShadow( color: kBackgroundSecondGrey, spreadRadius: 0.5, blurRadius: 1.1, offset: Offset(0, 1.1), // changes position of shadow ), ], ), child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(15.0), child: HtmlWidget( (mapContext.getSelectedMarker() as MapMarker).description!, customStylesBuilder: (element) { return {'text-align': 'center'}; }, textStyle: TextStyle(fontSize: kIsWeb ? kWebDescriptionSize : kDescriptionSize) ), ), ), ), ] ), if((mapContext.getSelectedMarker() as MapMarker).contents != null && (mapContext.getSelectedMarker() as MapMarker).contents!.length > 1) Positioned( top: MediaQuery.of(context).size.height * 0.125, right: -10, child: InkWell( onTap: () { if ((mapContext.getSelectedMarker() as MapMarker).contents!.length > 0) sliderController!.nextPage(duration: new Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); }, child: Icon( Icons.chevron_right, size: kIsWeb ? 100 : 85, color: kTestSecondColor, ), ) ), if((mapContext.getSelectedMarker() as MapMarker).contents != null && (mapContext.getSelectedMarker() as MapMarker).contents!.length > 1) Positioned( top: MediaQuery.of(context).size.height * 0.125, left: -10, child: InkWell( onTap: () { if ((mapContext.getSelectedMarker() as MapMarker).contents!.length > 0) sliderController!.previousPage(duration: new Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); }, child: Icon( Icons.chevron_left, size: kIsWeb ? 100 : 85, color: kTestSecondColor, ), ) ), ], ), ), ),*/ Positioned( right: 6.5, top: 12.5, child: GestureDetector( onTap: () { setState(() { mapContext.setSelectedPoint(null); mapContext.setSelectedPointForNavigate(null); }); }, child: Container( width: 50, height: 50, decoration: BoxDecoration( color: primaryColor, shape: BoxShape.circle, ), child: const Icon( Icons.close, size: 25, color: Colors.white, ), ), ), ), ]) ), ), ); } } getElementForResource(BuildContext context, AppContext appContext, ContentDTO i, bool addFullScreen) { var widgetToInclude; Size size = MediaQuery.of(context).size; VisitAppContext visitAppContext = appContext.getContext() as VisitAppContext; switch(i.resource?.type) { case ResourceType.Image: case ResourceType.ImageUrl: widgetToInclude = GestureDetector( onTap: () { if(addFullScreen) { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)) ), contentPadding: EdgeInsets.zero, // title: Text(eventAgenda.name!), content: Container( decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), color: kBackgroundColor, ), constraints: const BoxConstraints(minWidth: 250, minHeight: 250, maxHeight: 350), height: size.height * 0.6, width: size.width * 0.85, child: Container( decoration: BoxDecoration( //color: Colors.yellow, borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 15.0)), ), child: PhotoView( imageProvider: ImageCustomProvider.getImageProvider(appContext, i.resourceId!, i.resource!.url!), minScale: PhotoViewComputedScale.contained * 0.8, maxScale: PhotoViewComputedScale.contained * 3.0, backgroundDecoration: BoxDecoration( color: kBackgroundGrey, shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 15.0), ), ), ), ), ); }, ); } }, child: Container( decoration: BoxDecoration( //color: kBackgroundLight, image: DecorationImage( image: ImageCustomProvider.getImageProvider(appContext, i.resourceId!, i.resource!.url!), fit: BoxFit.cover, ), borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 15.0)), /*border: Border.all( color: kBackgroundGrey, width: 1.0, ),*/ ), ), ); break; case ResourceType.Video: case ResourceType.VideoUrl: case ResourceType.Audio: widgetToInclude = GestureDetector( behavior: HitTestBehavior.translucent, onTap: () { if(addFullScreen && i.resource!.type != ResourceType.Audio) { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)) ), contentPadding: EdgeInsets.zero, // title: Text(eventAgenda.name!), content: Container( decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)), color: kBackgroundColor, ), constraints: const BoxConstraints(minWidth: 250, minHeight: 250, maxHeight: 350), height: size.height * 0.6, width: size.width * 0.85, child: Center(child: showElementForResource(ResourceDTO(id: i.resourceId, url: i.resource?.url, type: i.resource?.type), appContext, false, true)), ), ); }, ); } }, child: IgnorePointer( ignoring: i.resource!.type != ResourceType.Audio, child: Container( decoration: BoxDecoration( shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 15.0), ), child: showElementForResource(ResourceDTO(id: i.resourceId, url: i.resource?.url, type: i.resource?.type), appContext, false, true), ), ), ); break; } return Center( child: Container( height: MediaQuery.of(context).size.height * 0.6, width: MediaQuery.of(context).size.width * 0.72, child: AspectRatio( aspectRatio: 16 / 9, child: ClipRect( child: widgetToInclude, ), ), ), ); }