Feat: Addition of more complete airport attributes in transactions

This commit is contained in:
orangdeso 2025-04-15 15:28:54 +07:00
parent 3d83f52565
commit 3c635dd951
11 changed files with 128 additions and 33 deletions

View File

@ -1,5 +1,6 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:developer';
import 'package:cloud_firestore/cloud_firestore.dart';
import '../../domain/models/airport.dart';
import '../../domain/repositories/airport_repository.dart';
@ -15,4 +16,19 @@ class AirportRepositoryImpl implements AirportRepository {
.map((doc) => Airport.fromMap(doc.data(), doc.id))
.toList();
}
@override
Future<Airport?> getAirportsById(String id) async {
try {
final doc = await firestore.collection('bandara').doc(id).get();
if (doc.exists) {
return Airport.fromMap(doc.data()!, doc.id);
}
return null;
} catch (e) {
log('Error fetching airport by ID: $e');
return null;
}
}
}

View File

@ -2,4 +2,5 @@ import '../models/airport.dart';
abstract class AirportRepository {
Future<List<Airport>> getAirports();
Future<Airport?> getAirportsById(String id);
}

View File

@ -9,4 +9,8 @@ class GetAirports {
Future<List<Airport>> call() async {
return await repository.getAirports();
}
Future<Airport?> get(String id) async {
return await repository.getAirportsById(id);
}
}

View File

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:get/get.dart';
import '../../domain/models/airport.dart';
@ -6,7 +8,7 @@ import '../../domain/usecases/get_airport.dart';
class SearchFlightController extends GetxController {
final GetAirports getAirports;
var airports = <Airport>[].obs; // Gunakan Rx agar bisa reaktif
var airports = <Airport>[].obs;
var filteredAirports = <Airport>[].obs;
var searchText = ''.obs;
@ -39,4 +41,13 @@ class SearchFlightController extends GetxController {
.toList());
}
}
Future<Airport?> getAirportById(String id) async {
try {
return await getAirports.get(id);
} catch (e) {
log('Error fetching airport by ID: $e');
return null;
}
}
}

View File

@ -129,7 +129,7 @@ class _PaymentScreenState extends State<PaymentScreen> {
onTap: () {
final argument = {
'ticketId': ticketId,
'transactionId': Get.arguments['transactionId'], // Ambil dari argumen yang diteruskan
'transactionId': Get.arguments['transactionId'],
'flightData': flightData,
'totalAll': totalAll,
};

View File

@ -1,4 +1,6 @@
// ignore_for_file: unnecessary_null_comparison
import 'dart:developer';
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';
@ -19,6 +21,8 @@ class SearchTicketsScreen extends StatefulWidget {
class _SearchTicketsScreenState extends State<SearchTicketsScreen> {
late final TicketController ticketController;
late final String fromId;
late final String toId;
late final String from;
late final String to;
late final DateTime leavingDate;
@ -28,9 +32,9 @@ class _SearchTicketsScreenState extends State<SearchTicketsScreen> {
@override
void initState() {
super.initState();
// Ambil parameter yang dikirim dari BookingTickets
final args = Get.arguments as Map<String, dynamic>;
fromId = args['fromId'];
toId = args['toId'];
from = args['from'];
to = args['to'];
leavingDate = args['leavingDate'];
@ -134,11 +138,15 @@ class _SearchTicketsScreenState extends State<SearchTicketsScreen> {
airlineLogo: flight.airlineLogo,
onTap: () {
final argument = {
"fromId": fromId,
"toId": toId,
"ticketId": ticketId,
"flightId": flightId,
"ticketDate": ticketDate,
"passenger": passengerCount,
};
log('[Search Ticket] ID from : $fromId');
log('[Search Ticket] ID to : $toId');
Get.toNamed(Routes.TICKETBOOKINGSTEP1, arguments: argument);
},
),

View File

@ -1,5 +1,7 @@
// ignore_for_file: deprecated_member_use
import 'dart:developer';
import 'package:e_porter/_core/component/appbar/appbar_component.dart';
import 'package:e_porter/_core/component/button/button_fill.dart';
import 'package:e_porter/_core/component/button/switch_button.dart';
@ -33,14 +35,20 @@ class TicketBookingStep1Screen extends StatefulWidget {
class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
bool isToggled = false;
late final String fromId;
late final String toId;
late final String ticketId;
late final String flightId;
late final String ticketDate;
late final int passenger;
late Future<FlightModel> _flightFuture;
late final TicketController ticketController;
final ProfilController profilController = Get.find<ProfilController>();
final currencyFormatter = NumberFormat.decimalPattern('id_ID');
dynamic _loggedUser;
List<PassengerModel?> selectedPassengers = [];
@ -61,7 +69,10 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
void initState() {
super.initState();
_loadPassengers();
final args = Get.arguments as Map<String, dynamic>;
fromId = args['fromId'];
toId = args['toId'];
ticketId = args['ticketId'];
flightId = args['flightId'];
ticketDate = args['ticketDate'];
@ -90,7 +101,6 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
}
final userId = userData.uid;
await profilController.fetchPassangerById(userId);
// logger.d('User ID: $userId');
}
bool isAllPassengersFilled() {
@ -183,6 +193,8 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
SnackbarHelper.showError('Error', 'Harap lengkapi slot penumpang');
} else {
final argument = {
"fromId": fromId,
"toId": toId,
'ticketId': ticketId,
'flightId': flightId,
'date': ticketDate,
@ -201,6 +213,7 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
'passenger': passenger,
'selectedPassenger': selectedPassengers,
};
log('[Ticket Booking Step1] From ID: $fromId');
Get.toNamed(Routes.TICKETBOOKINGSTEP2, arguments: argument);
}

View File

@ -1,3 +1,5 @@
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/constants/colors.dart';
@ -22,6 +24,8 @@ class TicketBookingStep2Screen extends StatefulWidget {
class _TicketBookingStep2ScreenState extends State<TicketBookingStep2Screen> {
late final TicketController ticketController;
late final String fromId;
late final String toId;
late final String ticketId;
late final String flightId;
String? ticketDate;
@ -45,6 +49,8 @@ class _TicketBookingStep2ScreenState extends State<TicketBookingStep2Screen> {
void initState() {
super.initState();
final args = Get.arguments as Map<String, dynamic>;
fromId = args['fromId'];
toId = args['toId'];
ticketId = args['ticketId'];
flightId = args['flightId'];
ticketDate = args['date'];
@ -63,8 +69,6 @@ class _TicketBookingStep2ScreenState extends State<TicketBookingStep2Screen> {
passenger = args['passenger'];
selectedPassengers = args['selectedPassenger'] ?? [];
selectedSeatNumbers = args['selectedSeatNumbers'] ?? List.filled(passenger, '');
// logger.d('Ticket ID: $ticketId \nFlight ID: $flightId');
}
@override
@ -114,11 +118,14 @@ class _TicketBookingStep2ScreenState extends State<TicketBookingStep2Screen> {
numberSeat: '${selectedSeatNumbers[index].isEmpty ? '-' : selectedSeatNumbers[index]}',
onTap: () async {
final argument = {
// "fromId": fromId,
// "toId": toId,
'ticketId': ticketId,
'flightId': flightId,
'passenger': passenger,
'selectedPassenger': selectedPassengers,
};
// log('[Ticket Booking Step2 in Passing Choose Seat] From ID: $fromId');
final result = await Get.toNamed(Routes.CHOOSECHAIR, arguments: argument);
if (result != null && result is List<String>) {
setState(() {
@ -147,6 +154,8 @@ class _TicketBookingStep2ScreenState extends State<TicketBookingStep2Screen> {
? null
: () {
final argument = {
"fromId": fromId,
"toId": toId,
'ticketId': ticketId,
'flightId': flightId,
'date': ticketDate,
@ -154,7 +163,7 @@ class _TicketBookingStep2ScreenState extends State<TicketBookingStep2Screen> {
'selectedPassenger': selectedPassengers,
'numberSeat': selectedSeatNumbers
};
// logger.d('Number Seat: $selectedSeatNumbers \n Passenger: $selectedPassengers');
log('[Ticket Booking Step2] From ID: $fromId');
Get.toNamed(Routes.TICKETBOOKINGSTEP3, arguments: argument);
},
),

View File

@ -40,6 +40,9 @@ class _TicketBookingStep3ScreenState extends State<TicketBookingStep3Screen> {
late final PorterServiceController _porterController;
final TicketController ticketController = Get.find<TicketController>();
late final String fromId;
late final String toId;
late final String ticketId;
late final String flightId;
late String? ticketDate;
@ -61,6 +64,8 @@ class _TicketBookingStep3ScreenState extends State<TicketBookingStep3Screen> {
void initState() {
super.initState();
final args = Get.arguments as Map<String, dynamic>;
fromId = args['fromId'];
toId = args['toId'];
ticketId = args['ticketId'];
flightId = args['flightId'];
ticketDate = args['date'];
@ -291,6 +296,8 @@ class _TicketBookingStep3ScreenState extends State<TicketBookingStep3Screen> {
selectedPorterServices['transit'] = selectedTransitService;
}
final argument = {
"fromId": fromId,
"toId": toId,
'ticketId': ticketId,
'flightId': flightId,
'date': ticketDate,
@ -302,25 +309,12 @@ class _TicketBookingStep3ScreenState extends State<TicketBookingStep3Screen> {
'selectedServiceLabels': selectedServiceLabels,
'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');
log('[Ticket Booking Step3] From ID: $fromId');
log('[Ticket Booking Step3] Ticket ID: $ticketId');
log('[Ticket Booking Step3] Flight ID: $flightId');
log('[Ticket Booking Step3] Ticket Date: $ticketDate');
log('[Ticket Booking Step3] Opsi Penerbangan: $selectedServiceLabels');
log('[Ticket Booking Step3] Layanan Porter: $selectedPorterServices');
Get.toNamed(Routes.TICKETBOOKINGSTEP4, arguments: argument);
},

View File

@ -3,6 +3,8 @@ import 'dart:developer';
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/typography.dart';
import 'package:e_porter/domain/models/airport.dart';
import 'package:e_porter/presentation/controllers/search_flight_controller.dart';
import 'package:e_porter/presentation/screens/home/component/footer_price.dart';
import 'package:e_porter/presentation/screens/routes/app_rountes.dart';
import 'package:flutter/material.dart';
@ -12,7 +14,6 @@ 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 '../../../../_core/service/preferences_service.dart';
import '../../../../_core/utils/snackbar/snackbar_helper.dart';
import '../../../../domain/models/porter_service_model.dart';
@ -30,6 +31,8 @@ class TicketBookingStep4Screen extends StatefulWidget {
}
class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
late final String fromId;
late final String toId;
late final String ticketId;
late final String flightId;
late String? ticketDate;
@ -45,14 +48,23 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
final TicketController ticketController = Get.find<TicketController>();
final TransactionController transactionController = Get.find<TransactionController>();
late final SearchFlightController searchFlightController;
FlightModel? flightData;
String? departureTime;
String? arrivalTime;
Airport? departureAirport;
Airport? arrivalAirport;
@override
void initState() {
super.initState();
searchFlightController = Get.find<SearchFlightController>();
final args = Get.arguments as Map<String, dynamic>;
fromId = args['fromId'] ?? '';
toId = args['toId'] ?? '';
ticketId = args['ticketId'] ?? '';
flightId = args['flightId'] ?? '';
ticketDate = args['date'];
@ -65,6 +77,7 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
selectedPorterServices = args['selectedPorterServices'] ?? {};
fetchDataFlight();
fetchAirportData();
transactionController.checkExpiredTransactions();
}
@ -77,7 +90,21 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
arrivalTime = DateFormat.jm().format(flightData!.arrivalTime);
});
} catch (e) {
logger.e('Terjadi kesalahan: $e');
log('Terjadi kesalahan: $e');
}
}
Future<void> fetchAirportData() async {
try {
if (fromId.isNotEmpty) {
departureAirport = await searchFlightController.getAirportById(fromId);
}
if (toId.isNotEmpty) {
arrivalAirport = await searchFlightController.getAirportById(toId);
}
setState(() {});
} catch (e) {
log('Error fetching airport data: $e');
}
}
@ -95,7 +122,7 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
try {
return NumberFormat.decimalPattern('id_ID').format(porter.price);
} catch (e) {
print("Error formatting porter price: $e");
log("Error formatting porter price: $e");
return '0';
}
}
@ -244,12 +271,16 @@ class _TicketBookingStep4ScreenState extends State<TicketBookingStep4Screen> {
// Persiapkan data bandara
final bandaraData = {
'departure': {
'id': fromId,
'code': flightData?.codeDeparture,
'city': flightData?.cityDeparture,
'name': departureAirport?.name ?? '',
},
'arrival': {
'id': toId,
'code': flightData?.codeArrival,
'city': flightData?.cityArrival,
'name': arrivalAirport?.name ?? ''
},
};

View File

@ -1,4 +1,5 @@
import 'package:e_porter/domain/bindings/auth_binding.dart';
import 'package:e_porter/domain/bindings/history_binding.dart';
import 'package:e_porter/domain/bindings/navigation_binding.dart';
import 'package:e_porter/domain/bindings/porter_service_binding.dart';
import 'package:e_porter/domain/bindings/profil_binding.dart';
@ -38,7 +39,10 @@ class AppRoutes {
GetPage(
name: Routes.NAVBAR,
page: () => MainNavigation(),
binding: MainNavigationBinding(),
bindings: [
MainNavigationBinding(),
HistoryBinding(),
],
),
GetPage(
name: Routes.SPLASH,
@ -61,6 +65,7 @@ class AppRoutes {
GetPage(
name: Routes.BOARDINGPASS,
page: () => BoardingPassScreen(),
binding: HistoryBinding(),
),
GetPage(
name: Routes.PROFILE,
@ -113,7 +118,10 @@ class AppRoutes {
GetPage(
name: Routes.TICKETBOOKINGSTEP4,
page: () => TicketBookingStep4Screen(),
binding: TransactionBinding(),
bindings: [
TransactionBinding(),
SearchFlightBinding(),
],
),
GetPage(
name: Routes.CHOOSECHAIR,