Feat: add conditional data not complete for feature add as passenger
This commit is contained in:
parent
edd2187c07
commit
74a09d4d3a
|
@ -271,7 +271,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||||
child: CarouselSlider(
|
child: CarouselSlider(
|
||||||
items: imageList,
|
items: imageList,
|
||||||
options: CarouselOptions(
|
options: CarouselOptions(
|
||||||
autoPlay: false,
|
autoPlay: true,
|
||||||
enlargeCenterPage: true,
|
enlargeCenterPage: true,
|
||||||
aspectRatio: 2.3,
|
aspectRatio: 2.3,
|
||||||
viewportFraction: 0.8,
|
viewportFraction: 0.8,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// ignore_for_file: deprecated_member_use
|
// ignore_for_file: deprecated_member_use
|
||||||
|
|
||||||
import 'dart:developer';
|
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/button/button_fill.dart';
|
import 'package:e_porter/_core/component/button/button_fill.dart';
|
||||||
import 'package:e_porter/_core/component/button/switch_button.dart';
|
import 'package:e_porter/_core/component/button/switch_button.dart';
|
||||||
|
@ -96,7 +95,7 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
|
||||||
Future<void> _loadPassengers() async {
|
Future<void> _loadPassengers() async {
|
||||||
final userData = await PreferencesService.getUserData();
|
final userData = await PreferencesService.getUserData();
|
||||||
if (userData == null || userData.uid.isEmpty) {
|
if (userData == null || userData.uid.isEmpty) {
|
||||||
SnackbarHelper.showError('Error', 'User ID tidak ditemukan, silakan login kembali');
|
SnackbarHelper.showError('Gagal', 'User ID tidak ditemukan, silakan login kembali');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final userId = userData.uid;
|
final userId = userData.uid;
|
||||||
|
@ -105,12 +104,47 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
|
||||||
|
|
||||||
bool isAllPassengersFilled() {
|
bool isAllPassengersFilled() {
|
||||||
if (isToggled && _loggedUser != null) {
|
if (isToggled && _loggedUser != null) {
|
||||||
return selectedPassengers.skip(1).every((p) => p != null);
|
if (!_isUserDataComplete(_loggedUser)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return selectedPassengers.skip(1).every((p) => p != null && _isPassengerDataComplete(p));
|
||||||
} else {
|
} else {
|
||||||
return selectedPassengers.every((p) => p != null);
|
return selectedPassengers.every((p) => p != null && _isPassengerDataComplete(p));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _isUserDataComplete(dynamic userData) {
|
||||||
|
return userData.tipeId != null && userData.tipeId!.isNotEmpty && userData.noId != null && userData.noId!.isNotEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _isPassengerDataComplete(PassengerModel passenger) {
|
||||||
|
return passenger.typeId.isNotEmpty && passenger.noId.isNotEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
String? _getValidationMessage() {
|
||||||
|
if (isToggled && _loggedUser != null && !_isUserDataComplete(_loggedUser)) {
|
||||||
|
return 'Data Anda tidak lengkap. Harap lengkapi tipe ID dan nomor ID di profil terlebih dahulu.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedPassengers.any((p) => p == null)) {
|
||||||
|
return 'Harap lengkapi semua slot penumpang';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isToggled && _loggedUser != null) {
|
||||||
|
final incompletePassengers = selectedPassengers.skip(1).where((p) => p != null && !_isPassengerDataComplete(p));
|
||||||
|
if (incompletePassengers.isNotEmpty) {
|
||||||
|
return 'Ada data penumpang yang tidak lengkap. Harap periksa kembali informasi penumpang.';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final incompletePassengers = selectedPassengers.where((p) => p != null && !_isPassengerDataComplete(p));
|
||||||
|
if (incompletePassengers.isNotEmpty) {
|
||||||
|
return 'Ada data penumpang yang tidak lengkap. Harap periksa kembali informasi penumpang.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
@ -188,34 +222,35 @@ 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: () {
|
||||||
if (selectedPassengers.any((p) => p == null)) {
|
final validationMessage = _getValidationMessage();
|
||||||
SnackbarHelper.showError('Error', 'Harap lengkapi slot penumpang');
|
if (validationMessage != null) {
|
||||||
} else {
|
SnackbarHelper.showError('Error', validationMessage);
|
||||||
final argument = {
|
return;
|
||||||
"fromId": fromId,
|
|
||||||
"toId": toId,
|
|
||||||
'ticketId': ticketId,
|
|
||||||
'flightId': flightId,
|
|
||||||
'date': ticketDate,
|
|
||||||
'departureTime': departureTime,
|
|
||||||
'arrivalTime': arrivalTime,
|
|
||||||
'cityDeparture': cityDeparture,
|
|
||||||
'cityArrival': cityArrival,
|
|
||||||
'airLines': airLines,
|
|
||||||
'code': code,
|
|
||||||
'flightClass': flightClass,
|
|
||||||
'transitAirplane': cityTransit,
|
|
||||||
'stop': stop,
|
|
||||||
'codeDeparture': codeDeparture,
|
|
||||||
'codeArrival': codeArrival,
|
|
||||||
'airlineLogo': airlineLogo,
|
|
||||||
'passenger': passenger,
|
|
||||||
'selectedPassenger': selectedPassengers,
|
|
||||||
};
|
|
||||||
log('[Ticket Booking Step1] From ID: $fromId');
|
|
||||||
|
|
||||||
Get.toNamed(Routes.TICKETBOOKINGSTEP2, arguments: argument);
|
|
||||||
}
|
}
|
||||||
|
final argument = {
|
||||||
|
"fromId": fromId,
|
||||||
|
"toId": toId,
|
||||||
|
'ticketId': ticketId,
|
||||||
|
'flightId': flightId,
|
||||||
|
'date': ticketDate,
|
||||||
|
'departureTime': departureTime,
|
||||||
|
'arrivalTime': arrivalTime,
|
||||||
|
'cityDeparture': cityDeparture,
|
||||||
|
'cityArrival': cityArrival,
|
||||||
|
'airLines': airLines,
|
||||||
|
'code': code,
|
||||||
|
'flightClass': flightClass,
|
||||||
|
'transitAirplane': cityTransit,
|
||||||
|
'stop': stop,
|
||||||
|
'codeDeparture': codeDeparture,
|
||||||
|
'codeArrival': codeArrival,
|
||||||
|
'airlineLogo': airlineLogo,
|
||||||
|
'passenger': passenger,
|
||||||
|
'selectedPassenger': selectedPassengers,
|
||||||
|
};
|
||||||
|
log('[Ticket Booking Step1] From ID: $fromId');
|
||||||
|
|
||||||
|
Get.toNamed(Routes.TICKETBOOKINGSTEP2, arguments: argument);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -316,114 +351,163 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
|
||||||
|
|
||||||
Widget _buildUserPassengerCard(dynamic user, int index) {
|
Widget _buildUserPassengerCard(dynamic user, int index) {
|
||||||
bool isSlotEditTable = !isToggled || index != 0;
|
bool isSlotEditTable = !isToggled || index != 0;
|
||||||
|
bool isDataComplete = _isUserDataComplete(user);
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.only(bottom: 16.h),
|
padding: EdgeInsets.only(bottom: 16.h),
|
||||||
child: CustomeShadowCotainner(
|
child: Container(
|
||||||
child: Row(
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(10.r),
|
||||||
|
border: !isDataComplete ? Border.all(color: Colors.red.shade300, width: 1.5.w) : null,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.1),
|
||||||
|
blurRadius: 8,
|
||||||
|
offset: Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Column(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
TypographyStyles.body(
|
Expanded(
|
||||||
'${_loggedUser.name}',
|
child: Column(
|
||||||
color: GrayColors.gray800,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
fontWeight: FontWeight.w500,
|
children: [
|
||||||
|
TypographyStyles.body(
|
||||||
|
'${_loggedUser.name}',
|
||||||
|
color: GrayColors.gray800,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
SizedBox(height: 4.h),
|
||||||
|
TypographyStyles.caption(
|
||||||
|
(_loggedUser.tipeId?.isEmpty ?? true) || (_loggedUser.noId?.isEmpty ?? true)
|
||||||
|
? "Data tidak lengkap"
|
||||||
|
: "${_loggedUser.tipeId} - ${_loggedUser.noId}",
|
||||||
|
color: !isDataComplete ? Colors.red.shade600 : GrayColors.gray800,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 4.h),
|
Row(
|
||||||
TypographyStyles.caption(
|
children: [
|
||||||
"${_loggedUser.tipeId} - ${_loggedUser.noId}",
|
ZoomTapAnimation(
|
||||||
color: GrayColors.gray800,
|
child: IconButton(
|
||||||
fontWeight: FontWeight.w400,
|
icon: CustomeIcons.RemoveOutline(),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
selectedPassengers[0] = null;
|
||||||
|
isToggled = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (isSlotEditTable)
|
||||||
|
ZoomTapAnimation(
|
||||||
|
child: GestureDetector(
|
||||||
|
child: CustomeIcons.EditOutline(),
|
||||||
|
onTap: () {
|
||||||
|
Get.bottomSheet(
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(left: 16.w, right: 16.w, bottom: 16.h),
|
||||||
|
child: Wrap(
|
||||||
|
children: [
|
||||||
|
TitleShowModal(
|
||||||
|
text: 'Informasi Penumpang',
|
||||||
|
onTap: () async {
|
||||||
|
if (Get.isBottomSheetOpen ?? false) {
|
||||||
|
Get.back();
|
||||||
|
}
|
||||||
|
await Future.delayed(Duration(seconds: 1));
|
||||||
|
var result = await Get.toNamed(Routes.ADDPASSENGER);
|
||||||
|
if (result == true) {
|
||||||
|
_loadPassengers().then((_) => setState(() {}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Obx(
|
||||||
|
() {
|
||||||
|
if (profilController.passengerList.isEmpty) {
|
||||||
|
return Center(
|
||||||
|
child: TypographyStyles.body(
|
||||||
|
"Belum ada penumpang",
|
||||||
|
color: GrayColors.gray400,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: profilController.passengerList.length,
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final passenger = profilController.passengerList[index];
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(top: 16.h),
|
||||||
|
child: _buildAddPassenger(
|
||||||
|
context,
|
||||||
|
title: "${passenger.name}",
|
||||||
|
subTitle: "${passenger.typeId} - ${passenger.noId}",
|
||||||
|
onTap: () {
|
||||||
|
selectedPassengers[index] = passenger;
|
||||||
|
Get.back();
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
isScrollControlled: true,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(10.r),
|
||||||
|
topRight: Radius.circular(10.r),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
if (!isDataComplete)
|
||||||
children: [
|
Container(
|
||||||
ZoomTapAnimation(
|
margin: EdgeInsets.only(top: 8.h),
|
||||||
child: IconButton(
|
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h),
|
||||||
icon: CustomeIcons.RemoveOutline(),
|
decoration: BoxDecoration(
|
||||||
onPressed: () {
|
color: Colors.red.shade50,
|
||||||
setState(() {
|
borderRadius: BorderRadius.circular(6.r),
|
||||||
selectedPassengers[0] = null;
|
|
||||||
isToggled = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (isSlotEditTable)
|
child: Row(
|
||||||
ZoomTapAnimation(
|
children: [
|
||||||
child: GestureDetector(
|
Icon(
|
||||||
child: CustomeIcons.EditOutline(),
|
Icons.warning_amber_rounded,
|
||||||
onTap: () {
|
size: 16.w,
|
||||||
Get.bottomSheet(
|
color: Colors.red.shade600,
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.only(left: 16.w, right: 16.w, bottom: 16.h),
|
|
||||||
child: Wrap(
|
|
||||||
children: [
|
|
||||||
TitleShowModal(
|
|
||||||
text: 'Informasi Penumpang',
|
|
||||||
onTap: () async {
|
|
||||||
if (Get.isBottomSheetOpen ?? false) {
|
|
||||||
Get.back();
|
|
||||||
}
|
|
||||||
await Future.delayed(Duration(seconds: 1));
|
|
||||||
var result = await Get.toNamed(Routes.ADDPASSENGER);
|
|
||||||
if (result == true) {
|
|
||||||
_loadPassengers().then((_) => setState(() {}));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Obx(
|
|
||||||
() {
|
|
||||||
if (profilController.passengerList.isEmpty) {
|
|
||||||
return Center(
|
|
||||||
child: TypographyStyles.body(
|
|
||||||
"Belum ada penumpang",
|
|
||||||
color: GrayColors.gray400,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return ListView.builder(
|
|
||||||
itemCount: profilController.passengerList.length,
|
|
||||||
shrinkWrap: true,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final passenger = profilController.passengerList[index];
|
|
||||||
return Padding(
|
|
||||||
padding: EdgeInsets.only(top: 16.h),
|
|
||||||
child: _buildAddPassenger(
|
|
||||||
context,
|
|
||||||
title: "${passenger.name}",
|
|
||||||
subTitle: "${passenger.typeId} - ${passenger.noId}",
|
|
||||||
onTap: () {
|
|
||||||
selectedPassengers[index] = passenger;
|
|
||||||
Get.back();
|
|
||||||
setState(() {});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
isScrollControlled: true,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(10.r),
|
|
||||||
topRight: Radius.circular(10.r),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
SizedBox(width: 6.w),
|
||||||
],
|
Expanded(
|
||||||
)
|
child: TypographyStyles.caption(
|
||||||
|
'Lengkapi tipe ID dan nomor ID di profil Anda',
|
||||||
|
color: Colors.red.shade600,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
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/button/button_outline.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/constants/typography.dart';
|
import 'package:e_porter/_core/constants/typography.dart';
|
||||||
|
|
Loading…
Reference in New Issue