After search and learn more about how can i add or update some field of data structure, we have below implementation
here we want to have a simple order
structure with data which user can add service to order or update selected service count, for example in first time user doesn't selected any service then we have OrderStructure:[]
which we initial that in constructor
:
OrderNotifier() : super(_initial);
static OrderStructure _initial = OrderStructure('', []);
when user selected any service we pass three argument to increment
method:
void increment({required int productId, required int serviceId, required int serviceCost})
if service doesn't exist it should be add which that belongs to product. each service belongs to product and we store that with productId
in increment
method we pass productId
, serviceId
and serviceCost
, which can search into class data structure as OrderStructure.
if productId exist then we try to search serviceId, if serviceId exists. productId = true && serviceId = true
then we should increment count
value,
if it doesn't exist it should be save as new item
notice we should't have multiple the same productId
or serviceId
into OrderStructure
.
each of them must be unique. each product can be have multiple service such as List
, OrderStructure
shouldn't have multiple productId
for example OrderStructure
data structure can be:
OrderStructure:
title : 'sample',
products:[
productId: 1
services : [
[serviceId:1, count:1, cost: 100],
[serviceId:2, count:9, cost: 500],
[serviceId:3, count:5, cost: 2000],
],
productId: 2
services : [
[serviceId:3, count:10, cost: 100],
[serviceId:5, count:6, cost: 500]
],
productId: 3
services : [
[serviceId:3, count:10, cost: 100],
[serviceId:5, count:6, cost: 500],
[serviceId:6, count:6, cost: 500],
[serviceId:7, count:6, cost: 500],
[serviceId:8, count:6, cost: 500],
],
]
when user selected seriveId
id 1
and productId
id is 1
, we search in this collection with productId
and then serviceId
, if its exists then count
should be increment, otherwise it should be added into OrderStructure
collection as a new one
for example:
OrderStructure:
title : 'sample',
products:[
productId: 1
services : [
[serviceId:1, count:2, cost: 100],
...
we have this code, but it doesn't correct:
void increment({required int productId, required int serviceId, required int serviceCost}) {
final newState = OrderStructure(state.title, [
...state.products,
for (final product in state.products)
if (product.id == productId)
for (final service in product.services)
if (service.id == serviceId)
SelectedProducts(productId,
[...product.services, SelectedProductServices(service.id, service.count + 1, service.cost)])
]);
// ignore: iterable_contains_unrelated_type
if (!newState.products.contains(productId) ||
// ignore: iterable_contains_unrelated_type
!newState.products.firstWhere((p) => p.id == productId).services.contains(serviceId)) {
newState.products.add(
SelectedProducts(serviceId, <SelectedProductServices>[SelectedProductServices(serviceId, 1, serviceCost)]));
}
state = newState;
}
FULL CODE:
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends ConsumerWidget {
@override
Widget build(BuildContext context,ScopedReader watch) {
final _orderProvider = watch(orderStateNotifierProvider.notifier);
final _product = SelectedProducts(1, []);
final _service = SelectedProductServices(1, 1, 111);
return Scaffold(
appBar: AppBar(
title: Text('test'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
TextButton(
child: Text('add new service'),
onPressed: ()=>context.read(orderStateNotifierProvider.notifier)
.increment(productId:1, serviceId:1, serviceCost:100),
),
// here we want to add new service to product, the same as above code, if productId doesn't exists
// into `OrderStructure` it should be save with
TextButton(
child: Text('append service to product`s services'),
onPressed: ()=>context.read(orderStateNotifierProvider.notifier)
.increment(productId:1, serviceId:2, serviceCost:500),
),
Text('product`s service count: ${_orderProvider.state.products[0].services.length}')
],
),
)
);
}
}
//------------------------
final orderStateNotifierProvider = StateNotifierProvider<OrderNotifier, OrderStructure>((ref) => OrderNotifier());
class OrderNotifier extends StateNotifier<OrderStructure> {
OrderNotifier() : super(_initial);
static OrderStructure _initial = OrderStructure('', []);
void resetOrder() {
_initial = const OrderStructure('', []);
}
void updateAddress({
required String title,
}) {
state = OrderStructure(title,state.products);
}
void increment({required int productId, required int serviceId, required int serviceCost}) {
final newState = OrderStructure(state.title, [
...state.products,
for (final product in state.products)
if (product.id == productId)
for (final service in product.services)
if (service.id == serviceId)
SelectedProducts(productId,
[...product.services, SelectedProductServices(service.id, service.count + 1, service.cost)])
]);
// ignore: iterable_contains_unrelated_type
if (!newState.products.contains(productId) ||
// ignore: iterable_contains_unrelated_type
!newState.products.firstWhere((p) => p.id == productId).services.contains(serviceId)) {
newState.products.add(
SelectedProducts(serviceId, <SelectedProductServices>[SelectedProductServices(serviceId, 1, serviceCost)]));
}
state = newState;
}
}
class OrderStructure {
final String title;
final List<SelectedProducts> products;
const OrderStructure(this.title, this.products);
}
class SelectedProducts {
final int id;
final List<SelectedProductServices> services;
SelectedProducts(this.id, this.services);
}
class SelectedProductServices {
final int id;
final int count;
final int cost;
const SelectedProductServices(this.id, this.count, this.cost);
}