Feat: Lacks overall total functionality
This commit is contained in:
parent
491ba3b55f
commit
4e3d4b5d33
|
@ -1,6 +1,4 @@
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:e_porter/_core/service/logger_service.dart';
|
|
||||||
|
|
||||||
import '../../domain/models/ticket_model.dart';
|
import '../../domain/models/ticket_model.dart';
|
||||||
import '../../domain/repositories/ticket_repository.dart';
|
import '../../domain/repositories/ticket_repository.dart';
|
||||||
|
|
||||||
|
@ -21,8 +19,7 @@ class TicketRepositoryImpl implements TicketRepository {
|
||||||
final startOfDay = DateTime(leavingDate.year, leavingDate.month, leavingDate.day);
|
final startOfDay = DateTime(leavingDate.year, leavingDate.month, leavingDate.day);
|
||||||
final endOfDay = startOfDay.add(Duration(days: 1));
|
final endOfDay = startOfDay.add(Duration(days: 1));
|
||||||
|
|
||||||
logger.d(
|
// logger.d("Fetching tickets with parameters: from = $from, to = $to, leavingDate between = ${Timestamp.fromDate(startOfDay)} and ${Timestamp.fromDate(endOfDay)}");
|
||||||
"Fetching tickets with parameters: from = $from, to = $to, leavingDate between = ${Timestamp.fromDate(startOfDay)} and ${Timestamp.fromDate(endOfDay)}");
|
|
||||||
|
|
||||||
final snapshot = await collection
|
final snapshot = await collection
|
||||||
.where('from', isEqualTo: from)
|
.where('from', isEqualTo: from)
|
||||||
|
@ -31,9 +28,9 @@ class TicketRepositoryImpl implements TicketRepository {
|
||||||
.where('leavingDate', isLessThan: Timestamp.fromDate(endOfDay))
|
.where('leavingDate', isLessThan: Timestamp.fromDate(endOfDay))
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
logger.d("Number of tickets found: ${snapshot.docs.length}");
|
// logger.d("Number of tickets found: ${snapshot.docs.length}");
|
||||||
snapshot.docs.forEach((doc) {
|
snapshot.docs.forEach((doc) {
|
||||||
logger.d("Doc ID: ${doc.id} => ${doc.data()}");
|
// logger.d("Doc ID: ${doc.id} => ${doc.data()}");
|
||||||
});
|
});
|
||||||
|
|
||||||
return snapshot.docs.map((doc) => TicketModel.fromDocument(doc)).toList();
|
return snapshot.docs.map((doc) => TicketModel.fromDocument(doc)).toList();
|
||||||
|
@ -52,9 +49,9 @@ class TicketRepositoryImpl implements TicketRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
final snapshot = await query.get();
|
final snapshot = await query.get();
|
||||||
logger.d("Number of flights found for ticket $ticketId with seatClass '$flightClass': ${snapshot.docs.length}");
|
// logger.d("Number of flights found for ticket $ticketId with seatClass '$flightClass': ${snapshot.docs.length}");
|
||||||
snapshot.docs.forEach((doc) {
|
snapshot.docs.forEach((doc) {
|
||||||
logger.d("Flight Doc ID: ${doc.id} => ${doc.data()}");
|
// logger.d("Flight Doc ID: ${doc.id} => ${doc.data()}");
|
||||||
});
|
});
|
||||||
|
|
||||||
return snapshot.docs.map((doc) => FlightModel.fromDocument(doc)).toList();
|
return snapshot.docs.map((doc) => FlightModel.fromDocument(doc)).toList();
|
||||||
|
@ -72,7 +69,7 @@ class TicketRepositoryImpl implements TicketRepository {
|
||||||
.doc(flightId)
|
.doc(flightId)
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
logger.d("getFlightById - TicketID: $ticketId, FlightID: $flightId, Data: ${doc.data()}");
|
// logger.d("getFlightById - TicketID: $ticketId, FlightID: $flightId, Data: ${doc.data()}");
|
||||||
|
|
||||||
return FlightModel.fromDocument(doc);
|
return FlightModel.fromDocument(doc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,9 @@ class CardFlightInformation extends StatelessWidget {
|
||||||
final String passenger;
|
final String passenger;
|
||||||
final String? transiAirplane;
|
final String? transiAirplane;
|
||||||
final String? stop;
|
final String? stop;
|
||||||
|
final String? departurePorter;
|
||||||
|
final String? arrivalPorter;
|
||||||
|
final String? transitPorter;
|
||||||
|
|
||||||
const CardFlightInformation({
|
const CardFlightInformation({
|
||||||
Key? key,
|
Key? key,
|
||||||
|
@ -31,6 +34,9 @@ class CardFlightInformation extends StatelessWidget {
|
||||||
required this.passenger,
|
required this.passenger,
|
||||||
this.transiAirplane,
|
this.transiAirplane,
|
||||||
this.stop,
|
this.stop,
|
||||||
|
this.departurePorter,
|
||||||
|
this.arrivalPorter,
|
||||||
|
this.transitPorter,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -85,12 +91,23 @@ class CardFlightInformation extends StatelessWidget {
|
||||||
servicePorter != null ? _buildText(context, text: servicePorter!) : SizedBox.shrink(),
|
servicePorter != null ? _buildText(context, text: servicePorter!) : SizedBox.shrink(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (departurePorter != null && departurePorter!.isNotEmpty) ... [
|
||||||
|
SizedBox(height: 4.h),
|
||||||
|
TypographyStyles.small(departurePorter!, color: GrayColors.gray600, fontWeight: FontWeight.w400),
|
||||||
|
],
|
||||||
|
if (arrivalPorter != null && arrivalPorter!.isNotEmpty) ... [
|
||||||
|
SizedBox(height: 4.h),
|
||||||
|
TypographyStyles.small(arrivalPorter!, color: GrayColors.gray600, fontWeight: FontWeight.w400),
|
||||||
|
],
|
||||||
|
if (transitPorter != null && transitPorter!.isNotEmpty) ... [
|
||||||
|
SizedBox(height: 4.h),
|
||||||
|
TypographyStyles.small(transitPorter!, color: GrayColors.gray600, fontWeight: FontWeight.w400),
|
||||||
|
],
|
||||||
SizedBox(height: 4.h),
|
SizedBox(height: 4.h),
|
||||||
TypographyStyles.small(
|
TypographyStyles.small(
|
||||||
'$passenger Dewasa',
|
'$passenger Dewasa',
|
||||||
color: GrayColors.gray600,
|
color: GrayColors.gray600,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
letterSpacing: 0.2,
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// ignore_for_file: unnecessary_null_comparison
|
// ignore_for_file: unnecessary_null_comparison
|
||||||
|
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:e_porter/_core/component/appbar/appbar_component.dart';
|
import 'package:e_porter/_core/component/appbar/appbar_component.dart';
|
||||||
import 'package:e_porter/_core/component/card/custome_shadow_cotainner.dart';
|
import 'package:e_porter/_core/component/card/custome_shadow_cotainner.dart';
|
||||||
import 'package:e_porter/_core/component/icons/icons_library.dart';
|
import 'package:e_porter/_core/component/icons/icons_library.dart';
|
||||||
|
@ -253,7 +255,7 @@ class _ChooseSeatScreenState extends State<ChooseSeatScreen> {
|
||||||
if (selectedSeatNumbers.any((seat) => seat.isEmpty)) {
|
if (selectedSeatNumbers.any((seat) => seat.isEmpty)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logger.d('Kursi: $selectedSeatNumbers');
|
log('Nomor Kursi: $selectedSeatNumbers');
|
||||||
Get.back(result: selectedSeatNumbers);
|
Get.back(result: selectedSeatNumbers);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// ignore_for_file: unnecessary_null_comparison
|
// ignore_for_file: unnecessary_null_comparison
|
||||||
|
|
||||||
import 'package:e_porter/_core/component/appbar/appbar_component.dart';
|
import 'package:e_porter/_core/component/appbar/appbar_component.dart';
|
||||||
import 'package:e_porter/_core/constants/colors.dart';
|
import 'package:e_porter/_core/constants/colors.dart';
|
||||||
import 'package:e_porter/_core/constants/typography.dart';
|
import 'package:e_porter/_core/constants/typography.dart';
|
||||||
|
@ -9,8 +8,6 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
import '../../../../_core/service/logger_service.dart';
|
|
||||||
import '../../../controllers/ticket_controller.dart';
|
import '../../../controllers/ticket_controller.dart';
|
||||||
|
|
||||||
class SearchTicketsScreen extends StatefulWidget {
|
class SearchTicketsScreen extends StatefulWidget {
|
||||||
|
@ -141,8 +138,7 @@ class _SearchTicketsScreenState extends State<SearchTicketsScreen> {
|
||||||
"ticketDate": ticketDate,
|
"ticketDate": ticketDate,
|
||||||
"passenger": passengerCount,
|
"passenger": passengerCount,
|
||||||
};
|
};
|
||||||
logger.d(
|
// logger.d('ID Ticket: $ticketId \nID Flight: $flightId \nTicket Date: $ticketDate \nPassenger: $passengerCount');
|
||||||
'ID Ticket: $ticketId \nID Flight: $flightId \nTicket Date: $ticketDate \nPassenger: $passengerCount');
|
|
||||||
Get.toNamed(Routes.TICKETBOOKINGSTEP1, arguments: argument);
|
Get.toNamed(Routes.TICKETBOOKINGSTEP1, arguments: argument);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -7,7 +7,6 @@ import 'package:e_porter/_core/component/card/custome_shadow_cotainner.dart';
|
||||||
import 'package:e_porter/_core/component/icons/icons_library.dart';
|
import 'package:e_porter/_core/component/icons/icons_library.dart';
|
||||||
import 'package:e_porter/_core/constants/colors.dart';
|
import 'package:e_porter/_core/constants/colors.dart';
|
||||||
import 'package:e_porter/_core/constants/typography.dart';
|
import 'package:e_porter/_core/constants/typography.dart';
|
||||||
import 'package:e_porter/_core/service/logger_service.dart';
|
|
||||||
import 'package:e_porter/_core/service/preferences_service.dart';
|
import 'package:e_porter/_core/service/preferences_service.dart';
|
||||||
import 'package:e_porter/_core/utils/snackbar/snackbar_helper.dart';
|
import 'package:e_porter/_core/utils/snackbar/snackbar_helper.dart';
|
||||||
import 'package:e_porter/domain/models/ticket_model.dart';
|
import 'package:e_porter/domain/models/ticket_model.dart';
|
||||||
|
@ -90,7 +89,7 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
|
||||||
}
|
}
|
||||||
final userId = userData.uid;
|
final userId = userData.uid;
|
||||||
await profilController.fetchPassangerById(userId);
|
await profilController.fetchPassangerById(userId);
|
||||||
logger.d('User ID: $userId');
|
// logger.d('User ID: $userId');
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isAllPassengersFilled() {
|
bool isAllPassengersFilled() {
|
||||||
|
@ -176,7 +175,7 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
|
||||||
textColor: Colors.white,
|
textColor: Colors.white,
|
||||||
backgroundColor: isAllPassengersFilled() ? PrimaryColors.primary800 : GrayColors.gray400,
|
backgroundColor: isAllPassengersFilled() ? PrimaryColors.primary800 : GrayColors.gray400,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
logger.d('Selected Passengers: $selectedPassengers');
|
// logger.d('Selected Passengers: $selectedPassengers');
|
||||||
if (selectedPassengers.any((p) => p == null)) {
|
if (selectedPassengers.any((p) => p == null)) {
|
||||||
SnackbarHelper.showError('Error', 'Harap lengkapi slot penumpang');
|
SnackbarHelper.showError('Error', 'Harap lengkapi slot penumpang');
|
||||||
} else {
|
} else {
|
||||||
|
@ -216,7 +215,7 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
|
||||||
} else if (snapshot.hasData && snapshot.data != null) {
|
} else if (snapshot.hasData && snapshot.data != null) {
|
||||||
final user = snapshot.data!;
|
final user = snapshot.data!;
|
||||||
_loggedUser = user;
|
_loggedUser = user;
|
||||||
logger.d('Data user: ${user.noId}');
|
// logger.d('Data user: ${user.noId}');
|
||||||
return CustomeShadowCotainner(
|
return CustomeShadowCotainner(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
@ -376,7 +375,7 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final passenger = profilController.passengerList[index];
|
final passenger = profilController.passengerList[index];
|
||||||
logger.d("Passenger Models : ${passenger.noId}");
|
// logger.d("Passenger Models : ${passenger.noId}");
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.only(top: 16.h),
|
padding: EdgeInsets.only(top: 16.h),
|
||||||
child: _buildAddPassenger(
|
child: _buildAddPassenger(
|
||||||
|
@ -574,7 +573,7 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
|
||||||
itemBuilder: (context, pIndex) {
|
itemBuilder: (context, pIndex) {
|
||||||
final passenger = profilController.passengerList[pIndex];
|
final passenger = profilController.passengerList[pIndex];
|
||||||
final isUsed = usedNoIds.contains(passenger.noId);
|
final isUsed = usedNoIds.contains(passenger.noId);
|
||||||
logger.d("Passenger Models : ${passenger.noId}");
|
// logger.d("Passenger Models : ${passenger.noId}");
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.only(top: 16.h),
|
padding: EdgeInsets.only(top: 16.h),
|
||||||
child: _buildAddPassenger(
|
child: _buildAddPassenger(
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import 'package:e_porter/_core/component/appbar/appbar_component.dart';
|
import 'package:e_porter/_core/component/appbar/appbar_component.dart';
|
||||||
import 'package:e_porter/_core/component/card/custome_shadow_cotainner.dart';
|
import 'package:e_porter/_core/component/card/custome_shadow_cotainner.dart';
|
||||||
import 'package:e_porter/_core/constants/colors.dart';
|
import 'package:e_porter/_core/constants/colors.dart';
|
||||||
import 'package:e_porter/_core/service/logger_service.dart';
|
|
||||||
import 'package:e_porter/domain/models/user_entity.dart';
|
import 'package:e_porter/domain/models/user_entity.dart';
|
||||||
import 'package:e_porter/presentation/controllers/ticket_controller.dart';
|
import 'package:e_porter/presentation/controllers/ticket_controller.dart';
|
||||||
import 'package:e_porter/presentation/screens/routes/app_rountes.dart';
|
import 'package:e_porter/presentation/screens/routes/app_rountes.dart';
|
||||||
|
@ -63,7 +62,7 @@ class _TicketBookingStep2ScreenState extends State<TicketBookingStep2Screen> {
|
||||||
selectedPassengers = args['selectedPassenger'] ?? [];
|
selectedPassengers = args['selectedPassenger'] ?? [];
|
||||||
selectedSeatNumbers = args['selectedSeatNumbers'] ?? List.filled(passenger, '');
|
selectedSeatNumbers = args['selectedSeatNumbers'] ?? List.filled(passenger, '');
|
||||||
|
|
||||||
logger.d('Ticket ID: $ticketId \nFlight ID: $flightId');
|
// logger.d('Ticket ID: $ticketId \nFlight ID: $flightId');
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -152,7 +151,7 @@ class _TicketBookingStep2ScreenState extends State<TicketBookingStep2Screen> {
|
||||||
'selectedPassenger': selectedPassengers,
|
'selectedPassenger': selectedPassengers,
|
||||||
'numberSeat': selectedSeatNumbers
|
'numberSeat': selectedSeatNumbers
|
||||||
};
|
};
|
||||||
logger.d('Number Seat: $selectedSeatNumbers \n Passenger: $selectedPassengers');
|
// logger.d('Number Seat: $selectedSeatNumbers \n Passenger: $selectedPassengers');
|
||||||
Get.toNamed(Routes.TICKETBOOKINGSTEP3, arguments: argument);
|
Get.toNamed(Routes.TICKETBOOKINGSTEP3, arguments: argument);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:e_porter/_core/component/card/custome_shadow_cotainner.dart';
|
import 'package:e_porter/_core/component/card/custome_shadow_cotainner.dart';
|
||||||
import 'package:e_porter/_core/component/icons/icons_library.dart';
|
import 'package:e_porter/_core/component/icons/icons_library.dart';
|
||||||
import 'package:e_porter/_core/constants/colors.dart';
|
import 'package:e_porter/_core/constants/colors.dart';
|
||||||
|
@ -49,6 +51,7 @@ class _TicketBookingStep3ScreenState extends State<TicketBookingStep3Screen> {
|
||||||
String? departureTime;
|
String? departureTime;
|
||||||
String? arrivalTime;
|
String? arrivalTime;
|
||||||
|
|
||||||
|
double totalPrice = 0.0;
|
||||||
double totalPriceService = 0.0;
|
double totalPriceService = 0.0;
|
||||||
PorterServiceModel? selectedDepartureService;
|
PorterServiceModel? selectedDepartureService;
|
||||||
PorterServiceModel? selectedArrivalService;
|
PorterServiceModel? selectedArrivalService;
|
||||||
|
@ -190,7 +193,7 @@ class _TicketBookingStep3ScreenState extends State<TicketBookingStep3Screen> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
double totalPrice = calculateTotalPrice(flightData?.price.toDouble() ?? 0.0, passenger);
|
totalPrice = calculateTotalPrice(flightData?.price.toDouble() ?? 0.0, passenger);
|
||||||
double grandTotal = totalPrice + totalPriceService;
|
double grandTotal = totalPrice + totalPriceService;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
@ -295,16 +298,37 @@ class _TicketBookingStep3ScreenState extends State<TicketBookingStep3Screen> {
|
||||||
selectedPorterServices['transit'] = selectedTransitService;
|
selectedPorterServices['transit'] = selectedTransitService;
|
||||||
}
|
}
|
||||||
final argument = {
|
final argument = {
|
||||||
'tickedId': ticketId,
|
'ticketId': ticketId,
|
||||||
'flightId': flightId,
|
'flightId': flightId,
|
||||||
'ticketDate': ticketDate,
|
'date': ticketDate,
|
||||||
'passenger': passenger,
|
'passenger': passenger,
|
||||||
'selectedPassenger': selectedPassengers,
|
'selectedPassenger': selectedPassengers,
|
||||||
'numberSeat': numberSeat,
|
'numberSeat': numberSeat,
|
||||||
|
'totalPrice': totalPrice,
|
||||||
'grandTotal': grandTotal,
|
'grandTotal': grandTotal,
|
||||||
'selectedServiceLabels': selectedServiceLabels,
|
'selectedServiceLabels': selectedServiceLabels,
|
||||||
'selectedPorter': selectedPorterServices,
|
'selectedPorterServices': selectedPorterServices,
|
||||||
};
|
};
|
||||||
|
log('Ticket ID: $ticketId');
|
||||||
|
log('Flight ID: $flightId');
|
||||||
|
log('Ticket Date: $ticketDate');
|
||||||
|
log('Opsi Penerbangan: $selectedServiceLabels');
|
||||||
|
log('Layanan Porter: $selectedPorterServices');
|
||||||
|
|
||||||
|
// final Map<String, dynamic> debugPorterServices = {};
|
||||||
|
// selectedPorterServices.forEach((key, value) {
|
||||||
|
// if (value != null) {
|
||||||
|
// debugPorterServices[key] = {
|
||||||
|
// 'id': value.id,
|
||||||
|
// 'name': value.name,
|
||||||
|
// 'price': value.price,
|
||||||
|
// };
|
||||||
|
// } else {
|
||||||
|
// debugPorterServices[key] = null;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// log('Layanan Porter: $debugPorterServices');
|
||||||
|
|
||||||
Get.toNamed(Routes.TICKETBOOKINGSTEP4, arguments: argument);
|
Get.toNamed(Routes.TICKETBOOKINGSTEP4, arguments: argument);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -10,8 +10,11 @@ import 'package:get/get.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import '../../../../_core/component/appbar/appbar_component.dart';
|
import '../../../../_core/component/appbar/appbar_component.dart';
|
||||||
import '../../../../_core/component/icons/icons_library.dart';
|
import '../../../../_core/component/icons/icons_library.dart';
|
||||||
|
import '../../../../_core/service/logger_service.dart';
|
||||||
import '../../../../domain/models/porter_service_model.dart';
|
import '../../../../domain/models/porter_service_model.dart';
|
||||||
|
import '../../../../domain/models/ticket_model.dart';
|
||||||
import '../../../../domain/models/user_entity.dart';
|
import '../../../../domain/models/user_entity.dart';
|
||||||
|
import '../../../controllers/ticket_controller.dart';
|
||||||
import '../component/card_flight_information.dart';
|
import '../component/card_flight_information.dart';
|
||||||
|
|
||||||
class TicketBookingStep4Screen extends StatefulWidget {
|
class TicketBookingStep4Screen extends StatefulWidget {
|
||||||
|
@ -28,27 +31,91 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
|
||||||
late final int passenger;
|
late final int passenger;
|
||||||
late final List<PassengerModel?> selectedPassengers;
|
late final List<PassengerModel?> selectedPassengers;
|
||||||
late List<String> numberSeat;
|
late List<String> numberSeat;
|
||||||
late double? grandTotal;
|
|
||||||
late List<String> selectedServiceLabels;
|
late List<String> selectedServiceLabels;
|
||||||
late Map<String, PorterServiceModel?> selectedPorterServices;
|
late Map<String, PorterServiceModel?> selectedPorterServices;
|
||||||
|
|
||||||
|
double? totalPrice;
|
||||||
|
double? grandTotal;
|
||||||
|
|
||||||
|
final TicketController ticketController = Get.find<TicketController>();
|
||||||
|
FlightModel? flightData;
|
||||||
|
String? departureTime;
|
||||||
|
String? arrivalTime;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
final args = Get.arguments as Map<String, dynamic>;
|
final args = Get.arguments as Map<String, dynamic>;
|
||||||
ticketId = args['ticketId'] ?? '';
|
ticketId = args['ticketId'] ?? '';
|
||||||
flightId = args['flightId'] ?? '';
|
flightId = args['flightId'] ?? '';
|
||||||
ticketDate = args['date'] ?? '';
|
ticketDate = args['date'];
|
||||||
passenger = args['passenger'] ?? 0;
|
passenger = args['passenger'] ?? 0;
|
||||||
selectedPassengers = args['selectedPassenger'] ?? [];
|
selectedPassengers = args['selectedPassenger'] ?? [];
|
||||||
numberSeat = args['numberSeat'] ?? '';
|
numberSeat = args['numberSeat'] ?? '';
|
||||||
grandTotal = args['grandTotal'] ?? 0;
|
totalPrice = args['totalPrice'] ?? 0.0;
|
||||||
|
grandTotal = args['grandTotal'] ?? 0.0;
|
||||||
selectedServiceLabels = args['selectedServiceLabels'] ?? [];
|
selectedServiceLabels = args['selectedServiceLabels'] ?? [];
|
||||||
selectedPorterServices = args['selectedPorterServices'] ?? {};
|
selectedPorterServices = args['selectedPorterServices'] ?? {};
|
||||||
|
|
||||||
|
// log('Ticket ID Step 4: $ticketId');
|
||||||
|
// log('Opsi Penerbangan Step 4: $selectedServiceLabels');
|
||||||
|
|
||||||
|
// if (selectedServiceLabels.isNotEmpty) {
|
||||||
|
// log('Opsi Penerbangan Step 4: ${selectedServiceLabels.join(", ")}');
|
||||||
|
// } else {
|
||||||
|
// log('Tidak ada opsi penerbangan yang dipilih');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// selectedPorterServices.forEach((key, value) {
|
||||||
|
// if (value != null) {
|
||||||
|
// log('Porter $key: ${value.name} - Rp ${value.price}');
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
fetchDataFlight();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> fetchDataFlight() async {
|
||||||
|
try {
|
||||||
|
FlightModel flight = await ticketController.getFlightById(ticketId: ticketId, flightId: flightId);
|
||||||
|
setState(() {
|
||||||
|
flightData = flight;
|
||||||
|
departureTime = DateFormat.jm().format(flightData!.departureTime);
|
||||||
|
arrivalTime = DateFormat.jm().format(flightData!.arrivalTime);
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
logger.e('Terjadi kesalahan: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String getPorterInfo(String type) {
|
||||||
|
final porter = selectedPorterServices[type];
|
||||||
|
if (porter != null) {
|
||||||
|
return '${porter.name}';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
String getPorterPrice(String type) {
|
||||||
|
final porter = selectedPorterServices[type];
|
||||||
|
if (porter != null) {
|
||||||
|
try {
|
||||||
|
return NumberFormat.decimalPattern('id_ID').format(porter.price);
|
||||||
|
} catch (e) {
|
||||||
|
print("Error formatting porter price: $e");
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final hasDeparturePorter =
|
||||||
|
selectedPorterServices.containsKey('departure') && selectedPorterServices['departure'] != null;
|
||||||
|
final hasArrivalPorter = selectedPorterServices.containsKey('arrival') && selectedPorterServices['arrival'] != null;
|
||||||
|
final hasTransitPorter = selectedPorterServices.containsKey('transit') && selectedPorterServices['transit'] != null;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: GrayColors.gray50,
|
backgroundColor: GrayColors.gray50,
|
||||||
appBar: ProgressAppbarComponent(
|
appBar: ProgressAppbarComponent(
|
||||||
|
@ -68,14 +135,18 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16.w),
|
padding: EdgeInsets.symmetric(horizontal: 16.w),
|
||||||
child: CardFlightInformation(
|
child: CardFlightInformation(
|
||||||
date: "Sen, 27 Jan 2025",
|
date: "$ticketDate",
|
||||||
time: "12.20 - 06.00 AM",
|
time: "$departureTime - $arrivalTime",
|
||||||
departureCity: "Yogyakarta",
|
departureCity: "${flightData?.cityDeparture}",
|
||||||
arrivalCity: "Lombok",
|
arrivalCity: "${flightData?.cityArrival}",
|
||||||
plane: "Citilink (103)",
|
plane: "${flightData?.airLines} (${flightData?.code})",
|
||||||
seatClass: "Economy",
|
seatClass: "${flightData?.flightClass}",
|
||||||
servicePorter: "Fast Track (FT)",
|
passenger: "$passenger",
|
||||||
passenger: "2",
|
transiAirplane: "${flightData?.transitAirplane}",
|
||||||
|
departurePorter: hasDeparturePorter ? "Keberangkatan (${getPorterInfo('departure')})" : null,
|
||||||
|
arrivalPorter: hasArrivalPorter ? "Kedatangan (${getPorterInfo('arrival')})" : null,
|
||||||
|
transitPorter: hasTransitPorter ? "Transit (${getPorterInfo('transit')})" : null,
|
||||||
|
stop: "${flightData?.stop}",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 32.h),
|
SizedBox(height: 32.h),
|
||||||
|
@ -86,13 +157,13 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
|
||||||
SizedBox(height: 20.h),
|
SizedBox(height: 20.h),
|
||||||
CustomeShadowCotainner(
|
CustomeShadowCotainner(
|
||||||
sizeRadius: 0.r,
|
sizeRadius: 0.r,
|
||||||
height: MediaQuery.of(context).size.height * 0.5,
|
height: MediaQuery.of(context).size.height * 0.4,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
TypographyStyles.body(
|
TypographyStyles.body(
|
||||||
"Citilink (103)",
|
"${flightData?.airLines} (${flightData?.code})",
|
||||||
color: GrayColors.gray800,
|
color: GrayColors.gray800,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
|
@ -101,30 +172,23 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 2.h),
|
SizedBox(height: 2.h),
|
||||||
Row(
|
_buildRowPorterWithClass(
|
||||||
children: [
|
detailDeparturePorter: hasDeparturePorter ? "${getPorterInfo('departure')}" : null,
|
||||||
TypographyStyles.small(
|
detailArrivalPorter: hasArrivalPorter ? "${getPorterInfo('arrival')}" : null,
|
||||||
"Fast Track (FT)",
|
detailTransitPorter: hasTransitPorter ? "${getPorterInfo('transit')}" : null,
|
||||||
color: GrayColors.gray600,
|
detailSeatClass: "${flightData?.flightClass}",
|
||||||
letterSpacing: 0.2,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
),
|
|
||||||
SizedBox(width: 10.w),
|
|
||||||
CircleAvatar(radius: 2.r, backgroundColor: Color(0xFFD9D9D9)),
|
|
||||||
SizedBox(width: 10.w),
|
|
||||||
TypographyStyles.small("Economy", color: GrayColors.gray600, fontWeight: FontWeight.w400),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
SizedBox(height: 16.h),
|
SizedBox(height: 16.h),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
TypographyStyles.caption(
|
TypographyStyles.caption(
|
||||||
"Rp 1.200.000",
|
"Rp ${NumberFormat.decimalPattern('id_ID').format(flightData?.price ?? 0.0)}",
|
||||||
color: GrayColors.gray600,
|
color: GrayColors.gray600,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
),
|
),
|
||||||
SizedBox(width: 8.w),
|
SizedBox(width: 8.w),
|
||||||
TypographyStyles.small("x 2", color: GrayColors.gray600, fontWeight: FontWeight.w400)
|
TypographyStyles.small("x ${passenger}",
|
||||||
|
color: GrayColors.gray600, fontWeight: FontWeight.w400)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
|
@ -140,14 +204,14 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
),
|
),
|
||||||
TypographyStyles.body(
|
TypographyStyles.body(
|
||||||
"Rp 2.400.000",
|
"Rp ${NumberFormat.decimalPattern('id_ID').format(totalPrice ?? 0.0)}",
|
||||||
color: GrayColors.gray600,
|
color: GrayColors.gray600,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 2.h),
|
SizedBox(height: 2.h),
|
||||||
_buildRowText(context, text: "Layanan porter (Fast Track)", valueText: "50.000"),
|
_buildTextService(),
|
||||||
SizedBox(height: 2.h),
|
SizedBox(height: 2.h),
|
||||||
_buildRowText(context, text: "Biaya layanan", valueText: "10.000"),
|
_buildRowText(context, text: "Biaya layanan", valueText: "10.000"),
|
||||||
],
|
],
|
||||||
|
@ -167,6 +231,84 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildRowPorterWithClass({
|
||||||
|
required String? detailDeparturePorter,
|
||||||
|
required String? detailArrivalPorter,
|
||||||
|
required String? detailTransitPorter,
|
||||||
|
required String detailSeatClass,
|
||||||
|
}) {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
if (detailDeparturePorter != null && detailDeparturePorter.isNotEmpty) ...[
|
||||||
|
TypographyStyles.small(
|
||||||
|
detailDeparturePorter,
|
||||||
|
color: GrayColors.gray600,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
SizedBox(width: 10.w),
|
||||||
|
CircleAvatar(radius: 2.r, backgroundColor: Color(0xFFD9D9D9)),
|
||||||
|
SizedBox(width: 10.w),
|
||||||
|
],
|
||||||
|
if (detailArrivalPorter != null && detailArrivalPorter.isNotEmpty) ...[
|
||||||
|
TypographyStyles.small(
|
||||||
|
detailArrivalPorter,
|
||||||
|
color: GrayColors.gray600,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
SizedBox(width: 10.w),
|
||||||
|
CircleAvatar(radius: 2.r, backgroundColor: Color(0xFFD9D9D9)),
|
||||||
|
SizedBox(width: 10.h),
|
||||||
|
],
|
||||||
|
if (detailTransitPorter != null && detailTransitPorter.isNotEmpty) ...[
|
||||||
|
TypographyStyles.small(
|
||||||
|
detailTransitPorter,
|
||||||
|
color: GrayColors.gray600,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
),
|
||||||
|
SizedBox(width: 10.w),
|
||||||
|
CircleAvatar(radius: 2.r, backgroundColor: Color(0xFFD9D9D9)),
|
||||||
|
SizedBox(width: 10.h),
|
||||||
|
],
|
||||||
|
TypographyStyles.small(detailSeatClass, color: GrayColors.gray600, fontWeight: FontWeight.w400),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTextService() {
|
||||||
|
final hasDeparturePorter =
|
||||||
|
selectedPorterServices.containsKey('departure') && selectedPorterServices['departure'] != null;
|
||||||
|
final hasArrivalPorter = selectedPorterServices.containsKey('arrival') && selectedPorterServices['arrival'] != null;
|
||||||
|
final hasTransitPorter = selectedPorterServices.containsKey('transit') && selectedPorterServices['transit'] != null;
|
||||||
|
final hasAnyPorter = hasDeparturePorter || hasArrivalPorter || hasTransitPorter;
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (!hasAnyPorter)
|
||||||
|
_buildContainerText(left: 0.w, label: 'Layanan Porter', price: '-')
|
||||||
|
else
|
||||||
|
_buildContainerText(left: 0.w, label: 'Layanan Porter', price: ''),
|
||||||
|
if (hasDeparturePorter)
|
||||||
|
_buildContainerText(
|
||||||
|
left: 8.w,
|
||||||
|
label: "Keberangkatan (${getPorterInfo('departure')})",
|
||||||
|
price: "Rp ${getPorterPrice('departure')}",
|
||||||
|
),
|
||||||
|
if (hasArrivalPorter)
|
||||||
|
_buildContainerText(
|
||||||
|
left: 8.w,
|
||||||
|
label: "Kedatangan (${getPorterInfo('arrival')})",
|
||||||
|
price: "Rp ${getPorterPrice('arrival')}",
|
||||||
|
),
|
||||||
|
if (hasTransitPorter)
|
||||||
|
_buildContainerText(
|
||||||
|
left: 8.w,
|
||||||
|
label: "Transit (${getPorterInfo('transit')})",
|
||||||
|
price: "Rp ${getPorterPrice('transit')}",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildRowText(
|
Widget _buildRowText(
|
||||||
BuildContext context, {
|
BuildContext context, {
|
||||||
required String text,
|
required String text,
|
||||||
|
@ -188,4 +330,21 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildContainerText({
|
||||||
|
required String label,
|
||||||
|
required String price,
|
||||||
|
required double left,
|
||||||
|
}) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.only(left: left),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
TypographyStyles.caption(label, color: GrayColors.gray600, fontWeight: FontWeight.w400),
|
||||||
|
TypographyStyles.caption(price, color: GrayColors.gray600, fontWeight: FontWeight.w400),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue