feat: Adds product editing and deletion features
Enables viewing and editing existing product details by passing the product ID to the form page. The form now loads and displays the product data based on the provided ID. Adds a delete button to each item in the product list, allowing users to remove products directly from the list view. Updates navigation from the product list and scanner pages to pass the product ID when navigating to the product form. Includes minor code style changes by applying the `sort_constructors_first` lint rule and updates dependencies (`flutter_lints`, `lints`).
This commit is contained in:
parent
09405b5da7
commit
6c3f2b80b0
@ -23,6 +23,13 @@ linter:
|
|||||||
rules:
|
rules:
|
||||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||||
|
- sort_constructors_first
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
exclude:
|
||||||
|
- "**/*.g.dart"
|
||||||
|
- "**/*.freezed.dart"
|
||||||
|
errors:
|
||||||
|
invalid_annotation_target: ignore
|
||||||
# Additional information about this file can be found at
|
# Additional information about this file can be found at
|
||||||
# https://dart.dev/guides/language/analysis-options
|
# https://dart.dev/guides/language/analysis-options
|
||||||
|
@ -4,16 +4,6 @@ import 'package:objectbox/objectbox.dart';
|
|||||||
/// Modèle de base de données ObjectBox
|
/// Modèle de base de données ObjectBox
|
||||||
@Entity()
|
@Entity()
|
||||||
class ProductEntity {
|
class ProductEntity {
|
||||||
@Id(assignable: true)
|
|
||||||
int id;
|
|
||||||
|
|
||||||
String? code;
|
|
||||||
String? name;
|
|
||||||
String? description;
|
|
||||||
String? price;
|
|
||||||
String? quantity;
|
|
||||||
String? image;
|
|
||||||
|
|
||||||
ProductEntity({
|
ProductEntity({
|
||||||
this.id = 0,
|
this.id = 0,
|
||||||
this.code,
|
this.code,
|
||||||
@ -23,6 +13,15 @@ class ProductEntity {
|
|||||||
this.quantity,
|
this.quantity,
|
||||||
this.image,
|
this.image,
|
||||||
});
|
});
|
||||||
|
@Id(assignable: true)
|
||||||
|
int id;
|
||||||
|
|
||||||
|
String? code;
|
||||||
|
String? name;
|
||||||
|
String? description;
|
||||||
|
String? price;
|
||||||
|
String? quantity;
|
||||||
|
String? image;
|
||||||
|
|
||||||
/// Convertir vers ProductStruct
|
/// Convertir vers ProductStruct
|
||||||
ProductStruct toStruct() {
|
ProductStruct toStruct() {
|
||||||
|
@ -8,11 +8,11 @@ export 'package:barcode_scanner/backend/objectbox/objectbox.g.dart';
|
|||||||
late ObjectboxManager objectboxManager;
|
late ObjectboxManager objectboxManager;
|
||||||
|
|
||||||
class ObjectboxManager {
|
class ObjectboxManager {
|
||||||
|
ObjectboxManager._create(this.store);
|
||||||
|
|
||||||
/// The Store of this app.
|
/// The Store of this app.
|
||||||
late final Store store;
|
late final Store store;
|
||||||
|
|
||||||
ObjectboxManager._create(this.store);
|
|
||||||
|
|
||||||
/// Create an instance of ObjectBox to use throughout the app.
|
/// Create an instance of ObjectBox to use throughout the app.
|
||||||
static Future<ObjectboxManager> create() async {
|
static Future<ObjectboxManager> create() async {
|
||||||
Directory directory;
|
Directory directory;
|
||||||
|
@ -1,22 +1,47 @@
|
|||||||
|
import 'package:barcode_scanner/components/loading_progress_component.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:barcode_scanner/components/primary_button_component.dart';
|
import 'package:barcode_scanner/components/primary_button_component.dart';
|
||||||
|
import 'package:barcode_scanner/pages/product_form_page/product_form_page_model.dart';
|
||||||
import 'package:barcode_scanner/router/go_secure_router_builder.dart';
|
import 'package:barcode_scanner/router/go_secure_router_builder.dart';
|
||||||
import 'package:barcode_scanner/themes/app_theme.dart';
|
import 'package:barcode_scanner/themes/app_theme.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/scheduler.dart';
|
||||||
|
|
||||||
class ProductFormPage extends StatefulWidget {
|
class ProductFormPage extends ConsumerStatefulWidget {
|
||||||
const ProductFormPage({super.key});
|
const ProductFormPage({super.key, required this.id});
|
||||||
|
final int id;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ProductFormPage> createState() => _ProductFormPageState();
|
ConsumerState<ProductFormPage> createState() => _ProductFormPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ProductFormPageState extends State<ProductFormPage> {
|
class _ProductFormPageState extends ConsumerState<ProductFormPage> {
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
final TextEditingController name = TextEditingController();
|
final TextEditingController name = TextEditingController();
|
||||||
final TextEditingController code = TextEditingController();
|
final TextEditingController code = TextEditingController();
|
||||||
final TextEditingController description = TextEditingController();
|
final TextEditingController description = TextEditingController();
|
||||||
final TextEditingController price = TextEditingController();
|
final TextEditingController price = TextEditingController();
|
||||||
|
final TextEditingController quantity = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
|
ref
|
||||||
|
.read(productFormPageModelProvider.notifier)
|
||||||
|
.getProductLocal(
|
||||||
|
id: widget.id,
|
||||||
|
onSuccess: (value) {
|
||||||
|
name.text = value?.name ?? '';
|
||||||
|
code.text = value?.id.toString() ?? '';
|
||||||
|
description.text = value?.description ?? '';
|
||||||
|
price.text = value?.price ?? '';
|
||||||
|
quantity.text = value?.quantity ?? '';
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
@ -41,6 +66,7 @@ class _ProductFormPageState extends State<ProductFormPage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final state = ref.watch(productFormPageModelProvider);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: AppTheme.of(context).primaryBackground,
|
backgroundColor: AppTheme.of(context).primaryBackground,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@ -58,63 +84,70 @@ class _ProductFormPageState extends State<ProductFormPage> {
|
|||||||
backgroundColor: AppTheme.of(context).primaryBackground,
|
backgroundColor: AppTheme.of(context).primaryBackground,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: state.loading
|
||||||
padding: const EdgeInsets.all(24),
|
? Center(child: LoadingProgressComponent())
|
||||||
child: Form(
|
: Padding(
|
||||||
key: _formKey,
|
padding: const EdgeInsets.all(24),
|
||||||
child: ListView(
|
child: Form(
|
||||||
children: [
|
key: _formKey,
|
||||||
/// Nom du produit
|
child: ListView(
|
||||||
TextFormField(
|
children: [
|
||||||
controller: name,
|
/// Nom du produit
|
||||||
decoration: _inputStyle("Nom du produit"),
|
TextFormField(
|
||||||
validator: (value) =>
|
controller: name,
|
||||||
(value == null || value.isEmpty) ? 'Champ requis' : null,
|
decoration: _inputStyle("Nom du produit"),
|
||||||
),
|
validator: (value) => (value == null || value.isEmpty)
|
||||||
const SizedBox(height: 16),
|
? 'Champ requis'
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
/// Code barre / code produit
|
/// Code barre / code produit
|
||||||
TextFormField(
|
TextFormField(
|
||||||
controller: code,
|
controller: code,
|
||||||
decoration: _inputStyle("Code produit / Code barre"),
|
decoration: _inputStyle("Code produit / Code barre"),
|
||||||
validator: (value) =>
|
validator: (value) => (value == null || value.isEmpty)
|
||||||
(value == null || value.isEmpty) ? 'Champ requis' : null,
|
? 'Champ requis'
|
||||||
),
|
: null,
|
||||||
const SizedBox(height: 16),
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
/// Description
|
/// Description
|
||||||
TextFormField(
|
TextFormField(
|
||||||
controller: description,
|
controller: description,
|
||||||
decoration: _inputStyle("Commentaires"),
|
decoration: _inputStyle("Commentaires"),
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
/// Prix
|
/// Prix
|
||||||
TextFormField(
|
TextFormField(
|
||||||
controller: price,
|
controller: quantity,
|
||||||
decoration: _inputStyle("Quantités"),
|
decoration: _inputStyle("Quantités"),
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
validator: (value) =>
|
validator: (value) => (value == null || value.isEmpty)
|
||||||
(value == null || value.isEmpty) ? 'Champ requis' : null,
|
? 'Champ requis'
|
||||||
),
|
: null,
|
||||||
const SizedBox(height: 24),
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
/// Bouton sauvegarder
|
/// Bouton sauvegarder
|
||||||
PrimaryButtonComponent(
|
PrimaryButtonComponent(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_formKey.currentState!.validate()) {
|
if (_formKey.currentState!.validate()) {
|
||||||
// Traitement ici
|
// Traitement ici
|
||||||
debugPrint("Produit : ${name.text}, Code : ${code.text}");
|
debugPrint(
|
||||||
HomeRoute().go(context);
|
"Produit : ${name.text}, Code : ${code.text}",
|
||||||
}
|
);
|
||||||
},
|
HomeRoute().go(context);
|
||||||
text: 'Sauvegarder',
|
}
|
||||||
|
},
|
||||||
|
text: 'Sauvegarder',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
lib/pages/product_form_page/product_form_page_model.dart
Normal file
39
lib/pages/product_form_page/product_form_page_model.dart
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import 'package:barcode_scanner/backend/objectbox/entities/product/product_entity.dart';
|
||||||
|
import 'package:barcode_scanner/backend/objectbox/objectbox_manager.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'product_form_page_model.freezed.dart';
|
||||||
|
|
||||||
|
/// The provider for the AuthViewModel, using Riverpod's StateNotifierProvider
|
||||||
|
/// with autoDispose to manage the lifecycle of the view model.
|
||||||
|
final productFormPageModelProvider =
|
||||||
|
StateNotifierProvider<ProductFormPageModel, ProductFormPageState>((ref) {
|
||||||
|
return ProductFormPageModel();
|
||||||
|
});
|
||||||
|
|
||||||
|
class ProductFormPageModel extends StateNotifier<ProductFormPageState> {
|
||||||
|
/// Constructor initializes the TaskRepository using the provider reference.
|
||||||
|
ProductFormPageModel() : super(const ProductFormPageState());
|
||||||
|
|
||||||
|
final productStore = objectboxManager.store.box<ProductEntity>();
|
||||||
|
|
||||||
|
Future getProductLocal({
|
||||||
|
required int id,
|
||||||
|
Function(ProductEntity? value)? onSuccess,
|
||||||
|
}) async {
|
||||||
|
state = state.copyWith(loading: true);
|
||||||
|
final product = await productStore.getAsync(id);
|
||||||
|
onSuccess?.call(product);
|
||||||
|
state = state.copyWith(product: product, loading: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class ProductFormPageState with _$ProductFormPageState {
|
||||||
|
const factory ProductFormPageState({
|
||||||
|
ProductEntity? product,
|
||||||
|
@Default(false) bool loading,
|
||||||
|
}) = _ProductFormPageState;
|
||||||
|
}
|
157
lib/pages/product_form_page/product_form_page_model.freezed.dart
Normal file
157
lib/pages/product_form_page/product_form_page_model.freezed.dart
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
// dart format width=80
|
||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'product_form_page_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// dart format off
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$ProductFormPageState implements DiagnosticableTreeMixin {
|
||||||
|
|
||||||
|
ProductEntity? get product; bool get loading;
|
||||||
|
/// Create a copy of ProductFormPageState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$ProductFormPageStateCopyWith<ProductFormPageState> get copyWith => _$ProductFormPageStateCopyWithImpl<ProductFormPageState>(this as ProductFormPageState, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||||
|
properties
|
||||||
|
..add(DiagnosticsProperty('type', 'ProductFormPageState'))
|
||||||
|
..add(DiagnosticsProperty('product', product))..add(DiagnosticsProperty('loading', loading));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is ProductFormPageState&&(identical(other.product, product) || other.product == product)&&(identical(other.loading, loading) || other.loading == loading));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,product,loading);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) {
|
||||||
|
return 'ProductFormPageState(product: $product, loading: $loading)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $ProductFormPageStateCopyWith<$Res> {
|
||||||
|
factory $ProductFormPageStateCopyWith(ProductFormPageState value, $Res Function(ProductFormPageState) _then) = _$ProductFormPageStateCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
ProductEntity? product, bool loading
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$ProductFormPageStateCopyWithImpl<$Res>
|
||||||
|
implements $ProductFormPageStateCopyWith<$Res> {
|
||||||
|
_$ProductFormPageStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final ProductFormPageState _self;
|
||||||
|
final $Res Function(ProductFormPageState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of ProductFormPageState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? product = freezed,Object? loading = null,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
product: freezed == product ? _self.product : product // ignore: cast_nullable_to_non_nullable
|
||||||
|
as ProductEntity?,loading: null == loading ? _self.loading : loading // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _ProductFormPageState with DiagnosticableTreeMixin implements ProductFormPageState {
|
||||||
|
const _ProductFormPageState({this.product, this.loading = false});
|
||||||
|
|
||||||
|
|
||||||
|
@override final ProductEntity? product;
|
||||||
|
@override@JsonKey() final bool loading;
|
||||||
|
|
||||||
|
/// Create a copy of ProductFormPageState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$ProductFormPageStateCopyWith<_ProductFormPageState> get copyWith => __$ProductFormPageStateCopyWithImpl<_ProductFormPageState>(this, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||||
|
properties
|
||||||
|
..add(DiagnosticsProperty('type', 'ProductFormPageState'))
|
||||||
|
..add(DiagnosticsProperty('product', product))..add(DiagnosticsProperty('loading', loading));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ProductFormPageState&&(identical(other.product, product) || other.product == product)&&(identical(other.loading, loading) || other.loading == loading));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,product,loading);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) {
|
||||||
|
return 'ProductFormPageState(product: $product, loading: $loading)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$ProductFormPageStateCopyWith<$Res> implements $ProductFormPageStateCopyWith<$Res> {
|
||||||
|
factory _$ProductFormPageStateCopyWith(_ProductFormPageState value, $Res Function(_ProductFormPageState) _then) = __$ProductFormPageStateCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
ProductEntity? product, bool loading
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$ProductFormPageStateCopyWithImpl<$Res>
|
||||||
|
implements _$ProductFormPageStateCopyWith<$Res> {
|
||||||
|
__$ProductFormPageStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _ProductFormPageState _self;
|
||||||
|
final $Res Function(_ProductFormPageState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of ProductFormPageState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? product = freezed,Object? loading = null,}) {
|
||||||
|
return _then(_ProductFormPageState(
|
||||||
|
product: freezed == product ? _self.product : product // ignore: cast_nullable_to_non_nullable
|
||||||
|
as ProductEntity?,loading: null == loading ? _self.loading : loading // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
@ -60,7 +60,7 @@ class _ProductListPageState extends ConsumerState<ProductListPage> {
|
|||||||
final product = state.products[index];
|
final product = state.products[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ProductFormRoute().push(context);
|
ProductFormRoute(id: product.id).push(context);
|
||||||
},
|
},
|
||||||
leading: Container(
|
leading: Container(
|
||||||
height: 60,
|
height: 60,
|
||||||
@ -89,6 +89,17 @@ class _ProductListPageState extends ConsumerState<ProductListPage> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
trailing: IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
ref
|
||||||
|
.read(productListPageModelProvider.notifier)
|
||||||
|
.deleteProductLocal(product.id);
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.delete,
|
||||||
|
color: AppTheme.of(context).error,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -17,13 +17,18 @@ class ProductListPageModel extends StateNotifier<ProductListPageState> {
|
|||||||
/// Constructor initializes the TaskRepository using the provider reference.
|
/// Constructor initializes the TaskRepository using the provider reference.
|
||||||
ProductListPageModel() : super(const ProductListPageState());
|
ProductListPageModel() : super(const ProductListPageState());
|
||||||
|
|
||||||
|
final productStore = objectboxManager.store.box<ProductEntity>();
|
||||||
|
|
||||||
Future getProductsLocal() async {
|
Future getProductsLocal() async {
|
||||||
Box<ProductEntity> productStore = objectboxManager.store
|
|
||||||
.box<ProductEntity>();
|
|
||||||
state = state.copyWith(loading: true);
|
state = state.copyWith(loading: true);
|
||||||
final products = await productStore.getAllAsync();
|
final products = await productStore.getAllAsync();
|
||||||
state = state.copyWith(products: products, loading: false);
|
state = state.copyWith(products: products, loading: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void deleteProductLocal(int id) {
|
||||||
|
productStore.remove(id);
|
||||||
|
getProductsLocal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -150,7 +150,7 @@ class _ScannerPageState extends ConsumerState<ScannerPage>
|
|||||||
unawaited(_subscription?.cancel());
|
unawaited(_subscription?.cancel());
|
||||||
_subscription = null;
|
_subscription = null;
|
||||||
unawaited(mobileScannerController.stop());
|
unawaited(mobileScannerController.stop());
|
||||||
ProductFormRoute().push(context);
|
ProductFormRoute(id: productStruct.id).push(context);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -224,7 +224,7 @@ class _ScannerPageState extends ConsumerState<ScannerPage>
|
|||||||
unawaited(_subscription?.cancel());
|
unawaited(_subscription?.cancel());
|
||||||
_subscription = null;
|
_subscription = null;
|
||||||
unawaited(mobileScannerController.stop());
|
unawaited(mobileScannerController.stop());
|
||||||
ProductFormRoute().push(context);
|
ProductFormRoute(id: productStruct.id).push(context);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -285,7 +285,7 @@ class _ScannerPageState extends ConsumerState<ScannerPage>
|
|||||||
child: MobileScanner(
|
child: MobileScanner(
|
||||||
controller: mobileScannerController,
|
controller: mobileScannerController,
|
||||||
onDetectError: (error, stackTrace) {
|
onDetectError: (error, stackTrace) {
|
||||||
print("===========> $error");
|
debugPrint("===========> $error");
|
||||||
},
|
},
|
||||||
errorBuilder: (c, p2) {
|
errorBuilder: (c, p2) {
|
||||||
return Center(child: Icon(Icons.error));
|
return Center(child: Icon(Icons.error));
|
||||||
|
@ -56,10 +56,12 @@ class ScannerRoute extends GoRouteData with _$ScannerRoute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ProductFormRoute extends GoRouteData with _$ProductFormRoute {
|
class ProductFormRoute extends GoRouteData with _$ProductFormRoute {
|
||||||
const ProductFormRoute();
|
const ProductFormRoute({required this.id});
|
||||||
|
final int id;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, GoRouterState state) => ProductFormPage();
|
Widget build(BuildContext context, GoRouterState state) =>
|
||||||
|
ProductFormPage(id: id);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProductListRoute extends GoRouteData with _$ProductListRoute {
|
class ProductListRoute extends GoRouteData with _$ProductListRoute {
|
||||||
|
@ -90,10 +90,15 @@ mixin _$ScannerRoute on GoRouteData {
|
|||||||
|
|
||||||
mixin _$ProductFormRoute on GoRouteData {
|
mixin _$ProductFormRoute on GoRouteData {
|
||||||
static ProductFormRoute _fromState(GoRouterState state) =>
|
static ProductFormRoute _fromState(GoRouterState state) =>
|
||||||
const ProductFormRoute();
|
ProductFormRoute(id: int.parse(state.uri.queryParameters['id']!)!);
|
||||||
|
|
||||||
|
ProductFormRoute get _self => this as ProductFormRoute;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get location => GoRouteData.$location('/SecurePage/ProductFormPage');
|
String get location => GoRouteData.$location(
|
||||||
|
'/SecurePage/ProductFormPage',
|
||||||
|
queryParams: {'id': _self.id.toString()},
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void go(BuildContext context) => context.go(location);
|
void go(BuildContext context) => context.go(location);
|
||||||
|
@ -290,10 +290,10 @@ packages:
|
|||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: flutter_lints
|
name: flutter_lints
|
||||||
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
|
sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.0.0"
|
version: "6.0.0"
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -529,10 +529,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: lints
|
name: lints
|
||||||
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
|
sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.1.1"
|
version: "6.0.0"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -67,7 +67,7 @@ dev_dependencies:
|
|||||||
# activated in the `analysis_options.yaml` file located at the root of your
|
# activated in the `analysis_options.yaml` file located at the root of your
|
||||||
# package. See that file for information about deactivating specific lint
|
# package. See that file for information about deactivating specific lint
|
||||||
# rules and activating additional ones.
|
# rules and activating additional ones.
|
||||||
flutter_lints: ^5.0.0
|
flutter_lints: ^6.0.0
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
Loading…
x
Reference in New Issue
Block a user