QueenFruits/Mobile Operasional/lib/features/profile/presentation/screens/profile_screen.dart

736 lines
30 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:latlong2/latlong.dart';
import 'package:niogu_app/core/constants/app_color.dart';
import 'package:niogu_app/core/constants/app_font_size.dart';
import 'package:niogu_app/core/providers/app_provider.dart';
import 'package:niogu_app/core/router/app_route.dart';
import 'package:niogu_app/core/utils/extension_format.dart';
import 'package:niogu_app/core/enums/member_level.dart';
import 'package:niogu_app/core/system/system_secure.dart';
import 'package:niogu_app/core/system/system_setting.dart';
import 'package:niogu_app/core/utils/time_zone.dart';
import 'package:niogu_app/core/enums/user_role.dart';
import 'package:niogu_app/core/widgets/custom_confirmation.dart';
import 'package:niogu_app/features/outlets/domain/entities/outlet.dart';
import 'package:niogu_app/features/outlets/presentation/providers/outlet_provider.dart';
import 'package:niogu_app/features/profile/domain/entities/profile.dart';
import 'package:niogu_app/features/profile/presentation/providers/profile_provider.dart';
import 'package:niogu_app/features/user/domain/entities/user.dart';
import 'package:niogu_app/features/user/presentation/providers/user_provider.dart';
import 'package:sizer/sizer.dart';
class ProfileScreen extends ConsumerWidget {
const ProfileScreen({super.key});
void _setCurrentOutlet(WidgetRef ref) {
ref.read(currentOutletIdProvider.notifier).state = null;
ref.read(currentOutletNameProvider.notifier).state = null;
}
void _setCurrentUser(WidgetRef ref) {
ref.read(currentUserIdProvider.notifier).state = null;
ref.read(currentUserNameProvider.notifier).state = null;
ref.read(currentUserEmailProvider.notifier).state = null;
ref.read(currentUserRoleProvider.notifier).state = null;
ref.read(outletIdByOwnerProvider.notifier).state = null;
ref.read(currentStatusLoginProvider.notifier).state = false;
}
Future<void> _logout(BuildContext context, WidgetRef ref) async {
showDialog(
context: context,
builder: (context) {
return CustomConfirmation(
title: "Keluar Akun",
body: "Anda yakin ingin keluar?",
color: Color(0xFFFFA000),
icon: Icons.logout_outlined,
onConfirm: () async {
await SystemSecure.deleteAccessToken();
await SystemSetting.clear();
_setCurrentOutlet(ref);
_setCurrentUser(ref);
},
);
},
);
}
@override
Widget build(BuildContext context, WidgetRef ref) {
return LayoutBuilder(
builder: (context, constraints) {
final bool isTablet = 100.w >= 600;
final isLoggedIn = ref.watch(currentStatusLoginProvider);
final currentUserName = ref.watch(currentUserNameProvider);
final currentUserEmail = ref.watch(currentUserEmailProvider);
final currentUserRole = ref.watch(currentUserRoleProvider);
ShiftInfo shiftInfo = ShiftInfo(
shiftName: '---',
shiftStartTime: '---',
shiftEndTime: '---',
);
if (isLoggedIn) {
final shiftInfoState = ref.watch(shiftInfoStreamProvider);
shiftInfoState.whenData((s) => shiftInfo = s);
}
double profileCompleteness = 0.0;
double businessCompleteness = 0.0;
double outletCompleteness = 0.0;
MemberLevel memberLevel = MemberLevel.standart;
if (isLoggedIn) {
final profileCompletenessState = ref.watch(
profileCompletenessStreamProvider,
);
if (currentUserRole == UserRole.owner) {
final businessCompletenessState = ref.watch(
businessCompletenessStreamProvider,
);
businessCompletenessState.whenData((b) => businessCompleteness = b);
} else if (currentUserRole == UserRole.admin) {
final outletCompletenessState = ref.watch(
outletCompletenessStreamProvider,
);
outletCompletenessState.whenData((o) => outletCompleteness = o);
}
profileCompletenessState.whenData((p) => profileCompleteness = p);
}
final double profilePercentCompleteness = profileCompleteness * 100;
final double businessPercentCompleteness = businessCompleteness * 100;
final double outletPercentCompleteness = outletCompleteness * 100;
if (isLoggedIn) {
final memberLevelState = ref.watch(memberLevelStreamProvider);
memberLevelState.whenData((m) => memberLevel = m);
}
return SafeArea(
top: false,
bottom: true,
right: false,
left: false,
child: Scaffold(
backgroundColor: const Color(0xFFF9FAFB),
body: SingleChildScrollView(
child: Column(
children: [
Container(
width: double.infinity,
padding: EdgeInsets.fromLTRB(5.w, 8.h, 5.w, 4.h),
decoration: BoxDecoration(
color: AppColor.primaryColor,
borderRadius: BorderRadius.vertical(
bottom: Radius.circular(8.w),
),
),
child: Row(
children: [
if (isLoggedIn) ...[
CircleAvatar(
radius: 7.w,
backgroundColor: Colors.white24,
child: Icon(
Icons.person,
color: Colors.white,
size: 7.w,
),
),
SizedBox(width: 4.w),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
currentUserName!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: isTablet
? AppFontSize.medium.sp
: AppFontSize.small.sp,
),
),
if (currentUserRole == UserRole.owner &&
currentUserEmail != null &&
currentUserEmail.isNotEmpty) ...[
SizedBox(height: 0.5.h),
Text(
currentUserEmail,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.white,
fontSize: isTablet
? AppFontSize.medium.sp
: AppFontSize.small.sp,
),
),
] else if (currentUserRole == UserRole.admin) ...[
SizedBox(height: 0.5.h),
Text(
"${shiftInfo.shiftName} : ${shiftInfo.shiftStartTime} ${TimeZone.getCurrentTimeZone()} - ${shiftInfo.shiftEndTime} ${TimeZone.getCurrentTimeZone()}",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: isTablet
? AppFontSize.medium.sp
: AppFontSize.small.sp,
),
),
],
SizedBox(height: 0.5.h),
Container(
padding: EdgeInsets.symmetric(
horizontal: 2.w,
vertical: 0.3.h,
),
decoration: BoxDecoration(
color: Colors.white24,
borderRadius: BorderRadius.circular(1.w),
),
child: Text(
currentUserRole == UserRole.owner
? "Owner Toko"
: "Staf Admin",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: isTablet
? AppFontSize.medium.sp
: AppFontSize.small.sp,
),
),
),
],
),
] else ...[
OutlinedButton.icon(
onPressed: () =>
context.goNamed(AppRoute.ownerLoginScreen),
icon: Icon(
Icons.login_rounded,
color: Colors.white,
size: 4.5.w,
),
label: Text(
"Masuk Akun",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: isTablet
? AppFontSize.medium.sp
: AppFontSize.small.sp,
),
),
style: OutlinedButton.styleFrom(
side: const BorderSide(
color: Colors.white70,
width: 1.5,
),
padding: EdgeInsets.symmetric(
horizontal: 4.w,
vertical: 1.h,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(2.w),
),
backgroundColor: Colors.white.withOpacity(0.1),
),
),
],
],
),
),
!isLoggedIn
? Column(
children: [
_buildCompactLogin(context, isTablet),
..._buildGeneralInformation(
context,
isTablet,
isLoggedIn,
),
],
)
: Padding(
padding: EdgeInsets.symmetric(vertical: 3.h),
child: Column(
children: [
SizedBox(
height: 14.h,
child: ListView(
scrollDirection: Axis.horizontal,
padding: EdgeInsets.symmetric(
horizontal: 5.w,
),
children: [
_buildProgressCard(
isTablet,
"Kelengkapan Profil",
profileCompleteness,
profileCompleteness == 1.0
? "Lengkap"
: "${profilePercentCompleteness.toStringAsFixed(0)}% Terisi",
),
SizedBox(width: 4.w),
if (currentUserRole == UserRole.owner)
_buildProgressCard(
isTablet,
"Kelengkapan Usaha",
businessCompleteness,
businessPercentCompleteness == 1.0
? "Lengkap"
: "${businessPercentCompleteness.toStringAsFixed(0)}% Terisi",
)
else if (currentUserRole == UserRole.admin)
_buildProgressCard(
isTablet,
"Kelengkapan Outlet",
outletCompleteness,
outletCompleteness == 1.0
? "Lengkap"
: "${outletPercentCompleteness.toStringAsFixed(0)}% Terisi",
),
],
),
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: 5.w,
vertical: 3.h,
),
child: Column(
children: [
if (currentUserRole == UserRole.owner) ...[
Container(
padding: EdgeInsets.all(4.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(
3.w,
),
border: Border.all(
color: Colors.grey.shade200,
),
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Icon(
Icons.verified_outlined,
color: Colors.blue,
size: 6.w,
),
SizedBox(width: 3.w),
Text(
"Level Kemitraan: ${memberLevel.level.capitalize()}",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: isTablet
? AppFontSize.medium.sp
: AppFontSize.small.sp,
),
),
],
),
],
),
),
SizedBox(height: 3.h),
],
_buildProfileMenu(
isTablet: isTablet,
icon: Icons.person_outline,
title: "Informasi Profil",
onTap: () async {
final profileInfo = await ref
.read(profileRepositoryProvider)
.fetchProfileInfo();
await Future.delayed(
const Duration(milliseconds: 400),
() {
context.pushNamed(
AppRoute.profileInfoScreen,
extra: profileInfo,
);
},
);
},
),
if (currentUserRole == UserRole.owner)
_buildProfileMenu(
isTablet: isTablet,
icon: Icons.storefront_outlined,
title: "Informasi Usaha",
onTap: () async {
final businessInfo = await ref
.read(profileRepositoryProvider)
.fetchBusinessInfo();
await Future.delayed(
const Duration(milliseconds: 400),
() {
context.pushNamed(
AppRoute.businessInfoScreen,
extra: businessInfo,
);
},
);
},
)
else if (currentUserRole == UserRole.admin)
_buildProfileMenu(
isTablet: isTablet,
icon: Icons.store_outlined,
title: "Informasi Outlet",
onTap: () async {
final currentOutletId = ref.read(
currentOutletIdProvider,
);
final outletDetail = await ref
.read(outletRepositoryProvider)
.getOutletById(currentOutletId!);
final outletInfo = OutletInfo(
imagePath: outletDetail.bannerPath,
tenantName: outletDetail.tenantName,
name: outletDetail.name,
phoneNumber:
outletDetail.phoneNumber,
email: outletDetail.email,
fullAddress:
outletDetail.fullAddress,
);
if (outletDetail.fullAddress !=
null &&
outletDetail.latitude != null &&
outletDetail.longitude != null) {
ref
.read(
mapOutletAddressProvider
.notifier,
)
.state = OutletAddressSelected(
fullAddress:
outletDetail.fullAddress!,
currentLocation: LatLng(
outletDetail.latitude!,
outletDetail.longitude!,
),
);
}
await Future.delayed(
const Duration(milliseconds: 400),
() {
context.pushNamed(
AppRoute.outletInfoScreen,
extra: outletInfo,
);
},
);
},
),
_buildProfileMenu(
isTablet: isTablet,
icon: Icons.headset_mic_outlined,
title: "Customer Service",
onTap: () {},
),
_buildProfileMenu(
isTablet: isTablet,
icon: Icons.print_outlined,
title: "Kertas Printer",
onTap: () {},
),
_buildProfileMenu(
isTablet: isTablet,
icon: Icons.lock_outlined,
title: "Ubah Password",
onTap: () {
context.pushNamed(
AppRoute.changePasswordScreen,
);
},
),
_buildProfileMenu(
isTablet: isTablet,
icon: Icons.logout_outlined,
iconColor: Colors.red,
titleColor: Colors.red,
title: "Keluar Akun",
onTap: () async =>
await _logout(context, ref),
),
..._buildGeneralInformation(
context,
isTablet,
isLoggedIn,
),
],
),
),
],
),
),
],
),
),
),
);
},
);
}
Widget _buildCompactLogin(BuildContext context, bool isTablet) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 5.w, vertical: 3.h),
padding: EdgeInsets.all(5.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4.w),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Row(
children: [
Container(
padding: EdgeInsets.all(3.w),
decoration: BoxDecoration(
color: Colors.blue[50],
shape: BoxShape.circle,
),
child: Icon(
Icons.lock_outline_rounded,
color: AppColor.primaryColor,
size: 6.w,
),
),
SizedBox(width: 4.w),
// Teks Ajakan
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Akses Terbatas",
style: TextStyle(
fontSize: (AppFontSize.medium - (isTablet ? 0 : 1.25)).sp,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
SizedBox(height: 0.5.h),
Text(
"Silakan login untuk melihat informasi profil lengkap Anda.",
style: TextStyle(
fontSize: isTablet
? AppFontSize.medium.sp
: AppFontSize.small.sp,
color: Colors.grey[600],
),
),
],
),
),
],
),
);
}
Widget _buildProgressCard(
bool isTablet,
String title,
double progress,
String label,
) {
return Container(
width: 65.w,
padding: EdgeInsets.all(4.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(3.w),
border: Border.all(color: Colors.grey.shade200),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
title,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: isTablet ? AppFontSize.medium.sp : AppFontSize.small.sp,
),
),
SizedBox(height: 1.5.h),
LinearProgressIndicator(
value: progress,
backgroundColor: Colors.grey[200],
color: AppColor.primaryColor,
minHeight: 1.h,
borderRadius: BorderRadius.circular(2.w),
),
SizedBox(height: 1.h),
Text(
label,
style: TextStyle(
color: Colors.grey.shade700,
fontSize: isTablet ? AppFontSize.medium.sp : AppFontSize.small.sp,
),
),
],
),
);
}
Widget _buildProfileMenu({
required bool isTablet,
required IconData icon,
Color? iconColor,
Color? titleColor,
required String title,
required VoidCallback onTap,
}) {
return Container(
margin: EdgeInsets.only(bottom: 2.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(3.w),
border: Border.all(color: Colors.grey.shade200),
),
child: ListTile(
onTap: onTap,
leading: Icon(
icon,
color: iconColor ?? AppColor.primaryColor,
size: 6.w,
),
title: Text(
title,
style: TextStyle(
color: titleColor ?? Colors.black87,
fontSize: isTablet ? AppFontSize.medium.sp : AppFontSize.small.sp,
fontWeight: FontWeight.w500,
),
),
trailing: Icon(Icons.chevron_right, color: Colors.grey, size: 5.w),
),
);
}
Widget _buildSocialIcon(IconData icon) {
return Container(
padding: EdgeInsets.all(2.5.w),
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.grey.shade300),
),
child: Icon(icon, color: Colors.grey[600], size: 5.w),
);
}
List<Widget> _buildGeneralInformation(
BuildContext context,
bool isTablet,
bool isLoggedIn,
) {
return [
Column(
children: [
Text(
"Ikuti kami di media sosial",
style: TextStyle(
fontSize: isTablet ? AppFontSize.medium.sp : AppFontSize.small.sp,
color: Colors.grey[600],
fontWeight: FontWeight.w500,
),
),
SizedBox(height: 2.h),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildSocialIcon(Icons.camera_alt_outlined),
SizedBox(width: 5.w),
_buildSocialIcon(Icons.facebook_outlined),
SizedBox(width: 5.w),
_buildSocialIcon(Icons.language_outlined),
],
),
],
),
SizedBox(height: 4.h),
Text(
"Powered By P.T. Niaga Nusantara",
style: TextStyle(
color: Colors.grey.shade600,
fontWeight: FontWeight.w500,
fontSize: isTablet ? AppFontSize.medium.sp : AppFontSize.small.sp,
),
),
if (isLoggedIn) ...[
SizedBox(height: 0.75.h),
Text(
"Versi 1.0.0",
style: TextStyle(
color: Colors.grey,
fontSize: isTablet ? AppFontSize.medium.sp : AppFontSize.small.sp,
),
),
],
SizedBox(height: 8.h),
];
}
}