Feat: add page passenger screen

This commit is contained in:
orangdeso 2025-03-12 22:54:18 +07:00
parent 5f4153fe62
commit 430cce5f10
23 changed files with 514 additions and 115 deletions

View File

@ -73,6 +73,12 @@
"packageUri": "lib/", "packageUri": "lib/",
"languageVersion": "3.1" "languageVersion": "3.1"
}, },
{
"name": "dropdown_button2",
"rootUri": "file:///C:/Users/ASUS/AppData/Local/Pub/Cache/hosted/pub.dev/dropdown_button2-2.3.9",
"packageUri": "lib/",
"languageVersion": "2.17"
},
{ {
"name": "fake_async", "name": "fake_async",
"rootUri": "file:///C:/Users/ASUS/AppData/Local/Pub/Cache/hosted/pub.dev/fake_async-1.3.1", "rootUri": "file:///C:/Users/ASUS/AppData/Local/Pub/Cache/hosted/pub.dev/fake_async-1.3.1",
@ -440,7 +446,7 @@
"languageVersion": "3.4" "languageVersion": "3.4"
} }
], ],
"generated": "2025-03-11T15:01:28.490605Z", "generated": "2025-03-12T12:18:16.494991Z",
"generator": "pub", "generator": "pub",
"generatorVersion": "3.5.0", "generatorVersion": "3.5.0",
"flutterRoot": "file:///D:/Flutter/flutter_sdk/flutter_3.24.0", "flutterRoot": "file:///D:/Flutter/flutter_sdk/flutter_3.24.0",

View File

@ -46,6 +46,10 @@ cupertino_icons
3.1 3.1
file:///C:/Users/ASUS/AppData/Local/Pub/Cache/hosted/pub.dev/cupertino_icons-1.0.8/ file:///C:/Users/ASUS/AppData/Local/Pub/Cache/hosted/pub.dev/cupertino_icons-1.0.8/
file:///C:/Users/ASUS/AppData/Local/Pub/Cache/hosted/pub.dev/cupertino_icons-1.0.8/lib/ file:///C:/Users/ASUS/AppData/Local/Pub/Cache/hosted/pub.dev/cupertino_icons-1.0.8/lib/
dropdown_button2
2.17
file:///C:/Users/ASUS/AppData/Local/Pub/Cache/hosted/pub.dev/dropdown_button2-2.3.9/
file:///C:/Users/ASUS/AppData/Local/Pub/Cache/hosted/pub.dev/dropdown_button2-2.3.9/lib/
fake_async fake_async
2.12 2.12
file:///C:/Users/ASUS/AppData/Local/Pub/Cache/hosted/pub.dev/fake_async-1.3.1/ file:///C:/Users/ASUS/AppData/Local/Pub/Cache/hosted/pub.dev/fake_async-1.3.1/

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
#Tue Mar 11 22:03:16 WIB 2025 #Wed Mar 12 19:14:57 WIB 2025
base.0=D\:\\Flutter\\Flutter Project\\e_porter\\build\\app\\intermediates\\dex\\debug\\mergeExtDexDebug\\classes.dex base.0=D\:\\Flutter\\Flutter Project\\e_porter\\build\\app\\intermediates\\dex\\debug\\mergeExtDexDebug\\classes.dex
base.1=D\:\\Flutter\\Flutter Project\\e_porter\\build\\app\\intermediates\\dex\\debug\\mergeLibDexDebug\\0\\classes.dex base.1=D\:\\Flutter\\Flutter Project\\e_porter\\build\\app\\intermediates\\dex\\debug\\mergeLibDexDebug\\0\\classes.dex
base.2=D\:\\Flutter\\Flutter Project\\e_porter\\build\\app\\intermediates\\dex\\debug\\mergeProjectDexDebug\\0\\classes.dex base.2=D\:\\Flutter\\Flutter Project\\e_porter\\build\\app\\intermediates\\dex\\debug\\mergeProjectDexDebug\\0\\classes.dex

View File

@ -1,6 +1,7 @@
import 'package:e_porter/_core/constants/colors.dart'; import 'package:e_porter/_core/constants/colors.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:zoom_tap_animation/zoom_tap_animation.dart';
import '../../constants/typography.dart'; import '../../constants/typography.dart';
@ -20,7 +21,8 @@ class ButtonFill extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SizedBox( return ZoomTapAnimation(
child: SizedBox(
width: double.infinity, width: double.infinity,
child: ElevatedButton( child: ElevatedButton(
onPressed: onTap, onPressed: onTap,
@ -43,6 +45,7 @@ class ButtonFill extends StatelessWidget {
), ),
), ),
), ),
),
); );
} }

View File

@ -0,0 +1,98 @@
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:e_porter/_core/constants/colors.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class DropdownComponent extends StatefulWidget {
final String? value;
final Function(String?) onChanged;
final String hintText;
const DropdownComponent({
Key? key,
this.value,
required this.onChanged,
required this.hintText,
}) : super(key: key);
@override
State<DropdownComponent> createState() => _DropdownComponentState();
}
class _DropdownComponentState extends State<DropdownComponent> {
final List<String> items = ["KTP", "Paspor"];
String? selectedValue;
bool _isMenuOpen = false;
@override
void initState() {
super.initState();
selectedValue = widget.value;
}
@override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.height * 0.14,
child: DropdownButtonHideUnderline(
child: DropdownButton2<String>(
isExpanded: true,
value: selectedValue,
items: items.map((String item) {
return DropdownMenuItem<String>(
value: item,
child: Text(
item,
style: TextStyle(
fontFamily: 'DMsans',
fontSize: 16.sp,
color: GrayColors.gray600,
fontWeight: FontWeight.w500,
),
),
);
}).toList(),
hint: Text(
widget.hintText,
style: TextStyle(
fontFamily: 'DMsans',
fontSize: 16.sp,
color: GrayColors.gray600,
fontWeight: FontWeight.w500,
),
),
onMenuStateChange: (isOpen) {
setState(() {
_isMenuOpen = isOpen;
});
},
onChanged: (String? newValue) {
setState(() {
selectedValue = newValue;
});
widget.onChanged(newValue);
},
buttonStyleData: ButtonStyleData(
padding: EdgeInsets.only(left: 10.w, right: 16.w, top: 4.h, bottom: 4.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.r),
border: Border.all(width: 1.w, color: _isMenuOpen ? PrimaryColors.primary800 : GrayColors.gray200),
color: Colors.white,
),
),
dropdownStyleData: DropdownStyleData(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.r),
color: Colors.white,
),
elevation: 1,
),
menuItemStyleData: MenuItemStyleData(
padding: EdgeInsets.only(left: 16.w, top: 8.h, bottom: 8.h),
),
),
),
);
}
}

View File

@ -18,6 +18,7 @@ class SearchBarComponent extends StatelessWidget {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(10.r)
), ),
child: TextField( child: TextField(
onChanged: onChanged, onChanged: onChanged,

View File

@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../../constants/colors.dart';
class TextFieldComponent extends StatelessWidget {
final TextEditingController? controller;
final String hintText;
const TextFieldComponent({this.controller, required this.hintText});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(10.r)),
child: TextField(
controller: controller,
decoration: InputDecoration(
prefix: Padding(padding: EdgeInsets.symmetric(horizontal: 10.w)),
hintText: hintText,
hintStyle: TextStyle(
fontFamily: 'DMsans',
fontSize: 16.sp,
color: GrayColors.gray600,
fontWeight: FontWeight.w500,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.r),
borderSide: BorderSide(width: 1, color: GrayColors.gray200),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.r),
borderSide: BorderSide(width: 1, color: GrayColors.gray200),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.r),
borderSide: BorderSide(width: 1.5.w, color: PrimaryColors.primary800),
),
contentPadding: EdgeInsets.symmetric(vertical: 16.h),
),
),
);
}
}

View File

@ -11,6 +11,8 @@ class UserEntity {
} }
class UserData { class UserData {
final String? tipeId;
final String? noId;
final String? name; final String? name;
final String? email; final String? email;
final String? phone; final String? phone;
@ -22,6 +24,8 @@ class UserData {
final String? role; final String? role;
UserData({ UserData({
required this.tipeId,
required this.noId,
required this.name, required this.name,
required this.email, required this.email,
required this.phone, required this.phone,
@ -46,6 +50,8 @@ class UserData {
} }
return UserData( return UserData(
tipeId: map['tipeId'] ?? '',
noId: map['noId'] ?? '',
name: map['name'] as String?, name: map['name'] as String?,
email: map['email'] as String?, email: map['email'] as String?,
phone: map['phone'] as String?, phone: map['phone'] as String?,
@ -60,6 +66,8 @@ class UserData {
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
'tipeId': tipeId,
'noId': noId,
'name': name, 'name': name,
'email': email, 'email': email,
'phone': phone, 'phone': phone,

View File

@ -1,3 +1,4 @@
import 'package:e_porter/_core/service/logger_service.dart';
import 'package:e_porter/presentation/screens/routes/app_rountes.dart'; import 'package:e_porter/presentation/screens/routes/app_rountes.dart';
import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -8,7 +9,7 @@ void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(); await Firebase.initializeApp();
print("Firebase Initialized Successfully!"); logger.d("Firebase Initialized Successfully!");
runApp(MyApp(initialRoute: Routes.SPLASH)); runApp(MyApp(initialRoute: Routes.SPLASH));
} }

View File

@ -59,22 +59,17 @@ class CardFlightInformation extends StatelessWidget {
SizedBox(height: 4.h), SizedBox(height: 4.h),
Row( Row(
children: [ children: [
TypographyStyles.body(departureCity, color: GrayColors.gray800, letterSpacing: 0.2), TypographyStyles.body(departureCity, color: GrayColors.gray800),
SizedBox(width: 10.w), SizedBox(width: 10.w),
CustomeIcons.PlaneRightFilled(color: PrimaryColors.primary800), CustomeIcons.PlaneRightFilled(color: PrimaryColors.primary800),
SizedBox(width: 10.w), SizedBox(width: 10.w),
TypographyStyles.body(arrivalCity, color: GrayColors.gray800, letterSpacing: 0.2) TypographyStyles.body(arrivalCity, color: GrayColors.gray800)
], ],
), ),
SizedBox(height: 4.h), SizedBox(height: 4.h),
Row( Row(
children: [ children: [
TypographyStyles.small( TypographyStyles.small(plane, color: GrayColors.gray600, fontWeight: FontWeight.w400),
plane,
color: GrayColors.gray600,
letterSpacing: 0.2,
fontWeight: FontWeight.w400,
),
_buildText(context, text: seatClass), _buildText(context, text: seatClass),
servicePorter != null ? _buildText(context, text: servicePorter!) : SizedBox.shrink(), servicePorter != null ? _buildText(context, text: servicePorter!) : SizedBox.shrink(),
], ],

View File

@ -17,6 +17,8 @@ import 'package:get/get.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:zoom_tap_animation/zoom_tap_animation.dart'; import 'package:zoom_tap_animation/zoom_tap_animation.dart';
import '../../../../_core/service/logger_service.dart';
class BookingTickets extends StatefulWidget { class BookingTickets extends StatefulWidget {
const BookingTickets({super.key}); const BookingTickets({super.key});
@ -117,7 +119,7 @@ class _BookingTicketsState extends State<BookingTickets> {
setState(() { setState(() {
selectedDate = picked; selectedDate = picked;
selectedDateText = DateFormat('EEE, d MMM yyyy', 'en_US').format(selectedDate); selectedDateText = DateFormat('EEE, d MMM yyyy', 'en_US').format(selectedDate);
print(selectedDate); logger.d(selectedDate);
}); });
} }
}, },
@ -202,8 +204,7 @@ class _BookingTicketsState extends State<BookingTickets> {
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
), ),
SizedBox(height: 20.h), SizedBox(height: 20.h),
ZoomTapAnimation( ButtonFill(
child: ButtonFill(
text: 'Cari Tiket', text: 'Cari Tiket',
textColor: Colors.white, textColor: Colors.white,
onTap: () { onTap: () {
@ -220,7 +221,6 @@ class _BookingTicketsState extends State<BookingTickets> {
Get.snackbar("Error", "Silakan pilih bandara keberangkatan dan tujuan"); Get.snackbar("Error", "Silakan pilih bandara keberangkatan dan tujuan");
} }
}, },
),
) )
], ],
), ),

View File

@ -1,5 +1,5 @@
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/search_bar/search_bar_component.dart'; import 'package:e_porter/_core/component/text_field/search_bar/search_bar_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';
import 'package:e_porter/presentation/controllers/search_flight_controller.dart'; import 'package:e_porter/presentation/controllers/search_flight_controller.dart';

View File

@ -14,8 +14,10 @@ import 'package:e_porter/presentation/screens/home/component/title_show_modal.da
import 'package:e_porter/presentation/screens/routes/app_rountes.dart'; import 'package:e_porter/presentation/screens/routes/app_rountes.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:zoom_tap_animation/zoom_tap_animation.dart'; import 'package:zoom_tap_animation/zoom_tap_animation.dart';
class TicketBookingStep1Screen extends StatefulWidget { class TicketBookingStep1Screen extends StatefulWidget {
@ -34,6 +36,7 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
late Future<FlightModel> _flightFuture; late Future<FlightModel> _flightFuture;
late final TicketController ticketController; late final TicketController ticketController;
final currencyFormatter = NumberFormat.decimalPattern('id_ID'); final currencyFormatter = NumberFormat.decimalPattern('id_ID');
dynamic _loggedUser;
@override @override
void initState() { void initState() {
@ -107,7 +110,6 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
), ),
bottomNavigationBar: CustomeShadowCotainner( bottomNavigationBar: CustomeShadowCotainner(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 20.h), padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 20.h),
child: ZoomTapAnimation(
child: ButtonFill( child: ButtonFill(
text: 'Lanjutkan', text: 'Lanjutkan',
textColor: Colors.white, textColor: Colors.white,
@ -116,7 +118,6 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
}, },
), ),
), ),
),
); );
} }
@ -124,11 +125,12 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
return FutureBuilder( return FutureBuilder(
future: PreferencesService.getUserData(), future: PreferencesService.getUserData(),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) { if (snapshot.connectionState == ConnectionState.none) {
return CustomeShadowCotainner(child: Center(child: CircularProgressIndicator())); return SizedBox.shrink();
} else if (snapshot.hasData && snapshot.data != null) { } else if (snapshot.hasData && snapshot.data != null) {
final user = snapshot.data!; final user = snapshot.data!;
logger.d('Data user: ${user.email}'); _loggedUser = user;
logger.d('Data user: ${user.noId}');
return CustomeShadowCotainner( return CustomeShadowCotainner(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -159,7 +161,10 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
SizedBox(width: 20.w), SizedBox(width: 20.w),
SwitchButton( SwitchButton(
value: isToggled, value: isToggled,
onChanged: (newValue) { onChanged: (newValue) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('isPassengerAdd', newValue);
setState( setState(
() { () {
isToggled = newValue; isToggled = newValue;
@ -191,17 +196,29 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
children: List.generate( children: List.generate(
passenger, passenger,
(index) { (index) {
if (isToggled && index == 0 && _loggedUser != null) {
return Padding( return Padding(
padding: EdgeInsets.only(bottom: 16.h), padding: EdgeInsets.only(bottom: 16.h),
child: CustomeShadowCotainner( child: CustomeShadowCotainner(
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
TypographyStyles.body( TypographyStyles.body(
'Penumpang 1 (Dewasa)', '${_loggedUser.name}',
color: GrayColors.gray800, color: GrayColors.gray800,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
SizedBox(height: 4.h),
TypographyStyles.caption(
"${_loggedUser.tipeId} - ${_loggedUser.noId}",
color: GrayColors.gray800,
fontWeight: FontWeight.w400,
)
],
),
ZoomTapAnimation( ZoomTapAnimation(
child: GestureDetector( child: GestureDetector(
child: CustomeIcons.EditOutline(), child: CustomeIcons.EditOutline(),
@ -238,6 +255,57 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
), ),
), ),
); );
} else {
return Padding(
padding: EdgeInsets.only(bottom: 16.h),
child: CustomeShadowCotainner(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TypographyStyles.body(
'Penumpang ${index + 1} (Dewasa)',
color: GrayColors.gray800,
fontWeight: FontWeight.w500,
),
ZoomTapAnimation(
child: GestureDetector(
child: CustomeIcons.EditOutline(),
onTap: () {
showModalBottomSheet(
context: context,
backgroundColor: Colors.white,
isScrollControlled: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.r),
topRight: Radius.circular(10.r),
),
),
builder: (context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w),
child: Wrap(
children: [
TitleShowModal(
text: 'Informasi Penumpang',
onTap: () {
Get.toNamed(Routes.ADDPASSENGER);
},
),
_buildAddPassenger(),
],
),
);
},
);
},
),
)
],
),
),
);
}
}, },
)); ));
} }
@ -245,6 +313,27 @@ class _TicketBookingStep1ScreenState extends State<TicketBookingStep1Screen> {
Widget _buildAddPassenger() { Widget _buildAddPassenger() {
return Padding( return Padding(
padding: EdgeInsets.symmetric(vertical: 16.h), padding: EdgeInsets.symmetric(vertical: 16.h),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h),
decoration: BoxDecoration(
color: GrayColors.gray50,
border: Border.all(width: 1.w, color: GrayColors.gray200),
borderRadius: BorderRadius.circular(10.r)),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TypographyStyles.body("Muhammad Al Kahfi", color: GrayColors.gray800),
SizedBox(height: 4.h),
TypographyStyles.caption("KTP - 3571", color: GrayColors.gray800, fontWeight: FontWeight.w400)
],
),
SvgPicture.asset('assets/icons/ic_more _than.svg')
],
),
),
); );
} }
} }

View File

@ -9,7 +9,8 @@ import 'package:zoom_tap_animation/zoom_tap_animation.dart';
import '../../../_core/constants/typography.dart'; import '../../../_core/constants/typography.dart';
import '../../controllers/navigation_controller.dart'; import '../../controllers/navigation_controller.dart';
import '../boarding_pass/pages/boarding_pass_screen.dart'; import '../boarding_pass/pages/boarding_pass_screen.dart';
import '../profile/profile_screen.dart'; import '../profile/pages/profile_screen.dart';
class MainNavigation extends StatefulWidget { class MainNavigation extends StatefulWidget {
final int initialTabIndex; final int initialTabIndex;

View File

@ -0,0 +1,131 @@
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/card/custome_shadow_cotainner.dart';
import 'package:e_porter/_core/component/text_field/dropdown/dropdown_component.dart';
import 'package:e_porter/_core/component/text_field/text_input/text_field_component.dart';
import 'package:e_porter/_core/constants/colors.dart';
import 'package:e_porter/_core/constants/typography.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
class AddPassengerScreen extends StatefulWidget {
const AddPassengerScreen({super.key});
@override
State<AddPassengerScreen> createState() => _AddPassengerScreenState();
}
class _AddPassengerScreenState extends State<AddPassengerScreen> {
final ValueNotifier<String> selectedGender = ValueNotifier<String>('');
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: GrayColors.gray50,
appBar: DefaultAppbarComponent(
backgroundColors: PrimaryColors.primary800,
title: "Tambah Penumpang",
textColor: Colors.white,
onTab: () {
Get.back();
},
),
body: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 20.h),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TypographyStyles.body(
"Silahkan isi informasi data diri calon penumpang baru",
color: GrayColors.gray600,
fontWeight: FontWeight.w400,
maxlines: 2,
),
SizedBox(height: 32.h),
TypographyStyles.body('Nama Lengkap', color: GrayColors.gray600, fontWeight: FontWeight.w400),
SizedBox(height: 16.w),
TextFieldComponent(hintText: 'Masukkan nama lengkap'),
SizedBox(height: 20.h),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TypographyStyles.body('Tipe ID', color: GrayColors.gray600, fontWeight: FontWeight.w400),
SizedBox(height: 16.h),
DropdownComponent(
hintText: "Pilih jenis dokument",
value: "KTP",
onChanged: (value) {},
),
],
),
SizedBox(width: 16.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TypographyStyles.body('No ID', color: GrayColors.gray600, fontWeight: FontWeight.w400),
SizedBox(height: 16.h),
TextFieldComponent(hintText: 'Masukkan ID')
],
),
)
],
),
SizedBox(height: 20.w),
TypographyStyles.body('Jenis Kelamin', color: GrayColors.gray600, fontWeight: FontWeight.w400),
Row(
children: [
_buildRadioButton(context, label: 'Laki-laki', value: 'Laki-laki'),
SizedBox(width: 40.h),
_buildRadioButton(context, label: 'Perempuan', value: 'Perempuan')
],
)
],
),
),
),
),
bottomNavigationBar: CustomeShadowCotainner(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 20.h),
borderRadius: BorderRadius.circular(0.r),
child: ButtonFill(
text: 'Simpan',
textColor: Colors.white,
onTap: () {},
),
),
);
}
Widget _buildRadioButton(
BuildContext context, {
required String label,
required String value,
}) {
return ValueListenableBuilder<String>(
valueListenable: selectedGender,
builder: (context, selected, child) {
return Row(
children: [
Radio<String>(
value: value,
groupValue: selected,
activeColor: PrimaryColors.primary800,
onChanged: (val) {
selectedGender.value = val!;
},
),
SizedBox(width: 10.w),
TypographyStyles.body(label, color: GrayColors.gray800, fontWeight: FontWeight.w500)
],
);
},
);
}
}

View File

@ -1,7 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../../_core/constants/colors.dart'; import '../../../../_core/constants/colors.dart';
import '../../../_core/constants/typography.dart'; import '../../../../_core/constants/typography.dart';
class ProfileScreen extends StatefulWidget { class ProfileScreen extends StatefulWidget {
const ProfileScreen({super.key}); const ProfileScreen({super.key});

View File

@ -19,7 +19,8 @@ import 'package:e_porter/presentation/screens/home/pages/ticket_booking_step3_sc
import 'package:e_porter/presentation/screens/home/pages/ticket_booking_step4_screen.dart'; import 'package:e_porter/presentation/screens/home/pages/ticket_booking_step4_screen.dart';
import 'package:e_porter/presentation/screens/navigation/main_navigation.dart'; import 'package:e_porter/presentation/screens/navigation/main_navigation.dart';
import 'package:e_porter/presentation/screens/onboarding/onboarding_screen.dart'; import 'package:e_porter/presentation/screens/onboarding/onboarding_screen.dart';
import 'package:e_porter/presentation/screens/profile/profile_screen.dart'; import 'package:e_porter/presentation/screens/profile/pages/profile_screen.dart';
import 'package:e_porter/presentation/screens/profile/pages/add_passenger_screen.dart';
import 'package:e_porter/presentation/screens/splash/splash_screen.dart'; import 'package:e_porter/presentation/screens/splash/splash_screen.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@ -82,7 +83,7 @@ class AppRoutes {
GetPage( GetPage(
name: Routes.SEARCHTICKETS, name: Routes.SEARCHTICKETS,
page: () => SearchTicketsScreen(), page: () => SearchTicketsScreen(),
binding: TicketBinding() binding: TicketBinding(),
), ),
GetPage( GetPage(
name: Routes.TICKETBOOKINGSTEP1, name: Routes.TICKETBOOKINGSTEP1,
@ -112,6 +113,10 @@ class AppRoutes {
name: Routes.TRANSACTIONHISTORY, name: Routes.TRANSACTIONHISTORY,
page: () => transactionHistory(), page: () => transactionHistory(),
), ),
GetPage(
name: Routes.ADDPASSENGER,
page: () => AddPassengerScreen(),
),
]; ];
} }
@ -136,4 +141,6 @@ class Routes {
static const CHOOSECHAIR = '/choose_chair'; static const CHOOSECHAIR = '/choose_chair';
static const PAYMENT = '/payment'; static const PAYMENT = '/payment';
static const TRANSACTIONHISTORY = '/transaction_history'; static const TRANSACTIONHISTORY = '/transaction_history';
static const ADDPASSENGER = '/add_passenger';
} }

View File

@ -97,6 +97,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.8" version: "1.0.8"
dropdown_button2:
dependency: "direct main"
description:
name: dropdown_button2
sha256: b0fe8d49a030315e9eef6c7ac84ca964250155a6224d491c1365061bc974a9e1
url: "https://pub.dev"
source: hosted
version: "2.3.9"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:

View File

@ -49,6 +49,7 @@ dependencies:
firebase_auth: ^5.5.1 firebase_auth: ^5.5.1
shared_preferences: ^2.5.2 shared_preferences: ^2.5.2
logger: ^2.5.0 logger: ^2.5.0
dropdown_button2: ^2.3.9
# pin_code_fields: ^8.0.1 # pin_code_fields: ^8.0.1
# dio: ^5.8.0+1 # dio: ^5.8.0+1