Feat: add logic create in queue potter
This commit is contained in:
parent
f395d6c4d2
commit
d34b170aab
|
@ -0,0 +1,74 @@
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:e_porter/domain/repositories/porter_queue_repository.dart';
|
||||||
|
|
||||||
|
import '../../domain/models/porter_queue_model.dart';
|
||||||
|
|
||||||
|
class PorterQueueRepositoryImpl implements PorterQueueRepository {
|
||||||
|
final FirebaseFirestore _firestore;
|
||||||
|
|
||||||
|
PorterQueueRepositoryImpl({
|
||||||
|
FirebaseFirestore? firestore,
|
||||||
|
}) : _firestore = firestore ?? FirebaseFirestore.instance;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> createPorterQueue(String userId) 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');
|
||||||
|
return existingPorter.id!;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buat data porter baru
|
||||||
|
final now = DateTime.now();
|
||||||
|
final porterData = PorterQueueModel(
|
||||||
|
userId: userId,
|
||||||
|
isTaken: true,
|
||||||
|
onlineAt: now,
|
||||||
|
).toJson();
|
||||||
|
|
||||||
|
// Simpan ke Firestore
|
||||||
|
final docRef = await _firestore.collection('porterOnline').add(porterData);
|
||||||
|
|
||||||
|
log('[PorterRepository] Berhasil membuat antrian porter dengan ID: ${docRef.id}');
|
||||||
|
return docRef.id;
|
||||||
|
} catch (e) {
|
||||||
|
log('[PorterRepository] Error membuat antrian porter: $e');
|
||||||
|
throw Exception('Gagal membuat antrian porter: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<PorterQueueModel?> getPorterByUserId(String userId) async {
|
||||||
|
try {
|
||||||
|
final snapshot = await _firestore.collection('porterOnline').where('userId', isEqualTo: userId).limit(1).get();
|
||||||
|
|
||||||
|
if (snapshot.docs.isNotEmpty) {
|
||||||
|
return PorterQueueModel.fromJson(snapshot.docs.first.data(), docId: snapshot.docs.first.id);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (e) {
|
||||||
|
log('[PorterRepository] Error mendapatkan porter by userId: $e');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> deletePorterQueue(String porterId) async {
|
||||||
|
try {
|
||||||
|
log('[PorterRepository] Menghapus antrian porter dengan ID: $porterId');
|
||||||
|
|
||||||
|
await _firestore.collection('porterOnline').doc(porterId).delete();
|
||||||
|
|
||||||
|
log('[PorterRepository] Berhasil menghapus antrian porter dengan ID: $porterId');
|
||||||
|
} catch (e) {
|
||||||
|
log('[PorterRepository] Error menghapus antrian porter: $e');
|
||||||
|
throw Exception('Gagal menghapus antrian porter: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
import 'package:e_porter/domain/usecases/porter_queue_usecase.dart';
|
||||||
|
import 'package:e_porter/presentation/controllers/porter_queue_controller.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
import '../../data/repositories/porter_queue_repository_impl.dart';
|
||||||
|
import '../repositories/porter_queue_repository.dart';
|
||||||
|
|
||||||
|
class PorterQueueBinding extends Bindings {
|
||||||
|
@override
|
||||||
|
void dependencies() {
|
||||||
|
// Repository
|
||||||
|
Get.lazyPut<PorterQueueRepository>(
|
||||||
|
() => PorterQueueRepositoryImpl(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// UseCase
|
||||||
|
Get.lazyPut<PorterQueueUsecase>(
|
||||||
|
() => PorterQueueUsecase(Get.find<PorterQueueRepository>()),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Controller
|
||||||
|
Get.lazyPut<PorterQueueController>(
|
||||||
|
() => PorterQueueController(Get.find<PorterQueueUsecase>()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
|
||||||
|
class PorterQueueModel {
|
||||||
|
final String? id;
|
||||||
|
final String userId;
|
||||||
|
final bool isTaken;
|
||||||
|
final DateTime onlineAt;
|
||||||
|
|
||||||
|
PorterQueueModel({
|
||||||
|
this.id,
|
||||||
|
required this.userId,
|
||||||
|
required this.isTaken,
|
||||||
|
required this.onlineAt,
|
||||||
|
});
|
||||||
|
|
||||||
|
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()
|
||||||
|
: DateTime.fromMillisecondsSinceEpoch(json['onlineAt'] ?? 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'userId': userId,
|
||||||
|
'isTaken': isTaken,
|
||||||
|
'onlineAt': onlineAt,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import '../models/porter_queue_model.dart';
|
||||||
|
|
||||||
|
abstract class PorterQueueRepository {
|
||||||
|
Future<String> createPorterQueue(String userId);
|
||||||
|
Future<PorterQueueModel?> getPorterByUserId(String userId);
|
||||||
|
Future<void> deletePorterQueue(String porterId);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import '../models/porter_queue_model.dart';
|
||||||
|
import '../repositories/porter_queue_repository.dart';
|
||||||
|
|
||||||
|
class PorterQueueUsecase {
|
||||||
|
final PorterQueueRepository _repository;
|
||||||
|
|
||||||
|
PorterQueueUsecase(this._repository);
|
||||||
|
|
||||||
|
Future<String> createPorterQueue(String userId) {
|
||||||
|
return _repository.createPorterQueue(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<PorterQueueModel?> getPorterByUserId(String userId) {
|
||||||
|
return _repository.getPorterByUserId(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> deletePorterQueue(String porterId) {
|
||||||
|
return _repository.deletePorterQueue(porterId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
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';
|
||||||
|
|
||||||
|
class PorterQueueController {
|
||||||
|
final PorterQueueUsecase _porterQueueUsecase;
|
||||||
|
|
||||||
|
PorterQueueController(this._porterQueueUsecase);
|
||||||
|
|
||||||
|
final RxBool isLoading = false.obs;
|
||||||
|
final RxString error = ''.obs;
|
||||||
|
final Rx<PorterQueueModel?> currentPorter = Rx<PorterQueueModel?>(null);
|
||||||
|
|
||||||
|
Future<String> createPorterQueue(String userId) async {
|
||||||
|
try {
|
||||||
|
isLoading.value = true;
|
||||||
|
error.value = '';
|
||||||
|
|
||||||
|
final porterId = await _porterQueueUsecase.createPorterQueue(userId);
|
||||||
|
|
||||||
|
final porter = await _porterQueueUsecase.getPorterByUserId(userId);
|
||||||
|
currentPorter.value = porter;
|
||||||
|
|
||||||
|
return porterId;
|
||||||
|
} catch (e) {
|
||||||
|
error.value = 'Gagal membuat antrian porter: $e';
|
||||||
|
throw Exception(error.value);
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validatePorterQueueForDeletion() {
|
||||||
|
final porter = currentPorter.value;
|
||||||
|
return porter != null && porter.id != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> deletePorterQueue(String porterId) async {
|
||||||
|
try {
|
||||||
|
isLoading.value = true;
|
||||||
|
error.value = '';
|
||||||
|
|
||||||
|
await _porterQueueUsecase.deletePorterQueue(porterId);
|
||||||
|
currentPorter.value = null;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
error.value = 'Gagal menghapus antrian porter: $e';
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> validateAndGetUserId(String? userId) async {
|
||||||
|
if (userId == null || userId.isEmpty) {
|
||||||
|
error.value = 'User ID tidak ditemukan. Silakan login kembali.';
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> loadCurrentPorter(String userId) async {
|
||||||
|
try {
|
||||||
|
isLoading.value = true;
|
||||||
|
error.value = '';
|
||||||
|
|
||||||
|
final porter = await _porterQueueUsecase.getPorterByUserId(userId);
|
||||||
|
currentPorter.value = porter;
|
||||||
|
} catch (e) {
|
||||||
|
error.value = 'Gagal memuat data porter: $e';
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import 'package:e_porter/_core/component/icons/icons_library.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/service/preferences_service.dart';
|
import 'package:e_porter/_core/service/preferences_service.dart';
|
||||||
|
import 'package:e_porter/presentation/controllers/porter_queue_controller.dart';
|
||||||
import 'package:e_porter/presentation/screens/home/component/card_service_porter.dart';
|
import 'package:e_porter/presentation/screens/home/component/card_service_porter.dart';
|
||||||
import 'package:e_porter/presentation/screens/home/component/profile_avatar.dart';
|
import 'package:e_porter/presentation/screens/home/component/profile_avatar.dart';
|
||||||
import 'package:e_porter/presentation/screens/home/component/summary_card.dart';
|
import 'package:e_porter/presentation/screens/home/component/summary_card.dart';
|
||||||
|
@ -18,6 +19,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:zoom_tap_animation/zoom_tap_animation.dart';
|
import 'package:zoom_tap_animation/zoom_tap_animation.dart';
|
||||||
|
|
||||||
|
import '../../../../_core/utils/snackbar/snackbar_helper.dart';
|
||||||
import '../../../../domain/models/user_entity.dart';
|
import '../../../../domain/models/user_entity.dart';
|
||||||
|
|
||||||
class HomeScreen extends StatefulWidget {
|
class HomeScreen extends StatefulWidget {
|
||||||
|
@ -31,6 +33,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||||
int _current = 0;
|
int _current = 0;
|
||||||
late final String role;
|
late final String role;
|
||||||
late Future<UserData?> _userDataFuture;
|
late Future<UserData?> _userDataFuture;
|
||||||
|
late PorterQueueController _porterQueueController;
|
||||||
final CarouselSliderController _carouselController = CarouselSliderController();
|
final CarouselSliderController _carouselController = CarouselSliderController();
|
||||||
|
|
||||||
final List<Widget> imageList = [
|
final List<Widget> imageList = [
|
||||||
|
@ -51,6 +54,106 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||||
super.initState();
|
super.initState();
|
||||||
role = Get.arguments ?? 'penumpang';
|
role = Get.arguments ?? 'penumpang';
|
||||||
_userDataFuture = PreferencesService.getUserData();
|
_userDataFuture = PreferencesService.getUserData();
|
||||||
|
|
||||||
|
if (role == 'porter') {
|
||||||
|
_porterQueueController = Get.find<PorterQueueController>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _handlePorterQueueCreation() async {
|
||||||
|
try {
|
||||||
|
final userData = await PreferencesService.getUserData();
|
||||||
|
if (userData?.uid == null) {
|
||||||
|
SnackbarHelper.showError(
|
||||||
|
'Gagal',
|
||||||
|
'User ID tidak ditemukan. Silakan login kembali.',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Get.isSnackbarOpen) {
|
||||||
|
Get.closeAllSnackbars();
|
||||||
|
}
|
||||||
|
|
||||||
|
_showLoadingDialog();
|
||||||
|
|
||||||
|
await _porterQueueController.createPorterQueue(userData!.uid);
|
||||||
|
|
||||||
|
if (Get.isDialogOpen == true) {
|
||||||
|
Get.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
SnackbarHelper.showSuccess(
|
||||||
|
'Berhasil',
|
||||||
|
'Anda telah masuk dalam antrian porter',
|
||||||
|
);
|
||||||
|
|
||||||
|
setState(() {});
|
||||||
|
} catch (e) {
|
||||||
|
if (Get.isDialogOpen == true) {
|
||||||
|
Get.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
SnackbarHelper.showError(
|
||||||
|
'Gagal',
|
||||||
|
'Gagal masuk antrian porter: ${e.toString()}',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _handleStopPorterQueue() async {
|
||||||
|
try {
|
||||||
|
final userData = await PreferencesService.getUserData();
|
||||||
|
final validUserId = await _porterQueueController.validateAndGetUserId(userData?.uid);
|
||||||
|
if (validUserId == null) {
|
||||||
|
SnackbarHelper.showError(
|
||||||
|
'Gagal',
|
||||||
|
_porterQueueController.error.value,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_porterQueueController.validatePorterQueueForDeletion()) {
|
||||||
|
SnackbarHelper.showError(
|
||||||
|
'Gagal',
|
||||||
|
'Tidak ada antrian porter yang aktif.',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final confirm = await _showStopConfirmationDialog();
|
||||||
|
|
||||||
|
if (!confirm) return;
|
||||||
|
_showLoadingDialog();
|
||||||
|
|
||||||
|
final porterId = _porterQueueController.currentPorter.value!.id!;
|
||||||
|
final success = await _porterQueueController.deletePorterQueue(porterId);
|
||||||
|
|
||||||
|
if (Get.isDialogOpen == true) {
|
||||||
|
Get.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
SnackbarHelper.showSuccess(
|
||||||
|
'Berhasil',
|
||||||
|
'Anda telah berhenti dari antrian porter',
|
||||||
|
);
|
||||||
|
setState(() {});
|
||||||
|
} else {
|
||||||
|
SnackbarHelper.showError(
|
||||||
|
'Gagal',
|
||||||
|
'Gagal menghentikan antrian porter: ${_porterQueueController.error.value}',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (Get.isDialogOpen == true) {
|
||||||
|
Get.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
SnackbarHelper.showError(
|
||||||
|
'Gagal',
|
||||||
|
'Gagal menghentikan antrian porter: ${e.toString()}',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -250,10 +353,16 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||||
future: _userDataFuture,
|
future: _userDataFuture,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
String userPorter = "Guest";
|
String userPorter = "Guest";
|
||||||
|
String userId = '';
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return Center(child: CircularProgressIndicator());
|
return Center(child: CircularProgressIndicator());
|
||||||
} else if (snapshot.hasData && snapshot.data?.name != null) {
|
} else if (snapshot.hasData && snapshot.data?.name != null) {
|
||||||
userPorter = snapshot.data!.name!;
|
userPorter = snapshot.data!.name!;
|
||||||
|
|
||||||
|
if (snapshot.data?.uid != null) {
|
||||||
|
userId = snapshot.data!.uid;
|
||||||
|
_porterQueueController.loadCurrentPorter(userId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@ -306,26 +415,48 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||||
),
|
),
|
||||||
SizedBox(height: 32.w),
|
SizedBox(height: 32.w),
|
||||||
CustomeShadowCotainner(
|
CustomeShadowCotainner(
|
||||||
|
child: ZoomTapAnimation(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () => _porterQueueController.currentPorter.value != null
|
||||||
|
? _handleStopPorterQueue()
|
||||||
|
: _handlePorterQueueCreation(),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 6.h),
|
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 6.h),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: PrimaryColors.primary200,
|
color: _porterQueueController.currentPorter.value != null
|
||||||
|
? RedColors.red100
|
||||||
|
: PrimaryColors.primary200,
|
||||||
borderRadius: BorderRadius.circular(10.r),
|
borderRadius: BorderRadius.circular(10.r),
|
||||||
),
|
),
|
||||||
child: SvgPicture.asset(
|
child: Obx(() => _porterQueueController.currentPorter.value != null
|
||||||
|
? Icon(
|
||||||
|
Icons.power_settings_new,
|
||||||
|
color: Colors.red,
|
||||||
|
size: 32.w,
|
||||||
|
)
|
||||||
|
: SvgPicture.asset(
|
||||||
'assets/icons/ic_account.svg',
|
'assets/icons/ic_account.svg',
|
||||||
width: 32.w,
|
width: 32.w,
|
||||||
height: 32.h,
|
height: 32.h,
|
||||||
),
|
)),
|
||||||
),
|
),
|
||||||
SizedBox(height: 10.h),
|
SizedBox(height: 10.h),
|
||||||
TypographyStyles.body(
|
Obx(
|
||||||
|
() => _porterQueueController.currentPorter.value != null
|
||||||
|
? TypographyStyles.body(
|
||||||
|
'Stop',
|
||||||
|
color: GrayColors.gray800,
|
||||||
|
)
|
||||||
|
: TypographyStyles.body(
|
||||||
'Mulai Antrian',
|
'Mulai Antrian',
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -338,6 +469,100 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> _showStopConfirmationDialog() async {
|
||||||
|
return await Get.dialog<bool>(
|
||||||
|
Dialog(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(10.r),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(16.w),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
TypographyStyles.h6(
|
||||||
|
'Konfirmasi',
|
||||||
|
color: GrayColors.gray800,
|
||||||
|
),
|
||||||
|
SizedBox(height: 16.h),
|
||||||
|
Text(
|
||||||
|
'Apakah Anda yakin ingin menghentikan layanan porter?',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14.sp,
|
||||||
|
color: GrayColors.gray600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 24.h),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () => Get.back(result: false),
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
foregroundColor: GrayColors.gray600,
|
||||||
|
),
|
||||||
|
child: Text('Batal'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 8.w),
|
||||||
|
Expanded(
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () => Get.back(result: true),
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: RedColors.red500,
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
),
|
||||||
|
child: Text('Berhenti'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) ??
|
||||||
|
false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showLoadingDialog() {
|
||||||
|
Get.dialog(
|
||||||
|
Dialog(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(10.r),
|
||||||
|
),
|
||||||
|
elevation: 0,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(16.w),
|
||||||
|
width: 80.w,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(10.r),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
CircularProgressIndicator(
|
||||||
|
color: PrimaryColors.primary800,
|
||||||
|
),
|
||||||
|
SizedBox(height: 12.h),
|
||||||
|
Text(
|
||||||
|
'Memproses...',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12.sp,
|
||||||
|
color: GrayColors.gray600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
barrierDismissible: false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAppbar(
|
Widget _buildAppbar(
|
||||||
|
@ -377,3 +602,4 @@ Widget _buildAppbar(
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -174,6 +174,127 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildPorterUI() {
|
Widget _buildPorterUI() {
|
||||||
return Scaffold();
|
return Scaffold(
|
||||||
|
backgroundColor: GrayColors.gray50,
|
||||||
|
appBar: BasicAppbarComponent(title: 'Profil'),
|
||||||
|
body: FutureBuilder<UserData?>(
|
||||||
|
future: _userDataFuture,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
String userName = "Guest";
|
||||||
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
return Center(child: CircularProgressIndicator());
|
||||||
|
} else if (snapshot.hasData && snapshot.data?.name != null) {
|
||||||
|
userName = snapshot.data!.name!;
|
||||||
|
}
|
||||||
|
return SafeArea(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 20.h),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
CustomeShadowCotainner(
|
||||||
|
borderRadius: BorderRadius.circular(0.r),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
ProfileAvatar(fullName: userName),
|
||||||
|
SizedBox(width: 16.w),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
TypographyStyles.caption('Hi,', color: GrayColors.gray600, fontWeight: FontWeight.w400),
|
||||||
|
TypographyStyles.body(userName, color: GrayColors.gray800),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 20.h),
|
||||||
|
CustomeShadowCotainner(
|
||||||
|
borderRadius: BorderRadius.circular(0.r),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
TypographyStyles.h6('Pengaturan', color: GrayColors.gray800),
|
||||||
|
SizedBox(height: 32.h),
|
||||||
|
ProfileMenu(
|
||||||
|
label: 'Lihat Profile',
|
||||||
|
svgIcon: 'assets/icons/ic_profile.svg',
|
||||||
|
onTap: () {},
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 20.h),
|
||||||
|
child: Divider(thickness: 1, color: GrayColors.gray100),
|
||||||
|
),
|
||||||
|
ProfileMenu(
|
||||||
|
label: 'Ganti Kata Sandi',
|
||||||
|
svgIcon: 'assets/icons/ic_lock.svg',
|
||||||
|
onTap: () {},
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 20.h),
|
||||||
|
child: Divider(thickness: 1, color: GrayColors.gray100),
|
||||||
|
),
|
||||||
|
ProfileMenu(
|
||||||
|
label: 'Logout',
|
||||||
|
svgIcon: 'assets/icons/ic_logout.svg',
|
||||||
|
onTap: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
title: TypographyStyles.body('Keluar', color: GrayColors.gray800),
|
||||||
|
content: TypographyStyles.caption(
|
||||||
|
'Apakah anda yakin untuk keluar dari akun ini?',
|
||||||
|
color: GrayColors.gray600,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
maxlines: 3,
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
ZoomTapAnimation(
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: TypographyStyles.caption(
|
||||||
|
'Tidak',
|
||||||
|
color: GrayColors.gray800,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ZoomTapAnimation(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
await PreferencesService.clearUserData();
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
Get.offAllNamed(Routes.SPLASH);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 30.w, vertical: 8.h),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: PrimaryColors.primary800,
|
||||||
|
borderRadius: BorderRadius.circular(8.r),
|
||||||
|
),
|
||||||
|
child: TypographyStyles.caption('Ya', color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:e_porter/domain/bindings/auth_binding.dart';
|
import 'package:e_porter/domain/bindings/auth_binding.dart';
|
||||||
import 'package:e_porter/domain/bindings/history_binding.dart';
|
import 'package:e_porter/domain/bindings/history_binding.dart';
|
||||||
import 'package:e_porter/domain/bindings/navigation_binding.dart';
|
import 'package:e_porter/domain/bindings/navigation_binding.dart';
|
||||||
|
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';
|
||||||
|
@ -42,6 +43,7 @@ class AppRoutes {
|
||||||
bindings: [
|
bindings: [
|
||||||
MainNavigationBinding(),
|
MainNavigationBinding(),
|
||||||
HistoryBinding(),
|
HistoryBinding(),
|
||||||
|
PorterQueueBinding(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
GetPage(
|
GetPage(
|
||||||
|
|
Loading…
Reference in New Issue