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:
mandreshope 2025-07-29 12:07:29 +03:00
parent 61345869e1
commit 41a660db9a
2 changed files with 115 additions and 10 deletions

View File

@ -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 dorigine", 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),
),
),
],
),
);
}
}

View File

@ -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);
}
}
}