import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:gap/gap.dart'; import 'package:go_router/go_router.dart'; import 'package:jiffy/jiffy.dart'; import 'package:path_provider/path_provider.dart'; import 'package:scroll_to_index/scroll_to_index.dart'; import 'package:tp5/core/basic_page.dart'; import 'package:tp5/core/utils.dart'; import 'package:tp5/lido/lido_api.dart'; import 'package:tp5/lido/model/Lidoapi_list.dart'; import 'package:tp5/lido/w_lidoflt.dart'; import 'package:tp5/pdf/pdf_page.dart'; class LidolistPage extends ConsumerStatefulWidget { const LidolistPage({super.key, required this.params}); final LidolistPageParams params; @override ConsumerState createState() => _LidolistPageState(); } class _LidolistPageState extends ConsumerState { final bottomnavstyle = ElevatedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5.0), ), backgroundColor: const Color.fromARGB(255, 0, 36, 53) //elevated btton background color ); final AutoScrollController _scrollCtrl = AutoScrollController(); List legs = []; _scrollToDate({Jiffy? date}) { final jdate = date ?? Jiffy.now().toUtc(); bool found = false; int id = 0; for (var leg in legs) { if (Jiffy.parseFromMillisecondsSinceEpoch( leg.leg?.estimatedDepartureTime ?? 0, isUtc: true) .isSameOrAfter(jdate.subtract(hours: 1))) { found = true; break; } id++; } Future.delayed(const Duration(milliseconds: 100)).then((value) { if (found && mounted && _scrollCtrl.hasClients) { _scrollCtrl.scrollToIndex(id, duration: const Duration(milliseconds: 1300), preferPosition: AutoScrollPosition.begin); } }); } @override void initState() { Future.delayed(Duration.zero).then((x) async { // print(await ref // .read(lidoapiProvider) // .login(user: "TAR13176", pass: "FaresWiem08_a")); ref.read(isLoadingProvider.notifier).state = true; final out = await ref.read(lidoapiProvider).list( start: widget.params.datestart, end: widget.params.dateend, dep: widget.params.dep ?? "", des: widget.params.des ?? "", al: widget.params.al ?? "", fnum: widget.params.fnum ?? "", ); if ((out["error"] == null && out["data"] is List) || (out["cache"] != null)) { final data = (out["error"] == null ? out["data"] : (out["cache"])["data"]); legs.clear(); for (var e in data ?? []) { //print(e); legs.add(LidoapiList.fromJson(e)); } } else { context.showError(out["error"]); } setState(() {}); ref.read(isLoadingProvider.notifier).state = false; _scrollToDate(); //print("Lidolistpage: out= $out"); // print((LidoapiList.fromJson(out["data"][0]))); // writeStringToFile("${out["data"][0]}"); }); super.initState(); } Future writeStringToFile(String content) async { try { final directory = await getApplicationDocumentsDirectory(); final file = File('${directory.path}/lidoapilist.txt'); // Write the content to the file await file.writeAsString(content); print('Content written to file: ${file.path}'); } catch (e) { print('Error writing to file: $e'); } } @override Widget build(BuildContext context) { // final now = ref.watch(clockProvider); return BasicPage( actions: [ IconButton( onPressed: () => context.push("/lido/settings"), icon: const Icon(Icons.settings)), const Gap(10) ], bottomNavigationBar: Container( padding: const EdgeInsets.all(8), // color: Colors.black, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.grey[700]!, Colors.black, ], )), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ ElevatedButton.icon( onPressed: () { _changeDay(context); }, icon: const Icon( Icons.calendar_month), //icon data for elevated button label: const Text("Change\n Day"), //label text style: bottomnavstyle, ), const Gap(10), ElevatedButton.icon( onPressed: () { _searchFlights(context); }, icon: const Icon(Icons.manage_search), label: const Text("Search\nFlights"), style: bottomnavstyle, ), const Gap(10), //icon data for elevated button ], ), ), title: "Lido / List", body: ListView.builder( itemCount: legs.length, itemBuilder: (_, index) => AutoScrollTag( key: ValueKey(index), controller: _scrollCtrl, index: index, child: _getItem(_, index)), shrinkWrap: true, controller: _scrollCtrl, ), ); } int? _loadingOFP; _getItem(BuildContext buildContext, int index) { return InkWell( onTap: () async { final legid = legs[index].briefingId ?? ""; if (_loadingOFP == null) { setState(() { _loadingOFP = index; }); final ofp = await ref.read(lidoapiProvider).ofppdf(legid: legid); setState(() { _loadingOFP = null; }); if (((ofp["data"] is Map) && (ofp["data"]?["downloaded"] ?? false) == true) || (ofp["cache"] != null)) { context.push("/pdf", extra: PdfPageParams( file: ofp["cache"] ?? ofp["data"]?["fileid"] ?? "", title: legid, initialZoom: 1)); } else { context.showError("Cannot download PDF File !!!"); } } }, child: // Text("${legs[index].leg?.departureAirportIcao} ${legs[index].leg?.destinationAirportIcao} ${legs[index].leg?.flightNumber} ${Jiffy.parseFromMillisecondsSinceEpoch(legs[index].leg?.estimatedDepartureTime ?? 0, isUtc: true).format(pattern: "ddMMMyy HHmm")} ${Jiffy.parseFromMillisecondsSinceEpoch(legs[index].leg?.scheduledDepartureTime ?? 0, isUtc: true).format(pattern: "ddMMMyy HHmm")} ${legs[index].leg?.fuel?.blockFuel}"), Row(children: [ if (_loadingOFP == index) const CircularProgressIndicator(), Expanded(child: WLidoflt(lidoapilist: legs[index])) ])); } void _changeDay(BuildContext context) {} TextEditingController ctrldep = TextEditingController(); TextEditingController ctrldes = TextEditingController(); TextEditingController ctrlairline = TextEditingController(); TextEditingController ctrlfnum = TextEditingController(); TextEditingController ctrlstartdate = TextEditingController(); TextEditingController ctrlenddate = TextEditingController(); void _searchFlights(xcontext) async { ref.read(isLoadingProvider.notifier).state = true; ref.read(isLoadingProvider.notifier).state = false; ctrldep.text = widget.params.dep ?? ""; ctrldes.text = widget.params.des ?? ""; ctrlairline.text = widget.params.al ?? ""; ctrlfnum.text = widget.params.fnum ?? ""; ctrlstartdate.text = widget.params.datestart?.format(pattern: "ddMMMyy") ?? ""; ctrlenddate.text = widget.params.dateend?.format(pattern: "ddMMMyy") ?? ""; final res = await showModalBottomSheet( context: context, builder: (context) => _searchFilter(xcontext, null, null)); if (res is LidolistPageParams) context.push("/lido/list", extra: res); } Widget _searchFilter(BuildContext context, DateTime? min, DateTime? max) { min = min ?? DateTime.now().subtract(const Duration(days: 7)); max = max ?? DateTime.now().add(const Duration(days: 7)); return Container( padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, children: [ Row( children: [ Expanded( child: TextField( decoration: const InputDecoration(labelText: "Departure Airport"), maxLength: 3, // Set maximum length controller: ctrldep, ), ), const SizedBox(width: 10), Expanded( child: TextField( decoration: const InputDecoration(labelText: "Arrival Airport"), maxLength: 3, // Set maximum length controller: ctrldes, ), ), ], ), const SizedBox(height: 15), Row( children: [ Expanded( child: TextField( controller: ctrlairline, decoration: const InputDecoration(labelText: "Airline IATA code"), maxLength: 2, // Set maximum length ), ), const SizedBox(width: 10), Expanded( child: TextField( controller: ctrlfnum, decoration: const InputDecoration(labelText: "Flight number"), maxLength: 6, // Set maximum length ), ), ], ), const SizedBox(height: 15), Row( children: [ Expanded( child: TextField( decoration: const InputDecoration(labelText: "Starting date"), controller: ctrlstartdate, readOnly: true, //set it true, so that user will not able to edit text onTap: () async { DateTime? pickedDate = await showDatePicker( context: context, initialDate: DateTime.now().toUtc(), firstDate: min!, //DateTime.now () - not to allow to choose before today. lastDate: max!); if (pickedDate != null) { String formattedDate = Jiffy.parseFromDateTime(pickedDate).format( pattern: "ddMMMyy"); //formatted date output using intl package => 2021-03-16 setState(() { ctrlstartdate.text = formattedDate; if (ctrlenddate.text == "" || Jiffy.parseFromDateTime(pickedDate).isAfter( Jiffy.parse(ctrlenddate.text, pattern: "ddMMMyy", isUtc: true))) { ctrlenddate.text = formattedDate; } }); } else { print("Date is not selected"); } }), ), const SizedBox(width: 10), Expanded( child: TextField( decoration: const InputDecoration(labelText: "Ending date"), controller: ctrlenddate, readOnly: true, //set it true, so that user will not able to edit text onTap: () async { DateTime? pickedDate = await showDatePicker( context: context, initialDate: DateTime.now().toUtc(), firstDate: min!, lastDate: max!); if (pickedDate != null) { String formattedDate = Jiffy.parseFromDateTime(pickedDate) .format(pattern: "ddMMMyy"); setState(() { ctrlenddate.text = formattedDate; if (ctrlstartdate.text == "" || Jiffy.parseFromDateTime(pickedDate).isBefore( Jiffy.parse(ctrlstartdate.text, pattern: "ddMMMyy", isUtc: true))) { ctrlstartdate.text = formattedDate; } }); } else { print("Date is not selected"); } }), ), ], ), const SizedBox(height: 35), SizedBox( width: 360, child: ElevatedButton( onPressed: () async => // await context.push("/lido/list", // extra: LidolistPageParams( // dep: ctrldep.text.toUpperCase(), // des: ctrldes.text.toUpperCase(), // al: ctrlairline.text.toUpperCase(), // fnum: ctrlfnum.text, // datestart: ctrlstartdate.text, // dateend: ctrlenddate.text, // )), Navigator.pop( context, LidolistPageParams( dep: ctrldep.text.toUpperCase(), des: ctrldes.text.toUpperCase(), al: ctrlairline.text.toUpperCase(), fnum: ctrlfnum.text, datestart: ctrlstartdate.text == "" ? null : Jiffy.parse(ctrlstartdate.text, pattern: "ddMMMyy", isUtc: true), dateend: ctrlenddate.text == "" ? null : Jiffy.parse(ctrlenddate.text, pattern: "ddMMMyy", isUtc: true), )), // Close the bottom sheet style: ElevatedButton.styleFrom( backgroundColor: Colors.green, // Set button color to green shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15), // Add rounded corners ), padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 15), ), child: const Text( 'Search Flights', style: TextStyle(fontSize: 18, color: Colors.white), ), ), ), ], ), ); } _titleInfo(String? title, String? info, {double sizetitle = 10, double sizeinfo = 16, Color color = Colors.blueGrey}) => Column( children: [ Text( title ?? "---", style: TextStyle(color: Colors.grey, fontSize: sizetitle), ), Text(info ?? "---", style: TextStyle(color: color, fontSize: sizeinfo)), ], ); } class LidolistPageParams { const LidolistPageParams({ this.dateend, this.datestart, this.dep, this.des, this.al, this.fnum, this.lidouser, this.lidopass, }); final Jiffy? dateend; final Jiffy? datestart; final String? dep; final String? des; final String? al; final String? fnum; final String? lidouser; final String? lidopass; }