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:e_porter/_core/service/logger_service.dart';
|
||||
|
||||
import '../../domain/models/ticket_model.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 endOfDay = startOfDay.add(Duration(days: 1));
|
||||
|
||||
logger.d(
|
||||
"Fetching tickets with parameters: from = $from, to = $to, leavingDate between = ${Timestamp.fromDate(startOfDay)} and ${Timestamp.fromDate(endOfDay)}");
|
||||
// logger.d("Fetching tickets with parameters: from = $from, to = $to, leavingDate between = ${Timestamp.fromDate(startOfDay)} and ${Timestamp.fromDate(endOfDay)}");
|
||||
|
||||
final snapshot = await collection
|
||||
.where('from', isEqualTo: from)
|
||||
|
@ -31,9 +28,9 @@ class TicketRepositoryImpl implements TicketRepository {
|
|||
.where('leavingDate', isLessThan: Timestamp.fromDate(endOfDay))
|
||||
.get();
|
||||
|
||||
logger.d("Number of tickets found: ${snapshot.docs.length}");
|
||||
// logger.d("Number of tickets found: ${snapshot.docs.length}");
|
||||
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();
|
||||
|
@ -52,9 +49,9 @@ class TicketRepositoryImpl implements TicketRepository {
|
|||
}
|
||||
|
||||
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) {
|
||||
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();
|
||||
|
@ -72,7 +69,7 @@ class TicketRepositoryImpl implements TicketRepository {
|
|||
.doc(flightId)
|
||||
.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);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,9 @@ class CardFlightInformation extends StatelessWidget {
|
|||
final String passenger;
|
||||
final String? transiAirplane;
|
||||
final String? stop;
|
||||
final String? departurePorter;
|
||||
final String? arrivalPorter;
|
||||
final String? transitPorter;
|
||||
|
||||
const CardFlightInformation({
|
||||
Key? key,
|
||||
|
@ -31,6 +34,9 @@ class CardFlightInformation extends StatelessWidget {
|
|||
required this.passenger,
|
||||
this.transiAirplane,
|
||||
this.stop,
|
||||
this.departurePorter,
|
||||
this.arrivalPorter,
|
||||
this.transitPorter,
|
||||
});
|
||||
|
||||
@override
|
||||
|
@ -85,12 +91,23 @@ class CardFlightInformation extends StatelessWidget {
|
|||
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),
|
||||
TypographyStyles.small(
|
||||
'$passenger Dewasa',
|
||||
color: GrayColors.gray600,
|
||||
fontWeight: FontWeight.w400,
|
||||
letterSpacing: 0.2,
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// 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/card/custome_shadow_cotainner.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)) {
|
||||
return;
|
||||
}
|
||||
logger.d('Kursi: $selectedSeatNumbers');
|
||||
log('Nomor Kursi: $selectedSeatNumbers');
|
||||
Get.back(result: selectedSeatNumbers);
|
||||
},
|
||||
),
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
// ignore_for_file: unnecessary_null_comparison
|
||||
|
||||
import 'package:e_porter/_core/component/appbar/appbar_component.dart';
|
||||
import 'package:e_porter/_core/constants/colors.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:get/get.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../../../../_core/service/logger_service.dart';
|
||||
import '../../../controllers/ticket_controller.dart';
|
||||
|
||||
class SearchTicketsScreen extends StatefulWidget {
|
||||
|
@ -141,8 +138,7 @@ class _SearchTicketsScreenState extends State<SearchTicketsScreen> {
|
|||
"ticketDate": ticketDate,
|
||||
"passenger": passengerCount,
|
||||
};
|
||||
logger.d(
|
||||
'ID Ticket: $ticketId \nID Flight: $flightId \nTicket Date: $ticketDate \nPassenger: $passengerCount');
|
||||
// logger.d('ID Ticket: $ticketId \nID Flight: $flightId \nTicket Date: $ticketDate \nPassenger: $passengerCount');
|
||||
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/constants/colors.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/utils/snackbar/snackbar_helper.dart';
|
||||
import 'package:e_porter/domain/models/ticket_model.dart';
|
||||
|
@ -90,7 +89,7 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
|
|||
}
|
||||
final userId = userData.uid;
|
||||
await profilController.fetchPassangerById(userId);
|
||||
logger.d('User ID: $userId');
|
||||
// logger.d('User ID: $userId');
|
||||
}
|
||||
|
||||
bool isAllPassengersFilled() {
|
||||
|
@ -176,7 +175,7 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
|
|||
textColor: Colors.white,
|
||||
backgroundColor: isAllPassengersFilled() ? PrimaryColors.primary800 : GrayColors.gray400,
|
||||
onTap: () {
|
||||
logger.d('Selected Passengers: $selectedPassengers');
|
||||
// logger.d('Selected Passengers: $selectedPassengers');
|
||||
if (selectedPassengers.any((p) => p == null)) {
|
||||
SnackbarHelper.showError('Error', 'Harap lengkapi slot penumpang');
|
||||
} else {
|
||||
|
@ -216,7 +215,7 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
|
|||
} else if (snapshot.hasData && snapshot.data != null) {
|
||||
final user = snapshot.data!;
|
||||
_loggedUser = user;
|
||||
logger.d('Data user: ${user.noId}');
|
||||
// logger.d('Data user: ${user.noId}');
|
||||
return CustomeShadowCotainner(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
@ -376,7 +375,7 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
|
|||
shrinkWrap: true,
|
||||
itemBuilder: (context, index) {
|
||||
final passenger = profilController.passengerList[index];
|
||||
logger.d("Passenger Models : ${passenger.noId}");
|
||||
// logger.d("Passenger Models : ${passenger.noId}");
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 16.h),
|
||||
child: _buildAddPassenger(
|
||||
|
@ -574,7 +573,7 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
|
|||
itemBuilder: (context, pIndex) {
|
||||
final passenger = profilController.passengerList[pIndex];
|
||||
final isUsed = usedNoIds.contains(passenger.noId);
|
||||
logger.d("Passenger Models : ${passenger.noId}");
|
||||
// logger.d("Passenger Models : ${passenger.noId}");
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 16.h),
|
||||
child: _buildAddPassenger(
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
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/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/presentation/controllers/ticket_controller.dart';
|
||||
import 'package:e_porter/presentation/screens/routes/app_rountes.dart';
|
||||
|
@ -63,7 +62,7 @@ class _TicketBookingStep2ScreenState extends State<TicketBookingStep2Screen> {
|
|||
selectedPassengers = args['selectedPassenger'] ?? [];
|
||||
selectedSeatNumbers = args['selectedSeatNumbers'] ?? List.filled(passenger, '');
|
||||
|
||||
logger.d('Ticket ID: $ticketId \nFlight ID: $flightId');
|
||||
// logger.d('Ticket ID: $ticketId \nFlight ID: $flightId');
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -152,7 +151,7 @@ class _TicketBookingStep2ScreenState extends State<TicketBookingStep2Screen> {
|
|||
'selectedPassenger': selectedPassengers,
|
||||
'numberSeat': selectedSeatNumbers
|
||||
};
|
||||
logger.d('Number Seat: $selectedSeatNumbers \n Passenger: $selectedPassengers');
|
||||
// logger.d('Number Seat: $selectedSeatNumbers \n Passenger: $selectedPassengers');
|
||||
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/icons/icons_library.dart';
|
||||
import 'package:e_porter/_core/constants/colors.dart';
|
||||
|
@ -49,6 +51,7 @@ class _TicketBookingStep3ScreenState extends State<TicketBookingStep3Screen> {
|
|||
String? departureTime;
|
||||
String? arrivalTime;
|
||||
|
||||
double totalPrice = 0.0;
|
||||
double totalPriceService = 0.0;
|
||||
PorterServiceModel? selectedDepartureService;
|
||||
PorterServiceModel? selectedArrivalService;
|
||||
|
@ -190,7 +193,7 @@ class _TicketBookingStep3ScreenState extends State<TicketBookingStep3Screen> {
|
|||
|
||||
@override
|
||||
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;
|
||||
|
||||
return Scaffold(
|
||||
|
@ -295,16 +298,37 @@ class _TicketBookingStep3ScreenState extends State<TicketBookingStep3Screen> {
|
|||
selectedPorterServices['transit'] = selectedTransitService;
|
||||
}
|
||||
final argument = {
|
||||
'tickedId': ticketId,
|
||||
'ticketId': ticketId,
|
||||
'flightId': flightId,
|
||||
'ticketDate': ticketDate,
|
||||
'date': ticketDate,
|
||||
'passenger': passenger,
|
||||
'selectedPassenger': selectedPassengers,
|
||||
'numberSeat': numberSeat,
|
||||
'totalPrice': totalPrice,
|
||||
'grandTotal': grandTotal,
|
||||
'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);
|
||||
},
|
||||
),
|
||||
|
|
|
@ -10,8 +10,11 @@ import 'package:get/get.dart';
|
|||
import 'package:intl/intl.dart';
|
||||
import '../../../../_core/component/appbar/appbar_component.dart';
|
||||
import '../../../../_core/component/icons/icons_library.dart';
|
||||
import '../../../../_core/service/logger_service.dart';
|
||||
import '../../../../domain/models/porter_service_model.dart';
|
||||
import '../../../../domain/models/ticket_model.dart';
|
||||
import '../../../../domain/models/user_entity.dart';
|
||||
import '../../../controllers/ticket_controller.dart';
|
||||
import '../component/card_flight_information.dart';
|
||||
|
||||
class TicketBookingStep4Screen extends StatefulWidget {
|
||||
|
@ -28,27 +31,91 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
|
|||
late final int passenger;
|
||||
late final List<PassengerModel?> selectedPassengers;
|
||||
late List<String> numberSeat;
|
||||
late double? grandTotal;
|
||||
late List<String> selectedServiceLabels;
|
||||
late Map<String, PorterServiceModel?> selectedPorterServices;
|
||||
|
||||
double? totalPrice;
|
||||
double? grandTotal;
|
||||
|
||||
final TicketController ticketController = Get.find<TicketController>();
|
||||
FlightModel? flightData;
|
||||
String? departureTime;
|
||||
String? arrivalTime;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final args = Get.arguments as Map<String, dynamic>;
|
||||
ticketId = args['ticketId'] ?? '';
|
||||
flightId = args['flightId'] ?? '';
|
||||
ticketDate = args['date'] ?? '';
|
||||
ticketDate = args['date'];
|
||||
passenger = args['passenger'] ?? 0;
|
||||
selectedPassengers = args['selectedPassenger'] ?? [];
|
||||
numberSeat = args['numberSeat'] ?? '';
|
||||
grandTotal = args['grandTotal'] ?? 0;
|
||||
totalPrice = args['totalPrice'] ?? 0.0;
|
||||
grandTotal = args['grandTotal'] ?? 0.0;
|
||||
selectedServiceLabels = args['selectedServiceLabels'] ?? [];
|
||||
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
|
||||
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(
|
||||
backgroundColor: GrayColors.gray50,
|
||||
appBar: ProgressAppbarComponent(
|
||||
|
@ -68,14 +135,18 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
|
|||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.w),
|
||||
child: CardFlightInformation(
|
||||
date: "Sen, 27 Jan 2025",
|
||||
time: "12.20 - 06.00 AM",
|
||||
departureCity: "Yogyakarta",
|
||||
arrivalCity: "Lombok",
|
||||
plane: "Citilink (103)",
|
||||
seatClass: "Economy",
|
||||
servicePorter: "Fast Track (FT)",
|
||||
passenger: "2",
|
||||
date: "$ticketDate",
|
||||
time: "$departureTime - $arrivalTime",
|
||||
departureCity: "${flightData?.cityDeparture}",
|
||||
arrivalCity: "${flightData?.cityArrival}",
|
||||
plane: "${flightData?.airLines} (${flightData?.code})",
|
||||
seatClass: "${flightData?.flightClass}",
|
||||
passenger: "$passenger",
|
||||
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),
|
||||
|
@ -86,13 +157,13 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
|
|||
SizedBox(height: 20.h),
|
||||
CustomeShadowCotainner(
|
||||
sizeRadius: 0.r,
|
||||
height: MediaQuery.of(context).size.height * 0.5,
|
||||
height: MediaQuery.of(context).size.height * 0.4,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
TypographyStyles.body(
|
||||
"Citilink (103)",
|
||||
"${flightData?.airLines} (${flightData?.code})",
|
||||
color: GrayColors.gray800,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
|
@ -101,30 +172,23 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
|
|||
],
|
||||
),
|
||||
SizedBox(height: 2.h),
|
||||
Row(
|
||||
children: [
|
||||
TypographyStyles.small(
|
||||
"Fast Track (FT)",
|
||||
color: GrayColors.gray600,
|
||||
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),
|
||||
],
|
||||
_buildRowPorterWithClass(
|
||||
detailDeparturePorter: hasDeparturePorter ? "${getPorterInfo('departure')}" : null,
|
||||
detailArrivalPorter: hasArrivalPorter ? "${getPorterInfo('arrival')}" : null,
|
||||
detailTransitPorter: hasTransitPorter ? "${getPorterInfo('transit')}" : null,
|
||||
detailSeatClass: "${flightData?.flightClass}",
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
Row(
|
||||
children: [
|
||||
TypographyStyles.caption(
|
||||
"Rp 1.200.000",
|
||||
"Rp ${NumberFormat.decimalPattern('id_ID').format(flightData?.price ?? 0.0)}",
|
||||
color: GrayColors.gray600,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
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(
|
||||
|
@ -140,14 +204,14 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
|
|||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
TypographyStyles.body(
|
||||
"Rp 2.400.000",
|
||||
"Rp ${NumberFormat.decimalPattern('id_ID').format(totalPrice ?? 0.0)}",
|
||||
color: GrayColors.gray600,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 2.h),
|
||||
_buildRowText(context, text: "Layanan porter (Fast Track)", valueText: "50.000"),
|
||||
_buildTextService(),
|
||||
SizedBox(height: 2.h),
|
||||
_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(
|
||||
BuildContext context, {
|
||||
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