Feat: fix bug in features history transaction porter

This commit is contained in:
orangdeso 2025-05-06 15:30:36 +07:00
parent 56b629b1d7
commit 6bf43369c4
5 changed files with 89 additions and 65 deletions

View File

@ -638,7 +638,7 @@
"languageVersion": "3.4" "languageVersion": "3.4"
} }
], ],
"generated": "2025-04-30T16:03:15.794012Z", "generated": "2025-05-05T05:14:47.271498Z",
"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

@ -670,7 +670,7 @@ class TransactionPorterRepositoryImpl implements TransactionPorterRepository {
'isAvailable': false, 'isAvailable': false,
'idTransaction': transactionId, 'idTransaction': transactionId,
'idUser': txData['idPassenger'] ?? '', 'idUser': txData['idPassenger'] ?? '',
'lastAssigned': now, 'onlineAt': now,
}); });
// 6. Update transaksi utama dengan format ReassignmentInfo // 6. Update transaksi utama dengan format ReassignmentInfo

View File

@ -5,7 +5,6 @@ import 'package:e_porter/_core/service/preferences_service.dart';
import 'package:e_porter/_core/utils/snackbar/snackbar_helper.dart'; import 'package:e_porter/_core/utils/snackbar/snackbar_helper.dart';
import 'package:e_porter/domain/models/porter_queue_model.dart'; import 'package:e_porter/domain/models/porter_queue_model.dart';
import 'package:e_porter/presentation/screens/boarding_pass/provider/porter_service_provider.dart'; import 'package:e_porter/presentation/screens/boarding_pass/provider/porter_service_provider.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import '../../domain/models/transaction_porter_model.dart'; import '../../domain/models/transaction_porter_model.dart';
import '../../domain/usecases/transaction_porter_usecase.dart'; import '../../domain/usecases/transaction_porter_usecase.dart';
@ -30,8 +29,6 @@ class TransactionPorterController extends GetxController {
final RxBool isRejecting = false.obs; final RxBool isRejecting = false.obs;
final RxBool needsRefresh = false.obs; final RxBool needsRefresh = false.obs;
final TextEditingController rejectionReasonController = TextEditingController();
StreamSubscription<List<PorterTransactionModel>>? _subscription; StreamSubscription<List<PorterTransactionModel>>? _subscription;
StreamSubscription<PorterQueueModel?>? _porterSubscription; StreamSubscription<PorterQueueModel?>? _porterSubscription;
StreamSubscription<List<PorterTransactionModel>>? _rejectedSubscription; StreamSubscription<List<PorterTransactionModel>>? _rejectedSubscription;
@ -524,18 +521,15 @@ class TransactionPorterController extends GetxController {
void showRejectDialog() { void showRejectDialog() {
rejectionReason.value = ''; rejectionReason.value = '';
rejectionReasonController.clear();
isRejectionDialogVisible.value = true; isRejectionDialogVisible.value = true;
} }
void hideRejectDialog() { void hideRejectDialog() {
isRejectionDialogVisible.value = false; isRejectionDialogVisible.value = false;
rejectionReasonController.clear();
} }
@override @override
void onClose() { void onClose() {
rejectionReasonController.dispose();
_porterSubscription?.cancel(); _porterSubscription?.cancel();
_subscription?.cancel(); _subscription?.cancel();
_rejectedSubscription?.cancel(); _rejectedSubscription?.cancel();
@ -545,51 +539,4 @@ class TransactionPorterController extends GetxController {
_transactionWatchers.clear(); _transactionWatchers.clear();
super.onClose(); super.onClose();
} }
void showRejectionDialog(String transactionId, BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Tolak Permintaan Porter'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('Masukkan alasan penolakan:'),
const SizedBox(height: 10),
TextField(
controller: rejectionReasonController,
decoration: const InputDecoration(
hintText: 'Contoh: Sedang melayani penumpang lain',
border: OutlineInputBorder(),
),
maxLines: 3,
),
],
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
rejectionReasonController.clear();
},
child: const Text('Batal'),
),
TextButton(
onPressed: () {
final reason = rejectionReasonController.text.trim();
Navigator.of(context).pop();
rejectTransaction(
transactionId: transactionId,
reason: reason,
);
},
child: const Text('Tolak'),
style: TextButton.styleFrom(foregroundColor: Colors.red),
),
],
);
},
);
}
} }

View File

@ -7,10 +7,13 @@ 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/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';
import 'package:e_porter/_core/utils/snackbar/snackbar_helper.dart';
import 'package:e_porter/domain/models/transaction_model.dart'; import 'package:e_porter/domain/models/transaction_model.dart';
import 'package:e_porter/domain/models/transaction_porter_model.dart'; import 'package:e_porter/domain/models/transaction_porter_model.dart';
import 'package:e_porter/presentation/controllers/history_controller.dart'; import 'package:e_porter/presentation/controllers/history_controller.dart';
import 'package:e_porter/presentation/controllers/navigation_controller.dart';
import 'package:e_porter/presentation/controllers/transaction_porter_controller.dart'; import 'package:e_porter/presentation/controllers/transaction_porter_controller.dart';
import 'package:e_porter/presentation/screens/navigation/main_navigation.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:flutter_svg/flutter_svg.dart';
@ -27,6 +30,7 @@ class DetailHistoryPorterScreen extends StatefulWidget {
class _DetailHistoryPorterScreenState extends State<DetailHistoryPorterScreen> { class _DetailHistoryPorterScreenState extends State<DetailHistoryPorterScreen> {
final TransactionPorterController _porterController = Get.find<TransactionPorterController>(); final TransactionPorterController _porterController = Get.find<TransactionPorterController>();
final HistoryController _historyController = Get.find<HistoryController>(); final HistoryController _historyController = Get.find<HistoryController>();
final _reasonController = TextEditingController();
PorterTransactionModel? porterTransaction; PorterTransactionModel? porterTransaction;
@ -42,12 +46,16 @@ class _DetailHistoryPorterScreenState extends State<DetailHistoryPorterScreen> {
final args = Get.arguments as Map<String, dynamic>; final args = Get.arguments as Map<String, dynamic>;
porterTransactionId = args['transactionPorterId']; porterTransactionId = args['transactionPorterId'];
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) async {
_fetchTransactioPorterById(); await _fetchTransactioPorterById();
_fetchTransactionData(); await _fetchTransactionData();
}); });
}
log('[Detail History Porter] ID Transaction Porter : $porterTransactionId'); @override
void dispose() {
_reasonController.dispose();
super.dispose();
} }
Future<void> _fetchTransactioPorterById() async { Future<void> _fetchTransactioPorterById() async {
@ -91,10 +99,7 @@ class _DetailHistoryPorterScreenState extends State<DetailHistoryPorterScreen> {
if (porterTransaction.ticketId.isNotEmpty && porterTransaction.transactionId.isNotEmpty) { if (porterTransaction.ticketId.isNotEmpty && porterTransaction.transactionId.isNotEmpty) {
await _historyController.getTransactionFromFirestore( await _historyController.getTransactionFromFirestore(
porterTransaction.ticketId, porterTransaction.transactionId); porterTransaction.ticketId, porterTransaction.transactionId);
log('[Detail History Porter] Berhasil mengambil ticket transaction');
} else { } else {
log('[Detail History Porter] ticketId atau transactionId kosong');
_historyController.selectedTransaction.value = null; _historyController.selectedTransaction.value = null;
} }
} }
@ -105,6 +110,50 @@ class _DetailHistoryPorterScreenState extends State<DetailHistoryPorterScreen> {
} }
} }
void _showRejectionDialog() {
showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text('Tolak Permintaan Porter'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Masukkan alasan penolakan:'),
SizedBox(height: 10),
TextField(
controller: _reasonController,
decoration: InputDecoration(
hintText: 'Sedang melayani penumpang lain',
border: OutlineInputBorder(),
),
maxLines: 3,
),
],
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
_reasonController.clear();
},
child: Text('Batal'),
),
TextButton(
onPressed: () {
final reason = _reasonController.text.trim();
Navigator.pop(context);
_porterController.rejectTransaction(
transactionId: porterTransactionId,
reason: reason,
);
},
child: Text('Tolak', style: TextStyle(color: Colors.red)),
),
],
),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -167,7 +216,31 @@ class _DetailHistoryPorterScreenState extends State<DetailHistoryPorterScreen> {
textColor: Colors.white, textColor: Colors.white,
backgroundColor: PrimaryColors.primary700, backgroundColor: PrimaryColors.primary700,
onTap: () { onTap: () {
_porterController.forceReassignTransaction(porterTransactionId); Get.dialog(
const Center(child: CircularProgressIndicator()),
barrierDismissible: false,
);
Get.delete<NavigationController>();
Get.put(NavigationController());
Get.offAll(
() => MainNavigation(initialTabIndex: 1),
arguments: 'porter',
);
_porterController.forceReassignTransaction(porterTransactionId).then((_) {
if (Get.isDialogOpen ?? false) Get.back();
SnackbarHelper.showSuccess(
'Berhasil',
'Transaksi berhasil dialihkan ke porter lain',
);
}).catchError((e) {
if (Get.isDialogOpen ?? false) Get.back();
SnackbarHelper.showError(
'Gagal',
'Transaksi gagal dialihkan: $e',
);
});
}, },
), ),
); );
@ -184,7 +257,7 @@ class _DetailHistoryPorterScreenState extends State<DetailHistoryPorterScreen> {
textColor: Colors.white, textColor: Colors.white,
backgroundColor: RedColors.red500, backgroundColor: RedColors.red500,
onTap: () { onTap: () {
_porterController.showRejectionDialog(porterTransactionId, context); _showRejectionDialog();
}, },
), ),
), ),

View File

@ -175,7 +175,11 @@ class AppRoutes {
GetPage( GetPage(
name: Routes.DETAILHISTORYPORTER, name: Routes.DETAILHISTORYPORTER,
page: () => DetailHistoryPorterScreen(), page: () => DetailHistoryPorterScreen(),
binding: TransactionPorterBinding() bindings: [
TransactionPorterBinding(),
TransactionBinding(),
HistoryBinding(),
],
), ),
GetPage( GetPage(
name: Routes.ADDPASSENGER, name: Routes.ADDPASSENGER,