feat: Adds home page navigation drawer
Introduces a side navigation drawer on the home page to improve navigation and centralize user actions. Displays the logged-in user's information (name, email) in the drawer header. Adds a link to the Product List page ("Inventaire") within the drawer. Moves the logout functionality to the drawer, ensuring user data is also cleared from local storage upon logout. Ensures user data is saved to local storage during the login process and fetched when the home page loads. Includes minor text updates on the Product Form page.
This commit is contained in:
parent
6f2f94b2da
commit
28a8027e20
17
lib/backend/schema/auth/auth_struct.dart
Normal file
17
lib/backend/schema/auth/auth_struct.dart
Normal file
@ -0,0 +1,17 @@
|
||||
import 'package:barcode_scanner/backend/schema/user/user_struct.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'auth_struct.freezed.dart';
|
||||
part 'auth_struct.g.dart';
|
||||
|
||||
@Freezed(toJson: false)
|
||||
abstract class AuthStruct with _$AuthStruct {
|
||||
factory AuthStruct({
|
||||
String? accessToken,
|
||||
String? refreshToken,
|
||||
UserStruct? user,
|
||||
}) = _AuthStruct;
|
||||
|
||||
factory AuthStruct.fromJson(Map<String, dynamic> json) =>
|
||||
_$AuthStructFromJson(json);
|
||||
}
|
173
lib/backend/schema/auth/auth_struct.freezed.dart
Normal file
173
lib/backend/schema/auth/auth_struct.freezed.dart
Normal file
@ -0,0 +1,173 @@
|
||||
// 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 'auth_struct.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$AuthStruct {
|
||||
|
||||
String? get accessToken; String? get refreshToken; UserStruct? get user;
|
||||
/// Create a copy of AuthStruct
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$AuthStructCopyWith<AuthStruct> get copyWith => _$AuthStructCopyWithImpl<AuthStruct>(this as AuthStruct, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AuthStruct&&(identical(other.accessToken, accessToken) || other.accessToken == accessToken)&&(identical(other.refreshToken, refreshToken) || other.refreshToken == refreshToken)&&(identical(other.user, user) || other.user == user));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,accessToken,refreshToken,user);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AuthStruct(accessToken: $accessToken, refreshToken: $refreshToken, user: $user)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $AuthStructCopyWith<$Res> {
|
||||
factory $AuthStructCopyWith(AuthStruct value, $Res Function(AuthStruct) _then) = _$AuthStructCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String? accessToken, String? refreshToken, UserStruct? user
|
||||
});
|
||||
|
||||
|
||||
$UserStructCopyWith<$Res>? get user;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$AuthStructCopyWithImpl<$Res>
|
||||
implements $AuthStructCopyWith<$Res> {
|
||||
_$AuthStructCopyWithImpl(this._self, this._then);
|
||||
|
||||
final AuthStruct _self;
|
||||
final $Res Function(AuthStruct) _then;
|
||||
|
||||
/// Create a copy of AuthStruct
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? accessToken = freezed,Object? refreshToken = freezed,Object? user = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
accessToken: freezed == accessToken ? _self.accessToken : accessToken // ignore: cast_nullable_to_non_nullable
|
||||
as String?,refreshToken: freezed == refreshToken ? _self.refreshToken : refreshToken // ignore: cast_nullable_to_non_nullable
|
||||
as String?,user: freezed == user ? _self.user : user // ignore: cast_nullable_to_non_nullable
|
||||
as UserStruct?,
|
||||
));
|
||||
}
|
||||
/// Create a copy of AuthStruct
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$UserStructCopyWith<$Res>? get user {
|
||||
if (_self.user == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $UserStructCopyWith<$Res>(_self.user!, (value) {
|
||||
return _then(_self.copyWith(user: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable(createToJson: false)
|
||||
|
||||
class _AuthStruct implements AuthStruct {
|
||||
_AuthStruct({this.accessToken, this.refreshToken, this.user});
|
||||
factory _AuthStruct.fromJson(Map<String, dynamic> json) => _$AuthStructFromJson(json);
|
||||
|
||||
@override final String? accessToken;
|
||||
@override final String? refreshToken;
|
||||
@override final UserStruct? user;
|
||||
|
||||
/// Create a copy of AuthStruct
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$AuthStructCopyWith<_AuthStruct> get copyWith => __$AuthStructCopyWithImpl<_AuthStruct>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AuthStruct&&(identical(other.accessToken, accessToken) || other.accessToken == accessToken)&&(identical(other.refreshToken, refreshToken) || other.refreshToken == refreshToken)&&(identical(other.user, user) || other.user == user));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,accessToken,refreshToken,user);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AuthStruct(accessToken: $accessToken, refreshToken: $refreshToken, user: $user)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$AuthStructCopyWith<$Res> implements $AuthStructCopyWith<$Res> {
|
||||
factory _$AuthStructCopyWith(_AuthStruct value, $Res Function(_AuthStruct) _then) = __$AuthStructCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String? accessToken, String? refreshToken, UserStruct? user
|
||||
});
|
||||
|
||||
|
||||
@override $UserStructCopyWith<$Res>? get user;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$AuthStructCopyWithImpl<$Res>
|
||||
implements _$AuthStructCopyWith<$Res> {
|
||||
__$AuthStructCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _AuthStruct _self;
|
||||
final $Res Function(_AuthStruct) _then;
|
||||
|
||||
/// Create a copy of AuthStruct
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? accessToken = freezed,Object? refreshToken = freezed,Object? user = freezed,}) {
|
||||
return _then(_AuthStruct(
|
||||
accessToken: freezed == accessToken ? _self.accessToken : accessToken // ignore: cast_nullable_to_non_nullable
|
||||
as String?,refreshToken: freezed == refreshToken ? _self.refreshToken : refreshToken // ignore: cast_nullable_to_non_nullable
|
||||
as String?,user: freezed == user ? _self.user : user // ignore: cast_nullable_to_non_nullable
|
||||
as UserStruct?,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of AuthStruct
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$UserStructCopyWith<$Res>? get user {
|
||||
if (_self.user == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $UserStructCopyWith<$Res>(_self.user!, (value) {
|
||||
return _then(_self.copyWith(user: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// dart format on
|
15
lib/backend/schema/auth/auth_struct.g.dart
Normal file
15
lib/backend/schema/auth/auth_struct.g.dart
Normal file
@ -0,0 +1,15 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'auth_struct.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_AuthStruct _$AuthStructFromJson(Map<String, dynamic> json) => _AuthStruct(
|
||||
accessToken: json['accessToken'] as String?,
|
||||
refreshToken: json['refreshToken'] as String?,
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: UserStruct.fromJson(json['user'] as Map<String, dynamic>),
|
||||
);
|
19
lib/backend/schema/product/product_struct.dart
Normal file
19
lib/backend/schema/product/product_struct.dart
Normal file
@ -0,0 +1,19 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'product_struct.freezed.dart';
|
||||
part 'product_struct.g.dart';
|
||||
|
||||
@Freezed(toJson: true)
|
||||
abstract class ProductStruct with _$ProductStruct {
|
||||
factory ProductStruct({
|
||||
String? id,
|
||||
String? code,
|
||||
String? name,
|
||||
String? description,
|
||||
String? price,
|
||||
String? quantity,
|
||||
}) = _ProductStruct;
|
||||
|
||||
factory ProductStruct.fromJson(Map<String, dynamic> json) =>
|
||||
_$ProductStructFromJson(json);
|
||||
}
|
163
lib/backend/schema/product/product_struct.freezed.dart
Normal file
163
lib/backend/schema/product/product_struct.freezed.dart
Normal file
@ -0,0 +1,163 @@
|
||||
// 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_struct.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ProductStruct {
|
||||
|
||||
String? get id; String? get code; String? get name; String? get description; String? get price; String? get quantity;
|
||||
/// Create a copy of ProductStruct
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$ProductStructCopyWith<ProductStruct> get copyWith => _$ProductStructCopyWithImpl<ProductStruct>(this as ProductStruct, _$identity);
|
||||
|
||||
/// Serializes this ProductStruct to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is ProductStruct&&(identical(other.id, id) || other.id == id)&&(identical(other.code, code) || other.code == code)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.price, price) || other.price == price)&&(identical(other.quantity, quantity) || other.quantity == quantity));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,code,name,description,price,quantity);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ProductStruct(id: $id, code: $code, name: $name, description: $description, price: $price, quantity: $quantity)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $ProductStructCopyWith<$Res> {
|
||||
factory $ProductStructCopyWith(ProductStruct value, $Res Function(ProductStruct) _then) = _$ProductStructCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String? id, String? code, String? name, String? description, String? price, String? quantity
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$ProductStructCopyWithImpl<$Res>
|
||||
implements $ProductStructCopyWith<$Res> {
|
||||
_$ProductStructCopyWithImpl(this._self, this._then);
|
||||
|
||||
final ProductStruct _self;
|
||||
final $Res Function(ProductStruct) _then;
|
||||
|
||||
/// Create a copy of ProductStruct
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = freezed,Object? code = freezed,Object? name = freezed,Object? description = freezed,Object? price = freezed,Object? quantity = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: freezed == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String?,code: freezed == code ? _self.code : code // ignore: cast_nullable_to_non_nullable
|
||||
as String?,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,price: freezed == price ? _self.price : price // ignore: cast_nullable_to_non_nullable
|
||||
as String?,quantity: freezed == quantity ? _self.quantity : quantity // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _ProductStruct implements ProductStruct {
|
||||
_ProductStruct({this.id, this.code, this.name, this.description, this.price, this.quantity});
|
||||
factory _ProductStruct.fromJson(Map<String, dynamic> json) => _$ProductStructFromJson(json);
|
||||
|
||||
@override final String? id;
|
||||
@override final String? code;
|
||||
@override final String? name;
|
||||
@override final String? description;
|
||||
@override final String? price;
|
||||
@override final String? quantity;
|
||||
|
||||
/// Create a copy of ProductStruct
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$ProductStructCopyWith<_ProductStruct> get copyWith => __$ProductStructCopyWithImpl<_ProductStruct>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$ProductStructToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ProductStruct&&(identical(other.id, id) || other.id == id)&&(identical(other.code, code) || other.code == code)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.price, price) || other.price == price)&&(identical(other.quantity, quantity) || other.quantity == quantity));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,code,name,description,price,quantity);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ProductStruct(id: $id, code: $code, name: $name, description: $description, price: $price, quantity: $quantity)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$ProductStructCopyWith<$Res> implements $ProductStructCopyWith<$Res> {
|
||||
factory _$ProductStructCopyWith(_ProductStruct value, $Res Function(_ProductStruct) _then) = __$ProductStructCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String? id, String? code, String? name, String? description, String? price, String? quantity
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$ProductStructCopyWithImpl<$Res>
|
||||
implements _$ProductStructCopyWith<$Res> {
|
||||
__$ProductStructCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _ProductStruct _self;
|
||||
final $Res Function(_ProductStruct) _then;
|
||||
|
||||
/// Create a copy of ProductStruct
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = freezed,Object? code = freezed,Object? name = freezed,Object? description = freezed,Object? price = freezed,Object? quantity = freezed,}) {
|
||||
return _then(_ProductStruct(
|
||||
id: freezed == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String?,code: freezed == code ? _self.code : code // ignore: cast_nullable_to_non_nullable
|
||||
as String?,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,price: freezed == price ? _self.price : price // ignore: cast_nullable_to_non_nullable
|
||||
as String?,quantity: freezed == quantity ? _self.quantity : quantity // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
27
lib/backend/schema/product/product_struct.g.dart
Normal file
27
lib/backend/schema/product/product_struct.g.dart
Normal file
@ -0,0 +1,27 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'product_struct.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_ProductStruct _$ProductStructFromJson(Map<String, dynamic> json) =>
|
||||
_ProductStruct(
|
||||
id: json['id'] as String?,
|
||||
code: json['code'] as String?,
|
||||
name: json['name'] as String?,
|
||||
description: json['description'] as String?,
|
||||
price: json['price'] as String?,
|
||||
quantity: json['quantity'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ProductStructToJson(_ProductStruct instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'code': instance.code,
|
||||
'name': instance.name,
|
||||
'description': instance.description,
|
||||
'price': instance.price,
|
||||
'quantity': instance.quantity,
|
||||
};
|
53
lib/backend/schema/user/user_struct.dart
Normal file
53
lib/backend/schema/user/user_struct.dart
Normal file
@ -0,0 +1,53 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:barcode_scanner/provider_container.dart';
|
||||
import 'package:barcode_scanner/services/secure_storage.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'user_struct.freezed.dart';
|
||||
part 'user_struct.g.dart';
|
||||
|
||||
@Freezed(toJson: true)
|
||||
abstract class UserStruct with _$UserStruct {
|
||||
factory UserStruct({
|
||||
String? id,
|
||||
String? firstName,
|
||||
String? lastName,
|
||||
String? email,
|
||||
String? phone,
|
||||
}) = _UserStruct;
|
||||
|
||||
factory UserStruct.fromJson(Map<String, dynamic> json) =>
|
||||
_$UserStructFromJson(json);
|
||||
}
|
||||
|
||||
extension UserStructExt on UserStruct {
|
||||
String get key => 'user';
|
||||
|
||||
String get fullName {
|
||||
final sb = StringBuffer();
|
||||
sb.write(firstName);
|
||||
if (firstName != null) {
|
||||
sb.write(' ');
|
||||
}
|
||||
sb.write(lastName);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
Future setToLocalStorage() {
|
||||
final storage = providerContainer.read(sharedPrefsProvider);
|
||||
return storage.write(key: id ?? key, value: jsonEncode(toJson()));
|
||||
}
|
||||
|
||||
Future<UserStruct?> getFromLocalStorage() async {
|
||||
final storage = providerContainer.read(sharedPrefsProvider);
|
||||
final jsonString = await storage.read(key: id ?? key);
|
||||
if (jsonString == null) return null;
|
||||
return UserStruct.fromJson(jsonDecode(jsonString));
|
||||
}
|
||||
|
||||
Future<void> deleteLocalStorage() {
|
||||
final storage = providerContainer.read(sharedPrefsProvider);
|
||||
return storage.delete(key: id ?? key);
|
||||
}
|
||||
}
|
160
lib/backend/schema/user/user_struct.freezed.dart
Normal file
160
lib/backend/schema/user/user_struct.freezed.dart
Normal file
@ -0,0 +1,160 @@
|
||||
// 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 'user_struct.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$UserStruct {
|
||||
|
||||
String? get id; String? get firstName; String? get lastName; String? get email; String? get phone;
|
||||
/// Create a copy of UserStruct
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$UserStructCopyWith<UserStruct> get copyWith => _$UserStructCopyWithImpl<UserStruct>(this as UserStruct, _$identity);
|
||||
|
||||
/// Serializes this UserStruct to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is UserStruct&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.email, email) || other.email == email)&&(identical(other.phone, phone) || other.phone == phone));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,firstName,lastName,email,phone);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'UserStruct(id: $id, firstName: $firstName, lastName: $lastName, email: $email, phone: $phone)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $UserStructCopyWith<$Res> {
|
||||
factory $UserStructCopyWith(UserStruct value, $Res Function(UserStruct) _then) = _$UserStructCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String? id, String? firstName, String? lastName, String? email, String? phone
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$UserStructCopyWithImpl<$Res>
|
||||
implements $UserStructCopyWith<$Res> {
|
||||
_$UserStructCopyWithImpl(this._self, this._then);
|
||||
|
||||
final UserStruct _self;
|
||||
final $Res Function(UserStruct) _then;
|
||||
|
||||
/// Create a copy of UserStruct
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = freezed,Object? firstName = freezed,Object? lastName = freezed,Object? email = freezed,Object? phone = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: freezed == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String?,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,email: freezed == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||
as String?,phone: freezed == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _UserStruct implements UserStruct {
|
||||
_UserStruct({this.id, this.firstName, this.lastName, this.email, this.phone});
|
||||
factory _UserStruct.fromJson(Map<String, dynamic> json) => _$UserStructFromJson(json);
|
||||
|
||||
@override final String? id;
|
||||
@override final String? firstName;
|
||||
@override final String? lastName;
|
||||
@override final String? email;
|
||||
@override final String? phone;
|
||||
|
||||
/// Create a copy of UserStruct
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$UserStructCopyWith<_UserStruct> get copyWith => __$UserStructCopyWithImpl<_UserStruct>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$UserStructToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _UserStruct&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.email, email) || other.email == email)&&(identical(other.phone, phone) || other.phone == phone));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,firstName,lastName,email,phone);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'UserStruct(id: $id, firstName: $firstName, lastName: $lastName, email: $email, phone: $phone)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$UserStructCopyWith<$Res> implements $UserStructCopyWith<$Res> {
|
||||
factory _$UserStructCopyWith(_UserStruct value, $Res Function(_UserStruct) _then) = __$UserStructCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String? id, String? firstName, String? lastName, String? email, String? phone
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$UserStructCopyWithImpl<$Res>
|
||||
implements _$UserStructCopyWith<$Res> {
|
||||
__$UserStructCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _UserStruct _self;
|
||||
final $Res Function(_UserStruct) _then;
|
||||
|
||||
/// Create a copy of UserStruct
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = freezed,Object? firstName = freezed,Object? lastName = freezed,Object? email = freezed,Object? phone = freezed,}) {
|
||||
return _then(_UserStruct(
|
||||
id: freezed == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String?,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,email: freezed == email ? _self.email : email // ignore: cast_nullable_to_non_nullable
|
||||
as String?,phone: freezed == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
24
lib/backend/schema/user/user_struct.g.dart
Normal file
24
lib/backend/schema/user/user_struct.g.dart
Normal file
@ -0,0 +1,24 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'user_struct.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_UserStruct _$UserStructFromJson(Map<String, dynamic> json) => _UserStruct(
|
||||
id: json['id'] as String?,
|
||||
firstName: json['firstName'] as String?,
|
||||
lastName: json['lastName'] as String?,
|
||||
email: json['email'] as String?,
|
||||
phone: json['phone'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$UserStructToJson(_UserStruct instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'firstName': instance.firstName,
|
||||
'lastName': instance.lastName,
|
||||
'email': instance.email,
|
||||
'phone': instance.phone,
|
||||
};
|
@ -1,8 +1,11 @@
|
||||
import 'package:barcode_scanner/backend/schema/user/user_struct.dart';
|
||||
import 'package:barcode_scanner/pages/home_page/home_page_model.dart';
|
||||
import 'package:barcode_scanner/pages/login_page/login_page_model.dart';
|
||||
import 'package:barcode_scanner/router/go_router_builder.dart';
|
||||
import 'package:barcode_scanner/router/go_secure_router_builder.dart';
|
||||
import 'package:barcode_scanner/themes/app_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class HomePage extends ConsumerStatefulWidget {
|
||||
@ -13,23 +16,91 @@ class HomePage extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class _HomePageState extends ConsumerState<HomePage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||
ref.read(homePageModelProvider.notifier).getUserConnected();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
drawer: Drawer(
|
||||
backgroundColor: AppTheme.of(context).primaryBackground,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 50),
|
||||
Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final state = ref.watch(homePageModelProvider);
|
||||
return ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: AppTheme.of(context).secondaryBackground,
|
||||
borderRadius: BorderRadius.circular(60),
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
state.user?.fullName ?? '',
|
||||
style: AppTheme.of(context).titleMedium,
|
||||
),
|
||||
subtitle: Text(
|
||||
state.user?.email ?? '',
|
||||
style: AppTheme.of(context).bodyMedium,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
Divider(),
|
||||
ListTile(
|
||||
leading: Icon(Icons.person),
|
||||
title: Text('Profil', style: AppTheme.of(context).bodyLarge),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
ProductListRoute().push(context);
|
||||
},
|
||||
leading: Icon(Icons.inventory),
|
||||
title: Text(
|
||||
'Inventaire',
|
||||
style: AppTheme.of(context).bodyLarge,
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
SafeArea(
|
||||
child: ListTile(
|
||||
onTap: () async {
|
||||
await ref.read(loginPageModelProvider.notifier).logOut();
|
||||
await UserStruct(id: '1').deleteLocalStorage();
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
SplashRoute().go(context);
|
||||
});
|
||||
},
|
||||
leading: Icon(Icons.logout),
|
||||
title: Text(
|
||||
'Se deconnecter',
|
||||
style: AppTheme.of(context).bodyLarge,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
backgroundColor: AppTheme.of(context).primaryBackground,
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
await ref.read(loginPageModelProvider.notifier).logOut();
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
SplashRoute().go(context);
|
||||
});
|
||||
},
|
||||
icon: Icon(Icons.login),
|
||||
),
|
||||
],
|
||||
title: Text('Barcode Scanner', style: AppTheme.of(context).titleLarge),
|
||||
centerTitle: true,
|
||||
backgroundColor: AppTheme.of(context).primaryBackground,
|
||||
actions: [],
|
||||
),
|
||||
body: Center(
|
||||
child: SingleChildScrollView(
|
||||
|
42
lib/pages/home_page/home_page_model.dart
Normal file
42
lib/pages/home_page/home_page_model.dart
Normal file
@ -0,0 +1,42 @@
|
||||
import 'package:barcode_scanner/backend/schema/user/user_struct.dart';
|
||||
import 'package:barcode_scanner/services/secure_storage.dart';
|
||||
import 'package:barcode_scanner/services/token_provider.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'home_page_model.freezed.dart';
|
||||
|
||||
/// The provider for the AuthViewModel, using Riverpod's StateNotifierProvider
|
||||
/// with autoDispose to manage the lifecycle of the view model.
|
||||
final homePageModelProvider =
|
||||
StateNotifierProvider<HomePageModel, HomePageState>((ref) {
|
||||
return HomePageModel(
|
||||
secureStorage: ref.read(sharedPrefsProvider),
|
||||
tokenProvider: ref.read(tokenProvider),
|
||||
);
|
||||
});
|
||||
|
||||
class HomePageModel extends StateNotifier<HomePageState> {
|
||||
/// Constructor initializes the TaskRepository using the provider reference.
|
||||
HomePageModel({required this.secureStorage, required this.tokenProvider})
|
||||
: super(const HomePageState());
|
||||
|
||||
late FlutterSecureStorage secureStorage;
|
||||
late TokenProvider tokenProvider;
|
||||
|
||||
Future getUserConnected() async {
|
||||
state = state.copyWith(loading: true);
|
||||
final user = await UserStruct(id: '1').getFromLocalStorage();
|
||||
state = state.copyWith(user: user);
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class HomePageState with _$HomePageState {
|
||||
const factory HomePageState({
|
||||
UserStruct? user,
|
||||
@Default(false) bool loading,
|
||||
}) = _HomePageState;
|
||||
}
|
181
lib/pages/home_page/home_page_model.freezed.dart
Normal file
181
lib/pages/home_page/home_page_model.freezed.dart
Normal file
@ -0,0 +1,181 @@
|
||||
// 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 'home_page_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$HomePageState implements DiagnosticableTreeMixin {
|
||||
|
||||
UserStruct? get user; bool get loading;
|
||||
/// Create a copy of HomePageState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$HomePageStateCopyWith<HomePageState> get copyWith => _$HomePageStateCopyWithImpl<HomePageState>(this as HomePageState, _$identity);
|
||||
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
properties
|
||||
..add(DiagnosticsProperty('type', 'HomePageState'))
|
||||
..add(DiagnosticsProperty('user', user))..add(DiagnosticsProperty('loading', loading));
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is HomePageState&&(identical(other.user, user) || other.user == user)&&(identical(other.loading, loading) || other.loading == loading));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,user,loading);
|
||||
|
||||
@override
|
||||
String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) {
|
||||
return 'HomePageState(user: $user, loading: $loading)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $HomePageStateCopyWith<$Res> {
|
||||
factory $HomePageStateCopyWith(HomePageState value, $Res Function(HomePageState) _then) = _$HomePageStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
UserStruct? user, bool loading
|
||||
});
|
||||
|
||||
|
||||
$UserStructCopyWith<$Res>? get user;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$HomePageStateCopyWithImpl<$Res>
|
||||
implements $HomePageStateCopyWith<$Res> {
|
||||
_$HomePageStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final HomePageState _self;
|
||||
final $Res Function(HomePageState) _then;
|
||||
|
||||
/// Create a copy of HomePageState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? user = freezed,Object? loading = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
user: freezed == user ? _self.user : user // ignore: cast_nullable_to_non_nullable
|
||||
as UserStruct?,loading: null == loading ? _self.loading : loading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
/// Create a copy of HomePageState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$UserStructCopyWith<$Res>? get user {
|
||||
if (_self.user == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $UserStructCopyWith<$Res>(_self.user!, (value) {
|
||||
return _then(_self.copyWith(user: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _HomePageState with DiagnosticableTreeMixin implements HomePageState {
|
||||
const _HomePageState({this.user, this.loading = false});
|
||||
|
||||
|
||||
@override final UserStruct? user;
|
||||
@override@JsonKey() final bool loading;
|
||||
|
||||
/// Create a copy of HomePageState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$HomePageStateCopyWith<_HomePageState> get copyWith => __$HomePageStateCopyWithImpl<_HomePageState>(this, _$identity);
|
||||
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
properties
|
||||
..add(DiagnosticsProperty('type', 'HomePageState'))
|
||||
..add(DiagnosticsProperty('user', user))..add(DiagnosticsProperty('loading', loading));
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _HomePageState&&(identical(other.user, user) || other.user == user)&&(identical(other.loading, loading) || other.loading == loading));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,user,loading);
|
||||
|
||||
@override
|
||||
String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) {
|
||||
return 'HomePageState(user: $user, loading: $loading)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$HomePageStateCopyWith<$Res> implements $HomePageStateCopyWith<$Res> {
|
||||
factory _$HomePageStateCopyWith(_HomePageState value, $Res Function(_HomePageState) _then) = __$HomePageStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
UserStruct? user, bool loading
|
||||
});
|
||||
|
||||
|
||||
@override $UserStructCopyWith<$Res>? get user;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$HomePageStateCopyWithImpl<$Res>
|
||||
implements _$HomePageStateCopyWith<$Res> {
|
||||
__$HomePageStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _HomePageState _self;
|
||||
final $Res Function(_HomePageState) _then;
|
||||
|
||||
/// Create a copy of HomePageState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? user = freezed,Object? loading = null,}) {
|
||||
return _then(_HomePageState(
|
||||
user: freezed == user ? _self.user : user // ignore: cast_nullable_to_non_nullable
|
||||
as UserStruct?,loading: null == loading ? _self.loading : loading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of HomePageState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$UserStructCopyWith<$Res>? get user {
|
||||
if (_self.user == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $UserStructCopyWith<$Res>(_self.user!, (value) {
|
||||
return _then(_self.copyWith(user: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// dart format on
|
@ -1,3 +1,4 @@
|
||||
import 'package:barcode_scanner/backend/schema/user/user_struct.dart';
|
||||
import 'package:barcode_scanner/services/secure_storage.dart';
|
||||
import 'package:barcode_scanner/services/token_provider.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@ -57,7 +58,15 @@ class LoginPageModel extends StateNotifier<LoginPageState> {
|
||||
state = state.copyWith(loading: true);
|
||||
await Future.delayed(Duration(seconds: 5));
|
||||
if (email == "user@yopmail.com" && password == "password") {
|
||||
setTokenInLocal('token');
|
||||
setTokenInLocal(
|
||||
'token',
|
||||
UserStruct(
|
||||
id: '1',
|
||||
firstName: 'User',
|
||||
lastName: 'Anonymous',
|
||||
email: 'user@yopmail.com',
|
||||
),
|
||||
);
|
||||
state = state.copyWith(
|
||||
loading: false,
|
||||
status: LoginPageStateStatus.logOut,
|
||||
@ -79,12 +88,12 @@ class LoginPageModel extends StateNotifier<LoginPageState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setTokenInLocal(String token) async {
|
||||
Future<void> setTokenInLocal(String token, UserStruct user) async {
|
||||
await Future.wait([
|
||||
tokenProvider.setToken(token),
|
||||
tokenProvider.setRefreshToken(token),
|
||||
user.setToLocalStorage(),
|
||||
]);
|
||||
|
||||
state = state.copyWith(loading: false, status: LoginPageStateStatus.logged);
|
||||
debugPrint("$token");
|
||||
}
|
||||
|
@ -3,3 +3,4 @@ export 'login_page/login_page.dart';
|
||||
export 'product_form_page/product_form_page.dart';
|
||||
export 'scanner_page/scanner_page.dart';
|
||||
export 'splash_page/splash_page.dart';
|
||||
export 'product_list_page/product_list_page.dart';
|
||||
|
@ -53,10 +53,7 @@ class _ProductFormPageState extends State<ProductFormPage> {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
title: Text(
|
||||
'Formulaire Produit',
|
||||
style: AppTheme.of(context).titleLarge,
|
||||
),
|
||||
title: Text('Fiche Produit', style: AppTheme.of(context).titleLarge),
|
||||
centerTitle: true,
|
||||
backgroundColor: AppTheme.of(context).primaryBackground,
|
||||
elevation: 0,
|
||||
@ -88,7 +85,7 @@ class _ProductFormPageState extends State<ProductFormPage> {
|
||||
/// Description
|
||||
TextFormField(
|
||||
controller: description,
|
||||
decoration: _inputStyle("Description"),
|
||||
decoration: _inputStyle("Commentaires"),
|
||||
maxLines: 3,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
@ -96,7 +93,7 @@ class _ProductFormPageState extends State<ProductFormPage> {
|
||||
/// Prix
|
||||
TextFormField(
|
||||
controller: price,
|
||||
decoration: _inputStyle("Prix"),
|
||||
decoration: _inputStyle("Quantités"),
|
||||
keyboardType: TextInputType.number,
|
||||
validator: (value) =>
|
||||
(value == null || value.isEmpty) ? 'Champ requis' : null,
|
||||
|
38
lib/pages/product_list_page/product_list_page.dart
Normal file
38
lib/pages/product_list_page/product_list_page.dart
Normal file
@ -0,0 +1,38 @@
|
||||
import 'package:barcode_scanner/themes/app_theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class ProductListPage extends ConsumerStatefulWidget {
|
||||
const ProductListPage({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<ConsumerStatefulWidget> createState() =>
|
||||
_ProductListPageState();
|
||||
}
|
||||
|
||||
class _ProductListPageState extends ConsumerState<ProductListPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppTheme.of(context).primaryBackground,
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
icon: Icon(
|
||||
Icons.arrow_back_ios,
|
||||
color: AppTheme.of(context).primaryText,
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
title: Text(
|
||||
'Inventaire des produits',
|
||||
style: AppTheme.of(context).titleLarge,
|
||||
),
|
||||
centerTitle: true,
|
||||
backgroundColor: AppTheme.of(context).primaryBackground,
|
||||
elevation: 0,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ const String _securePage = 'SecurePage';
|
||||
const String _homePage = 'HomePage';
|
||||
const String _scannerPage = 'ScannerPage';
|
||||
const String _productFormPage = 'ProductFormPage';
|
||||
const String _productListPage = 'ProductListPage';
|
||||
|
||||
// Groupe des routes sécurisées
|
||||
@TypedGoRoute<SecureRoute>(
|
||||
@ -20,6 +21,7 @@ const String _productFormPage = 'ProductFormPage';
|
||||
TypedGoRoute<HomeRoute>(path: _homePage),
|
||||
TypedGoRoute<ScannerRoute>(path: _scannerPage),
|
||||
TypedGoRoute<ProductFormRoute>(path: _productFormPage),
|
||||
TypedGoRoute<ProductListRoute>(path: _productListPage),
|
||||
],
|
||||
)
|
||||
class SecureRoute extends GoRouteData with _$SecureRoute {
|
||||
@ -59,3 +61,10 @@ class ProductFormRoute extends GoRouteData with _$ProductFormRoute {
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) => ProductFormPage();
|
||||
}
|
||||
|
||||
class ProductListRoute extends GoRouteData with _$ProductListRoute {
|
||||
const ProductListRoute();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, GoRouterState state) => ProductListPage();
|
||||
}
|
||||
|
@ -20,6 +20,11 @@ RouteBase get $secureRoute => GoRouteData.$route(
|
||||
|
||||
factory: _$ProductFormRoute._fromState,
|
||||
),
|
||||
GoRouteData.$route(
|
||||
path: 'ProductListPage',
|
||||
|
||||
factory: _$ProductListRoute._fromState,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@ -103,3 +108,24 @@ mixin _$ProductFormRoute on GoRouteData {
|
||||
@override
|
||||
void replace(BuildContext context) => context.replace(location);
|
||||
}
|
||||
|
||||
mixin _$ProductListRoute on GoRouteData {
|
||||
static ProductListRoute _fromState(GoRouterState state) =>
|
||||
const ProductListRoute();
|
||||
|
||||
@override
|
||||
String get location => GoRouteData.$location('/SecurePage/ProductListPage');
|
||||
|
||||
@override
|
||||
void go(BuildContext context) => context.go(location);
|
||||
|
||||
@override
|
||||
Future<T?> push<T>(BuildContext context) => context.push<T>(location);
|
||||
|
||||
@override
|
||||
void pushReplacement(BuildContext context) =>
|
||||
context.pushReplacement(location);
|
||||
|
||||
@override
|
||||
void replace(BuildContext context) => context.replace(location);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user