barcode_scanner/lib/components/quick_action_component.dart
your-name 18f74daae4 feat: Implement explicit synchronization and validation
Refactors the reception process to provide clearer control over data synchronization and validation.

- Replaces the `isDraft` property with `synchronized` in `StockPickingRecordEntity` to accurately represent the local data's sync status with the backend.
- Introduces a new API endpoint and corresponding logic for `validateStockPicking`, allowing finalization of receptions.
- Splits the "Save" action into "Synchronize data" and "Validate reception" on the details page. "Validate" now implicitly performs a synchronization first.
- Updates UI elements (cards, quick actions) to reflect the new synchronization state and expose the new actions.
- Corrects a typo in the `updateAllMoveLineOnStockPicking` API method name.
- Improves local data update logic for scanned items, marking them as unsynchronized.
2025-07-31 02:34:50 +03:00

133 lines
4.4 KiB
Dart

import 'package:e_scan/components/components.dart';
import 'package:e_scan/themes/app_theme.dart';
import 'package:flutter/material.dart';
class QuickActionComponent extends StatelessWidget {
const QuickActionComponent({
super.key,
this.onTapAdd,
this.onTapScan,
this.onTapSearch,
this.onTapValidateReception,
this.onTapSyncReception,
this.syncReceptionLoading = false,
this.validateReceptionLoading = false,
});
final VoidCallback? onTapAdd;
final VoidCallback? onTapScan;
final VoidCallback? onTapSearch;
final VoidCallback? onTapValidateReception;
final VoidCallback? onTapSyncReception;
final bool syncReceptionLoading;
final bool validateReceptionLoading;
@override
Widget build(BuildContext context) {
return Card(
elevation: 0,
color: AppTheme.of(context).secondaryBackground,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
side: BorderSide(color: AppTheme.of(context).alternate),
),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'Actions Rapides',
style: AppTheme.of(
context,
).bodyMedium.copyWith(fontWeight: FontWeight.bold),
),
const Spacer(),
// Container(
// padding: const EdgeInsets.symmetric(
// horizontal: 10,
// vertical: 4,
// ),
// decoration: BoxDecoration(
// color: AppTheme.of(context).alternate,
// borderRadius: BorderRadius.circular(20),
// ),
// child: Text(
// '3 en attente',
// style: AppTheme.of(context).bodySmall,
// ),
// ),
],
),
if (onTapValidateReception != null) ...[
const SizedBox(height: 16),
SizedBox(
width: double.maxFinite,
child: PrimaryButtonComponent(
loading: validateReceptionLoading,
centered: true,
leading: Icon(Icons.save, color: AppTheme.of(context).white),
text: 'Valider la réception',
onPressed: onTapValidateReception,
),
),
],
if (onTapSyncReception != null) ...[
const SizedBox(height: 16),
SizedBox(
width: double.maxFinite,
child: PrimaryButtonComponent(
loading: syncReceptionLoading,
centered: true,
leading: Icon(
Icons.cloud_upload_outlined,
color: AppTheme.of(context).white,
),
text: 'Synchroniser les données',
onPressed: onTapSyncReception,
),
),
],
if (onTapAdd != null) ...[
const SizedBox(height: 16),
SizedBox(
width: double.maxFinite,
child: PrimaryButtonComponent(
centered: true,
leading: Icon(Icons.add, color: AppTheme.of(context).white),
text: 'Nouvelle Réception',
onPressed: onTapAdd,
),
),
],
if (onTapScan != null) ...[
const SizedBox(height: 12),
SizedBox(
width: double.maxFinite,
child: OutlineButtonComponent(
centered: true,
leading: const Icon(Icons.qr_code_scanner),
text: 'Scanner Code-Barres',
onPressed: onTapScan,
),
),
const SizedBox(height: 12),
],
if (onTapSearch != null)
SizedBox(
width: double.maxFinite,
child: OutlineButtonComponent(
centered: true,
leading: const Icon(Icons.search),
text: 'Rechercher Existant',
onPressed: onTapSearch,
),
),
],
),
),
);
}
}