feat(frontend): add emprunt confirmation screen (completes borrow flow)
This commit is contained in:
@@ -4,6 +4,7 @@ import "../theme/ensup_colors.dart";
|
||||
import "../models/materiel_item.dart";
|
||||
import "../widgets/ensup_top_bar.dart";
|
||||
import "../widgets/brand_corners.dart";
|
||||
import "confirmation_screen.dart";
|
||||
|
||||
enum _Etat { present, absent, deteriore }
|
||||
|
||||
@@ -25,8 +26,20 @@ class _ChecklistDepartScreenState extends State<ChecklistDepartScreen> {
|
||||
);
|
||||
|
||||
void _valider() {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text("Confirmation de l'emprunt — écran à venir")),
|
||||
final anomalies = <String>[];
|
||||
for (var i = 0; i < _etats.length; i++) {
|
||||
if (_etats[i] == _Etat.absent) {
|
||||
anomalies.add("${widget.item.accessoires[i]} absent au départ");
|
||||
} else if (_etats[i] == _Etat.deteriore) {
|
||||
anomalies.add("${widget.item.accessoires[i]} détérioré au départ");
|
||||
}
|
||||
}
|
||||
final note = anomalies.isEmpty ? null : anomalies.join(", ");
|
||||
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (_) => ConfirmationScreen(item: widget.item, note: note),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
import "package:flutter/material.dart";
|
||||
import "package:google_fonts/google_fonts.dart";
|
||||
import "../theme/ensup_colors.dart";
|
||||
import "../models/materiel_item.dart";
|
||||
import "../widgets/ensup_top_bar.dart";
|
||||
import "../widgets/brand_corners.dart";
|
||||
|
||||
/// Écran de succès clôturant l'emprunt : confirmation + récapitulatif.
|
||||
class ConfirmationScreen extends StatelessWidget {
|
||||
const ConfirmationScreen({super.key, required this.item, this.note});
|
||||
|
||||
final MaterielItem item;
|
||||
final String? note;
|
||||
|
||||
static String _deuxChiffres(int valeur) => valeur.toString().padLeft(2, "0");
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final now = DateTime.now();
|
||||
final date = "${_deuxChiffres(now.day)}/${_deuxChiffres(now.month)}/${now.year}";
|
||||
final heure = "${_deuxChiffres(now.hour)}:${_deuxChiffres(now.minute)}";
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: EnsupColors.soft,
|
||||
body: Stack(
|
||||
children: [
|
||||
Center(
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 1280, maxHeight: 820),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(24),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: EnsupColors.text.withValues(alpha: 0.14),
|
||||
blurRadius: 60,
|
||||
offset: const Offset(0, 18),
|
||||
),
|
||||
],
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Column(
|
||||
children: [
|
||||
const EnsupTopBar(
|
||||
brandText: "EME · Confirmation",
|
||||
campusTag: "Paris · Ensitech",
|
||||
),
|
||||
Expanded(
|
||||
child: DecoratedBox(
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [Color(0xFFF0FDF4), Color(0xFFF8FAFC)],
|
||||
),
|
||||
),
|
||||
child: Center(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 32),
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 560),
|
||||
child: Column(
|
||||
children: [
|
||||
_boiteSucces(),
|
||||
const SizedBox(height: 16),
|
||||
_recapitulatif(date, heure),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: FilledButton.icon(
|
||||
onPressed: () => Navigator.of(context).popUntil(
|
||||
(route) => route.settings.name == "home",
|
||||
),
|
||||
icon: const Icon(Icons.home_outlined, size: 18),
|
||||
label: Text(
|
||||
"Retour à l'accueil",
|
||||
style: GoogleFonts.darkerGrotesque(
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: EnsupColors.cyan,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Positioned.fill(child: BrandCorners()),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _boiteSucces() {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(36),
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(colors: [Color(0xFFF0FDF4), Color(0xFFECFDF5)]),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(color: const Color(0xFFBBF7D0), width: 2),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
width: 72,
|
||||
height: 72,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
gradient: const LinearGradient(colors: [Color(0xFF16A34A), Color(0xFF22C55E)]),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: const Color(0xFF16A34A).withValues(alpha: 0.3),
|
||||
blurRadius: 20,
|
||||
offset: const Offset(0, 6),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: const Icon(Icons.check, color: Colors.white, size: 36),
|
||||
),
|
||||
const SizedBox(height: 18),
|
||||
Text(
|
||||
"Emprunt enregistré !",
|
||||
style: GoogleFonts.darkerGrotesque(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.w900,
|
||||
color: const Color(0xFF15803D),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
"Votre emprunt a bien été enregistré. Vous pouvez récupérer le matériel.",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.titilliumWeb(fontSize: 14, color: const Color(0xFF166534)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _recapitulatif(String date, String heure) {
|
||||
final note = this.note;
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(18),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: EnsupColors.line, width: 1.5),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"RÉCAPITULATIF DE L'EMPRUNT",
|
||||
style: GoogleFonts.darkerGrotesque(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: EnsupColors.muted,
|
||||
letterSpacing: 0.6,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
_rrow("Matériel", item.nom),
|
||||
_rrow("Référence", item.reference),
|
||||
_rrow("Emprunteur", "Lucas Martin"),
|
||||
_rrow("Date d'emprunt", date),
|
||||
_rrow("Heure", heure),
|
||||
_rrow("Campus", item.campus),
|
||||
if (note != null) _rrow("Note", note, valueColor: const Color(0xFFD97706)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _rrow(String cle, String valeur, {Color? valueColor}) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 7),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(cle, style: GoogleFonts.titilliumWeb(fontSize: 13, color: EnsupColors.muted)),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Text(
|
||||
valeur,
|
||||
textAlign: TextAlign.right,
|
||||
style: GoogleFonts.titilliumWeb(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: valueColor ?? EnsupColors.text,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,10 @@ class LoginScreen extends StatelessWidget {
|
||||
|
||||
void _identifier(BuildContext context) {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (_) => const HomeScreen()),
|
||||
MaterialPageRoute(
|
||||
builder: (_) => const HomeScreen(),
|
||||
settings: const RouteSettings(name: "home"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user