barcode_scanner/lib/pages/operation/reception/reception_details_page.dart
mandreshope 9435907c28 feat: Adds session management and reception detail view
Updates the sign-in API endpoint to `/simpos/v1/sign_in`.
Captures the `set-cookie` header from successful sign-in responses and stores it as a `sessionId`.
Persists the session ID using secure storage and includes it in subsequent API requests via the `Cookie` header for improved session management.
Extends the `AuthModel` to include the new `sessionId` field.

Enables navigation from the reception list to a new reception details page, passing the selected reception's ID.
Refactors the `StockPickingCard` into a dedicated component and adds loading indicators to the reception list.
2025-07-29 13:45:24 +03:00

109 lines
4.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 ReceptionDetailsPage extends ConsumerStatefulWidget {
const ReceptionDetailsPage({super.key, required this.receptionId});
final int receptionId;
@override
ConsumerState<ReceptionDetailsPage> createState() =>
_ReceptionDetailsPageState();
}
class _ReceptionDetailsPageState extends ConsumerState<ReceptionDetailsPage> {
final globalKey = GlobalKey<ScaffoldState>();
@override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) {
ref.read(receptionPageModelProvider.notifier).getUserConnected();
});
}
@override
Widget build(BuildContext context) {
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),
Consumer(
builder: (_, WidgetRef ref, _) {
final state = ref.watch(receptionPageModelProvider);
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 record =
state.receptions?.result?.records![index];
return GestureDetector(
onTap: () {},
child: StockPickingCard(
reference: record?.name ?? '',
from: record?.locationId?.completeName,
to: record?.locationDestId?.completeName,
contact: record?.partnerId?.displayName,
origin: record?.origin,
status: record?.state,
),
);
},
),
],
),
),
);
},
),
],
),
),
);
}
}