feat: Displays recent stock receptions
Fetches and displays a list of recent stock reception operations on the reception page. Introduces a new `StockPickingCard` component to present each reception record clearly and consistently. The `ReceptionPageModel` now automatically fetches reception data upon initialization. Provides visual feedback for loading states and when no reception data is available, enhancing the user's overview of recent activities.
This commit is contained in:
parent
61345869e1
commit
41a660db9a
@ -1,3 +1,4 @@
|
||||
import 'package:barcode_scanner/backend/schema/stock_picking/stock_picking_model.dart';
|
||||
import 'package:barcode_scanner/components/components.dart';
|
||||
import 'package:barcode_scanner/pages/operation/reception/reception_page_model.dart';
|
||||
import 'package:barcode_scanner/themes/app_theme.dart';
|
||||
@ -24,6 +25,7 @@ class _ReceptionPageState extends ConsumerState<ReceptionPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final state = ref.watch(receptionPageModelProvider);
|
||||
return Scaffold(
|
||||
backgroundColor: AppTheme.of(context).primaryBackground,
|
||||
key: globalKey,
|
||||
@ -41,7 +43,7 @@ class _ReceptionPageState extends ConsumerState<ReceptionPage> {
|
||||
QuickActionComponent(),
|
||||
const SizedBox(height: 16),
|
||||
Card(
|
||||
color: AppTheme.of(context).secondaryBackground,
|
||||
color: AppTheme.of(context).primaryBackground,
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
@ -49,11 +51,39 @@ class _ReceptionPageState extends ConsumerState<ReceptionPage> {
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Text(
|
||||
'Activité Récente',
|
||||
style: AppTheme.of(
|
||||
context,
|
||||
).bodyMedium.copyWith(fontWeight: FontWeight.bold),
|
||||
child: Column(
|
||||
spacing: 10,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Réceptions récentes',
|
||||
style: AppTheme.of(
|
||||
context,
|
||||
).bodyMedium.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
state.receptions?.result?.records?.isEmpty == true
|
||||
? Text('No data')
|
||||
: ListView.builder(
|
||||
primary: true,
|
||||
shrinkWrap: true,
|
||||
itemCount:
|
||||
(state.receptions?.result?.records ??
|
||||
<StockPickingRecordModel>[])
|
||||
.length,
|
||||
itemBuilder: (context, index) {
|
||||
final record =
|
||||
state.receptions?.result?.records![index];
|
||||
return StockPickingCard(
|
||||
reference: record?.name ?? '',
|
||||
from: record?.locationId?.completeName,
|
||||
to: record?.locationDestId?.completeName,
|
||||
contact: record?.partnerId?.displayName,
|
||||
origin: record?.origin,
|
||||
status: record?.state,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -63,3 +93,68 @@ class _ReceptionPageState extends ConsumerState<ReceptionPage> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
});
|
||||
final String? reference;
|
||||
final String? from;
|
||||
final String? to;
|
||||
final String? contact;
|
||||
final String? origin;
|
||||
final String? status;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
elevation: 2,
|
||||
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: [
|
||||
Text(
|
||||
reference ?? 'Référence inconnue',
|
||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_infoRow("De", from),
|
||||
_infoRow("Vers", to),
|
||||
_infoRow("Contact", contact),
|
||||
_infoRow("Document d’origine", origin),
|
||||
_infoRow("Statut", status),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _infoRow(String label, String? value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"$label : ",
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
value ?? "-",
|
||||
style: const TextStyle(color: Colors.black87),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,9 @@ class ReceptionPageModel extends StateNotifier<ReceptionPageState> {
|
||||
required this.secureStorage,
|
||||
required this.tokenProvider,
|
||||
required this.userConnectedProvider,
|
||||
}) : super(const ReceptionPageState());
|
||||
}) : super(const ReceptionPageState()) {
|
||||
getAllReceptions();
|
||||
}
|
||||
|
||||
late FlutterSecureStorage secureStorage;
|
||||
late TokenProvider tokenProvider;
|
||||
@ -39,10 +41,18 @@ class ReceptionPageModel extends StateNotifier<ReceptionPageState> {
|
||||
|
||||
Future getAllReceptions() async {
|
||||
try {
|
||||
state = state.copyWith(loadingReceptions: true);
|
||||
final res = await ApiCalls.getAllStockPiking();
|
||||
state = state.copyWith(loadingReceptions: true);
|
||||
final res = await ApiCalls.getAllStockPiking();
|
||||
res.when(
|
||||
(data) {
|
||||
state = state.copyWith(receptions: data, loadingReceptions: false);
|
||||
},
|
||||
(error) {
|
||||
state = state.copyWith(loadingReceptions: false);
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
state = state.copyWith(loadingReceptions: false);
|
||||
state = state.copyWith(loadingReceptions: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user