1
0

rosters_page.bak3 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. import 'package:collection/collection.dart';
  2. import 'package:flutter/foundation.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter_riverpod/flutter_riverpod.dart';
  5. import 'package:gap/gap.dart';
  6. import 'package:go_router/go_router.dart';
  7. import 'package:hive_flutter/hive_flutter.dart';
  8. import 'package:jiffy/jiffy.dart';
  9. import 'package:tp5/core/basic_page.dart';
  10. import 'package:tp5/core/utils.dart';
  11. import 'package:tp5/csv/data.dart';
  12. import 'package:linked_scroll_controller/linked_scroll_controller.dart';
  13. import 'package:tp5/fltinfo/view/dutyinfo_page.dart';
  14. import 'package:tp5/fltinfo/view/fltinfo_page.dart';
  15. import 'package:tp5/rosters/rosters_crew_filter.dart';
  16. import 'package:tp5/widgets/my_col.dart';
  17. import 'package:tp5/widgets/my_row.dart';
  18. import 'package:google_fonts/google_fonts.dart';
  19. class RostersPage extends ConsumerStatefulWidget {
  20. const RostersPage({super.key});
  21. @override
  22. ConsumerState<ConsumerStatefulWidget> createState() => _RostersPageState();
  23. }
  24. class _RostersPageState extends ConsumerState<RostersPage> {
  25. final scrollControllerGroup = LinkedScrollControllerGroup();
  26. Map<int, ScrollController> scrollCtrls = {};
  27. ScrollController? _getCtrl(int i) {
  28. if (!scrollCtrls.containsKey(i)) {
  29. scrollCtrls[i] = scrollControllerGroup.addAndGet();
  30. }
  31. return scrollCtrls[i];
  32. }
  33. final bottomnavstyle = ElevatedButton.styleFrom(
  34. shape: RoundedRectangleBorder(
  35. borderRadius: BorderRadius.circular(5.0),
  36. ),
  37. backgroundColor:
  38. const Color.fromARGB(255, 0, 36, 53) //elevated btton background color
  39. );
  40. TextEditingController ctrldep = TextEditingController();
  41. TextEditingController ctrldes = TextEditingController();
  42. TextEditingController ctrlairline = TextEditingController();
  43. TextEditingController ctrlfnum = TextEditingController();
  44. Map<String, String> flightFilter = {
  45. "dep": "",
  46. "des": "",
  47. "al": "",
  48. "fnum": ""
  49. };
  50. void _searchFlights(xcontext) async {
  51. ctrldep.text = flightFilter["dep"] ?? "";
  52. ctrldes.text = flightFilter["des"] ?? "";
  53. ctrlairline.text = flightFilter["al"] ?? "";
  54. ctrlfnum.text = flightFilter["fnum"] ?? "";
  55. final res = await showModalBottomSheet(
  56. context: context, builder: (context) => _flightFilter(xcontext));
  57. if (res is Map<String, String>) {
  58. Hive.box("settings").put("rosters.filter.flights", (res));
  59. await recalcultlcs();
  60. setState(() {
  61. flightFilter = res;
  62. });
  63. }
  64. }
  65. Widget _flightFilter(BuildContext context) {
  66. return Container(
  67. padding: const EdgeInsets.all(20),
  68. child: Column(mainAxisSize: MainAxisSize.min, children: [
  69. Row(
  70. children: [
  71. Expanded(
  72. child: TextField(
  73. decoration:
  74. const InputDecoration(labelText: "Departure Airport"),
  75. maxLength: 3, // Set maximum length
  76. controller: ctrldep,
  77. ),
  78. ),
  79. const SizedBox(width: 10),
  80. Expanded(
  81. child: TextField(
  82. decoration:
  83. const InputDecoration(labelText: "Arrival Airport"),
  84. maxLength: 3, // Set maximum length
  85. controller: ctrldes,
  86. ),
  87. ),
  88. ],
  89. ),
  90. const SizedBox(height: 15),
  91. Row(
  92. children: [
  93. Expanded(
  94. child: TextField(
  95. controller: ctrlairline,
  96. decoration:
  97. const InputDecoration(labelText: "Airline IATA code"),
  98. maxLength: 2, // Set maximum length
  99. ),
  100. ),
  101. const SizedBox(width: 10),
  102. Expanded(
  103. child: TextField(
  104. controller: ctrlfnum,
  105. decoration: const InputDecoration(labelText: "Flight number"),
  106. maxLength: 6, // Set maximum length
  107. ),
  108. ),
  109. ],
  110. ),
  111. const SizedBox(height: 15),
  112. const SizedBox(height: 35),
  113. SizedBox(
  114. width: 360,
  115. child: ElevatedButton(
  116. onPressed: () async => Navigator.pop(context, {
  117. "dep": ctrldep.text.toUpperCase(),
  118. "des": ctrldes.text.toUpperCase(),
  119. "al": ctrlairline.text.toUpperCase(),
  120. "fnum": ctrlfnum.text.toUpperCase()
  121. }), // Close the bottom sheet
  122. style: ElevatedButton.styleFrom(
  123. backgroundColor: Colors.green, // Set button color to green
  124. shape: RoundedRectangleBorder(
  125. borderRadius:
  126. BorderRadius.circular(15), // Add rounded corners
  127. ),
  128. padding:
  129. const EdgeInsets.symmetric(horizontal: 20, vertical: 15),
  130. ),
  131. child: const Text(
  132. 'Flight filter',
  133. style: TextStyle(fontSize: 18, color: Colors.white),
  134. ),
  135. ),
  136. ),
  137. ]));
  138. }
  139. Map<String, List<String>> crewFilter = {"college": [], "ac": [], "base": []};
  140. void _searchCrew(xcontext, List<Qualif> qualif) async {
  141. final res = await showModalBottomSheet(
  142. context: context,
  143. builder: (context) =>
  144. RostersCrewFilter(qualif: qualif, crewFilter: crewFilter));
  145. if (res is Map<String, List<String>>) {
  146. Hive.box("settings").put("rosters.filter.crew", (res));
  147. await recalcultlcs();
  148. setState(() {
  149. crewFilter = res;
  150. });
  151. }
  152. }
  153. final double rosterswidth = 110;
  154. final double rostersheight = 60;
  155. Widget _duty2line(Pnleg leg, {bool showdatedep = true}) {
  156. // print(
  157. // ">>${leg.label},${leg.type},${leg.dep},${leg.arr},${leg.jdep?.format(pattern: "HHmm")},${leg.jarr?.format(pattern: "HHmm")},");
  158. final whdep = showdatedep
  159. ? Text(
  160. "${leg.jdep?.format(pattern: "HHmm")}",
  161. style: const TextStyle(fontSize: 10, color: Colors.teal),
  162. )
  163. : const Row(children: [
  164. Icon(
  165. Icons.arrow_back_ios_new_outlined,
  166. size: 12,
  167. color: Colors.teal,
  168. ),
  169. Icon(
  170. Icons.arrow_back_ios_new_outlined,
  171. size: 12,
  172. color: Colors.teal,
  173. ),
  174. ]);
  175. final wharr = Text(
  176. "${leg.jarr?.format(pattern: "HHmm")}",
  177. style: const TextStyle(fontSize: 10, color: Colors.teal),
  178. );
  179. if (leg.type == "L" || (leg.type == "F")) {
  180. return InkWell(
  181. onTap: () {
  182. context.push("/fltinfo",
  183. extra: FltinfoParams(
  184. al: leg.al,
  185. fnum: leg.fnum,
  186. dep: leg.dep,
  187. des: leg.arr,
  188. jdep: leg.jdep,
  189. jdes: leg.jarr));
  190. },
  191. child: MyRow(children: [
  192. whdep,
  193. const Gap(3),
  194. Text(
  195. "${leg.dep}-${leg.arr}",
  196. style: GoogleFonts.robotoMono(
  197. fontSize: 11, fontWeight: FontWeight.w300),
  198. ),
  199. const Gap(3),
  200. wharr,
  201. ]),
  202. );
  203. } else if ((leg.type == "G") ||
  204. ((leg.dep ?? "") != "" && (leg.arr ?? "") != "")) {
  205. return InkWell(
  206. onTap: () {
  207. context.push("/dutyinfo",
  208. extra: DutyinfoParams(
  209. dutytype: leg.dutytype,
  210. label: leg.label,
  211. dep: leg.dep,
  212. des: leg.arr,
  213. jdep: leg.jdep,
  214. jdes: leg.jarr));
  215. },
  216. child: MyRow(children: [
  217. whdep,
  218. const Gap(3),
  219. const Text("Limo ",
  220. style: TextStyle(fontSize: 11, color: Colors.amber)),
  221. Text(
  222. "${leg.dep}-${leg.arr}",
  223. style: GoogleFonts.robotoMono(
  224. fontSize: 11, fontWeight: FontWeight.w300),
  225. ),
  226. const Gap(3),
  227. wharr,
  228. ]),
  229. );
  230. }
  231. // else if ((leg.type == "F") ||
  232. // ((leg.dep ?? "") != "" && (leg.arr ?? "") != "")) {
  233. // return MyRow(children: [
  234. // whdep,
  235. // const Gap(3),
  236. // const Text("DH ", style: TextStyle(fontSize: 11, color: Colors.amber)),
  237. // Text(
  238. // "${leg.dep}-${leg.arr}",
  239. // style:
  240. // GoogleFonts.robotoMono(fontSize: 11, fontWeight: FontWeight.w300),
  241. // ),
  242. // const Gap(3),
  243. // wharr,
  244. // ]);
  245. // }
  246. else if ((!["OFF", "CM", "CA", "PP"].contains(leg.label)) &&
  247. (leg.jarr != null &&
  248. leg.jdep != null &&
  249. DTInterval(leg.jdep!, leg.jarr!).duration.inHours < 18)) {
  250. return InkWell(
  251. onTap: () {
  252. context.push("/dutyinfo",
  253. extra: DutyinfoParams(
  254. dutytype: leg.dutytype,
  255. label: leg.label,
  256. dep: leg.dep,
  257. des: leg.arr,
  258. jdep: leg.jdep,
  259. jdes: leg.jarr));
  260. },
  261. child: MyRow(children: [
  262. whdep,
  263. const Gap(3),
  264. Text("${leg.type == "S" ? "SIMU " : ""}${leg.label}",
  265. style: const TextStyle(fontSize: 11, color: Colors.amber)),
  266. Text(
  267. " ${leg.dep}",
  268. style: GoogleFonts.robotoMono(
  269. fontSize: 8, fontWeight: FontWeight.w300),
  270. ),
  271. const Gap(3),
  272. wharr,
  273. ]),
  274. );
  275. } else {
  276. return Text(
  277. leg.label ?? "",
  278. style: TextStyle(
  279. fontSize: 16,
  280. color: Colors.blueGrey[800],
  281. fontWeight: FontWeight.w700,
  282. letterSpacing: 1),
  283. );
  284. }
  285. }
  286. Widget _rostersDay(
  287. {required Jiffy date,
  288. required List<Pnleg> legs,
  289. Color? color,
  290. bool border = false}) {
  291. return Container(
  292. decoration: BoxDecoration(
  293. border: border ? Border.all(color: Colors.white, width: 1) : null,
  294. color: color ?? Colors.grey[900]),
  295. width: rosterswidth,
  296. height: rosterswidth,
  297. child: Column(children: [
  298. Row(
  299. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  300. children: [
  301. Text(
  302. date.format(pattern: "EEE"),
  303. style: const TextStyle(
  304. fontSize: 14,
  305. color: Colors.blueGrey,
  306. fontWeight: FontWeight.w700),
  307. ),
  308. Text(
  309. date.format(pattern: "dd MMM "),
  310. style: const TextStyle(
  311. fontSize: 14,
  312. color: Color.fromARGB(255, 151, 163, 55),
  313. fontWeight: FontWeight.w500),
  314. )
  315. ],
  316. ),
  317. Expanded(
  318. child: MyCol(
  319. crossAxisAlignment: CrossAxisAlignment.start,
  320. children: legs
  321. .map((leg) => _duty2line(leg,
  322. showdatedep: date.yMEd == leg.jdep?.yMEd))
  323. .toList()))
  324. ]),
  325. );
  326. }
  327. bool showalldates = false;
  328. recalcultlcs() async {
  329. final data = ref.read(dataProvider);
  330. final pnlegTlcs = ref.read(pnlegMeta).tlcs;
  331. final pnleg = data.pnleg;
  332. final qualif = data.qualif;
  333. tlcs = await compute(
  334. calcultlcs,
  335. {
  336. "crewFilter": crewFilter,
  337. "flightFilter": flightFilter,
  338. "pnleg": pnleg,
  339. "pnlegTlcs": pnlegTlcs,
  340. "qualif": qualif
  341. },
  342. debugLabel: "calcul tlcs");
  343. setState(() {});
  344. // print("rosterspages: recalcultlcs: $tlcs");
  345. }
  346. // recalculdates() async {
  347. // final data = ref.watch(dataProvider);
  348. // final pnleg = data.pnleg;
  349. // dates = await compute(calculdates, pnleg, debugLabel: "calcul dates");
  350. // setState(() {});
  351. // print("rosterspages: recalculdates: $dates");
  352. // }
  353. // static List<Jiffy> calculdates(List<Pnleg> pnleg) {
  354. // return pnleg
  355. // .fold(
  356. // <Jiffy>{},
  357. // (t, e) => {
  358. // ...t,
  359. // e.jdep?.startOf(Unit.day) ??
  360. // Jiffy.parse(e.date ?? "01/01/1970",
  361. // pattern: "dd/MM/yyyy", isUtc: true)
  362. // })
  363. // .sortedBy((e) => e.dateTime)
  364. // .where((e) =>
  365. // e.isAfter(Jiffy.now().toUtc().startOf(Unit.day).subtract(days: 3)))
  366. // .toList();
  367. // }
  368. static List<String> calcultlcs(Map data) {
  369. final List<Qualif> qualif = data["qualif"];
  370. final crewFilter = data["crewFilter"];
  371. final flightFilter = data["flightFilter"];
  372. final List<Pnleg> pnleg = data["pnleg"];
  373. final Set<String> tlcsCrewfilter = qualif
  374. .where((e) => ((crewFilter["college"]!.isEmpty ||
  375. crewFilter["college"]!.contains(e.college)) &&
  376. (crewFilter["ac"]!.isEmpty || crewFilter["ac"]!.contains(e.ac)) &&
  377. (crewFilter["base"]!.isEmpty ||
  378. crewFilter["base"]!.contains(e.base))))
  379. .map((e) => e.tlc ?? "")
  380. .toSet();
  381. final List<String> pnlegTlcs = data["pnlegTlcs"];
  382. // final List<String> pnlegTlcs =
  383. // pnleg.fold(<String>{}, (t, e) => {...t, e.tlc ?? ""}).sortedBy((e) {
  384. // final pn = qualif.firstWhereOrNull((q) => q.tlc == e);
  385. // return "${pn?.lname} ${pn?.fname}";
  386. // });
  387. final Set<String> tlcsFlightfilter = pnlegTlcs
  388. .where((e) => ((flightFilter["al"] == "" ||
  389. pnleg.firstWhereOrNull((k) => (k.tlc == e) && (k.al == flightFilter["al"])) !=
  390. null) &&
  391. (flightFilter["fnum"] == "" ||
  392. pnleg.firstWhereOrNull((k) =>
  393. (k.tlc == e) && (k.fnum == flightFilter["fnum"])) !=
  394. null) &&
  395. (flightFilter["dep"] == "" ||
  396. pnleg.firstWhereOrNull((k) => (k.tlc == e) && (k.dep == flightFilter["dep"])) !=
  397. null) &&
  398. (flightFilter["des"] == "" ||
  399. pnleg.firstWhereOrNull((k) =>
  400. (k.tlc == e) && (k.arr == flightFilter["des"])) !=
  401. null)))
  402. .toSet();
  403. return tlcsCrewfilter.intersection(tlcsFlightfilter).sortedBy((e) =>
  404. "${qualif.firstWhereOrNull((k) => k.tlc == e)?.lname} ${qualif.firstWhereOrNull((k) => k.tlc == e)?.fname}");
  405. }
  406. List<String> tlcs = [];
  407. // List<Jiffy> dates = [];
  408. @override
  409. Widget build(BuildContext context) {
  410. final data = ref.watch(dataProvider);
  411. final pnleg = data.pnleg;
  412. final qualif = data.qualif;
  413. // final now = ref.watch(clockProvider);
  414. final now = Jiffy.now().toUtc();
  415. final pnlegmeta = ref.watch(pnlegMeta);
  416. final dates = pnlegmeta.dates;
  417. final alltlcs = pnlegmeta.tlcs;
  418. // final dates = data.pnleg_dates;
  419. // final tlcs = data.pnleg_tlcs;
  420. return BasicPage(
  421. actions: [Text("showing ${tlcs.length} crew member"), const Gap(5)],
  422. bottomNavigationBar: Container(
  423. padding: const EdgeInsets.only(left: 8, right: 8, bottom: 2, top: 6),
  424. // color: Colors.black,
  425. decoration: BoxDecoration(
  426. gradient: LinearGradient(
  427. begin: Alignment.topCenter,
  428. end: Alignment.bottomCenter,
  429. colors: [
  430. Colors.grey[700]!,
  431. Colors.black,
  432. ],
  433. )),
  434. child: Column(
  435. mainAxisSize: MainAxisSize.min,
  436. children: [
  437. Row(
  438. mainAxisAlignment: MainAxisAlignment.spaceAround,
  439. children: [
  440. Row(
  441. children: [
  442. ElevatedButton.icon(
  443. onPressed: () {
  444. _searchCrew(context, qualif);
  445. },
  446. icon: const Icon(
  447. Icons.calendar_month), //icon data for elevated button
  448. label: const Text("Filter\nCrew"), //label text
  449. style: bottomnavstyle,
  450. ),
  451. const Gap(10),
  452. Row(
  453. children: [
  454. Column(
  455. mainAxisSize: MainAxisSize.min,
  456. children: crewFilter.keys
  457. .where((e) => crewFilter[e]!.isNotEmpty)
  458. .map((e) => Text(
  459. "${crewFilter[e]}",
  460. style: const TextStyle(
  461. fontSize: 12, color: Colors.yellow),
  462. ))
  463. .toList()),
  464. const Gap(10),
  465. if (crewFilter.values.flattened.isNotEmpty)
  466. Badge(
  467. label: Text(
  468. crewFilter.values.flattened.length.toString()),
  469. child: IconButton.outlined(
  470. onPressed: () {
  471. for (var k in crewFilter.keys) {
  472. crewFilter[k]!.clear();
  473. }
  474. Hive.box("settings")
  475. .delete("rosters.filter.crew");
  476. setState(() {});
  477. },
  478. icon: const Icon(Icons.filter_alt_off_rounded,
  479. size: 18)),
  480. ),
  481. ],
  482. )
  483. ],
  484. ),
  485. const Gap(10),
  486. Row(
  487. children: [
  488. ElevatedButton.icon(
  489. onPressed: () {
  490. _searchFlights(context);
  491. },
  492. icon: const Icon(Icons.manage_search),
  493. label: const Text("Filter\nFlights"),
  494. style: bottomnavstyle,
  495. ),
  496. const Gap(10),
  497. if (flightFilter.values.any((e) => e != ""))
  498. Badge(
  499. label: Text(flightFilter.values
  500. .where((e) => e != "")
  501. .length
  502. .toString()),
  503. child: IconButton.outlined(
  504. onPressed: () {
  505. for (var k in flightFilter.keys) {
  506. flightFilter[k] = "";
  507. }
  508. Hive.box("settings")
  509. .delete("rosters.filter.flights");
  510. setState(() {});
  511. },
  512. icon: const Icon(Icons.filter_alt_off_rounded,
  513. size: 18)),
  514. )
  515. ],
  516. ),
  517. const Gap(10), //icon data for elevated button
  518. ],
  519. ),
  520. Row(
  521. mainAxisAlignment: MainAxisAlignment.end,
  522. children: [
  523. data.aclegupdate != null
  524. ? Text("data retrieved ${data.pnlegupdate?.from(now)}",
  525. style: GoogleFonts.robotoMono(
  526. fontSize: 10,
  527. fontWeight: FontWeight.w300,
  528. color: Colors.white))
  529. : Text("no data found",
  530. style: GoogleFonts.robotoMono(
  531. fontSize: 10, fontWeight: FontWeight.w300))
  532. ],
  533. ),
  534. ],
  535. ),
  536. ),
  537. title: "Rosters",
  538. body: tlcs.isEmpty
  539. ? const Text("no Pnleg data")
  540. : ListView.builder(
  541. itemCount: tlcs.length, // Number of list items
  542. itemBuilder: (context, index) {
  543. final qualifData =
  544. qualif.where((k) => k.tlc == tlcs.elementAt(index));
  545. final tlc = tlcs.elementAt(index);
  546. final dutiesTlc = ref.watch(pnlegByTlcProvider(tlc)).where(
  547. (e) => ((flightFilter["al"] == "" ||
  548. e.al == flightFilter["al"]) &&
  549. (flightFilter["fnum"] == "" ||
  550. e.fnum == flightFilter["fnum"]) &&
  551. (flightFilter["dep"] == "" ||
  552. e.dep == flightFilter["dep"]) &&
  553. (flightFilter["des"] == "" ||
  554. e.arr == flightFilter["des"])));
  555. final name =
  556. "${qualifData.firstOrNull?.lname?.capitalizeword()}, ${qualifData.firstOrNull?.fname?.capitalizeword()}";
  557. final base = "${qualifData.map((e) => e.base).toSet()}";
  558. return Column(
  559. crossAxisAlignment: CrossAxisAlignment.start,
  560. children: [
  561. Padding(
  562. padding: const EdgeInsets.all(2),
  563. child: Row(children: [
  564. const Gap(10),
  565. Text(name,
  566. style: const TextStyle(
  567. fontWeight: FontWeight.w700,
  568. letterSpacing: 1)),
  569. const Gap(10),
  570. Text(
  571. tlc,
  572. style: const TextStyle(
  573. fontSize: 12, fontWeight: FontWeight.w300),
  574. ),
  575. const Gap(5),
  576. Text(
  577. base,
  578. style: GoogleFonts.robotoMono(
  579. fontSize: 11, fontWeight: FontWeight.w300),
  580. )
  581. ])),
  582. SizedBox(
  583. height: rostersheight,
  584. child: (dates.isEmpty)
  585. ? const Text("No Pnlegs data found")
  586. : ListView.builder(
  587. // controller: scrollControllerGroup.addAndGet(), //_scrollCtrl,
  588. controller: _getCtrl(index), //_scrollCtrl,
  589. scrollDirection: Axis.horizontal,
  590. itemCount:
  591. dates.length, // Number of horizontal items
  592. itemBuilder: (context, horizontalIndex) {
  593. final date = dates.elementAt(horizontalIndex);
  594. final duties = dutiesTlc.where((e) =>
  595. DTInterval(
  596. e.jdep ??
  597. e.jdate?.startOf(Unit.day) ??
  598. Jiffy.now(),
  599. e.jarr ??
  600. e.jdate?.endOf(Unit.day) ??
  601. Jiffy.now())
  602. .isOverlap(DTInterval(
  603. date.startOf(Unit.day),
  604. date.endOf(Unit.day))));
  605. if (pnleg.isEmpty) {
  606. return const Padding(
  607. padding: EdgeInsets.all(5.0),
  608. child: Center(
  609. child: Text("No Pnlegs data found"),
  610. ),
  611. );
  612. }
  613. return Padding(
  614. padding: const EdgeInsets.symmetric(
  615. horizontal: 2, vertical: 1),
  616. child: _rostersDay(
  617. date: date,
  618. legs: duties.toList(),
  619. color: date
  620. .endOf(Unit.day)
  621. .isBefore(now.startOf(Unit.day))
  622. ? Colors.grey[900]
  623. : Colors.black,
  624. border: date.yMEd == now.yMEd),
  625. );
  626. },
  627. ),
  628. ),
  629. ],
  630. );
  631. },
  632. ),
  633. );
  634. }
  635. @override
  636. void initState() {
  637. Future.delayed(Duration.zero).then((x) async {
  638. final savedcrewfilter =
  639. await Hive.box("settings").get("rosters.filter.crew");
  640. final savedflightsfilter =
  641. await Hive.box("settings").get("rosters.filter.flights");
  642. print(
  643. "rosters: saved crew filter: ${savedcrewfilter.runtimeType} $savedcrewfilter");
  644. print("rosters: saved flights filter: $savedflightsfilter");
  645. if (savedcrewfilter != null && savedcrewfilter is Map) {
  646. crewFilter = savedcrewfilter
  647. .map((key, value) => MapEntry(key, List<String>.from(value)));
  648. }
  649. if (savedflightsfilter != null && savedflightsfilter is Map) {
  650. flightFilter =
  651. savedflightsfilter.map((key, value) => MapEntry(key, value));
  652. }
  653. });
  654. super.initState();
  655. }
  656. }
  657. class PnlegMeta {
  658. PnlegMeta({required this.tlcs, required this.dates});
  659. final List<String> tlcs;
  660. final List<Jiffy> dates;
  661. }
  662. // final pnlegMeta = Provider((ref) {
  663. // print("data: start analyzing pnleg");
  664. // final now = Jiffy.now();
  665. // final data = ref.watch(dataProvider);
  666. // final pnlegs = data.pnleg;
  667. // final qualif = data.qualif;
  668. // Set<String> tlcs = {};
  669. // Set<Jiffy> dates = {};
  670. // for (Pnleg pnleg in pnlegs) {
  671. // tlcs.add(pnleg.tlc ?? "");
  672. // dates.add(pnleg.jdep?.startOf(Unit.day) ??
  673. // Jiffy.parse(pnleg.date ?? "01/01/1970",
  674. // pattern: "dd/MM/yyyy", isUtc: true));
  675. // }
  676. // // final restlcs = tlcs.sortedBy((k) =>qualif.firstWhereOrNull((q) => q.tlc == k)?.lname ?? "zzzzzzzzzzzzz");
  677. // final restlcs = tlcs.sortedBy((e) =>
  678. // "${qualif.firstWhereOrNull((k) => k.tlc == e)?.lname} ${qualif.firstWhereOrNull((k) => k.tlc == e)?.fname}");
  679. // final resdates = dates.sortedBy((k) => k.millisecondsSinceEpoch.toString());
  680. // print(
  681. // "data: end analyzing pnleg ${Duration(milliseconds: Jiffy.now().millisecondsSinceEpoch - now.millisecondsSinceEpoch).inSeconds} sec");
  682. // return PnlegMeta(tlcs: restlcs, dates: resdates);
  683. // });
  684. final pnlegMeta = Provider((ref) {
  685. print("data: start analyzing pnleg");
  686. final now = Jiffy.now();
  687. final data = ref.watch(dataProvider);
  688. final pnlegs = data.pnleg;
  689. final qualif = data.qualif;
  690. print(
  691. "data: end analyzing pnleg ${Duration(milliseconds: Jiffy.now().millisecondsSinceEpoch - now.millisecondsSinceEpoch).inSeconds} sec");
  692. return PnlegMeta(tlcs: pnleg.fold(<String>{}, (t, e) => {...t, e.tlc ?? ""}).sortedBy((e) {
  693. final pn = qualif.firstWhereOrNull((q) => q.tlc == e);
  694. return "${pn?.lname} ${pn?.fname}";
  695. }), dates: pnleg.fold(
  696. <Jiffy>{},
  697. (t, e) => {
  698. ...t,
  699. e.jdep?.startOf(Unit.day) ??
  700. Jiffy.parse(e.date ?? "01/01/1970",
  701. pattern: "dd/MM/yyyy", isUtc: true)
  702. }).sortedBy((e) => e.dateTime));
  703. });