
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.
161 lines
5.3 KiB
Dart
161 lines
5.3 KiB
Dart
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';
|
||
import 'package:flutter/scheduler.dart';
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import 'package:flutter/material.dart';
|
||
|
||
class ReceptionPage extends ConsumerStatefulWidget {
|
||
const ReceptionPage({super.key});
|
||
|
||
@override
|
||
ConsumerState<ReceptionPage> createState() => _ReceptionPageState();
|
||
}
|
||
|
||
class _ReceptionPageState extends ConsumerState<ReceptionPage> {
|
||
final globalKey = GlobalKey<ScaffoldState>();
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||
ref.read(receptionPageModelProvider.notifier).getUserConnected();
|
||
});
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
final state = ref.watch(receptionPageModelProvider);
|
||
return Scaffold(
|
||
backgroundColor: AppTheme.of(context).primaryBackground,
|
||
key: globalKey,
|
||
drawer: DrawerComponent(isOperationExpanded: true),
|
||
appBar: MainAppbarComponent(
|
||
scaffoledKey: globalKey,
|
||
title: "Réceptions",
|
||
subTitle: "Opérations d'Entrepôt",
|
||
),
|
||
body: Padding(
|
||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||
child: ListView(
|
||
children: [
|
||
const SizedBox(height: 16),
|
||
QuickActionComponent(),
|
||
const SizedBox(height: 16),
|
||
Card(
|
||
color: AppTheme.of(context).primaryBackground,
|
||
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 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,
|
||
);
|
||
},
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
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),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|