import 'dart:async'; import 'package:flutter/material.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:intl/intl.dart'; import 'package:mobdr/main.dart'; import 'package:mobdr/config/constant.dart'; import 'package:mobdr/config/global_style.dart'; import 'package:mobdr/service/shared_prefs.dart'; import 'package:mobdr/events.dart'; import 'package:mobdr/model/visit_model.dart'; import 'package:mobdr/ui/reusable/cache_image_network.dart'; import 'package:mobdr/ui/sync/upload_photos.dart'; import 'package:mobdr/ui/sync/check_connection.dart'; import 'package:mobdr/ui/sync/sync_calendar.dart'; class SynchronizationPage extends StatefulWidget { @override _SynchronizationPageState createState() => _SynchronizationPageState(); } class _SynchronizationPageState extends State { late List tosyncVisitData = []; // _listKey is used for AnimatedList var _listKey = GlobalKey(); @override void initState() { super.initState(); loadData(); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { final double boxImageSize = (MediaQuery.of(context).size.width / 4); return Scaffold( appBar: AppBar( iconTheme: IconThemeData( color: GlobalStyle.appBarIconThemeColor, ), elevation: GlobalStyle.appBarElevation, title: Text( 'Data synchronization', style: GlobalStyle.appBarTitle, ), backgroundColor: GlobalStyle.appBarBackgroundColor, systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle), body: Column( children: [ Container( padding: EdgeInsets.fromLTRB(16, 16, 16, 0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Calendar', style: GlobalStyle.horizontalTitle), Row( children: [ Icon(Icons.refresh), Text(SharedPrefs().lastCalendarRefresh.isNotEmpty ? SharedPrefs().lastCalendarRefresh : "Never"), ], ), ], ), ), SizedBox(height: 8), // Ajout de l'espace ici ElevatedButton( onPressed: () async { final result = await Navigator.push( context, MaterialPageRoute(builder: (context) => SyncCalendarPage()), ); // Refresh the widget if the synchronization was successful. if (result == true) { SharedPrefs().lastCalendarRefresh = DateFormat('dd/MM/yyyy HH:mm').format(DateTime.now()); eventBus.fire( RefreshCalendarEvent(SharedPrefs().lastCalendarRefresh)); setState(() { loadData(); }); } else SharedPrefs().lastCalendarRefresh = ""; }, child: Text('Synchroniser'), ), Container( padding: EdgeInsets.fromLTRB(16, 16, 16, 0), child: Row( children: [ Text('Visits', style: GlobalStyle.horizontalTitle), ], ), ), if (tosyncVisitData.isEmpty) Container( padding: EdgeInsets.all(16), child: Text("You didn't take any photos..."), ), Flexible( child: AnimatedList( key: _listKey, initialItemCount: tosyncVisitData.length, physics: AlwaysScrollableScrollPhysics(), itemBuilder: (context, index, animation) { return Dismissible( key: UniqueKey(), direction: DismissDirection.endToStart, onDismissed: (direction) { // the photo must be removed setState(() { tosyncVisitData.removeAt(index); _listKey = GlobalKey(); }); }, background: Container( color: Colors.red, child: Stack( children: [ Positioned.fill( child: Align( alignment: Alignment.center, child: Icon( Icons.delete, color: Colors.white, ), ), ), ], ), ), child: _buildVisitlistCard( tosyncVisitData[index], boxImageSize, animation, index), ); }, ), ), Container( padding: EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Colors.grey, offset: Offset(0.0, 1.0), //(x,y) blurRadius: 2.0, ), ], ), child: Row( children: [ Container( child: GestureDetector( onTap: () { // TODO functionality to be implemented /*` Navigator.push( context, MaterialPageRoute( builder: (context) => ChatUsPage())); */ }, child: ClipOval( child: Container( color: SOFT_BLUE, padding: EdgeInsets.all(9), child: Icon(Icons.filter_list, color: Colors.white, size: 16)), ), ), ), SizedBox( width: 10, ), Expanded( child: GestureDetector( onTap: tosyncVisitData.isNotEmpty ? () { navigateToPage(context, 0); } : null, child: Container( alignment: Alignment.center, padding: EdgeInsets.fromLTRB(12, 8, 12, 8), margin: EdgeInsets.only(right: 8), decoration: BoxDecoration( color: Colors.white, border: Border.all( width: 1, color: tosyncVisitData.isNotEmpty ? Colors.red : Colors.grey), borderRadius: BorderRadius.all( Radius.circular(10), ), ), child: Text( 'Synchronize ALL visits', style: TextStyle( color: tosyncVisitData.isNotEmpty ? Colors.red : Colors.grey, fontWeight: FontWeight.bold, ), ), ), ), ), ], ), ), ], ), ); } Widget _buildVisitlistCard(VisitModel data, boxImageSize, animation, index) { return SizeTransition( sizeFactor: animation, child: Container( margin: EdgeInsets.fromLTRB(12, 6, 12, 0), child: Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), elevation: 2, color: Colors.white, child: Container( margin: EdgeInsets.all(8), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( borderRadius: BorderRadius.all(Radius.circular(10)), child: buildCacheNetworkImage( width: boxImageSize, height: boxImageSize, url: data.image, ), ), SizedBox( width: 10, ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( margin: EdgeInsets.only(top: 5), child: Row( children: [ Text(data.name, style: GlobalStyle.productPrice) ], ), ), Container(height: 8), Text( data.date, style: GlobalStyle.productSale, ), Container( margin: EdgeInsets.only(top: 5), child: Text( '${data.photoCount} Photo(s)', style: GlobalStyle.productPrice, ), ), Container(height: 8), Container( margin: EdgeInsets.only(top: 5), child: Row( children: [ Icon( Icons.store, color: SOFT_GREY, size: 20, ), Text( ' ' + data.type_visite, style: GlobalStyle.productName.copyWith( fontSize: 13, ), maxLines: 1, overflow: TextOverflow.ellipsis, ) ], ), ), ], ), ) ], ), Container( margin: EdgeInsets.only(top: 12), child: Row( children: [ Expanded( child: (data.photoCount == 0) ? TextButton( style: ButtonStyle( minimumSize: MaterialStateProperty.all(Size(0, 30)), backgroundColor: MaterialStateProperty.resolveWith( (Set states) => Colors.grey[300]!, ), overlayColor: MaterialStateProperty.all( Colors.transparent), shape: MaterialStateProperty.all( RoundedRectangleBorder( borderRadius: BorderRadius.circular(5.0), )), ), onPressed: () {}, child: Text( 'Synchronize', style: TextStyle( color: Colors.grey[600], fontWeight: FontWeight.bold, fontSize: 13), textAlign: TextAlign.center, )) : OutlinedButton( onPressed: () { navigateToPage(context, data.id_visite); }, style: ButtonStyle( minimumSize: MaterialStateProperty.all(Size(0, 30)), overlayColor: MaterialStateProperty.all( Colors.transparent), shape: MaterialStateProperty.all( RoundedRectangleBorder( borderRadius: BorderRadius.circular(5.0), )), side: MaterialStateProperty.all( BorderSide(color: SOFT_BLUE, width: 1.0), )), child: Text( 'Synchronize', style: TextStyle( color: SOFT_BLUE, fontWeight: FontWeight.bold, fontSize: 13), textAlign: TextAlign.center, )), ), ], ), ) ], ), ), ), ), ); } Future navigateToPage(BuildContext context, int id_visite) async { var connectivityResult = await (Connectivity().checkConnectivity()); if (connectivityResult == ConnectivityResult.none) { Navigator.push( context, MaterialPageRoute( builder: (_) => CheckConnectionPage( redirectPage: UploadPhotosPage(pp_id_visite: id_visite), ), ), ); } else { Navigator.push( context, MaterialPageRoute( builder: (_) => UploadPhotosPage(pp_id_visite: id_visite))); } } /// Initializes data when the page loads. void loadData() { // initialization of data with all visits to be synchronized tosyncVisitData = VisitModel.getToSyncVisits(); } }