Feat: completed features porter queue and history transaction porter

This commit is contained in:
orangdeso 2025-04-29 11:18:07 +07:00
parent 0b381d2571
commit 08331d69ca
8 changed files with 669 additions and 29 deletions

View File

@ -638,7 +638,7 @@
"languageVersion": "3.4"
}
],
"generated": "2025-04-23T15:39:37.293764Z",
"generated": "2025-04-27T19:47:24.712851Z",
"generator": "pub",
"generatorVersion": "3.5.0",
"flutterRoot": "file:///D:/Flutter/flutter_sdk/flutter_3.24.0",

View File

@ -1,4 +1,5 @@
buildscript {
ext.kotlin_version = '2.1.0'
repositories {
google()
mavenCentral()
@ -6,7 +7,7 @@ buildscript {
}
dependencies {
classpath "com.android.tools.build:gradle:8.2.0"
classpath "com.android.tools.build:gradle:8.4.0"
classpath 'com.google.gms:google-services:4.4.2' // firebase
}
}

View File

@ -1,7 +1,9 @@
import 'dart:async';
import 'dart:developer';
import 'dart:math' hide log;
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:e_porter/domain/repositories/porter_queue_repository.dart';
import 'package:firebase_database/firebase_database.dart';
import '../../domain/models/porter_queue_model.dart';
@ -12,27 +14,41 @@ class PorterQueueRepositoryImpl implements PorterQueueRepository {
FirebaseFirestore? firestore,
}) : _firestore = firestore ?? FirebaseFirestore.instance;
String _generateId() {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
final rand = Random();
return List.generate(7, (index) => chars[rand.nextInt(chars.length)]).join();
}
@override
Future<String> createPorterQueue(String userId) async {
Future<String> createPorterQueue(String userId, String locationPorter) async {
try {
log('[PorterRepository] Membuat antrian porter untuk userId: $userId');
// Periksa apakah porter dengan userId ini sudah ada
final existingPorter = await getPorterByUserId(userId);
if (existingPorter != null) {
log('[PorterRepository] Porter dengan userId: $userId sudah ada di antrian');
if (!existingPorter.isAvailable) {
await _firestore.collection('porterOnline').doc(existingPorter.id).update({
'isAvailable': true,
'idUser': null,
'idTransaction': null,
'onlineAt': FieldValue.serverTimestamp(),
});
log('[PorterRepository] Status porter diperbarui menjadi available');
}
return existingPorter.id!;
}
// Buat data porter baru
final now = DateTime.now();
final porterData = PorterQueueModel(
userId: userId,
isTaken: true,
onlineAt: now,
isAvailable: true,
onlineAt: DateTime.now(),
locationPorter: locationPorter,
).toJson();
// Simpan ke Firestore
final docRef = await _firestore.collection('porterOnline').add(porterData);
log('[PorterRepository] Berhasil membuat antrian porter dengan ID: ${docRef.id}');
@ -63,6 +79,16 @@ class PorterQueueRepositoryImpl implements PorterQueueRepository {
try {
log('[PorterRepository] Menghapus antrian porter dengan ID: $porterId');
// Periksa apakah porter sedang memiliki transaksi aktif
final porterDoc = await _firestore.collection('porterOnline').doc(porterId).get();
if (porterDoc.exists) {
final data = porterDoc.data();
if (data != null && data['idTransaction'] != null) {
log('[PorterRepository] Porter memiliki transaksi aktif, tidak dapat dihapus');
throw Exception('Porter sedang menangani transaksi, selesaikan transaksi terlebih dahulu');
}
}
await _firestore.collection('porterOnline').doc(porterId).delete();
log('[PorterRepository] Berhasil menghapus antrian porter dengan ID: $porterId');
@ -71,4 +97,363 @@ class PorterQueueRepositoryImpl implements PorterQueueRepository {
throw Exception('Gagal menghapus antrian porter: $e');
}
}
@override
Future<PorterQueueModel?> getNextAvailablePorter() async {
try {
log('[PorterRepository] Mencari porter yang tersedia...');
final snapshot = await _firestore
.collection('porterOnline')
.where('isAvailable', isEqualTo: true)
.orderBy('onlineAt', descending: false)
.limit(1)
.get()
.timeout(Duration(seconds: 10), onTimeout: () {
throw TimeoutException('Waktu pencarian porter habis');
});
log('[PorterRepository] Query result: ${snapshot.docs.length} porters available');
if (snapshot.docs.isNotEmpty) {
final porter = PorterQueueModel.fromJson(snapshot.docs.first.data(), docId: snapshot.docs.first.id);
log('[PorterRepository] Porter tersedia: ${porter.id}');
return porter;
}
log('[PorterRepository] Tidak ada porter yang tersedia');
return null;
} catch (e) {
log('[PorterRepository] Error mendapatkan porter tersedia: $e');
return null;
}
}
@override
Future<bool> assignPorterToUser(String porterId, String userId, String transactionId) async {
try {
return await _firestore.runTransaction((transaction) async {
final porterDoc = await transaction.get(_firestore.collection('porterOnline').doc(porterId));
if (!porterDoc.exists) {
log('[PorterRepository] Porter tidak ditemukan');
return false;
}
final porterData = porterDoc.data();
if (porterData == null || porterData['isAvailable'] != true) {
log('[PorterRepository] Porter tidak tersedia');
return false;
}
transaction.update(_firestore.collection('porterOnline').doc(porterId), {
'isAvailable': false,
'idUser': userId,
'idTransaction': transactionId,
});
log('[PorterRepository] Porter berhasil ditugaskan ke user: $userId');
return true;
});
} catch (e) {
log('[PorterRepository] Error menugaskan porter: $e');
return false;
}
}
@override
Future<void> createPorterTransaction(
{required String porterTransactionId,
required String porterId,
required String passengerId,
required String ticketId,
required String transactionId,
required String locationPassenger,
required String locationPorter}) async {
try {
log('[PorterRepository] Membuat transaksi porter: $porterTransactionId');
final now = DateTime.now().millisecondsSinceEpoch;
final kodePorter = _generateId();
// Dapatkan userId porter dari dokumen porterOnline
final porterDoc = await _firestore.collection('porterOnline').doc(porterId).get();
String porterUserId = '';
if (porterDoc.exists && porterDoc.data() != null) {
porterUserId = porterDoc.data()!['userId'] ?? '';
log('[PorterRepository] Mendapatkan userId porter: $porterUserId');
}
if (porterUserId.isEmpty) {
log('[PorterRepository] PERINGATAN: userId porter tidak ditemukan, menggunakan porterId: $porterId');
porterUserId = porterId; // Fallback ke porterId jika userId tidak ditemukan
}
final data = {
'kodePorter': kodePorter,
'porterOnlineId': porterId,
'porterUserId': porterUserId, // Tambahkan porterUserId dalam data transaksi
'idPassenger': passengerId,
'ticketId': ticketId,
'transactionId': transactionId,
'status': 'pending',
'locationPassenger': locationPassenger,
'locationPorter': locationPorter,
'createdAt': now,
};
// 1. Update Firestore
final batch = _firestore.batch();
final porterDocId = _firestore.collection('porterOnline').doc(porterId);
final txDoc = _firestore.collection('porterTransactions').doc(porterTransactionId);
batch.update(porterDocId, {
'isAvailable': false,
'idUser': passengerId,
'idTransaction': porterTransactionId,
'locationPorter': locationPorter,
});
batch.set(txDoc, data);
await batch.commit();
log('[PorterRepository] Dokumen Firestore berhasil diperbarui');
// 2. Simpan transaksi di Realtime Database
final rtdb = FirebaseDatabase.instance.ref();
// 2.1 Data transaksi utama
await rtdb.child('porterTransactions/$porterTransactionId').set(data);
log('[PorterRepository] Data transaksi utama disimpan di RTDB');
// 2.2 Simpan referensi di porterHistory berdasarkan porterId (untuk kompatibilitas mundur)
await rtdb.child('porterHistory/$porterId/$porterTransactionId').set({
'timestamp': now,
'transactionId': porterTransactionId,
});
log('[PorterRepository] Referensi disimpan di porterHistory/$porterId');
// 2.3 Simpan referensi di porterHistory berdasarkan userId porter (baru)
if (porterUserId != porterId && porterUserId.isNotEmpty) {
await rtdb.child('porterHistory/$porterUserId/$porterTransactionId').set({
'timestamp': now,
'transactionId': porterTransactionId,
});
log('[PorterRepository] Referensi disimpan di porterHistory/$porterUserId');
}
// 2.4 Simpan referensi di passengerHistory
await rtdb.child('passengerHistory/$passengerId/$porterTransactionId').set({
'timestamp': now,
'transactionId': porterTransactionId,
});
log('[PorterRepository] Referensi disimpan di passengerHistory/$passengerId');
log('[PorterRepository] Transaksi porter berhasil dibuat');
} catch (e) {
log('[PorterRepository] Error membuat transaksi porter: $e');
throw Exception('Gagal membuat transaksi porter: $e');
}
}
// @override
// Future<List<String>> getPorterTransactionIds(String porterId) async {
// try {
// final rtdb = FirebaseDatabase.instance.ref();
// final snapshot = await rtdb.child('porterHistory/$porterId').get();
// if (snapshot.exists && snapshot.value != null) {
// final Map<dynamic, dynamic> data = snapshot.value as Map<dynamic, dynamic>;
// return data.keys.map((key) => key.toString()).toList();
// }
// return [];
// } catch (e) {
// log('[PorterRepository] Error getting porter transaction IDs: $e');
// return [];
// }
// }
// @override
// Future<Map<String, dynamic>?> getPorterTransactionById(String transactionId) async {
// try {
// final rtdb = FirebaseDatabase.instance.ref();
// final snapshot = await rtdb.child('porterTransactions/$transactionId').get();
// if (snapshot.exists && snapshot.value != null) {
// return Map<String, dynamic>.from(snapshot.value as Map);
// }
// return null;
// } catch (e) {
// log('[PorterRepository] Error getting porter transaction: $e');
// return null;
// }
// }
@override
Future<void> completePorterAssignment(String porterId) async {
try {
// Dapatkan dokumen porter
final porterDoc = await _firestore.collection('porterOnline').doc(porterId).get();
if (porterDoc.exists) {
final porterData = porterDoc.data();
final transactionId = porterData?['idTransaction'];
if (transactionId != null) {
// Update status transaksi di Firestore
await _firestore.collection('porterTransactions').doc(transactionId).update({
'status': 'selesai',
'updatedAt': FieldValue.serverTimestamp(),
});
// Update status transaksi di Realtime DB
final rtdb = FirebaseDatabase.instance.ref();
await rtdb.child('porterTransactions/$transactionId').update({
'status': 'selesai',
'updatedAt': DateTime.now().millisecondsSinceEpoch,
});
}
// Reset status porter
await _firestore.collection('porterOnline').doc(porterId).update({
'isAvailable': true,
'idUser': null,
'idTransaction': null,
});
log('[PorterRepository] Tugas porter selesai, status diperbarui');
}
} catch (e) {
log('[PorterRepository] Error menyelesaikan tugas porter: $e');
throw Exception('Gagal menyelesaikan tugas porter: $e');
}
}
// @override
// Future<void> createPorterTransaction(
// {required String porterTransactionId,
// required String porterId,
// required String passengerId,
// required String ticketId,
// required String transactionId,
// required String locationPassenger,
// required String locationPorter}) async {
// final now = FieldValue.serverTimestamp();
// final kodePorter = _generateId();
// final data = {
// 'kodePorter': kodePorter,
// 'porterOnlineId': porterId,
// 'idPassenger': passengerId,
// 'ticketId': ticketId,
// 'transactionId': transactionId,
// 'status': 'pending',
// 'locationPassenger': locationPassenger,
// 'locationPorter': locationPorter,
// 'createdAt': now,
// };
// final batch = _firestore.batch();
// final porterDoc = _firestore.collection('porterOnline').doc(porterId);
// final txDoc = _firestore.collection('porterTransactions').doc(porterTransactionId);
// batch.update(porterDoc, {
// 'isAvailable': false,
// 'idUser': passengerId,
// 'idTransaction': porterTransactionId,
// 'locationPorter': locationPorter,
// });
// batch.set(txDoc, data);
// await batch.commit();
// // tulis juga ke Realtime Database agar porter bisa listen secara real-time
// final rtdb = FirebaseDatabase.instance.ref();
// await rtdb.child('porterTransactions/$porterId/$porterTransactionId').set({
// ...data,
// 'createdAt': DateTime.now().millisecondsSinceEpoch,
// });
// }
// @override
// Future<void> completePorterAssignment(String porterId) async {
// try {
// await _firestore.collection('porterOnline').doc(porterId).update({
// 'isAvailable': true,
// 'idUser': null,
// 'idTransaction': null,
// });
// log('[PorterRepository] Tugas porter selesai, status diperbarui');
// } catch (e) {
// log('[PorterRepository] Error menyelesaikan tugas porter: $e');
// throw Exception('Gagal menyelesaikan tugas porter: $e');
// }
// }
@override
Future<PorterQueueModel?> getPorterById(String porterId) async {
try {
log('[PorterRepository] Mendapatkan porter by ID: $porterId');
final snapshot = await _firestore.collection('porterOnline').doc(porterId).get();
if (snapshot.exists && snapshot.data() != null) {
return PorterQueueModel.fromJson(snapshot.data()!, docId: snapshot.id);
}
log('[PorterRepository] Porter tidak ditemukan dengan ID: $porterId');
return null;
} catch (e) {
log('[PorterRepository] Error mendapatkan porter by ID: $e');
return null;
}
}
@override
Future<bool> checkConditionForPorter(String porterId) async {
try {
// Memeriksa apakah porter ada dan tidak memiliki transaksi aktif
final porterDoc = await _firestore.collection('porterOnline').doc(porterId).get();
if (!porterDoc.exists) {
return false;
}
final data = porterDoc.data();
if (data != null && data['idTransaction'] != null) {
return false;
}
return true;
} catch (e) {
throw Exception('Gagal memeriksa kondisi porter: $e');
}
}
@override
Stream<PorterQueueModel?> watchPorterByUserId(String userId) {
try {
log('[PorterRepository] Memulai stream porter dengan userId: $userId');
return _firestore
.collection('porterOnline')
.where('userId', isEqualTo: userId)
.limit(1)
.snapshots()
.map((snapshot) {
if (snapshot.docs.isEmpty) {
log('[PorterRepository] Tidak ada porter dengan userId: $userId');
return null;
}
final doc = snapshot.docs.first;
log('[PorterRepository] Porter ditemukan dengan ID: ${doc.id}');
return PorterQueueModel.fromJson(doc.data(), docId: doc.id);
});
} catch (e) {
log('[PorterRepository] Error watching porter by userId: $e');
throw Exception('Gagal memantau data porter: $e');
}
}
}

View File

@ -3,32 +3,44 @@ import 'package:cloud_firestore/cloud_firestore.dart';
class PorterQueueModel {
final String? id;
final String userId;
final bool isTaken;
final bool isAvailable;
final DateTime onlineAt;
final String? idUser;
final String? idTransaction;
final String? locationPorter;
PorterQueueModel({
this.id,
required this.userId,
required this.isTaken,
required this.isAvailable,
required this.onlineAt,
this.idUser,
this.idTransaction,
this.locationPorter,
});
factory PorterQueueModel.fromJson(Map<String, dynamic> json, {String? docId}) {
return PorterQueueModel(
id: docId ?? json['id'],
userId: json['userId'] ?? '',
isTaken: json['isTaken'] ?? false,
onlineAt: (json['onlineAt'] is Timestamp)
? (json['onlineAt'] as Timestamp).toDate()
isAvailable: json['isAvailable'] ?? true,
onlineAt: (json['onlineAt'] is Timestamp)
? (json['onlineAt'] as Timestamp).toDate()
: DateTime.fromMillisecondsSinceEpoch(json['onlineAt'] ?? 0),
idUser: json['idUser'],
idTransaction: json['idTransaction'],
locationPorter: json['locationPorter'],
);
}
Map<String, dynamic> toJson() {
return {
'userId': userId,
'isTaken': isTaken,
'isAvailable': isAvailable,
'onlineAt': onlineAt,
'idUser': idUser,
'idTransaction': idTransaction,
'locationPorter': locationPorter,
};
}
}
}

View File

@ -1,7 +1,27 @@
import '../models/porter_queue_model.dart';
abstract class PorterQueueRepository {
Future<String> createPorterQueue(String userId);
Future<String> createPorterQueue(String userId, String locationPorter);
Future<PorterQueueModel?> getPorterByUserId(String userId);
Future<void> deletePorterQueue(String porterId);
}
// Sisi Porter
Future<PorterQueueModel?> getNextAvailablePorter();
Future<bool> assignPorterToUser(String porterId, String userId, String transactionId);
Future<void> createPorterTransaction(
{required String porterTransactionId,
required String porterId,
required String passengerId,
required String transactionId,
required String ticketId,
required String locationPassenger,
required String locationPorter});
// Future<List<String>> getPorterTransactionIds(String porterId);
// Future<Map<String, dynamic>?> getPorterTransactionById(String transactionId);
Future<void> completePorterAssignment(String porterId);
Future<PorterQueueModel?> getPorterById(String porterId);
Future<bool> checkConditionForPorter(String porterId);
Stream<PorterQueueModel?> watchPorterByUserId(String userId);
}

View File

@ -6,8 +6,8 @@ class PorterQueueUsecase {
PorterQueueUsecase(this._repository);
Future<String> createPorterQueue(String userId) {
return _repository.createPorterQueue(userId);
Future<String> createPorterQueue(String userId, String locationPorter) {
return _repository.createPorterQueue(userId, locationPorter);
}
Future<PorterQueueModel?> getPorterByUserId(String userId) {
@ -17,4 +17,61 @@ class PorterQueueUsecase {
Future<void> deletePorterQueue(String porterId) {
return _repository.deletePorterQueue(porterId);
}
// Sisi Porter
Future<PorterQueueModel?> getNextAvailablePorter() {
return _repository.getNextAvailablePorter();
}
Future<bool> assignPorterToUser(String porterId, String userId, String transactionId) {
return _repository.assignPorterToUser(porterId, userId, transactionId);
}
Future<Map<String, String>> requestPorter({
required String passengerId,
required String ticketId,
required String transactionId,
required String locationPassenger,
}) async {
final porter = await _repository.getNextAvailablePorter();
if (porter == null) throw Exception('Porter tidak tersedia');
final porterId = porter.id!;
final txId = DateTime.now().millisecondsSinceEpoch.toString();
final locPorter = porter.locationPorter!;
final ok = await _repository.assignPorterToUser(porterId, passengerId, txId);
if (!ok) throw Exception('Gagal menugaskan porter');
await _repository.createPorterTransaction(
porterTransactionId: txId,
porterId: porterId,
passengerId: passengerId,
transactionId: transactionId,
ticketId: ticketId,
locationPassenger: locationPassenger,
locationPorter: locPorter,
);
return {
'porterId': porterId,
'transactionId': txId,
};
}
Future<void> completePorterAssignment(String porterId) {
return _repository.completePorterAssignment(porterId);
}
Future<PorterQueueModel?> getPorterById(String porterId) {
return _repository.getPorterById(porterId);
}
Future<bool> checkConditionForPorter(String porterId) {
return _repository.checkConditionForPorter(porterId);
}
Stream<PorterQueueModel?> watchPorterByUserId(String userId) {
return _repository.watchPorterByUserId(userId);
}
}

View File

@ -1,3 +1,6 @@
import 'dart:developer';
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/usecases/porter_queue_usecase.dart';
import 'package:get/get.dart';
@ -11,12 +14,12 @@ class PorterQueueController {
final RxString error = ''.obs;
final Rx<PorterQueueModel?> currentPorter = Rx<PorterQueueModel?>(null);
Future<String> createPorterQueue(String userId) async {
Future<String> createPorterQueue(String userId, String locationPorter) async {
try {
isLoading.value = true;
error.value = '';
final porterId = await _porterQueueUsecase.createPorterQueue(userId);
final porterId = await _porterQueueUsecase.createPorterQueue(userId, locationPorter);
final porter = await _porterQueueUsecase.getPorterByUserId(userId);
currentPorter.value = porter;
@ -32,7 +35,16 @@ class PorterQueueController {
bool validatePorterQueueForDeletion() {
final porter = currentPorter.value;
return porter != null && porter.id != null;
if (porter == null || porter.id == null) {
return false;
}
if (porter.idTransaction != null) {
error.value = 'Porter sedang menangani transaksi, selesaikan transaksi terlebih dahulu';
return false;
}
return true;
}
Future<bool> deletePorterQueue(String porterId) async {
@ -40,13 +52,23 @@ class PorterQueueController {
isLoading.value = true;
error.value = '';
// Gunakan metode cek kondisi yang telah diperbaiki
final canProceed = await checkConditionForPorter(porterId);
if (!canProceed) {
return false;
}
await _porterQueueUsecase.deletePorterQueue(porterId);
currentPorter.value = null;
currentPorter.value = null;
return true;
} catch (e) {
error.value = 'Gagal menghapus antrian porter: $e';
return false;
SnackbarHelper.showError(
'Gagal',
'Gagal menghapus antrian porter.',
);
return false;
} finally {
isLoading.value = false;
}
@ -73,4 +95,140 @@ class PorterQueueController {
isLoading.value = false;
}
}
// Belum
Future<PorterQueueModel?> getNextAvailablePorter() async {
try {
isLoading.value = true;
error.value = '';
return await _porterQueueUsecase.getNextAvailablePorter();
} catch (e) {
error.value = 'Gagal mendapatkan porter tersedia: $e';
return null;
} finally {
isLoading.value = false;
}
}
Future<bool> assignPorterToUser(String porterId, String userId, String transactionId) async {
try {
isLoading.value = true;
error.value = '';
return await _porterQueueUsecase.assignPorterToUser(porterId, userId, transactionId);
} catch (e) {
error.value = 'Gagal menugaskan porter: $e';
return false;
} finally {
isLoading.value = false;
}
}
Future<Map<String, String>> requestPorter({
required String passengerId,
required String ticketId,
required String transactionId,
required String location,
}) async {
try {
isLoading.value = true;
error.value = '';
// Panggil usecase dan dapatkan result berupa map
final result = await _porterQueueUsecase.requestPorter(
passengerId: passengerId,
ticketId: ticketId,
transactionId: transactionId,
locationPassenger: location,
);
return result;
} catch (e) {
// Simpan pesan error dan lempar ulang
error.value = e.toString();
rethrow;
} finally {
isLoading.value = false;
}
}
Future<void> completePorterAssignment(String porterId) async {
try {
isLoading.value = true;
error.value = '';
await _porterQueueUsecase.completePorterAssignment(porterId);
if (currentPorter.value?.id == porterId) {
final userId = currentPorter.value?.userId;
if (userId != null) {
await loadCurrentPorter(userId);
}
}
} catch (e) {
error.value = 'Gagal menyelesaikan tugas porter: $e';
} finally {
isLoading.value = false;
}
}
Future<bool> checkConditionForPorter(String porterId) async {
try {
isLoading.value = true;
error.value = '';
// 1. Dapatkan data terbaru porter langsung dari repository
final freshPorterData = await _porterQueueUsecase.getPorterById(porterId);
if (freshPorterData == null) {
error.value = 'Data porter tidak ditemukan.';
SnackbarHelper.showError('Gagal', error.value);
return false;
}
// 2. Gunakan data terbaru untuk validasi
if (freshPorterData.idTransaction != null) {
error.value = 'Porter sedang menangani transaksi, selesaikan transaksi terlebih dahulu.';
SnackbarHelper.showError('Gagal', error.value);
return false;
}
if (freshPorterData.idUser != null) {
error.value = 'Porter masih melayani penumpang, selesaikan tugas terlebih dahulu.';
SnackbarHelper.showError('Gagal', error.value);
return false;
}
if (freshPorterData.isAvailable != true) {
error.value = 'Porter belum tersedia untuk keluar antrian.';
SnackbarHelper.showError('Gagal', error.value);
return false;
}
return true;
} catch (e) {
error.value = 'Gagal memeriksa kondisi porter: $e';
SnackbarHelper.showError('Gagal', 'Gagal memeriksa kondisi porter.');
return false;
} finally {
isLoading.value = false;
}
}
Stream<PorterQueueModel?> watchPorter(String userId) {
if (userId.isEmpty) {
log('[PorterQueueController] Error: userId kosong');
return Stream.value(null);
}
log('[PorterQueueController] Memulai pemantauan porter dengan userId: $userId');
return _porterQueueUsecase.watchPorterByUserId(userId);
}
void setError(String message) {
error.value = message;
log('[PorterQueueController] Error: $message');
}
}

View File

@ -120,6 +120,7 @@ class _HomeScreenState extends State<HomeScreen> {
return;
}
// Periksa apakah ada porterOnline yang aktif
if (_porterQueueController.currentPorter.value == null) {
SnackbarHelper.showError(
'Gagal',
@ -127,9 +128,15 @@ class _HomeScreenState extends State<HomeScreen> {
);
return;
}
final porterId = _porterQueueController.currentPorter.value!.id!;
final canProceed = await _porterQueueController.checkConditionForPorter(porterId);
// Dapatkan ID porter saat ini
final porterId = _porterQueueController.currentPorter.value!.id!;
// Muat ulang data porter sebelum melakukan pengecekan (optional)
await _porterQueueController.loadCurrentPorter(validUserId);
// Gunakan metode cek kondisi yang diperbaiki
final canProceed = await _porterQueueController.checkConditionForPorter(porterId);
if (!canProceed) {
return;
}
@ -158,7 +165,7 @@ class _HomeScreenState extends State<HomeScreen> {
}
SnackbarHelper.showError(
'Gagal',
'Gagal menghentikan antrian porter.',
'Gagal menghentikan antrian porter: ${e.toString()}',
);
}
}