refactor: Refactor product scanned component and scanner page

Refactor `ProductScannedComponent`:
- Removes redundant full-screen container.
- Adjusts padding and image size.
- Updates button styles to `FilledButton`.

Improve `ScannerPage`:
- Correctly updates loading state after product API calls.
- Simplifies fake barcode simulation for testing with a hardcoded value.
This commit is contained in:
mandreshope 2025-06-20 16:17:05 +03:00
parent b705142d48
commit aaeae104c5
2 changed files with 192 additions and 210 deletions

View File

@ -25,164 +25,146 @@ class ProductScannedComponent extends StatefulWidget {
class _ProductScannedComponentState extends State<ProductScannedComponent> {
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(color: Color(0x80000000)),
child: Padding(
padding: EdgeInsets.all(24.0),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.all(24.0),
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.0),
),
child: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
spacing: 16,
children: [
Container(
width: 80.0,
height: 80.0,
decoration: BoxDecoration(
color: Colors.green,
shape: BoxShape.circle,
),
child: Align(
alignment: AlignmentDirectional(0.0, 0.0),
child: Icon(
Icons.check_rounded,
color: Colors.white,
size: 40.0,
),
),
return Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.all(24.0),
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.0),
),
child: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
spacing: 16,
children: [
Container(
width: 80.0,
height: 80.0,
decoration: BoxDecoration(
color: Colors.green,
shape: BoxShape.circle,
),
child: Align(
alignment: AlignmentDirectional(0.0, 0.0),
child: Icon(
Icons.check_rounded,
color: Colors.white,
size: 40.0,
),
Text('Scan terminé!', textAlign: TextAlign.center),
Padding(
padding: EdgeInsets.all(16.0),
child: Container(
width: double.infinity,
child: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
),
),
Text('Scan terminé!', textAlign: TextAlign.center),
Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: SizedBox(
width: double.infinity,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8,
children: [
Align(
alignment: Alignment.topCenter,
child: Image.network(
widget.img,
height: MediaQuery.sizeOf(context).height * .2,
),
),
SizedBox(height: 15),
Divider(
height: 1.0,
thickness: 1.0,
color: Colors.grey.shade300,
),
Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Align(
alignment: Alignment.topCenter,
child: Image.network(
widget.img,
width: 60,
height: 60,
),
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('Type de code:'),
Text('EAN-13'),
],
),
Divider(
height: 1.0,
thickness: 1.0,
color: Colors.grey.shade300,
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('Code scanné:'),
Text(widget.codeScanned),
],
),
Divider(
height: 1.0,
thickness: 1.0,
color: Colors.grey.shade300,
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('Produit:'),
Expanded(child: Text(widget.productName)),
],
),
Divider(
height: 1.0,
thickness: 1.0,
color: Colors.grey.shade300,
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text('Marque:'),
Text(widget.brands),
],
),
Divider(
height: 1.0,
thickness: 1.0,
color: Colors.grey.shade300,
),
// Row(
// mainAxisSize: MainAxisSize.max,
// mainAxisAlignment:
// MainAxisAlignment.spaceBetween,
// children: [Text('Prix:'), Text('4,99 €')],
// ),
Text('Code scanné:'),
Text(widget.codeScanned),
],
),
),
Divider(
height: 1.0,
thickness: 1.0,
color: Colors.grey.shade300,
),
Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Produit: '),
Expanded(
child: Text(
widget.productName,
textAlign: TextAlign.end,
),
),
],
),
Divider(
height: 1.0,
thickness: 1.0,
color: Colors.grey.shade300,
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [Text('Marque:'), Text(widget.brands)],
),
Divider(
height: 1.0,
thickness: 1.0,
color: Colors.grey.shade300,
),
// Row(
// mainAxisSize: MainAxisSize.max,
// mainAxisAlignment:
// MainAxisAlignment.spaceBetween,
// children: [Text('Prix:'), Text('4,99 €')],
// ),
],
),
),
Row(
mainAxisSize: MainAxisSize.max,
spacing: 12,
children: [
Expanded(
child: TextButton(
onPressed: () async {
await widget.onRescan?.call();
},
child: Text('Nouveau scan'),
),
),
Expanded(
child: TextButton(
onPressed: () async {
await widget.onDetails?.call();
},
child: Text('Voir détails'),
),
),
],
),
),
Row(
mainAxisSize: MainAxisSize.max,
spacing: 12,
children: [
Expanded(
child: FilledButton.tonal(
onPressed: () async {
await widget.onRescan?.call();
},
child: Text('Nouveau scan'),
),
),
Expanded(
child: FilledButton(
onPressed: () async {
await widget.onDetails?.call();
},
child: Text('Voir détails'),
),
),
],
),
),
],
),
),
],
),
),
),
],
);
}
}

View File

@ -97,7 +97,9 @@ class _ScannerPageState extends ConsumerState<ScannerPage>
});
final product = await ApiCalls.fetchProduct(code.displayValue!);
if (product != null) {
loading = false;
setState(() {
loading = false;
});
print('Nom du produit : ${product["product_name"]}');
print('Marque : ${product["brands"]}');
print('Image : ${product["image_url"]}');
@ -144,78 +146,76 @@ class _ScannerPageState extends ConsumerState<ScannerPage>
},
);
} else {
setState(() {
loading = false;
});
print('Aucun produit trouvé.');
}
}
}
Future<void> _fakeBarcode(BarcodeCapture barcodeCapture) async {
if (qrcodeFound) return;
if (barcodeCapture.barcodes.isNotEmpty) {
qrcodeFound = true;
mobileScannerController.stop();
final code = barcodeCapture.barcodes.first;
final qrcodeValue = code.displayValue;
debugPrint("Code détecté : ${code.displayValue}");
if (qrcodeValue == null) {
debugPrint("Qrcode non valide");
return;
}
Future<void> _fakeBarcode() async {
final qrcodeValue = "0737628064502";
qrcodeFound = true;
mobileScannerController.stop();
setState(() {
loading = true;
});
final product = await ApiCalls.fetchProduct(qrcodeValue);
if (product != null) {
setState(() {
loading = true;
});
final product = await ApiCalls.fetchProduct(code.displayValue!);
if (product != null) {
loading = false;
print('Nom du produit : ${product["product_name"]}');
print('Marque : ${product["brands"]}');
print('Image : ${product["image_url"]}');
//show dialog
await showDialog(
barrierDismissible: false,
context: context,
builder: (dialogContext) {
return Dialog(
elevation: 0,
insetPadding: EdgeInsets.zero,
backgroundColor: Colors.transparent,
alignment: AlignmentDirectional(
0.0,
0.0,
).resolve(Directionality.of(context)),
child: GestureDetector(
onTap: () {
FocusScope.of(dialogContext).unfocus();
FocusManager.instance.primaryFocus?.unfocus();
},
child: Container(
width: MediaQuery.sizeOf(context).width * 0.9,
child: ProductScannedComponent(
img: product["image_url"],
productName: product["product_name"],
brands: product["brands"],
codeScanned: qrcodeValue,
onRescan: () async {
Navigator.of(context).pop();
qrcodeFound = false;
mobileScannerController.start();
},
onDetails: () async {
Navigator.of(context).pop();
unawaited(_subscription?.cancel());
_subscription = null;
unawaited(mobileScannerController.stop());
},
),
});
print('Nom du produit : ${product["product_name"]}');
print('Marque : ${product["brands"]}');
print('Image : ${product["image_url"]}');
//show dialog
await showDialog(
barrierDismissible: false,
context: context,
builder: (dialogContext) {
return Dialog(
elevation: 0,
insetPadding: EdgeInsets.zero,
backgroundColor: Colors.transparent,
alignment: AlignmentDirectional(
0.0,
0.0,
).resolve(Directionality.of(context)),
child: GestureDetector(
onTap: () {
FocusScope.of(dialogContext).unfocus();
FocusManager.instance.primaryFocus?.unfocus();
},
child: SizedBox(
width: MediaQuery.sizeOf(context).width * 0.9,
child: ProductScannedComponent(
img: product["image_url"],
productName: product["product_name"],
brands: product["brands"],
codeScanned: qrcodeValue,
onRescan: () async {
Navigator.of(context).pop();
qrcodeFound = false;
mobileScannerController.start();
},
onDetails: () async {
Navigator.of(context).pop();
unawaited(_subscription?.cancel());
_subscription = null;
unawaited(mobileScannerController.stop());
},
),
),
);
},
);
} else {
print('Aucun produit trouvé.');
}
),
);
},
);
} else {
setState(() {
loading = false;
});
print('Aucun produit trouvé.');
}
}
@ -333,7 +333,7 @@ class _ScannerPageState extends ConsumerState<ScannerPage>
),
child: GestureDetector(
onTap: () {
// _fakeBarcode();
_fakeBarcode();
qrcodeFound = false;
mobileScannerController.start();
},