barcode_scanner/lib/components/backorder_dialog_component.dart
mandreshope c231790f59 feat: Implements backorder confirmation flow for receptions
Corrects API endpoints for creating, processing with, and processing without backorder confirmations.

Adds a new `isBackorder` getter to stock picking records for identifying backordered items, and improves the robustness of the `isDone` getter.

Integrates backorder detection into the reception validation process, prompting a dedicated confirmation dialog when a backorder is present.

Introduces new state management and methods (`withBackorder`, `withoutBackorder`) in the reception details model to handle the backorder confirmation logic.

Enhances the primary button component with a `backgroundColor` property for greater customization.
2025-08-04 09:37:26 +03:00

116 lines
4.0 KiB
Dart

import 'package:e_scan/pages/operation/reception/reception_details_page_model.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:e_scan/components/components.dart';
import 'package:e_scan/themes/app_theme.dart';
import 'package:flutter/material.dart';
class DeleteCategorieDialogComponentWidget extends ConsumerWidget {
const DeleteCategorieDialogComponentWidget({
super.key,
required this.stockPickingId,
});
final int stockPickingId;
static void show(BuildContext context, {required int stockPickingId}) {
showDialog(
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.of(context).size.width * .8,
child: DeleteCategorieDialogComponentWidget(
stockPickingId: stockPickingId,
),
),
),
);
},
);
}
@override
Widget build(BuildContext context, WidgetRef ref) {
return Container(
width: double.infinity,
decoration: BoxDecoration(
color: AppTheme.of(context).primaryBackground,
borderRadius: BorderRadius.circular(8.0),
),
child: Padding(
padding: EdgeInsets.all(20.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Vous avez traité moins de produits que la demande initiale.',
style: AppTheme.of(context).titleSmall,
textAlign: TextAlign.center,
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(0.0, 20.0, 0.0, 0.0),
child: Text(
'Créer un reliquat si vous vous attendez à traiter la quantité de produits restante. Ne créez pas de reliquat si vous ne voulez pas traiter la quantité de produits restante.',
textAlign: TextAlign.center,
style: AppTheme.of(context).bodyMedium,
),
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(0.0, 40.0, 0.0, 0.0),
child: Row(
spacing: 5,
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: PrimaryButtonComponent(
text: 'Créer un reliquat',
onPressed: () async {
await ref
.read(receptionDetailsPageModelProvider.notifier)
.withBackorder(
receptionId: stockPickingId,
onSuccess: () {
Navigator.of(context).pop();
},
);
},
),
),
Expanded(
child: PrimaryButtonComponent(
backgroundColor: Colors.red,
text: 'Aucun reliquat',
onPressed: () async {
await ref
.read(receptionDetailsPageModelProvider.notifier)
.withoutBackorder(
receptionId: stockPickingId,
onSuccess: () {
Navigator.of(context).pop();
},
);
// Navigator.pop(context);
},
),
),
],
),
),
],
),
),
);
}
}