| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787 |
- // ignore_for_file: use_build_context_synchronously
- import 'package:collection/collection.dart';
- 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:hive_flutter/hive_flutter.dart';
- import 'package:jiffy/jiffy.dart';
- import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
- import 'package:tp5/core/basic_page.dart';
- import 'package:tp5/core/utils.dart';
- import 'package:tp5/ftl/provider/ftl.dart';
- import 'package:tp5/ftl/widget/w_shadowbox.dart';
- import 'package:tp5/roster/api/crewlink_api.dart';
- import 'package:tp5/roster/models/duty.dart';
- import 'package:scroll_to_index/scroll_to_index.dart';
- import 'package:tp5/roster/widgets/w_airport.dart';
- import 'package:tp5/roster/widgets/w_hour.dart';
- class FtlPage extends ConsumerStatefulWidget {
- const FtlPage({super.key, required this.params});
- final FtlPageParams params;
- @override
- ConsumerState<ConsumerStatefulWidget> createState() => _FtlPageState();
- }
- class _FtlPageState extends ConsumerState<FtlPage> {
- late String crewlinkUser;
- late String crewlinkPass;
- late String startdate;
- late String enddate;
- Map? roster;
- List<Duty> duties = [];
- String _rosterKey({String? clUser, String? start, String? end}) =>
- "roster_${clUser ?? crewlinkUser}_${start ?? startdate}_${end ?? enddate}";
- String fileidroster({String? clUser, String? start, String? end}) =>
- PathTo().crewlinkFile(
- "${_rosterKey(clUser: clUser, start: start, end: end)}.pdf");
- // String get _rosterKey =>
- // "roster_${crewlinkUser}_${widget.params.datestart}_${widget.params.dateend}";
- // String get fileidroster => PathTo().crewlinkFile("$_rosterKey.pdf");
- final AutoScrollController _scrollCtrl = AutoScrollController();
- late Jiffy now;
- @override
- void initState() {
- crewlinkUser = widget.params.crewlinkuser ??
- Hive.box("profile").get("crewlink_user") ??
- "";
- crewlinkPass = widget.params.crewlinkpass ??
- Hive.box("profile").get("crewlink_pass") ??
- "";
- startdate = widget.params.datestart ??
- Jiffy.now().toUtc().startOf(Unit.month).format(pattern: "ddMMMyy");
- enddate = widget.params.dateend ??
- Jiffy.now()
- .toUtc()
- //.add(months: 1)
- .endOf(Unit.month)
- .format(pattern: "ddMMMyy");
- Future.delayed(Duration.zero, () async {
- await _loadMinMax();
- //await _loadRoster();
- await _loadOldRoster();
- await _ftlCalc(base: 'DJE');
- }).then(
- (value) => Future.delayed(const Duration(milliseconds: 200), () async {
- _scrollToDate();
- }));
- super.initState();
- }
- bool _isLoading = false;
- Future<Map?> _loadRosterOnline(
- {String? clUser, String? start, String? end}) async {
- //print("FtlPage: Requesting ONline roster $start -> $end");
- if (!ref.read(crewlinkapiProvider).logged) {
- final login = await ref
- .read(crewlinkapiProvider)
- .login(username: crewlinkUser, password: crewlinkPass);
- if (login["data"]?["logged"] != true) {
- context.showError(login["error"] ?? "Unknown error");
- return null;
- }
- }
- final roster = await ref.read(crewlinkapiProvider).roster(
- start: start ?? startdate
- //??Jiffy.now().toUtc().startOf(Unit.month).format(pattern: "ddMMMyy")
- ,
- end: end ?? enddate
- //??Jiffy.now().toUtc().endOf(Unit.month).format(pattern: "ddMMMyy")
- ,
- fileid: fileidroster(clUser: clUser, start: start, end: end));
- if (roster?["data"]?["msg"] != null) {
- context.showError(roster?["data"]?["msg"] ?? "Unknown error");
- }
- if (roster["error"] == null && roster["data"] != null) {
- if (roster["msg"] != null) context.showAlert(roster["msg"]);
- Hive.box("crewlink")
- .put(_rosterKey(clUser: clUser, start: start, end: end), roster);
- return roster;
- }
- return null;
- }
- Future<Map?> _loadRosterOffline(
- {String? clUser, String? start, String? end}) async {
- //print("FtlPage: Requesting OFFline roster $start -> $end");
- return Hive.box("crewlink")
- .get(_rosterKey(clUser: clUser, start: start, end: end));
- }
- _loadRoster(
- {String? clUser,
- String? start,
- String? end,
- bool cachefirst = false}) async {
- try {
- ref.read(isLoadingProvider.notifier).state = true;
- final rosterOffline =
- await _loadRosterOffline(clUser: clUser, start: start, end: end);
- if (rosterOffline?["data"]?["decoded"] is Map) {
- print(
- "FTL Page: found offline: $start ${rosterOffline?["data"]?["decoded"] is Map}");
- _convertRoster(rosterOffline);
- setState(() {});
- }
- if (rosterOffline?["data"]?["decoded"] is! Map || !cachefirst) {
- final rosterOnline =
- await _loadRosterOnline(clUser: clUser, start: start, end: end);
- if (rosterOnline?["data"]?["decoded"] is Map) {
- print(
- "FTL Page: found online: $start ${rosterOnline?["data"]?["decoded"] is Map}");
- _convertRoster(rosterOnline);
- setState(() {});
- } else if (rosterOffline?["data"]?["decoded"] is Map) {
- print(
- "FTL Page: found offline: $start ${rosterOffline?["data"]?["decoded"] is Map}");
- _convertRoster(rosterOnline);
- setState(() {});
- }
- }
- } finally {
- ref.read(isLoadingProvider.notifier).state = false;
- }
- }
- _loadOldRoster() async {
- bool exitnow = false;
- // _rosterMax = Jiffy.now().toUtc().endOf(Unit.month).subtract(hours: 10);
- Jiffy date1 = Jiffy.parse(startdate, pattern: "ddMMMyy")
- .subtract(months: 11)
- .startOf(Unit.day)
- .startOf(Unit.month)
- .max(_rosterMin ?? Jiffy.now().toUtc().startOf(Unit.month));
- while (!exitnow) {
- Jiffy date2 = date1
- .endOf(Unit.month)
- .min(_rosterMax?.endOf(Unit.day) ?? Jiffy.now().toUtc().add(days: 3));
- if (date2.isAfter(date1) &&
- date2.endOf(Unit.month) == date1.endOf(Unit.month)) {
- //print("ftlpage: loadoldroster: loading ${DTInterval(date1, date2)}");
- await _loadRoster(
- start: date1.format(pattern: "ddMMMyy"),
- end: date2.format(pattern: "ddMMMyy"),
- cachefirst: date1
- .endOf(Unit.month)
- .isBefore(Jiffy.now().endOf(Unit.month)));
- } else {
- exitnow = true;
- }
- date1 = date1.add(months: 1).startOf(Unit.month);
- }
- }
- String get _rosterMinMaxKey => "minmax_$crewlinkUser";
- _loadMinMax() async {
- final resoff = Hive.box("crewlink").get(_rosterMinMaxKey);
- //print("ftlpage: resoff: $resoff");
- final reson = await ref.read(crewlinkapiProvider).rosterMinMax();
- //print("ftlpage: reson: $reson");
- ref.read(isLoadingProvider.notifier).state = false;
- dynamic res;
- if (reson != null && reson["error"] == null && reson?["data"] != null) {
- Hive.box("crewlink").put(_rosterMinMaxKey, reson["data"]);
- res = reson["data"];
- } else if (resoff == null) {
- //print(reson["error"] ?? "Unknown error");
- }
- res = res ?? resoff;
- _rosterMin =
- Jiffy.parse(res["mindate"], pattern: "yyyy-MM-dd", isUtc: true);
- _rosterMax =
- Jiffy.parse(res["maxdate"], pattern: "yyyy-MM-dd", isUtc: true);
- }
- Jiffy? _rosterMin;
- Jiffy? _rosterMax;
- _scrollToDate({Jiffy? date}) async {
- final jdate = date ?? Jiffy.now().toUtc();
- bool found = false;
- int id = 0;
- for (Duty duty in duties) {
- // if (duty.jdate.yMd == jdate.yMd) {
- if (duty.jdate.isSameOrAfter(jdate)) {
- found = true;
- break;
- }
- id++;
- }
- if (found && mounted && _scrollCtrl.hasClients) {
- // await _scrollCtrl.scrollToIndex(duties.length - 30,
- // duration: const Duration(milliseconds: 500),
- // preferPosition: AutoScrollPosition.end);
- await _scrollCtrl.scrollToIndex(0,
- duration: const Duration(milliseconds: 1000),
- preferPosition: AutoScrollPosition.end);
- await _scrollCtrl.scrollToIndex(id,
- duration: const Duration(milliseconds: 1000),
- preferPosition: AutoScrollPosition.end);
- }
- }
- int i = 0;
- _convertRoster(Map? input) {
- roster = input;
- final decoded = (input?["data"]?["decoded"]?["roster"] ?? {});
- for (var date in decoded.keys) {
- duties = duties.where((e) => e.date != date).toList();
- var dutylist = (decoded[date] as List);
- for (var duty in dutylist) {
- i++;
- duties.add(
- Duty(date: date, type: duty["type"], data: duty["data"], order: i));
- //print("${(duties.last).jdate.yMd} ${(duties.last).type} ${(duties.last).start?.Hm} ${(duties.last).end?.Hm}");
- }
- }
- }
- Ftl ftldata = Ftl.fromCrewlink(clDuties: [], base: 'DJE');
- Jiffy ftlcalcdate = Jiffy.now().subtract(days: 30).startOf(Unit.month);
- _ftlCalc({required String base}) async {
- ref.read(isLoadingProvider.notifier).state = true;
- ftldata = Ftl.fromCrewlink(clDuties: duties, base: base);
- //await compute(ftlCalc, {"clDuties": duties, "base": base});
- // await ftldata.calcduties(date: null);
- await ftldata.calcduties(date: ftlcalcdate);
- ref.read(isLoadingProvider.notifier).state = false;
- }
- @override
- Widget build(BuildContext context) {
- return BasicPage(
- actions: [
- ElevatedButton(
- onPressed: _isLoading
- ? null
- : () async {
- setState(() {
- _isLoading = true;
- });
- await _ftlCalc(base: "DJE");
- setState(() {
- _isLoading = false;
- });
- },
- child: const Text("calc"))
- ],
- title: "FTL",
- body: ftldata.duties.isEmpty
- ? const Text("Please wait, calculations in progress...")
- : ListView.builder(
- itemCount: ftldata.duties.length,
- itemBuilder: (contexte, index) => AutoScrollTag(
- key: ValueKey(index),
- controller: _scrollCtrl,
- index: index,
- child: (ftldata.duties
- .elementAt(index)
- .start!
- .isSameOrAfter(ftlcalcdate))
- ? _getItem(contexte, index)
- : Container(),
- ),
- shrinkWrap: false,
- controller: _scrollCtrl,
- ),
- );
- }
- bool _is36h(DTInterval? e, String station) {
- if (e == null) return false;
- final firstnight = DTInterval.fromHm(
- apartir: Ftl.changeTz(e.start, station).toUtc(),
- h: 23,
- m: 0,
- duration: const Duration(hours: 7, minutes: 59),
- ap: station);
- final secondnight =
- DTInterval(firstnight.start.add(days: 1), firstnight.end.add(days: 1));
- if (e.duration.inHours >= 36 &&
- e.contains(firstnight) &&
- e.contains(secondnight)) {
- return true;
- } else {
- return false;
- }
- }
- bool _is48h(DTInterval? e, String station) {
- if (e == null) return false;
- final localdays = DTInterval.fromHm(
- apartir: Ftl.changeTz(e.start, station).toUtc(),
- h: 0,
- m: 0,
- duration: const Duration(hours: 47, minutes: 59),
- ap: station);
- if (e.contains(localdays)) {
- return true;
- } else {
- return false;
- }
- }
- _showDutyInfo(int i) {
- final duty = ftldata.duties[i];
- //print("ftlpage: ${duty.interval} ${duty.type}");
- final margin =
- ((duty.fdpExt ? duty.fdpExtMax : duty.fdpMax) ?? Duration.zero)
- .subtract(duty.fdpLength);
- showMaterialModalBottomSheet(
- bounce: true,
- context: context,
- builder: (context) => Container(
- padding: const EdgeInsets.all(10),
- decoration: const BoxDecoration(
- border: Border(top: BorderSide(width: 3, color: Colors.white70))),
- //height: 250,
- child: SingleChildScrollView(
- child: Column(
- children: [
- const Gap(5),
- ElevatedButton(
- onPressed: () {
- context.pop();
- },
- child: const Text(
- "Close",
- style: TextStyle(
- color: Colors.red, fontWeight: FontWeight.w700),
- )),
- const Gap(5),
- const Text(
- "Duty FTL Details",
- style: TextStyle(fontSize: 22),
- ),
- const Gap(10),
- Row(
- children: [
- const Text("Duty:",
- style: TextStyle(fontWeight: FontWeight.w800)),
- const Gap(20),
- _titleInfo(duty.start!.yMMMEd, duty.start!.Hm),
- const Gap(20),
- _titleInfo(duty.start!.yMMMEd, duty.end!.Hm)
- ],
- ),
- const Gap(20),
- if (duty.fdpStart != null)
- Row(
- children: [
- const Text("FDP:",
- style: TextStyle(fontWeight: FontWeight.w800)),
- const Gap(20),
- _titleInfo("FDP Length", duty.fdpLength.tohhmm),
- const Gap(20),
- _titleInfo("Fdp Max", duty.fdpMax!.tohhmm),
- const Gap(20),
- _titleInfo("Fdp Ext Max", duty.fdpExtMax!.tohhmm),
- const Gap(20),
- _titleInfo(margin.isNegative ? "Exceeded" : "Margin",
- margin.abs().tohhmm,
- color: margin.isNegative ? Colors.red : Colors.green,
- sizeinfo: 12),
- ],
- ),
- const Gap(20),
- if (duty.fdpStart != null)
- Row(
- children: [
- const Text("Acclim:",
- style: TextStyle(fontWeight: FontWeight.w800)),
- const Gap(20),
- _titleInfo("Acclim type", duty.acclim),
- const Gap(20),
- _titleInfo("Ref time", duty.reftime),
- ],
- ),
- const Gap(20),
- if (duty.fdpStart != null)
- Row(
- children: [
- const Text("Report:",
- style: TextStyle(fontWeight: FontWeight.w800)),
- const Gap(10),
- _titleInfo("Report time", duty.start?.Hm ?? "----"),
- const Gap(10),
- _titleInfo(
- "Delayed Report1", duty.reportdelay1?.Hm ?? "----"),
- const Gap(10),
- _titleInfo(
- "Delayed Report1", duty.reportdelay2?.Hm ?? "----"),
- ],
- ),
- const Gap(20),
- if (duty.fdpStart != null &&
- (duty.lateFinish || duty.earlyStart || duty.nightDuty))
- Row(
- children: [
- const Text("Disruptive:",
- style: TextStyle(fontWeight: FontWeight.w800)),
- const Gap(10),
- if (duty.earlyStart)
- const Text("early start duty",
- style: TextStyle(
- fontWeight: FontWeight.w800,
- fontSize: 12,
- color: Colors.cyan)),
- const Gap(10),
- if (duty.lateFinish)
- const Text("late finish duty",
- style: TextStyle(
- fontWeight: FontWeight.w800,
- fontSize: 12,
- color: Colors.cyan)),
- const Gap(10),
- if (duty.nightDuty)
- const Text("night duty",
- style: TextStyle(
- fontWeight: FontWeight.w800,
- fontSize: 12,
- color: Colors.cyan)),
- const Gap(10),
- ],
- ),
- const Gap(20),
- Row(
- children: [
- SingleChildScrollView(
- scrollDirection: Axis.horizontal,
- child: Row(
- mainAxisSize: MainAxisSize.max,
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- const Text("Detail:",
- style: TextStyle(fontWeight: FontWeight.w800)),
- ...(duty.dutiesDetailsIndex.map((e) {
- final detail = ftldata.dutiesDetails[e];
- final label = (detail.placeEnd != null)
- ? "${detail.placeStart}-${detail.placeEnd}"
- : "${detail.label}";
- return [
- const Gap(20),
- _titleInfo(label,
- "${detail.start?.Hm}-${detail.end?.Hm}",
- sizeinfo: 10)
- ];
- }).flattened),
- ]),
- ),
- ],
- ),
- const Gap(20),
- Row(
- children: [
- const Text("Tot duties hrs:",
- style: TextStyle(fontWeight: FontWeight.w800)),
- const Gap(10),
- _titleInfo("7 days",
- "${duty.dutyTotal?.dutylast7?.tohhmm}|${Ftl.maxdutylast7.tohhmm}",
- sizeinfo: 10),
- const Gap(5),
- _titleInfo("14 days",
- "${duty.dutyTotal?.dutylast14?.tohhmm}|${Ftl.maxdutylast14.tohhmm}",
- sizeinfo: 10),
- const Gap(5),
- _titleInfo("28 days",
- "${duty.dutyTotal?.dutylast28?.tohhmm}|${Ftl.maxdutylast28.tohhmm}",
- sizeinfo: 10),
- ],
- ),
- const Gap(20),
- Row(
- children: [
- const Text("Tot Flt hrs:",
- style: TextStyle(fontWeight: FontWeight.w800)),
- const Gap(10),
- _titleInfo("28 days",
- "${duty.dutyTotal?.fltlast28?.tohhmm}|${Ftl.maxfltlast28.tohhmm}",
- sizeinfo: 10),
- const Gap(5),
- _titleInfo("12 months",
- "${duty.dutyTotal?.fltlast12?.tohhmm}|${Ftl.maxfltlast12.tohhmm}",
- sizeinfo: 10),
- const Gap(5),
- _titleInfo("year",
- "${duty.dutyTotal?.fltyear?.tohhmm}|${Ftl.maxfltlastyear.tohhmm}",
- sizeinfo: 10),
- ],
- ),
- ],
- ),
- ),
- ),
- );
- }
- _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)),
- ],
- );
- Widget _getItem(BuildContext _, int i) {
- final duty = ftldata.duties.elementAt(i);
- final lastduty = i == 0 ? null : ftldata.duties.elementAt(i - 1);
- final rest =
- lastduty == null ? null : DTInterval(lastduty.end!, duty.start!);
- Color legal;
- if (duty.legals.isEmpty) {
- legal = Colors.green[900]!;
- } else if (duty.legals.every((e) => (e.condition ?? "") != "")) {
- legal = Colors.amber;
- } else {
- legal = Colors.red;
- }
- return Column(
- children: [
- if (lastduty != null)
- WShadowbox(
- child: Column(children: [
- Container(
- decoration: const BoxDecoration(
- color: Color.fromARGB(255, 8, 9, 9),
- border: Border(top: BorderSide(width: 5)),
- borderRadius: BorderRadius.all(Radius.circular(10.0)),
- ),
- padding: const EdgeInsets.all(5),
- // width: double.infinity,
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Column(
- children: [
- _titleInfo("Rest",
- "${(rest?.duration.inDays ?? 0)} days, ${(rest?.duration.inHours ?? 0) % 24} hours, ${(rest?.duration.inMinutes ?? 0) % 60} minutes",
- sizeinfo: 10),
- ],
- ),
- Column(children: [
- if (_is48h(rest, lastduty.placeEnd ?? "UTC"))
- Container(
- color: Colors.teal[900],
- padding: const EdgeInsets.all(5),
- child: Text(
- "48h with 2 local days",
- style: TextStyle(
- color: Colors.yellow[600]!,
- fontSize: 11,
- fontWeight: FontWeight.w600),
- )),
- if (_is36h(rest, lastduty.placeEnd ?? "UTC"))
- Container(
- color: Colors.teal[800],
- padding: const EdgeInsets.all(5),
- child: Text(
- "36h with 2 local nights",
- style: TextStyle(
- color: Colors.yellow[500]!,
- fontSize: 11,
- fontWeight: FontWeight.w600),
- ))
- ]),
- ],
- ),
- )
- ])),
- InkWell(
- onTap: () => _showDutyInfo(i),
- child: WShadowbox(
- child: Column(
- children: [
- Container(
- decoration: BoxDecoration(
- color: const Color.fromARGB(255, 1, 45, 47),
- border: Border(top: BorderSide(width: 5, color: legal)),
- borderRadius:
- const BorderRadius.vertical(top: Radius.circular(10.0)),
- ),
- padding: const EdgeInsets.symmetric(horizontal: 20),
- // width: double.infinity,
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text(
- "${duty.start?.format(pattern: "dd MMM'yy")}",
- style: const TextStyle(color: Colors.white54),
- ),
- if (duty.start != null) WHour(jiffy: duty.start!),
- ],
- ),
- ),
- Container(
- width: double.infinity,
- padding: const EdgeInsets.only(left: 20, right: 10),
- decoration: const BoxDecoration(
- color: Colors.black,
- ),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: duty.legals
- .map((e) => Text(
- "+ ${e.condition ?? ""} ${e.legalCauseMsg}",
- style: const TextStyle(fontSize: 10),
- ))
- .toList()),
- ),
- //details
- ...duty.dutiesDetailsIndex.map((index) {
- final FtlDutyDetails dutydetail =
- ftldata.dutiesDetails[index];
- return Row(
- children: [
- const Gap(40),
- SizedBox(
- width: 50,
- child: Row(children: [
- Text(
- dutydetail.typeString,
- style: TextStyle(
- backgroundColor: Colors.blueGrey[900],
- color: Colors.yellow,
- fontSize: 10,
- fontWeight: FontWeight.w600,
- ),
- )
- ]),
- ),
- SizedBox(
- width: 60,
- child: Row(
- children: [
- WHour(
- jiffy: dutydetail.start!,
- size: 12,
- color: Colors.white38,
- ),
- const Gap(5),
- WHour(
- jiffy: dutydetail.end!,
- size: 12,
- color: Colors.white38,
- ),
- ],
- ),
- ),
- SizedBox(
- // width: 80,
- child: Row(children: [
- const Gap(10),
- if (dutydetail.placeStart != null)
- WAirport(iata: dutydetail.placeStart!, size: 12),
- if (dutydetail.placeEnd != null) ...[
- const Icon(Icons.arrow_right_alt, size: 9),
- WAirport(iata: dutydetail.placeEnd!, size: 12)
- ] else if ((dutydetail.label ?? "") != "")
- Text(" (${dutydetail.label})",
- style: const TextStyle(
- color: Colors.white54,
- fontSize: 10,
- letterSpacing: 2),
- overflow: TextOverflow.ellipsis),
- ]),
- ),
- ],
- );
- }),
- Container(
- decoration: const BoxDecoration(
- color: Color.fromARGB(255, 1, 45, 47),
- borderRadius:
- BorderRadius.vertical(bottom: Radius.circular(10.0)),
- ),
- padding: const EdgeInsets.symmetric(horizontal: 20),
- // width: double.infinity,
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- if (duty.end != null && duty.start != null)
- _titleInfo(
- "Duty length",
- duty.end!.dateTime
- .difference(duty.start!.dateTime)
- .tohhmm),
- const Row(children: []),
- Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Text(
- (duty.end?.yMMMd != duty.start?.yMMMd)
- ? "${duty.end?.format(pattern: "dd MMM")}"
- : "",
- style: const TextStyle(
- color: Colors.white54, fontSize: 12),
- ),
- if (duty.end != null) WHour(jiffy: duty.end!),
- ],
- ),
- ],
- ),
- ),
- ],
- ),
- ),
- ),
- ],
- );
- }
- }
- class FtlPageParams {
- const FtlPageParams({
- this.dateend,
- this.datestart,
- this.crewlinkuser,
- this.crewlinkpass,
- });
- final String? dateend;
- final String? datestart;
- final String? crewlinkuser;
- final String? crewlinkpass;
- }
|