feat: syn product
This commit is contained in:
@@ -254,8 +254,7 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
|
||||
0,
|
||||
(previousValue, element) =>
|
||||
previousValue +
|
||||
(element.product.price!
|
||||
.toIntegerFromText *
|
||||
(element.product.price! *
|
||||
element.quantity),
|
||||
));
|
||||
return Text(
|
||||
@@ -315,8 +314,7 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
|
||||
0,
|
||||
(previousValue, element) =>
|
||||
previousValue +
|
||||
(element.product.price!
|
||||
.toIntegerFromText *
|
||||
(element.product.price! *
|
||||
element.quantity),
|
||||
));
|
||||
|
||||
@@ -373,8 +371,7 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
|
||||
0,
|
||||
(previousValue, element) =>
|
||||
previousValue +
|
||||
(element.product.price!
|
||||
.toIntegerFromText *
|
||||
(element.product.price! *
|
||||
element.quantity),
|
||||
),
|
||||
);
|
||||
@@ -457,8 +454,7 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
|
||||
0,
|
||||
(previousValue, element) =>
|
||||
previousValue +
|
||||
(element.product.price!
|
||||
.toIntegerFromText *
|
||||
(element.product.price! *
|
||||
element.quantity),
|
||||
),
|
||||
);
|
||||
@@ -509,8 +505,7 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
|
||||
0,
|
||||
(previousValue, element) =>
|
||||
previousValue +
|
||||
(element.product.price!
|
||||
.toIntegerFromText *
|
||||
(element.product.price! *
|
||||
element.quantity),
|
||||
),
|
||||
);
|
||||
@@ -1262,8 +1257,7 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
|
||||
0,
|
||||
(previousValue, element) =>
|
||||
previousValue +
|
||||
(element.product.price!
|
||||
.toIntegerFromText *
|
||||
(element.product.price! *
|
||||
element.quantity),
|
||||
),
|
||||
);
|
||||
@@ -1566,10 +1560,8 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
|
||||
0,
|
||||
(sum, item) =>
|
||||
sum +
|
||||
(int.tryParse(item
|
||||
.product
|
||||
.price ??
|
||||
'0') ??
|
||||
(item.product
|
||||
.price ??
|
||||
0) *
|
||||
item.quantity),
|
||||
);
|
||||
|
||||
@@ -282,8 +282,7 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
|
||||
0,
|
||||
(previousValue, element) =>
|
||||
previousValue +
|
||||
(element.product.price!
|
||||
.toIntegerFromText *
|
||||
(element.product.price! *
|
||||
element.quantity),
|
||||
));
|
||||
return Text(
|
||||
@@ -340,8 +339,7 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
|
||||
0,
|
||||
(previousValue, element) =>
|
||||
previousValue +
|
||||
(element.product.price!
|
||||
.toIntegerFromText *
|
||||
(element.product.price! *
|
||||
element.quantity),
|
||||
),
|
||||
);
|
||||
@@ -417,8 +415,7 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
|
||||
0,
|
||||
(previousValue, element) =>
|
||||
previousValue +
|
||||
(element.product.price!
|
||||
.toIntegerFromText *
|
||||
(element.product.price! *
|
||||
element.quantity),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'package:enaklo_pos/presentation/home/bloc/product_loader/product_loader_bloc.dart';
|
||||
import 'package:enaklo_pos/presentation/home/widgets/home_right_title.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import 'package:enaklo_pos/core/extensions/build_context_ext.dart';
|
||||
import 'package:enaklo_pos/core/extensions/int_ext.dart';
|
||||
import 'package:enaklo_pos/core/extensions/string_ext.dart';
|
||||
import 'package:enaklo_pos/data/models/response/table_model.dart';
|
||||
import 'package:enaklo_pos/presentation/home/bloc/local_product/local_product_bloc.dart';
|
||||
import 'package:enaklo_pos/presentation/home/pages/confirm_payment_page.dart';
|
||||
import 'package:enaklo_pos/data/datasources/product_local_datasource.dart';
|
||||
import 'package:enaklo_pos/presentation/setting/bloc/sync_product/sync_product_bloc.dart';
|
||||
import 'package:enaklo_pos/data/models/response/product_response_model.dart';
|
||||
|
||||
import '../../../core/assets/assets.gen.dart';
|
||||
@@ -49,12 +46,15 @@ class _HomePageState extends State<HomePage> {
|
||||
|
||||
void _syncAndLoadProducts() {
|
||||
// Trigger sync from API first
|
||||
context.read<SyncProductBloc>().add(const SyncProductEvent.syncProduct());
|
||||
// context.read<SyncProductBloc>().add(const SyncProductEvent.syncProduct());
|
||||
|
||||
// Also load local products initially in case sync fails or takes time
|
||||
// context
|
||||
// .read<LocalProductBloc>()
|
||||
// .add(const LocalProductEvent.getLocalProduct());
|
||||
context
|
||||
.read<LocalProductBloc>()
|
||||
.add(const LocalProductEvent.getLocalProduct());
|
||||
.read<ProductLoaderBloc>()
|
||||
.add(const ProductLoaderEvent.getProduct());
|
||||
|
||||
// Initialize checkout with tax and service charge settings
|
||||
context.read<CheckoutBloc>().add(const CheckoutEvent.started());
|
||||
@@ -83,7 +83,7 @@ class _HomePageState extends State<HomePage> {
|
||||
List<Product> products, int categoryId) {
|
||||
final filteredBySearch = _filterProducts(products);
|
||||
return filteredBySearch
|
||||
.where((element) => element.category?.id == categoryId)
|
||||
.where((element) => element.price == categoryId)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@@ -93,451 +93,420 @@ class _HomePageState extends State<HomePage> {
|
||||
tag: 'confirmation_screen',
|
||||
child: Scaffold(
|
||||
backgroundColor: AppColors.white,
|
||||
body: BlocListener<SyncProductBloc, SyncProductState>(
|
||||
listener: (context, state) {
|
||||
state.maybeWhen(
|
||||
orElse: () {},
|
||||
error: (message) {
|
||||
// If sync fails, still try to load local products
|
||||
context
|
||||
.read<LocalProductBloc>()
|
||||
.add(const LocalProductEvent.getLocalProduct());
|
||||
},
|
||||
loaded: (productResponseModel) async {
|
||||
// Store context reference before async operations
|
||||
final localProductBloc = context.read<LocalProductBloc>();
|
||||
|
||||
// Save synced products to local database
|
||||
await ProductLocalDatasource.instance.deleteAllProducts();
|
||||
await ProductLocalDatasource.instance.insertProducts(
|
||||
productResponseModel.data!,
|
||||
);
|
||||
// Then load local products to display
|
||||
localProductBloc.add(const LocalProductEvent.getLocalProduct());
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Align(
|
||||
alignment: AlignmentDirectional.topStart,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
HomeTitle(
|
||||
controller: searchController,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
searchQuery = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
BlocBuilder<LocalProductBloc, LocalProductState>(
|
||||
builder: (context, state) {
|
||||
return Expanded(
|
||||
child: CustomTabBarV2(
|
||||
tabTitles: const [
|
||||
'Semua',
|
||||
'Makanan',
|
||||
'Minuman',
|
||||
'Paket'
|
||||
],
|
||||
tabViews: [
|
||||
// All Products Tab
|
||||
SizedBox(
|
||||
child: state.maybeWhen(orElse: () {
|
||||
body: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Align(
|
||||
alignment: AlignmentDirectional.topStart,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
HomeTitle(
|
||||
controller: searchController,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
searchQuery = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
BlocBuilder<ProductLoaderBloc, ProductLoaderState>(
|
||||
builder: (context, state) {
|
||||
return Expanded(
|
||||
child: CustomTabBarV2(
|
||||
tabTitles: const [
|
||||
'Semua',
|
||||
'Makanan',
|
||||
'Minuman',
|
||||
'Paket'
|
||||
],
|
||||
tabViews: [
|
||||
// All Products Tab
|
||||
SizedBox(
|
||||
child: state.maybeWhen(orElse: () {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}, loading: () {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}, loaded: (products) {
|
||||
final filteredProducts =
|
||||
_filterProducts(products);
|
||||
if (filteredProducts.isEmpty) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
child: Text('No Items Found'),
|
||||
);
|
||||
}, loading: () {
|
||||
}
|
||||
return GridView.builder(
|
||||
itemCount: filteredProducts.length,
|
||||
padding: const EdgeInsets.all(16),
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 180,
|
||||
mainAxisSpacing: 30,
|
||||
crossAxisSpacing: 30,
|
||||
childAspectRatio: 180 / 240,
|
||||
),
|
||||
itemBuilder: (context, index) =>
|
||||
ProductCard(
|
||||
data: filteredProducts[index],
|
||||
onCartButton: () {},
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
// Makanan Tab
|
||||
SizedBox(
|
||||
child: state.maybeWhen(orElse: () {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}, loading: () {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}, loaded: (products) {
|
||||
if (products.isEmpty) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
child: Text('No Items'),
|
||||
);
|
||||
}, loaded: (products) {
|
||||
final filteredProducts =
|
||||
_filterProducts(products);
|
||||
if (filteredProducts.isEmpty) {
|
||||
return const Center(
|
||||
child: Text('No Items Found'),
|
||||
);
|
||||
}
|
||||
return GridView.builder(
|
||||
itemCount: filteredProducts.length,
|
||||
padding: const EdgeInsets.all(16),
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 180,
|
||||
mainAxisSpacing: 30,
|
||||
crossAxisSpacing: 30,
|
||||
childAspectRatio: 180 / 240,
|
||||
),
|
||||
itemBuilder: (context, index) =>
|
||||
ProductCard(
|
||||
data: filteredProducts[index],
|
||||
onCartButton: () {},
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
// Makanan Tab
|
||||
SizedBox(
|
||||
child: state.maybeWhen(orElse: () {
|
||||
}
|
||||
final filteredProducts =
|
||||
_filterProductsByCategory(products, 1);
|
||||
return filteredProducts.isEmpty
|
||||
? const _IsEmpty()
|
||||
: GridView.builder(
|
||||
itemCount: filteredProducts.length,
|
||||
padding: const EdgeInsets.all(16),
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent:
|
||||
200, // Lebar maksimal tiap item (bisa kamu ubah)
|
||||
mainAxisSpacing: 30,
|
||||
crossAxisSpacing: 30,
|
||||
childAspectRatio: 0.85,
|
||||
),
|
||||
itemBuilder: (context, index) =>
|
||||
ProductCard(
|
||||
data: filteredProducts[index],
|
||||
onCartButton: () {},
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
// Minuman Tab
|
||||
SizedBox(
|
||||
child: state.maybeWhen(orElse: () {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}, loading: () {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}, loaded: (products) {
|
||||
if (products.isEmpty) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
child: Text('No Items'),
|
||||
);
|
||||
}, loading: () {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}, loaded: (products) {
|
||||
if (products.isEmpty) {
|
||||
return const Center(
|
||||
child: Text('No Items'),
|
||||
);
|
||||
}
|
||||
final filteredProducts =
|
||||
_filterProductsByCategory(products, 1);
|
||||
return filteredProducts.isEmpty
|
||||
? const _IsEmpty()
|
||||
: GridView.builder(
|
||||
itemCount: filteredProducts.length,
|
||||
padding: const EdgeInsets.all(16),
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent:
|
||||
200, // Lebar maksimal tiap item (bisa kamu ubah)
|
||||
mainAxisSpacing: 30,
|
||||
crossAxisSpacing: 30,
|
||||
childAspectRatio: 0.85,
|
||||
),
|
||||
itemBuilder: (context, index) =>
|
||||
ProductCard(
|
||||
}
|
||||
final filteredProducts =
|
||||
_filterProductsByCategory(products, 2);
|
||||
return filteredProducts.isEmpty
|
||||
? const _IsEmpty()
|
||||
: GridView.builder(
|
||||
itemCount: filteredProducts.length,
|
||||
padding: const EdgeInsets.all(16),
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent:
|
||||
200, // Lebar maksimal tiap item (bisa kamu ubah)
|
||||
mainAxisSpacing: 30,
|
||||
crossAxisSpacing: 30,
|
||||
childAspectRatio: 0.85,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
return ProductCard(
|
||||
data: filteredProducts[index],
|
||||
onCartButton: () {},
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
// Minuman Tab
|
||||
SizedBox(
|
||||
child: state.maybeWhen(orElse: () {
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
// Snack Tab
|
||||
SizedBox(
|
||||
child: state.maybeWhen(orElse: () {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}, loading: () {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}, loaded: (products) {
|
||||
if (products.isEmpty) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
child: Text('No Items'),
|
||||
);
|
||||
}, loading: () {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}, loaded: (products) {
|
||||
if (products.isEmpty) {
|
||||
return const Center(
|
||||
child: Text('No Items'),
|
||||
);
|
||||
}
|
||||
final filteredProducts =
|
||||
_filterProductsByCategory(products, 2);
|
||||
return filteredProducts.isEmpty
|
||||
? const _IsEmpty()
|
||||
: GridView.builder(
|
||||
itemCount: filteredProducts.length,
|
||||
padding: const EdgeInsets.all(16),
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent:
|
||||
200, // Lebar maksimal tiap item (bisa kamu ubah)
|
||||
mainAxisSpacing: 30,
|
||||
crossAxisSpacing: 30,
|
||||
childAspectRatio: 0.85,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
return ProductCard(
|
||||
data: filteredProducts[index],
|
||||
onCartButton: () {},
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
// Snack Tab
|
||||
SizedBox(
|
||||
child: state.maybeWhen(orElse: () {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}, loading: () {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}, loaded: (products) {
|
||||
if (products.isEmpty) {
|
||||
return const Center(
|
||||
child: Text('No Items'),
|
||||
);
|
||||
}
|
||||
final filteredProducts =
|
||||
_filterProductsByCategory(products, 3);
|
||||
return filteredProducts.isEmpty
|
||||
? const _IsEmpty()
|
||||
: GridView.builder(
|
||||
itemCount: filteredProducts.length,
|
||||
padding: const EdgeInsets.all(16),
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent:
|
||||
200, // Lebar maksimal tiap item (bisa kamu ubah)
|
||||
mainAxisSpacing: 30,
|
||||
crossAxisSpacing: 30,
|
||||
childAspectRatio: 0.85,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
return ProductCard(
|
||||
data: filteredProducts[index],
|
||||
onCartButton: () {},
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
}
|
||||
final filteredProducts =
|
||||
_filterProductsByCategory(products, 3);
|
||||
return filteredProducts.isEmpty
|
||||
? const _IsEmpty()
|
||||
: GridView.builder(
|
||||
itemCount: filteredProducts.length,
|
||||
padding: const EdgeInsets.all(16),
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent:
|
||||
200, // Lebar maksimal tiap item (bisa kamu ubah)
|
||||
mainAxisSpacing: 30,
|
||||
crossAxisSpacing: 30,
|
||||
childAspectRatio: 0.85,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
return ProductCard(
|
||||
data: filteredProducts[index],
|
||||
onCartButton: () {},
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Material(
|
||||
color: Colors.white,
|
||||
child: Column(
|
||||
children: [
|
||||
HomeRightTitle(
|
||||
table: widget.table,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0)
|
||||
.copyWith(bottom: 0, top: 27),
|
||||
child: Column(
|
||||
children: [
|
||||
const Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Item',
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Material(
|
||||
color: Colors.white,
|
||||
child: Column(
|
||||
children: [
|
||||
HomeRightTitle(
|
||||
table: widget.table,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0)
|
||||
.copyWith(bottom: 0, top: 27),
|
||||
child: Column(
|
||||
children: [
|
||||
const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Item',
|
||||
style: TextStyle(
|
||||
color: AppColors.primary,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 130,
|
||||
),
|
||||
SizedBox(
|
||||
width: 50.0,
|
||||
child: Text(
|
||||
'Qty',
|
||||
style: TextStyle(
|
||||
color: AppColors.primary,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 130,
|
||||
),
|
||||
SizedBox(
|
||||
width: 50.0,
|
||||
child: Text(
|
||||
'Qty',
|
||||
style: TextStyle(
|
||||
color: AppColors.primary,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
child: Text(
|
||||
'Price',
|
||||
style: TextStyle(
|
||||
color: AppColors.primary,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
child: Text(
|
||||
'Price',
|
||||
style: TextStyle(
|
||||
color: AppColors.primary,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SpaceHeight(8),
|
||||
const Divider(),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16.0).copyWith(top: 0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
BlocBuilder<CheckoutBloc, CheckoutState>(
|
||||
builder: (context, state) {
|
||||
return state.maybeWhen(
|
||||
orElse: () => const Center(
|
||||
child: Text('No Items'),
|
||||
),
|
||||
),
|
||||
],
|
||||
loaded: (products,
|
||||
discountModel,
|
||||
discount,
|
||||
discountAmount,
|
||||
tax,
|
||||
serviceCharge,
|
||||
totalQuantity,
|
||||
totalPrice,
|
||||
draftName,
|
||||
orderType) {
|
||||
if (products.isEmpty) {
|
||||
return const Center(
|
||||
child: Text('No Items'),
|
||||
);
|
||||
}
|
||||
return ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics:
|
||||
const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) =>
|
||||
OrderMenu(data: products[index]),
|
||||
separatorBuilder: (context, index) =>
|
||||
const SpaceHeight(1.0),
|
||||
itemCount: products.length,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
const SpaceHeight(8),
|
||||
const Divider(),
|
||||
const SpaceHeight(8.0),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding:
|
||||
const EdgeInsets.all(16.0).copyWith(top: 0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0).copyWith(top: 0),
|
||||
child: Column(
|
||||
children: [
|
||||
const Divider(),
|
||||
const SpaceHeight(16.0),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'Pajak',
|
||||
style: TextStyle(
|
||||
color: AppColors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
BlocBuilder<CheckoutBloc, CheckoutState>(
|
||||
builder: (context, state) {
|
||||
return state.maybeWhen(
|
||||
orElse: () => const Center(
|
||||
child: Text('No Items'),
|
||||
final tax = state.maybeWhen(
|
||||
orElse: () => 0,
|
||||
loaded: (products,
|
||||
discountModel,
|
||||
discount,
|
||||
discountAmount,
|
||||
tax,
|
||||
serviceCharge,
|
||||
totalQuantity,
|
||||
totalPrice,
|
||||
draftName,
|
||||
orderType) {
|
||||
if (products.isEmpty) {
|
||||
return 0;
|
||||
}
|
||||
return tax;
|
||||
});
|
||||
return Text(
|
||||
'$tax %',
|
||||
style: const TextStyle(
|
||||
color: AppColors.primary,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
loaded: (products,
|
||||
discountModel,
|
||||
discount,
|
||||
discountAmount,
|
||||
tax,
|
||||
serviceCharge,
|
||||
totalQuantity,
|
||||
totalPrice,
|
||||
draftName,
|
||||
orderType) {
|
||||
if (products.isEmpty) {
|
||||
return const Center(
|
||||
child: Text('No Items'),
|
||||
);
|
||||
}
|
||||
return ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics:
|
||||
const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) =>
|
||||
OrderMenu(data: products[index]),
|
||||
separatorBuilder: (context, index) =>
|
||||
const SpaceHeight(1.0),
|
||||
itemCount: products.length,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
const SpaceHeight(8.0),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0).copyWith(top: 0),
|
||||
child: Column(
|
||||
children: [
|
||||
const Divider(),
|
||||
const SpaceHeight(16.0),
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'Pajak',
|
||||
style: TextStyle(
|
||||
color: AppColors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
BlocBuilder<CheckoutBloc, CheckoutState>(
|
||||
builder: (context, state) {
|
||||
final tax = state.maybeWhen(
|
||||
orElse: () => 0,
|
||||
loaded: (products,
|
||||
discountModel,
|
||||
discount,
|
||||
discountAmount,
|
||||
tax,
|
||||
serviceCharge,
|
||||
totalQuantity,
|
||||
totalPrice,
|
||||
draftName,
|
||||
orderType) {
|
||||
if (products.isEmpty) {
|
||||
return 0;
|
||||
}
|
||||
return tax;
|
||||
});
|
||||
return Text(
|
||||
'$tax %',
|
||||
style: const TextStyle(
|
||||
color: AppColors.primary,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
const SpaceHeight(16.0),
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'Sub total',
|
||||
style: TextStyle(
|
||||
color: AppColors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
BlocBuilder<CheckoutBloc, CheckoutState>(
|
||||
builder: (context, state) {
|
||||
final price = state.maybeWhen(
|
||||
orElse: () => 0,
|
||||
loaded: (products,
|
||||
discountModel,
|
||||
discount,
|
||||
discountAmount,
|
||||
tax,
|
||||
serviceCharge,
|
||||
totalQuantity,
|
||||
totalPrice,
|
||||
draftName,
|
||||
orderType) {
|
||||
if (products.isEmpty) {
|
||||
return 0;
|
||||
}
|
||||
return products
|
||||
.map((e) =>
|
||||
e.product.price!
|
||||
.toIntegerFromText *
|
||||
e.quantity)
|
||||
.reduce((value, element) =>
|
||||
value + element);
|
||||
});
|
||||
|
||||
return Text(
|
||||
price.currencyFormatRp,
|
||||
style: const TextStyle(
|
||||
color: AppColors.primary,
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
SpaceHeight(16.0),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Expanded(
|
||||
child: Button.filled(
|
||||
borderRadius: 12,
|
||||
elevation: 1,
|
||||
onPressed: () {
|
||||
context.push(ConfirmPaymentPage(
|
||||
isTable: widget.isTable,
|
||||
table: widget.table,
|
||||
));
|
||||
},
|
||||
label: 'Lanjutkan Pembayaran',
|
||||
const SpaceHeight(16.0),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'Sub total',
|
||||
style: TextStyle(
|
||||
color: AppColors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
BlocBuilder<CheckoutBloc, CheckoutState>(
|
||||
builder: (context, state) {
|
||||
final price = state.maybeWhen(
|
||||
orElse: () => 0,
|
||||
loaded: (products,
|
||||
discountModel,
|
||||
discount,
|
||||
discountAmount,
|
||||
tax,
|
||||
serviceCharge,
|
||||
totalQuantity,
|
||||
totalPrice,
|
||||
draftName,
|
||||
orderType) {
|
||||
if (products.isEmpty) {
|
||||
return 0;
|
||||
}
|
||||
return products
|
||||
.map((e) =>
|
||||
e.product.price! * e.quantity)
|
||||
.reduce((value, element) =>
|
||||
value + element);
|
||||
});
|
||||
|
||||
return Text(
|
||||
price.currencyFormatRp,
|
||||
style: const TextStyle(
|
||||
color: AppColors.primary,
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
SpaceHeight(16.0),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Expanded(
|
||||
child: Button.filled(
|
||||
borderRadius: 12,
|
||||
elevation: 1,
|
||||
onPressed: () {
|
||||
context.push(ConfirmPaymentPage(
|
||||
isTable: widget.isTable,
|
||||
table: widget.table,
|
||||
));
|
||||
},
|
||||
label: 'Lanjutkan Pembayaran',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user