style: Applies global theme and refines Reception page UI

Integrates `AppTheme` for consistent styling across the Reception page, affecting backgrounds, app bar, cards, and text.

Enhances `PrimaryButtonComponent` to support leading icons and centered content, and introduces `OutlineButtonComponent` for secondary actions, standardizing button usage.

Improves the AppBar by adding a drawer toggle and updating the title layout and styling. Removes the bottom navigation bar to streamline page navigation.
This commit is contained in:
mandreshope 2025-07-24 09:05:43 +03:00
parent 855770b428
commit 27863f800e
4 changed files with 145 additions and 76 deletions

View File

@ -2,3 +2,4 @@ export 'drawer_component.dart';
export 'loading_progress_component.dart';
export 'primary_button_component.dart';
export 'product_scanned_component.dart';
export 'outline_button_component.dart';

View File

@ -0,0 +1,56 @@
import 'package:barcode_scanner/components/loading_progress_component.dart';
import 'package:barcode_scanner/themes/app_theme.dart';
import 'package:flutter/material.dart';
class OutlineButtonComponent extends StatelessWidget {
const OutlineButtonComponent({
super.key,
required this.text,
required this.onPressed,
this.loading = false,
this.leading,
this.centered = false,
});
final void Function()? onPressed;
final String text;
final bool loading;
final Widget? leading;
final bool centered;
@override
Widget build(BuildContext context) {
final textWidget = Text(
text,
style: AppTheme.of(context).bodySmall.copyWith(
color: AppTheme.of(context).primaryText,
fontWeight: FontWeight.bold,
),
);
return OutlinedButton(
style: OutlinedButton.styleFrom(
side: BorderSide(color: AppTheme.of(context).alternate),
backgroundColor: AppTheme.of(context).primaryBackground,
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
),
onPressed: loading ? null : onPressed,
child: loading
? SizedBox(
height: 20,
width: 20,
child: Center(
child: LoadingProgressComponent(
color: AppTheme.of(context).primary,
),
),
)
: leading == null
? textWidget
: Row(
mainAxisSize: centered ? MainAxisSize.min : MainAxisSize.max,
spacing: 10,
children: [?leading, textWidget],
),
);
}
}

View File

@ -8,17 +8,28 @@ class PrimaryButtonComponent extends StatelessWidget {
required this.text,
required this.onPressed,
this.loading = false,
this.leading,
this.centered = false,
});
final void Function()? onPressed;
final String text;
final bool loading;
final Widget? leading;
final bool centered;
@override
Widget build(BuildContext context) {
final textWidget = Text(
text,
style: TextStyle(
fontWeight: FontWeight.bold,
color: AppTheme.of(context).white,
),
);
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: AppTheme.of(context).primary,
padding: const EdgeInsets.symmetric(vertical: 16),
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
),
onPressed: loading ? null : onPressed,
@ -32,12 +43,12 @@ class PrimaryButtonComponent extends StatelessWidget {
),
),
)
: Text(
text,
style: TextStyle(
fontWeight: FontWeight.bold,
color: AppTheme.of(context).white,
),
: leading == null
? textWidget
: Row(
mainAxisSize: centered ? MainAxisSize.min : MainAxisSize.max,
spacing: 10,
children: [?leading, textWidget],
),
);
}

View File

@ -1,5 +1,7 @@
import 'package:barcode_scanner/components/components.dart';
import 'package:barcode_scanner/components/drawer_component.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';
@ -12,6 +14,7 @@ class ReceptionPage extends ConsumerStatefulWidget {
}
class _ReceptionPageState extends ConsumerState<ReceptionPage> {
final globalKey = GlobalKey<ScaffoldState>();
@override
void initState() {
super.initState();
@ -23,39 +26,53 @@ class _ReceptionPageState extends ConsumerState<ReceptionPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppTheme.of(context).primaryBackground,
key: globalKey,
drawer: DrawerComponent(isOperationExpanded: true),
appBar: AppBar(
title: const Column(
crossAxisAlignment: CrossAxisAlignment.start,
leading: IconButton(
icon: Icon(Icons.menu, color: AppTheme.of(context).white),
onPressed: () {
globalKey.currentState?.openDrawer();
},
),
title: Row(
children: [
Text("Gestionnaire d'Inventaire", style: TextStyle(fontSize: 18)),
Text("Opérations d'Entrepôt", style: TextStyle(fontSize: 12)),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Réceptions",
style: AppTheme.of(
context,
).titleMedium.copyWith(color: AppTheme.of(context).white),
),
Text(
"Opérations d'Entrepôt",
style: AppTheme.of(
context,
).bodyMedium.copyWith(color: AppTheme.of(context).white),
),
],
),
],
),
toolbarHeight: 60,
backgroundColor: Colors.blue,
backgroundColor: AppTheme.of(context).primary,
elevation: 4,
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: ListView(
children: [
Row(
children: [
const Icon(Icons.arrow_back),
const SizedBox(width: 8),
const Text(
'Réceptions',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
],
),
const SizedBox(height: 16),
Card(
elevation: 0,
color: AppTheme.of(context).secondaryBackground,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
side: BorderSide(color: Colors.grey.shade300),
side: BorderSide(color: AppTheme.of(context).alternate),
),
child: Padding(
padding: const EdgeInsets.all(16),
@ -64,12 +81,11 @@ class _ReceptionPageState extends ConsumerState<ReceptionPage> {
children: [
Row(
children: [
const Text(
Text(
'Actions Rapides',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
style: AppTheme.of(
context,
).bodyMedium.copyWith(fontWeight: FontWeight.bold),
),
const Spacer(),
Container(
@ -78,41 +94,47 @@ class _ReceptionPageState extends ConsumerState<ReceptionPage> {
vertical: 4,
),
decoration: BoxDecoration(
color: Colors.grey.shade200,
color: AppTheme.of(context).alternate,
borderRadius: BorderRadius.circular(20),
),
child: const Text(
child: Text(
'3 en attente',
style: TextStyle(fontSize: 12),
style: AppTheme.of(context).bodySmall,
),
),
],
),
const SizedBox(height: 16),
ElevatedButton.icon(
icon: const Icon(Icons.add),
label: const Text('Nouvelle Réception'),
onPressed: () {},
style: ElevatedButton.styleFrom(
minimumSize: const Size.fromHeight(50),
SizedBox(
width: double.maxFinite,
child: PrimaryButtonComponent(
centered: true,
leading: Icon(
Icons.add,
color: AppTheme.of(context).white,
),
text: 'Nouvelle Réception',
onPressed: () {},
),
),
const SizedBox(height: 12),
OutlinedButton.icon(
icon: const Icon(Icons.qr_code_scanner),
label: const Text('Scanner Code-Barres'),
onPressed: () {},
style: OutlinedButton.styleFrom(
minimumSize: const Size.fromHeight(50),
SizedBox(
width: double.maxFinite,
child: OutlineButtonComponent(
centered: true,
leading: const Icon(Icons.qr_code_scanner),
text: 'Scanner Code-Barres',
onPressed: () {},
),
),
const SizedBox(height: 12),
OutlinedButton.icon(
icon: const Icon(Icons.search),
label: const Text('Rechercher Existant'),
onPressed: () {},
style: OutlinedButton.styleFrom(
minimumSize: const Size.fromHeight(50),
SizedBox(
width: double.maxFinite,
child: OutlineButtonComponent(
centered: true,
leading: const Icon(Icons.search),
text: 'Rechercher Existant',
onPressed: () {},
),
),
],
@ -121,46 +143,25 @@ class _ReceptionPageState extends ConsumerState<ReceptionPage> {
),
const SizedBox(height: 16),
Card(
color: AppTheme.of(context).secondaryBackground,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
side: BorderSide(color: Colors.grey.shade300),
side: BorderSide(color: AppTheme.of(context).alternate),
),
child: const Padding(
child: Padding(
padding: EdgeInsets.all(16),
child: Text(
'Activité Récente',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
style: AppTheme.of(
context,
).bodyMedium.copyWith(fontWeight: FontWeight.bold),
),
),
),
],
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: 1, // Opérations sélectionné
selectedItemColor: Colors.blue,
unselectedItemColor: Colors.grey,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home_outlined),
label: 'Accueil',
),
BottomNavigationBarItem(icon: Icon(Icons.inbox), label: 'Opérations'),
BottomNavigationBarItem(
icon: Icon(Icons.insert_chart),
label: 'Produits',
),
BottomNavigationBarItem(
icon: Icon(Icons.history),
label: 'Historique',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'Paramètres',
),
],
),
);
}
}