feat: Implements visual status for pickings
Introduces an `isDone` extension property for stock picking records to simplify status checks. Enhances the `StockPickingCard` to visually represent the picking's completion status with a distinct icon and color (green for 'done', grey for 'in progress'), improving clarity at a glance. Information row values are now consistently uppercased. Conditionally displays scan-related actions (QuickActionComponent and FloatingActionButton) in the reception details page, making them available only when the picking is not yet completed. This guides users by preventing interactions on finished operations.
This commit is contained in:
parent
61047f266d
commit
d09d8ace8c
@ -100,3 +100,7 @@ abstract class StockPickingTypeModel with _$StockPickingTypeModel {
|
||||
factory StockPickingTypeModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$StockPickingTypeModelFromJson(json);
|
||||
}
|
||||
|
||||
extension StockPickingRecordModelExt on StockPickingRecordModel {
|
||||
bool get isDone => state == "done";
|
||||
}
|
||||
|
@ -10,8 +10,10 @@ class StockPickingCard extends StatelessWidget {
|
||||
required this.contact,
|
||||
required this.origin,
|
||||
required this.status,
|
||||
required this.isDone,
|
||||
this.margin,
|
||||
});
|
||||
final bool isDone;
|
||||
final String? reference;
|
||||
final String? from;
|
||||
final String? to;
|
||||
@ -48,17 +50,46 @@ class StockPickingCard extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
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),
|
||||
_infoRow(Icons.check_circle, "Statut", status),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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),
|
||||
@ -72,7 +103,7 @@ class StockPickingCard extends StatelessWidget {
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
value ?? "-",
|
||||
(value ?? "-").toUpperCase(),
|
||||
style: const TextStyle(color: Colors.black87),
|
||||
),
|
||||
),
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:e_scan/backend/schema/stock_picking/stock_picking_model.dart';
|
||||
import 'package:e_scan/components/components.dart';
|
||||
import 'package:e_scan/pages/operation/reception/reception_details_page_model.dart';
|
||||
import 'package:e_scan/router/go_secure_router_builder.dart';
|
||||
@ -43,13 +44,16 @@ class _ReceptionDetailsPageState extends ConsumerState<ReceptionDetailsPage> {
|
||||
child: ListView(
|
||||
children: [
|
||||
const SizedBox(height: 16),
|
||||
QuickActionComponent(
|
||||
onTapScan: () {
|
||||
ScannerRoute().push(context);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
if (reception?.isDone == false) ...[
|
||||
QuickActionComponent(
|
||||
onTapScan: () {
|
||||
ScannerRoute().push(context);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
StockPickingCard(
|
||||
isDone: reception?.isDone == true,
|
||||
margin: EdgeInsets.symmetric(horizontal: 5),
|
||||
reference: reception?.name ?? '',
|
||||
from: reception?.locationId?.completeName,
|
||||
@ -61,6 +65,13 @@ class _ReceptionDetailsPageState extends ConsumerState<ReceptionDetailsPage> {
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: reception?.isDone == false
|
||||
? FloatingActionButton(
|
||||
backgroundColor: AppTheme.of(context).primary,
|
||||
onPressed: () {},
|
||||
child: Icon(Icons.qr_code, color: AppTheme.of(context).white),
|
||||
)
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -52,63 +52,54 @@ class _ReceptionPageState extends ConsumerState<ReceptionPage> {
|
||||
if (state.loadingReceptions) {
|
||||
return Center(child: LoadingProgressComponent());
|
||||
}
|
||||
return Card(
|
||||
color: AppTheme.of(context).secondaryBackground,
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
side: BorderSide(color: AppTheme.of(context).alternate),
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Réceptions',
|
||||
style: AppTheme.of(
|
||||
context,
|
||||
).bodyMedium.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
state.receptions?.result?.records?.isEmpty == true
|
||||
? Text('No data')
|
||||
: ListView.builder(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
primary: true,
|
||||
shrinkWrap: true,
|
||||
itemCount:
|
||||
(state.receptions?.result?.records ??
|
||||
<StockPickingRecordModel>[])
|
||||
.length,
|
||||
itemBuilder: (context, index) {
|
||||
final reception =
|
||||
state.receptions?.result?.records![index];
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
final id = reception?.id;
|
||||
if (id == null) return;
|
||||
ReceptionDetailsRoute(
|
||||
receptionId: id,
|
||||
).push(context);
|
||||
},
|
||||
child: StockPickingCard(
|
||||
reference: reception?.name ?? '',
|
||||
from: reception?.locationId?.completeName,
|
||||
to: reception
|
||||
?.locationDestId
|
||||
?.completeName,
|
||||
contact:
|
||||
reception?.partnerId?.displayName,
|
||||
origin: reception?.origin,
|
||||
status: reception?.state,
|
||||
),
|
||||
);
|
||||
return Column(
|
||||
spacing: 10,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Text(
|
||||
// 'Réceptions',
|
||||
// style: AppTheme.of(
|
||||
// context,
|
||||
// ).bodyMedium.copyWith(fontWeight: FontWeight.bold),
|
||||
// ),
|
||||
state.receptions?.result?.records?.isEmpty == true
|
||||
? Text('No data')
|
||||
: ListView.builder(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
primary: true,
|
||||
shrinkWrap: true,
|
||||
itemCount:
|
||||
(state.receptions?.result?.records ??
|
||||
<StockPickingRecordModel>[])
|
||||
.length,
|
||||
itemBuilder: (context, index) {
|
||||
final reception =
|
||||
state.receptions?.result?.records![index];
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
final id = reception?.id;
|
||||
if (id == null) return;
|
||||
ReceptionDetailsRoute(
|
||||
receptionId: id,
|
||||
).push(context);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: StockPickingCard(
|
||||
margin: EdgeInsets.symmetric(
|
||||
horizontal: 5,
|
||||
vertical: 5,
|
||||
),
|
||||
isDone: reception?.isDone == true,
|
||||
reference: reception?.name ?? '',
|
||||
from: reception?.locationId?.completeName,
|
||||
to: reception?.locationDestId?.completeName,
|
||||
contact: reception?.partnerId?.displayName,
|
||||
origin: reception?.origin,
|
||||
status: reception?.state,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
|
Loading…
x
Reference in New Issue
Block a user