QueenFruits/Mobile Operasional/lib/features/outlets/presentation/screens/outlet_screen.dart

504 lines
28 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:niogu_app/core/components/top_back_bar_app.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/widgets/custom_error_screen.dart';
import 'package:niogu_app/core/providers/app_provider.dart';
import 'package:niogu_app/core/router/app_route.dart';
import 'package:niogu_app/core/widgets/custom_empty_screen.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/outlets/presentation/widgets/outlet_shimmer.dart';
import 'package:niogu_app/features/outlets/presentation/widgets/quota_indicator.dart';
import 'package:sizer/sizer.dart';
class OutletScreen extends ConsumerWidget {
const OutletScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return LayoutBuilder(
builder: (context, constraints) {
final bool isTablet = 100.w >= 600;
final outletState = ref.watch(displayOutletStreamProvider);
int limitOutlet = 5;
final limitOutletState = ref.watch(limitOutletStreamProvider);
limitOutletState.whenData((limit) => limitOutlet = limit);
bool isLimitReached = false;
outletState.whenData((outlets) {
isLimitReached = outlets.length >= limitOutlet;
});
final userDeletedState = ref.watch(userDeletedByOutletStreamProvider);
final List<UserDeletedByOutlet> userDeleted = [];
userDeletedState.whenData((u) => userDeleted.addAll(u));
final outletEmptyState = ref.watch(displayOutletEmptyProvider);
final outletIdByOwnerState = ref.watch(outletIdByOwnerProvider);
return SafeArea(
top: false,
bottom: true,
right: false,
left: false,
child: Scaffold(
backgroundColor: const Color(0xFFF9FAFB),
appBar: TopBackBarApp(
title: "Outlet Usaha",
onTap: () => context.pop(),
),
body: outletState.when(
data: (outlets) {
switch (outletEmptyState) {
case DisplayOutletEmpty.loading:
return const SizedBox();
case DisplayOutletEmpty.empty_database:
return CustomEmptyScreen(
title: "Tidak Ada Outlet",
body: "Kamu belum memiliki outlet",
);
case DisplayOutletEmpty.has_data:
return Column(
children: [
QuotaIndicator(current: outlets.length, max: limitOutlet),
Expanded(
child: ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 5.w),
itemCount: outlets.length,
itemBuilder: (context, index) {
final outlet = outlets[index];
final bool imagePathAvailable =
outlet.bannerPath != null &&
outlet.bannerPath!.isNotEmpty;
final File imageFile = File(
imagePathAvailable
? outlet.bannerPath!
: "image not found",
);
int userStaffAmount = outlet.userStaffAmount;
final bool isOutletOwner =
outletIdByOwnerState != null &&
outlet.id == outletIdByOwnerState;
if (userDeleted.isNotEmpty) {
for (final user in userDeleted) {
if (isOutletOwner &&
user.outletId == outlet.id) {
userStaffAmount =
outlet.userStaffAmount -
user.amount -
1;
} else if (user.outletId == outlet.id) {
userStaffAmount =
outlet.userStaffAmount -
user.amount;
}
}
} else {
if (isOutletOwner) {
userStaffAmount =
outlet.userStaffAmount - 1;
}
}
final bool imageFileExists = imageFile
.existsSync();
return Material(
color: Colors.transparent,
type: MaterialType.transparency,
child: InkWell(
onTap: () {
context.pushNamed(
AppRoute.editOutletScreen,
pathParameters: {"id": outlet.id},
);
},
child: Container(
margin: EdgeInsets.only(bottom: 3.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(
4.w,
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(
0.06,
),
blurRadius: 15,
offset: const Offset(0, 8),
),
],
),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Stack(
children: [
imageFileExists
? Container(
height: 22.h,
width: double.infinity,
decoration: BoxDecoration(
borderRadius:
BorderRadius.vertical(
top:
Radius.circular(
4.w,
),
),
image:
DecorationImage(
image:
FileImage(
imageFile,
),
fit: BoxFit
.cover,
),
),
)
: Container(
height: 22.h,
width: double.infinity,
decoration: BoxDecoration(
borderRadius:
BorderRadius.vertical(
top:
Radius.circular(
4.w,
),
),
color: Colors
.grey
.shade200,
),
child: Column(
mainAxisAlignment:
MainAxisAlignment
.center,
children: [
Icon(
Icons
.store_outlined,
color:
Colors.grey,
size: 20.w,
),
],
),
),
if (imageFileExists)
Container(
height: 22.h,
width: double.infinity,
decoration: BoxDecoration(
borderRadius:
BorderRadius.vertical(
top:
Radius.circular(
4.w,
),
),
gradient: LinearGradient(
begin:
Alignment.topCenter,
end: Alignment
.bottomCenter,
colors: [
Colors.black
.withOpacity(0.4),
Colors.transparent,
],
),
),
),
],
),
Padding(
padding: EdgeInsets.all(4.w),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(
outlet.name,
style: TextStyle(
color: Colors.black87,
fontSize: isTablet
? AppFontSize
.medium
.sp
: AppFontSize
.small
.sp,
fontWeight:
FontWeight.bold,
),
),
Row(
children: [
Container(
width: 2.w,
height: 2.w,
decoration: BoxDecoration(
color:
outlet
.isActive
? Colors.green
: Colors.red,
shape: BoxShape
.circle,
),
),
SizedBox(
width: 1.5.w,
),
Text(
outlet.isActive
? 'Aktif / Buka'
: 'Non Aktif / Tutup',
style: TextStyle(
fontSize: isTablet
? (AppFontSize.medium -
2)
.sp
: (AppFontSize.small -
2)
.sp,
color:
outlet
.isActive
? Colors.green
: Colors.red,
fontWeight:
FontWeight
.w600,
),
),
],
),
],
),
SizedBox(height: 1.h),
if (outlet.isMainOutlet)
Text(
"• Outlet Utama",
style: TextStyle(
color: Colors
.grey
.shade700,
fontSize: isTablet
? (AppFontSize.medium -
2)
.sp
: (AppFontSize.small -
2)
.sp,
fontWeight:
FontWeight.bold,
),
),
if (outlet.fullAddress !=
null &&
outlet
.fullAddress!
.isNotEmpty) ...[
SizedBox(height: 1.5.h),
Row(
children: [
Icon(
Icons
.location_on_outlined,
size: 5.w,
color: Colors.grey,
),
SizedBox(width: 2.w),
Expanded(
child: Text(
outlet.fullAddress!,
style: TextStyle(
color: Colors
.grey
.shade700,
fontSize: isTablet
? (AppFontSize.medium -
1.25)
.sp
: (AppFontSize.small -
1.25)
.sp,
),
maxLines: 1,
overflow:
TextOverflow
.ellipsis,
),
),
],
),
],
SizedBox(height: 1.h),
Divider(
color: Colors.grey[100],
),
SizedBox(height: 1.h),
Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
_buildInfoMini(
Icons.people_outline,
"$userStaffAmount Staf",
isTablet,
),
_buildInfoMini(
Icons
.shopping_bag_outlined,
"${outlet.transactionAmount} Transaksi",
isTablet,
),
Icon(
Icons.arrow_forward_ios,
size: 3.5.w,
color: Colors.grey[400],
),
],
),
],
),
),
],
),
),
),
);
},
),
),
],
);
}
},
error: (error, stackTrace) {
return CustomErrorScreen(
message: "Ups, terjadi kesalahan",
onRefresh: () {},
);
},
loading: () => const OutletShimmer(),
),
bottomNavigationBar: outletState.isLoading
? null
: Container(
padding: EdgeInsets.all(5.w),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, -5),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ElevatedButton(
onPressed: isLimitReached
? null
: () {
final outletState = ref.read(
outletStreamProvider,
);
bool isLimitReached = false;
outletState.whenData((outlets) {
isLimitReached = outlets.length >= 5;
});
if (isLimitReached) {
} else {
context.pushNamed(
AppRoute.addOutletScreen,
);
}
},
style: ElevatedButton.styleFrom(
backgroundColor: AppColor.primaryColor,
minimumSize: Size(double.infinity, 6.5.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(3.w),
),
disabledBackgroundColor: !isLimitReached
? null
: Colors.grey.shade300,
),
child: Text(
"Tambah Outlet Baru",
style: TextStyle(
fontSize: AppFontSize.medium.sp,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
],
),
),
),
);
},
);
}
Widget _buildInfoMini(IconData icon, String label, bool isTablet) {
return Row(
children: [
Icon(icon, size: 4.w, color: AppColor.primaryColor),
SizedBox(width: 1.5.w),
Text(
label,
style: TextStyle(
color: Colors.black54,
fontSize: isTablet
? (AppFontSize.medium - 1.25).sp
: (AppFontSize.small - 1.25).sp,
fontWeight: FontWeight.w500,
),
),
],
);
}
}