Feat: update progress finishing features profile
This commit is contained in:
parent
4436670550
commit
52edb41fb2
|
@ -680,7 +680,7 @@
|
||||||
"languageVersion": "3.4"
|
"languageVersion": "3.4"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"generated": "2025-05-12T05:36:15.239350Z",
|
"generated": "2025-05-14T06:38:43.763178Z",
|
||||||
"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",
|
||||||
|
|
|
@ -11,7 +11,7 @@ class TransactionReassignmentService {
|
||||||
FirebaseFirestore? firestore,
|
FirebaseFirestore? firestore,
|
||||||
}) : _firestore = firestore ?? FirebaseFirestore.instance;
|
}) : _firestore = firestore ?? FirebaseFirestore.instance;
|
||||||
|
|
||||||
void startService({int intervalSeconds = 30}) {
|
void startService({int intervalSeconds = 60}) {
|
||||||
log('[TransactionReassignmentService] Memulai service pengalihan transaksi dengan interval $intervalSeconds detik');
|
log('[TransactionReassignmentService] Memulai service pengalihan transaksi dengan interval $intervalSeconds detik');
|
||||||
_timer?.cancel();
|
_timer?.cancel();
|
||||||
_timer = Timer.periodic(Duration(seconds: intervalSeconds), (_) {
|
_timer = Timer.periodic(Duration(seconds: intervalSeconds), (_) {
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
// ignore_for_file: deprecated_member_use
|
||||||
|
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:e_porter/domain/repositories/profil_repository.dart';
|
import 'package:e_porter/domain/repositories/profil_repository.dart';
|
||||||
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import '../../_core/service/logger_service.dart';
|
import '../../_core/service/logger_service.dart';
|
||||||
import '../../domain/models/user_entity.dart';
|
import '../../domain/models/user_entity.dart';
|
||||||
|
|
||||||
|
@ -42,4 +45,96 @@ class ProfilRepositoryImpl implements ProfilRepository {
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> changePassword({
|
||||||
|
required String oldPassword,
|
||||||
|
required String newPassword,
|
||||||
|
}) async {
|
||||||
|
final user = FirebaseAuth.instance.currentUser;
|
||||||
|
if (user == null) {
|
||||||
|
throw Exception("User belum login");
|
||||||
|
}
|
||||||
|
|
||||||
|
final cred = EmailAuthProvider.credential(
|
||||||
|
email: user.email!,
|
||||||
|
password: oldPassword,
|
||||||
|
);
|
||||||
|
await user.reauthenticateWithCredential(cred);
|
||||||
|
await user.updatePassword(newPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> changePhone({
|
||||||
|
required String oldPassword,
|
||||||
|
required String newPhone,
|
||||||
|
}) async {
|
||||||
|
final user = FirebaseAuth.instance.currentUser;
|
||||||
|
if (user == null) {
|
||||||
|
throw Exception("User belum login");
|
||||||
|
}
|
||||||
|
|
||||||
|
final cred = EmailAuthProvider.credential(
|
||||||
|
email: user.email!,
|
||||||
|
password: oldPassword,
|
||||||
|
);
|
||||||
|
await user.reauthenticateWithCredential(cred);
|
||||||
|
await _firestore.collection('users').doc(user.uid).update({'phone': newPhone});
|
||||||
|
}
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// Future<void> changeEmail({
|
||||||
|
// required String oldPassword,
|
||||||
|
// required String newEmail,
|
||||||
|
// }) async {
|
||||||
|
// final user = FirebaseAuth.instance.currentUser;
|
||||||
|
// if (user == null) throw Exception("User belum login");
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// final cred = EmailAuthProvider.credential(
|
||||||
|
// email: user.email!,
|
||||||
|
// password: oldPassword,
|
||||||
|
// );
|
||||||
|
// await user.reauthenticateWithCredential(cred);
|
||||||
|
// await user.updateEmail(newEmail);
|
||||||
|
// await FirebaseFirestore.instance.collection('users').doc(user.uid).update({'email': newEmail});
|
||||||
|
|
||||||
|
// await user.sendEmailVerification();
|
||||||
|
|
||||||
|
// log("Email berhasil diperbarui ke: $newEmail");
|
||||||
|
// log("Email verifikasi telah dikirim");
|
||||||
|
// } catch (e) {
|
||||||
|
// log("Error pada changeEmail: $e");
|
||||||
|
// rethrow;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// Future<void> changeEmail({
|
||||||
|
// required String oldPassword,
|
||||||
|
// required String newEmail,
|
||||||
|
// }) async {
|
||||||
|
// final user = FirebaseAuth.instance.currentUser;
|
||||||
|
// if (user == null) throw Exception("User belum login");
|
||||||
|
|
||||||
|
// // re-authenticate
|
||||||
|
// final cred = EmailAuthProvider.credential(
|
||||||
|
// email: user.email!,
|
||||||
|
// password: oldPassword,
|
||||||
|
// );
|
||||||
|
// await user.reauthenticateWithCredential(cred);
|
||||||
|
|
||||||
|
// // gunakan verifyBeforeUpdateEmail (ini kirim link + set newEmail di backend)
|
||||||
|
// await user.verifyBeforeUpdateEmail(
|
||||||
|
// newEmail,
|
||||||
|
// ActionCodeSettings(
|
||||||
|
// url: 'https://eporter.page.link/verifyEmail',
|
||||||
|
// handleCodeInApp: true,
|
||||||
|
// androidPackageName: 'com.example.e_porter',
|
||||||
|
// androidInstallApp: true,
|
||||||
|
// androidMinimumVersion: '1',
|
||||||
|
// dynamicLinkDomain: 'eporter.page.link',
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:e_porter/domain/repositories/statistic_repository.dart';
|
||||||
|
|
||||||
|
class StatisticRepositoryImpl implements StatisticRepository {
|
||||||
|
final FirebaseFirestore _firestore;
|
||||||
|
StatisticRepositoryImpl(this._firestore);
|
||||||
|
|
||||||
|
Timestamp _tsFromDate(DateTime d) =>
|
||||||
|
Timestamp.fromDate(DateTime(d.year, d.month, d.day));
|
||||||
|
Timestamp _tsToDate(DateTime d) =>
|
||||||
|
Timestamp.fromDate(DateTime(d.year, d.month, d.day).add(const Duration(days: 1)));
|
||||||
|
|
||||||
|
Query _baseQuery({
|
||||||
|
required String porterId,
|
||||||
|
required String status,
|
||||||
|
required DateTime date,
|
||||||
|
}) {
|
||||||
|
return _firestore
|
||||||
|
.collection('porterTransactions')
|
||||||
|
.where('porterUserId', isEqualTo: porterId)
|
||||||
|
.where('status', isEqualTo: status)
|
||||||
|
.where('createdAt', isGreaterThanOrEqualTo: _tsFromDate(date))
|
||||||
|
.where('createdAt', isLessThan: _tsToDate(date));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<int> getIncomingOrdersCount({
|
||||||
|
required String porterId,
|
||||||
|
required DateTime date,
|
||||||
|
}) {
|
||||||
|
return _baseQuery(porterId: porterId, status: 'pending', date: date)
|
||||||
|
.snapshots()
|
||||||
|
.map((snap) => snap.docs.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<int> getInProgressOrdersCount({
|
||||||
|
required String porterId,
|
||||||
|
required DateTime date,
|
||||||
|
}) {
|
||||||
|
return _baseQuery(porterId: porterId, status: 'proses', date: date)
|
||||||
|
.snapshots()
|
||||||
|
.map((snap) => snap.docs.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<int> getCompletedOrdersCount({
|
||||||
|
required String porterId,
|
||||||
|
required DateTime date,
|
||||||
|
}) {
|
||||||
|
return _baseQuery(porterId: porterId, status: 'selesai', date: date)
|
||||||
|
.snapshots()
|
||||||
|
.map((snap) => snap.docs.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<double> getRevenue({
|
||||||
|
required String porterId,
|
||||||
|
required DateTime date,
|
||||||
|
}) {
|
||||||
|
|
||||||
|
return _baseQuery(porterId: porterId, status: 'selesai', date: date)
|
||||||
|
.snapshots()
|
||||||
|
.asyncMap((snap) async {
|
||||||
|
double total = 0;
|
||||||
|
for (final doc in snap.docs) {
|
||||||
|
final data = doc.data();
|
||||||
|
final ticketId = (data as Map<String, dynamic>?)?['ticketId'] ?? '';
|
||||||
|
final transactionId = (data as Map<String, dynamic>?)?['transactionId'] ?? '';
|
||||||
|
if (ticketId != null && transactionId != null) {
|
||||||
|
// join ke sub‐collection payments
|
||||||
|
final payDoc = await _firestore
|
||||||
|
.collection('tickets')
|
||||||
|
.doc(ticketId)
|
||||||
|
.collection('payments')
|
||||||
|
.doc(transactionId)
|
||||||
|
.get();
|
||||||
|
if (payDoc.exists && payDoc.data()!.containsKey('porterServiceDetails')) {
|
||||||
|
final ps = payDoc['porterServiceDetails'] as Map<String, dynamic>;
|
||||||
|
final a = (ps['arrival']['price'] as num).toDouble();
|
||||||
|
final b = (ps['departure']['price'] as num).toDouble();
|
||||||
|
total += a + b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,12 +13,18 @@ class ProfilBinding extends Bindings {
|
||||||
Get.lazyPut(() => CreatePassengerUseCase(Get.find()));
|
Get.lazyPut(() => CreatePassengerUseCase(Get.find()));
|
||||||
Get.lazyPut(() => GetPassengerByIdUseCase(Get.find()));
|
Get.lazyPut(() => GetPassengerByIdUseCase(Get.find()));
|
||||||
Get.lazyPut(() => GetUserByIdUseCase(Get.find()));
|
Get.lazyPut(() => GetUserByIdUseCase(Get.find()));
|
||||||
|
Get.lazyPut(() => ChangePasswordUseCase(Get.find()));
|
||||||
|
Get.lazyPut(() => ChangePhoneUseCase(Get.find()));
|
||||||
|
// Get.lazyPut(() => ChangeEmailUseCase(Get.find()));
|
||||||
|
|
||||||
Get.lazyPut(
|
Get.lazyPut(
|
||||||
() => ProfilController(
|
() => ProfilController(
|
||||||
createPassengerUseCase: Get.find(),
|
createPassengerUseCase: Get.find(),
|
||||||
getPassengerByIdUseCase: Get.find(),
|
getPassengerByIdUseCase: Get.find(),
|
||||||
getUserByIdUseCase: Get.find(),
|
getUserByIdUseCase: Get.find(),
|
||||||
|
changePasswordUseCase: Get.find(),
|
||||||
|
changePhoneUseCase: Get.find(),
|
||||||
|
// changeEmailUseCase: Get.find(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:e_porter/data/repositories/statistic_repository_impl.dart';
|
||||||
|
import 'package:e_porter/domain/repositories/statistic_repository.dart';
|
||||||
|
import 'package:e_porter/domain/usecases/statistic_usecase.dart';
|
||||||
|
import 'package:e_porter/presentation/controllers/statistic_controller.dart';
|
||||||
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
class StatisticBinding extends Bindings {
|
||||||
|
@override
|
||||||
|
void dependencies() {
|
||||||
|
// Repository
|
||||||
|
Get.lazyPut<StatisticRepository>(
|
||||||
|
() => StatisticRepositoryImpl(FirebaseFirestore.instance),
|
||||||
|
);
|
||||||
|
|
||||||
|
// UseCase
|
||||||
|
Get.lazyPut(() => StatisticUseCase(Get.find()));
|
||||||
|
|
||||||
|
// Controller: di sini kita ambil current user ID langsung dari FirebaseAuth
|
||||||
|
Get.lazyPut(() => StatisticController(
|
||||||
|
useCase: Get.find(),
|
||||||
|
porterId: FirebaseAuth.instance.currentUser!.uid,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,5 +7,21 @@ abstract class ProfilRepository {
|
||||||
});
|
});
|
||||||
|
|
||||||
Future<List<PassengerModel>> getPassengerById(String userId);
|
Future<List<PassengerModel>> getPassengerById(String userId);
|
||||||
|
|
||||||
Future<UserData> getUserById(String userId);
|
Future<UserData> getUserById(String userId);
|
||||||
|
|
||||||
|
Future<void> changePassword({
|
||||||
|
required String oldPassword,
|
||||||
|
required String newPassword,
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<void> changePhone({
|
||||||
|
required String oldPassword,
|
||||||
|
required String newPhone,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Future<void> changeEmail({
|
||||||
|
// required String oldPassword,
|
||||||
|
// required String newEmail,
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
abstract class StatisticRepository {
|
||||||
|
Stream<int> getIncomingOrdersCount({
|
||||||
|
required String porterId,
|
||||||
|
required DateTime date,
|
||||||
|
});
|
||||||
|
|
||||||
|
Stream<int> getInProgressOrdersCount({
|
||||||
|
required String porterId,
|
||||||
|
required DateTime date,
|
||||||
|
});
|
||||||
|
|
||||||
|
Stream<int> getCompletedOrdersCount({
|
||||||
|
required String porterId,
|
||||||
|
required DateTime date,
|
||||||
|
});
|
||||||
|
|
||||||
|
Stream<double> getRevenue({
|
||||||
|
required String porterId,
|
||||||
|
required DateTime date,
|
||||||
|
});
|
||||||
|
}
|
|
@ -33,3 +33,48 @@ class GetUserByIdUseCase {
|
||||||
|
|
||||||
Future<UserData> call(String userId) => profilRepository.getUserById(userId);
|
Future<UserData> call(String userId) => profilRepository.getUserById(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ChangePasswordUseCase {
|
||||||
|
final ProfilRepository profilRepository;
|
||||||
|
ChangePasswordUseCase(this.profilRepository);
|
||||||
|
|
||||||
|
Future<void> call({
|
||||||
|
required String oldPassword,
|
||||||
|
required String newPassword,
|
||||||
|
}) {
|
||||||
|
return profilRepository.changePassword(
|
||||||
|
oldPassword: oldPassword,
|
||||||
|
newPassword: newPassword,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangePhoneUseCase {
|
||||||
|
final ProfilRepository profilRepository;
|
||||||
|
ChangePhoneUseCase(this.profilRepository);
|
||||||
|
|
||||||
|
Future<void> call({
|
||||||
|
required String oldPassword,
|
||||||
|
required String newPhone,
|
||||||
|
}) {
|
||||||
|
return profilRepository.changePhone(
|
||||||
|
oldPassword: oldPassword,
|
||||||
|
newPhone: newPhone,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// class ChangeEmailUseCase {
|
||||||
|
// final ProfilRepository profilRepository;
|
||||||
|
// ChangeEmailUseCase(this.profilRepository);
|
||||||
|
|
||||||
|
// Future<void> call({
|
||||||
|
// required String oldPassword,
|
||||||
|
// required String newEmail,
|
||||||
|
// }) {
|
||||||
|
// return profilRepository.changeEmail(
|
||||||
|
// oldPassword: oldPassword,
|
||||||
|
// newEmail: newEmail,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
import 'package:e_porter/domain/repositories/statistic_repository.dart';
|
||||||
|
|
||||||
|
class StatisticUseCase {
|
||||||
|
final StatisticRepository _repo;
|
||||||
|
StatisticUseCase(this._repo);
|
||||||
|
|
||||||
|
Stream<int> getIncomingOrders({
|
||||||
|
required String porterId,
|
||||||
|
required DateTime date,
|
||||||
|
}) => _repo.getIncomingOrdersCount(porterId: porterId, date: date);
|
||||||
|
|
||||||
|
Stream<int> getInProgressOrders({
|
||||||
|
required String porterId,
|
||||||
|
required DateTime date,
|
||||||
|
}) => _repo.getInProgressOrdersCount(porterId: porterId, date: date);
|
||||||
|
|
||||||
|
Stream<int> getCompletedOrders({
|
||||||
|
required String porterId,
|
||||||
|
required DateTime date,
|
||||||
|
}) => _repo.getCompletedOrdersCount(porterId: porterId, date: date);
|
||||||
|
|
||||||
|
Stream<double> getRevenue({
|
||||||
|
required String porterId,
|
||||||
|
required DateTime date,
|
||||||
|
}) => _repo.getRevenue(porterId: porterId, date: date);
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:e_porter/_core/service/logger_service.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:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
@ -12,15 +12,24 @@ class ProfilController extends GetxController {
|
||||||
final CreatePassengerUseCase createPassengerUseCase;
|
final CreatePassengerUseCase createPassengerUseCase;
|
||||||
final GetPassengerByIdUseCase getPassengerByIdUseCase;
|
final GetPassengerByIdUseCase getPassengerByIdUseCase;
|
||||||
final GetUserByIdUseCase getUserByIdUseCase;
|
final GetUserByIdUseCase getUserByIdUseCase;
|
||||||
|
final ChangePasswordUseCase changePasswordUseCase;
|
||||||
|
final ChangePhoneUseCase changePhoneUseCase;
|
||||||
|
// final ChangeEmailUseCase changeEmailUseCase;
|
||||||
|
|
||||||
var passengerList = <PassengerModel>[].obs;
|
var passengerList = <PassengerModel>[].obs;
|
||||||
var userData = Rxn<UserData>();
|
var userData = Rxn<UserData>();
|
||||||
var isLoading = false.obs;
|
var isLoading = false.obs;
|
||||||
|
var isChangingPassword = false.obs;
|
||||||
|
var isChangingPhone = false.obs;
|
||||||
|
// var isChangingEmail = false.obs;
|
||||||
|
|
||||||
ProfilController({
|
ProfilController({
|
||||||
required this.createPassengerUseCase,
|
required this.createPassengerUseCase,
|
||||||
required this.getPassengerByIdUseCase,
|
required this.getPassengerByIdUseCase,
|
||||||
required this.getUserByIdUseCase,
|
required this.getUserByIdUseCase,
|
||||||
|
required this.changePasswordUseCase,
|
||||||
|
required this.changePhoneUseCase,
|
||||||
|
// required this.changeEmailUseCase,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -29,6 +38,19 @@ class ProfilController extends GetxController {
|
||||||
_loadProfile();
|
_loadProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Future<void> reloadProfile() async {
|
||||||
|
// final user = FirebaseAuth.instance.currentUser;
|
||||||
|
// if (user == null) return;
|
||||||
|
// final uid = user.uid;
|
||||||
|
|
||||||
|
// await FirebaseFirestore.instance.collection('users').doc(uid).update({'email': user.email});
|
||||||
|
|
||||||
|
// final fresh = await getUserByIdUseCase(uid);
|
||||||
|
// userData.value = fresh;
|
||||||
|
|
||||||
|
// await PreferencesService.saveUserData(fresh);
|
||||||
|
// }
|
||||||
|
|
||||||
Future<void> _loadProfile() async {
|
Future<void> _loadProfile() async {
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
try {
|
try {
|
||||||
|
@ -78,4 +100,133 @@ class ProfilController extends GetxController {
|
||||||
logger.e("Error fetching passengers: $e");
|
logger.e("Error fetching passengers: $e");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> changePassword({
|
||||||
|
required String oldPassword,
|
||||||
|
required String newPassword,
|
||||||
|
}) async {
|
||||||
|
isChangingPassword.value = true;
|
||||||
|
try {
|
||||||
|
await changePasswordUseCase(
|
||||||
|
oldPassword: oldPassword,
|
||||||
|
newPassword: newPassword,
|
||||||
|
);
|
||||||
|
SnackbarHelper.showSuccess("Berhasil", "Password berhasil diperbarui.");
|
||||||
|
return true;
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
if (e.code == 'wrong-password' || e.code == 'invalid-credential') {
|
||||||
|
SnackbarHelper.showError("Gagal", "Password lama salah.");
|
||||||
|
} else if (e.code == 'weak-password') {
|
||||||
|
SnackbarHelper.showError("Gagal", "Password baru terlalu lemah.");
|
||||||
|
} else {
|
||||||
|
SnackbarHelper.showError("Gagal", "Error: ${e.message}");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (e) {
|
||||||
|
SnackbarHelper.showError("Gagal", "Terjadi kesalahan.");
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
isChangingPassword.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> changePhone({
|
||||||
|
required String oldPassword,
|
||||||
|
required String newPhone,
|
||||||
|
}) async {
|
||||||
|
isChangingPhone.value = true;
|
||||||
|
try {
|
||||||
|
await changePhoneUseCase(
|
||||||
|
oldPassword: oldPassword,
|
||||||
|
newPhone: newPhone,
|
||||||
|
);
|
||||||
|
await _loadProfile();
|
||||||
|
SnackbarHelper.showSuccess("Berhasil", "Nomor telepon berhasil diperbarui.");
|
||||||
|
return true;
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
if (e.code == 'wrong-password' || e.code == 'invalid-credential') {
|
||||||
|
SnackbarHelper.showError("Gagal", "Password lama salah.");
|
||||||
|
} else {
|
||||||
|
SnackbarHelper.showError("Gagal", e.message ?? "Terjadi kesalahan.");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (_) {
|
||||||
|
SnackbarHelper.showError("Gagal", "Terjadi kesalahan.");
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
isChangingPhone.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Future<bool> changeEmail({
|
||||||
|
// required String oldPassword,
|
||||||
|
// required String newEmail,
|
||||||
|
// }) async {
|
||||||
|
// isChangingEmail.value = true;
|
||||||
|
// try {
|
||||||
|
// await changeEmailUseCase(
|
||||||
|
// oldPassword: oldPassword,
|
||||||
|
// newEmail: newEmail,
|
||||||
|
// );
|
||||||
|
|
||||||
|
// await reloadProfile();
|
||||||
|
|
||||||
|
// SnackbarHelper.showSuccess("Berhasil", "Email berhasil diubah. Silakan cek $newEmail untuk verifikasi.");
|
||||||
|
// return true;
|
||||||
|
// } on FirebaseAuthException catch (e) {
|
||||||
|
// switch (e.code) {
|
||||||
|
// case 'wrong-password':
|
||||||
|
// case 'invalid-credential':
|
||||||
|
// SnackbarHelper.showError("Gagal", "Password lama salah.");
|
||||||
|
// break;
|
||||||
|
// case 'email-already-in-use':
|
||||||
|
// SnackbarHelper.showError("Gagal", "Email baru sudah digunakan.");
|
||||||
|
// break;
|
||||||
|
// case 'operation-not-allowed':
|
||||||
|
// SnackbarHelper.showError("Gagal", "Email/Password signin belum diaktifkan di Firebase Console.");
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// SnackbarHelper.showError("Gagal", e.message ?? e.code);
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// } finally {
|
||||||
|
// isChangingEmail.value = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Future<bool> changeEmail({
|
||||||
|
// required String oldPassword,
|
||||||
|
// required String newEmail,
|
||||||
|
// }) async {
|
||||||
|
// isChangingEmail.value = true;
|
||||||
|
// try {
|
||||||
|
// await changeEmailUseCase(oldPassword: oldPassword, newEmail: newEmail);
|
||||||
|
// SnackbarHelper.showSuccess("Link Terkirim", "Silakan cek email $newEmail untuk verifikasi.");
|
||||||
|
// return true;
|
||||||
|
// } on FirebaseAuthException catch (e) {
|
||||||
|
// switch (e.code) {
|
||||||
|
// case 'wrong-password':
|
||||||
|
// case 'invalid-credential':
|
||||||
|
// SnackbarHelper.showError("Gagal", "Password lama salah.");
|
||||||
|
// break;
|
||||||
|
// case 'email-already-in-use':
|
||||||
|
// SnackbarHelper.showError("Gagal", "Email baru sudah digunakan.");
|
||||||
|
// break;
|
||||||
|
// case 'unauthorized-domain':
|
||||||
|
// SnackbarHelper.showError(
|
||||||
|
// "Gagal",
|
||||||
|
// "Domain verifikasi belum diizinkan. "
|
||||||
|
// "Tambahkan \"eporter.page.link\" di Firebase Console → Authentication → Settings → Authorized domains.");
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// SnackbarHelper.showError("Gagal", e.message ?? e.code);
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// } catch (_) {
|
||||||
|
// SnackbarHelper.showError("Gagal", "Terjadi kesalahan.");
|
||||||
|
// return false;
|
||||||
|
// } finally {
|
||||||
|
// isChangingEmail.value = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
import 'package:e_porter/domain/usecases/statistic_usecase.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
class StatisticController extends GetxController {
|
||||||
|
final StatisticUseCase useCase;
|
||||||
|
final String porterId;
|
||||||
|
|
||||||
|
final date = DateTime.now().obs;
|
||||||
|
|
||||||
|
final incoming = 0.obs;
|
||||||
|
final inProgress = 0.obs;
|
||||||
|
final completed = 0.obs;
|
||||||
|
final revenue = 0.0.obs;
|
||||||
|
|
||||||
|
StatisticController({
|
||||||
|
required this.useCase,
|
||||||
|
required this.porterId,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onInit() {
|
||||||
|
super.onInit();
|
||||||
|
_bindAllStreams();
|
||||||
|
ever(date, (_) => _bindAllStreams());
|
||||||
|
}
|
||||||
|
|
||||||
|
void _bindAllStreams() {
|
||||||
|
incoming.bindStream(
|
||||||
|
useCase.getIncomingOrders(porterId: porterId, date: date.value),
|
||||||
|
);
|
||||||
|
inProgress.bindStream(
|
||||||
|
useCase.getInProgressOrders(porterId: porterId, date: date.value),
|
||||||
|
);
|
||||||
|
completed.bindStream(
|
||||||
|
useCase.getCompletedOrders(porterId: porterId, date: date.value),
|
||||||
|
);
|
||||||
|
revenue.bindStream(
|
||||||
|
useCase.getRevenue(porterId: porterId, date: date.value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeDate(DateTime newDate) => date.value = newDate;
|
||||||
|
}
|
|
@ -74,7 +74,7 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Obx(() {
|
Obx(() {
|
||||||
if (!authController.isLoading.value) {
|
if (authController.isLoading.value) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: 48.h,
|
height: 48.h,
|
||||||
|
|
|
@ -26,7 +26,7 @@ class HeaderInformation extends StatelessWidget {
|
||||||
child: TypographyStyles.caption(
|
child: TypographyStyles.caption(
|
||||||
title,
|
title,
|
||||||
color: GrayColors.gray500,
|
color: GrayColors.gray500,
|
||||||
maxlines: 5,
|
maxlines: 6,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -6,9 +6,11 @@ import 'package:e_porter/_core/constants/typography.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/profil_controller.dart';
|
import 'package:e_porter/presentation/controllers/profil_controller.dart';
|
||||||
import 'package:e_porter/presentation/screens/profile/component/header_information.dart';
|
import 'package:e_porter/presentation/screens/profile/component/header_information.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:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:zoom_tap_animation/zoom_tap_animation.dart';
|
||||||
|
|
||||||
class InformationUsersScreen extends StatefulWidget {
|
class InformationUsersScreen extends StatefulWidget {
|
||||||
const InformationUsersScreen({super.key});
|
const InformationUsersScreen({super.key});
|
||||||
|
@ -73,9 +75,18 @@ class _InformationUsersScreenState extends State<InformationUsersScreen> {
|
||||||
child: CustomeShadowCotainner(
|
child: CustomeShadowCotainner(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
itemWithButton(label: 'Nomor Telepon', value: userData.phone ?? '-'),
|
itemWithButton(
|
||||||
|
label: 'Email',
|
||||||
|
value: userData.email ?? '-',
|
||||||
|
),
|
||||||
SizedBox(height: 24.h),
|
SizedBox(height: 24.h),
|
||||||
itemWithButton(label: 'Email', value: userData.email ?? '-'),
|
itemWithButton(
|
||||||
|
label: 'Nomor Telepon',
|
||||||
|
value: userData.phone ?? '-',
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.CHANGENUMBER);
|
||||||
|
},
|
||||||
|
),
|
||||||
SizedBox(height: 24.h),
|
SizedBox(height: 24.h),
|
||||||
itemDoubleWithButton(
|
itemDoubleWithButton(
|
||||||
label1: 'Tipe ID', value1: userData.tipeId ?? '-', label2: 'No ID', value2: userData.noId ?? '-'),
|
label1: 'Tipe ID', value1: userData.tipeId ?? '-', label2: 'No ID', value2: userData.noId ?? '-'),
|
||||||
|
@ -92,7 +103,12 @@ class _InformationUsersScreenState extends State<InformationUsersScreen> {
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
itemWithButton(label: 'Nama Lengkap', value: userData.name ?? '-', isDivider: false),
|
itemWithButton(
|
||||||
|
label: 'Nama Lengkap',
|
||||||
|
value: userData.name ?? '-',
|
||||||
|
isDivider: false,
|
||||||
|
onTap: () {},
|
||||||
|
),
|
||||||
SizedBox(height: 24.h),
|
SizedBox(height: 24.h),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
|
@ -113,7 +129,12 @@ class _InformationUsersScreenState extends State<InformationUsersScreen> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget itemWithButton({required String label, required String value, bool isDivider = true}) {
|
Widget itemWithButton({
|
||||||
|
required String label,
|
||||||
|
required String value,
|
||||||
|
bool isDivider = true,
|
||||||
|
VoidCallback? onTap,
|
||||||
|
}) {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
|
@ -136,22 +157,28 @@ class _InformationUsersScreenState extends State<InformationUsersScreen> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
if (onTap != null)
|
||||||
padding: EdgeInsets.symmetric(vertical: 6.h, horizontal: 10.w),
|
Container(
|
||||||
decoration: BoxDecoration(
|
padding: EdgeInsets.symmetric(vertical: 6.h, horizontal: 10.w),
|
||||||
color: PrimaryColors.primary100,
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(10.r),
|
color: PrimaryColors.primary100,
|
||||||
),
|
borderRadius: BorderRadius.circular(10.r),
|
||||||
child: Row(
|
),
|
||||||
children: [
|
child: ZoomTapAnimation(
|
||||||
Icon(Icons.edit, color: PrimaryColors.primary800, size: 14.sp),
|
child: GestureDetector(
|
||||||
Padding(
|
onTap: onTap,
|
||||||
padding: EdgeInsets.only(left: 8.w),
|
child: Row(
|
||||||
child: TypographyStyles.small('Ubah', color: PrimaryColors.primary800),
|
children: [
|
||||||
|
Icon(Icons.edit, color: PrimaryColors.primary800, size: 14.sp),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(left: 8.w),
|
||||||
|
child: TypographyStyles.small('Ubah', color: PrimaryColors.primary800),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
)
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (isDivider)
|
if (isDivider)
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
// ignore_for_file: deprecated_member_use
|
||||||
|
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/constants/colors.dart';
|
||||||
|
import 'package:e_porter/_core/constants/typography.dart';
|
||||||
|
import 'package:e_porter/presentation/screens/routes/app_rountes.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:zoom_tap_animation/zoom_tap_animation.dart';
|
||||||
|
|
||||||
|
class PassengerListScreen extends StatefulWidget {
|
||||||
|
const PassengerListScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<PassengerListScreen> createState() => _PassengerListScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PassengerListScreenState extends State<PassengerListScreen> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: GrayColors.gray50,
|
||||||
|
appBar: DefaultAppbarComponent(
|
||||||
|
title: 'Daftar Penumpang',
|
||||||
|
textColor: Colors.white,
|
||||||
|
backgroundColors: PrimaryColors.primary800,
|
||||||
|
onTab: () {
|
||||||
|
Get.back();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 20.h),
|
||||||
|
child: ListView.builder(
|
||||||
|
itemCount: 2,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(bottom: 16.h),
|
||||||
|
child: _buildCardItem(
|
||||||
|
value: 'Name',
|
||||||
|
onTap: () {
|
||||||
|
// Get.toNamed(Routes.passengerDetail);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
bottomNavigationBar: CustomeShadowCotainner(
|
||||||
|
child: ButtonFill(
|
||||||
|
text: 'Tambah Penumpang',
|
||||||
|
textColor: Colors.white,
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.ADDPASSENGER);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildCardItem({required String value, required VoidCallback onTap}) {
|
||||||
|
return ZoomTapAnimation(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(10.r),
|
||||||
|
border: Border.all(color: GrayColors.gray200),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
TypographyStyles.caption('Dewasa', fontWeight: FontWeight.w400, color: GrayColors.gray500),
|
||||||
|
TypographyStyles.body(value, color: GrayColors.gray800)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SvgPicture.asset(
|
||||||
|
'assets/icons/ic_more_than.svg',
|
||||||
|
color: GrayColors.gray500,
|
||||||
|
width: 20.w,
|
||||||
|
height: 20.h,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -107,7 +107,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||||
ProfileMenu(
|
ProfileMenu(
|
||||||
label: 'Tambah Penumpang',
|
label: 'Tambah Penumpang',
|
||||||
svgIcon: 'assets/icons/ic_add_user_female.svg',
|
svgIcon: 'assets/icons/ic_add_user_female.svg',
|
||||||
onTap: () {},
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.PASSENGERLIST);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(vertical: 20.h),
|
padding: EdgeInsets.symmetric(vertical: 20.h),
|
||||||
|
@ -234,7 +236,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||||
ProfileMenu(
|
ProfileMenu(
|
||||||
label: 'Ganti Kata Sandi',
|
label: 'Ganti Kata Sandi',
|
||||||
svgIcon: 'assets/icons/ic_lock.svg',
|
svgIcon: 'assets/icons/ic_lock.svg',
|
||||||
onTap: () {},
|
onTap: () {
|
||||||
|
Get.toNamed(Routes.CHANGEPASSWORD);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(vertical: 20.h),
|
padding: EdgeInsets.symmetric(vertical: 20.h),
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'package:e_porter/domain/bindings/porter_queue_binding.dart';
|
||||||
import 'package:e_porter/domain/bindings/porter_service_binding.dart';
|
import 'package:e_porter/domain/bindings/porter_service_binding.dart';
|
||||||
import 'package:e_porter/domain/bindings/profil_binding.dart';
|
import 'package:e_porter/domain/bindings/profil_binding.dart';
|
||||||
import 'package:e_porter/domain/bindings/search_flight_binding.dart';
|
import 'package:e_porter/domain/bindings/search_flight_binding.dart';
|
||||||
|
import 'package:e_porter/domain/bindings/statistic_binding.dart';
|
||||||
import 'package:e_porter/domain/bindings/ticket_binding.dart';
|
import 'package:e_porter/domain/bindings/ticket_binding.dart';
|
||||||
import 'package:e_porter/domain/bindings/transaction_binding.dart';
|
import 'package:e_porter/domain/bindings/transaction_binding.dart';
|
||||||
import 'package:e_porter/domain/bindings/transaction_porter_binding.dart';
|
import 'package:e_porter/domain/bindings/transaction_porter_binding.dart';
|
||||||
|
@ -34,8 +35,11 @@ import 'package:e_porter/presentation/screens/home/pages/ticket_booking_step4_sc
|
||||||
import 'package:e_porter/presentation/screens/home/pages/upload_file_screen.dart';
|
import 'package:e_porter/presentation/screens/home/pages/upload_file_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/pages/change_email_screen.dart';
|
||||||
|
import 'package:e_porter/presentation/screens/profile/pages/change_number_screen.dart';
|
||||||
import 'package:e_porter/presentation/screens/profile/pages/change_password_screen.dart';
|
import 'package:e_porter/presentation/screens/profile/pages/change_password_screen.dart';
|
||||||
import 'package:e_porter/presentation/screens/profile/pages/information_users_screen.dart';
|
import 'package:e_porter/presentation/screens/profile/pages/information_users_screen.dart';
|
||||||
|
import 'package:e_porter/presentation/screens/profile/pages/passenger_list_screen.dart';
|
||||||
import 'package:e_porter/presentation/screens/profile/pages/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/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';
|
||||||
|
@ -53,6 +57,7 @@ class AppRoutes {
|
||||||
HistoryBinding(),
|
HistoryBinding(),
|
||||||
PorterQueueBinding(),
|
PorterQueueBinding(),
|
||||||
TransactionPorterBinding(),
|
TransactionPorterBinding(),
|
||||||
|
StatisticBinding()
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
GetPage(
|
GetPage(
|
||||||
|
@ -203,6 +208,20 @@ class AppRoutes {
|
||||||
GetPage(
|
GetPage(
|
||||||
name: Routes.CHANGEPASSWORD,
|
name: Routes.CHANGEPASSWORD,
|
||||||
page: () => ChangePasswordScreen(),
|
page: () => ChangePasswordScreen(),
|
||||||
|
binding: ProfilBinding(),
|
||||||
|
),
|
||||||
|
GetPage(
|
||||||
|
name: Routes.CHANGENUMBER,
|
||||||
|
page: () => ChangeNumberScreen(),
|
||||||
|
),
|
||||||
|
GetPage(
|
||||||
|
name: Routes.CHANGEEMAIL,
|
||||||
|
page: () => ChangeEmailScreen(),
|
||||||
|
binding: ProfilBinding(),
|
||||||
|
),
|
||||||
|
GetPage(
|
||||||
|
name: Routes.PASSENGERLIST,
|
||||||
|
page: () => PassengerListScreen(),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -249,4 +268,7 @@ class Routes {
|
||||||
static const ADDPASSENGER = '/add_passenger';
|
static const ADDPASSENGER = '/add_passenger';
|
||||||
static const INFORMATIONS = '/informations';
|
static const INFORMATIONS = '/informations';
|
||||||
static const CHANGEPASSWORD = '/change_password';
|
static const CHANGEPASSWORD = '/change_password';
|
||||||
|
static const CHANGENUMBER = '/change_number';
|
||||||
|
static const CHANGEEMAIL = '/change_email';
|
||||||
|
static const PASSENGERLIST = '/passenger_list';
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue