
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.
141 lines
4.1 KiB
Dart
141 lines
4.1 KiB
Dart
import 'package:e_scan/themes/app_theme.dart';
|
||
import 'package:flutter/material.dart';
|
||
|
||
class StockPickingCard extends StatelessWidget {
|
||
const StockPickingCard({
|
||
super.key,
|
||
required this.reference,
|
||
required this.from,
|
||
required this.to,
|
||
required this.contact,
|
||
required this.origin,
|
||
required this.status,
|
||
required this.isDone,
|
||
this.synchronized = true,
|
||
this.margin,
|
||
});
|
||
final bool isDone;
|
||
final bool synchronized;
|
||
final String? reference;
|
||
final String? from;
|
||
final String? to;
|
||
final String? contact;
|
||
final String? origin;
|
||
final String? status;
|
||
final EdgeInsetsGeometry? margin;
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Card(
|
||
elevation: 3,
|
||
color: AppTheme.of(context).primaryBackground,
|
||
margin: margin ?? const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||
child: Padding(
|
||
padding: const EdgeInsets.all(16.0),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Row(
|
||
children: [
|
||
Expanded(
|
||
child: Row(
|
||
spacing: 8,
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
const Icon(Icons.receipt_long, color: Colors.blue),
|
||
Expanded(
|
||
child: Text(
|
||
reference ?? 'Référence inconnue',
|
||
style: const TextStyle(
|
||
fontSize: 18,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
if (!synchronized)
|
||
Chip(
|
||
backgroundColor: Colors.red,
|
||
label: Row(
|
||
spacing: 8,
|
||
children: [
|
||
Icon(Icons.cloud_off_outlined, color: Colors.white),
|
||
Text(
|
||
'Non synchronisé',
|
||
style: TextStyle(
|
||
color: Colors.white,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 12),
|
||
_infoStateRow(isDone, "Statut", status),
|
||
_infoRow(Icons.call_made, "De", from),
|
||
_infoRow(Icons.call_received, "Vers", to),
|
||
_infoRow(Icons.person, "Contact", contact),
|
||
_infoRow(Icons.insert_drive_file, "Document d’origine", origin),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _infoStateRow(bool isDone, String label, String? value) {
|
||
var color = Colors.grey[700];
|
||
var icon = Icons.refresh;
|
||
if (isDone) {
|
||
icon = Icons.check_circle;
|
||
color = Colors.green;
|
||
}
|
||
|
||
return Padding(
|
||
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||
child: Row(
|
||
children: [
|
||
Icon(icon, size: 20, color: color),
|
||
const SizedBox(width: 8),
|
||
Text(
|
||
"$label : ",
|
||
style: TextStyle(fontWeight: FontWeight.bold, color: color),
|
||
),
|
||
Expanded(
|
||
child: Text(
|
||
(value ?? "-").toUpperCase(),
|
||
style: TextStyle(color: color, fontWeight: FontWeight.bold),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget _infoRow(IconData icon, String label, String? value) {
|
||
return Padding(
|
||
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||
child: Row(
|
||
children: [
|
||
Icon(icon, size: 20, color: Colors.grey[700]),
|
||
const SizedBox(width: 8),
|
||
Text(
|
||
"$label : ",
|
||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||
),
|
||
Expanded(
|
||
child: Text(
|
||
(value ?? "-").toUpperCase(),
|
||
style: const TextStyle(color: Colors.black87),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|