|
|
@ -1,62 +1,9 @@ |
|
|
import 'dart:convert'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import 'dart:convert'; |
|
|
import 'package:flutter/material.dart'; |
|
|
import 'package:flutter/material.dart'; |
|
|
import 'package:http/http.dart' as http; |
|
|
import 'package:http/http.dart' as http; |
|
|
|
|
|
|
|
|
// Use your actual models and http logic |
|
|
import '../models/menus.dart'; |
|
|
class MenuPlat { |
|
|
|
|
|
final int id; |
|
|
|
|
|
final String nom; |
|
|
|
|
|
final String? commentaire; |
|
|
|
|
|
final double prix; |
|
|
|
|
|
final String? imageUrl; |
|
|
|
|
|
final bool disponible; |
|
|
|
|
|
final List<MenuCategory> categories; // Default to true |
|
|
|
|
|
MenuPlat({ |
|
|
|
|
|
required this.id, |
|
|
|
|
|
required this.nom, |
|
|
|
|
|
this.commentaire, |
|
|
|
|
|
required this.prix, |
|
|
|
|
|
this.imageUrl, |
|
|
|
|
|
required this.disponible, |
|
|
|
|
|
required this.categories, |
|
|
|
|
|
}); |
|
|
|
|
|
factory MenuPlat.fromJson(Map<String, dynamic> json) { |
|
|
|
|
|
return MenuPlat( |
|
|
|
|
|
id: json['id'], |
|
|
|
|
|
nom: json['nom'], |
|
|
|
|
|
commentaire: json['commentaire'], |
|
|
|
|
|
prix: (json['prix'] as num).toDouble(), |
|
|
|
|
|
imageUrl: json['image_url'], |
|
|
|
|
|
disponible: json['disponible'] ?? true, |
|
|
|
|
|
categories: |
|
|
|
|
|
(json['categories'] as List) |
|
|
|
|
|
.map((c) => MenuCategory.fromJson(c)) |
|
|
|
|
|
.toList(), |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
class MenuCategory { |
|
|
|
|
|
final int id; |
|
|
|
|
|
final String nom; |
|
|
|
|
|
|
|
|
|
|
|
MenuCategory({required this.id, required this.nom}); |
|
|
|
|
|
|
|
|
|
|
|
factory MenuCategory.fromJson(Map<String, dynamic> json) { |
|
|
|
|
|
return MenuCategory(id: json['id'], nom: json['nom']); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
|
bool operator ==(Object other) => |
|
|
|
|
|
identical(this, other) || |
|
|
|
|
|
other is MenuCategory && |
|
|
|
|
|
runtimeType == other.runtimeType && |
|
|
|
|
|
id == other.id; |
|
|
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
|
int get hashCode => id.hashCode; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
class PlatEditPage extends StatefulWidget { |
|
|
class PlatEditPage extends StatefulWidget { |
|
|
final List<MenuCategory> categories; |
|
|
final List<MenuCategory> categories; |
|
|
@ -76,9 +23,9 @@ class PlatEditPage extends StatefulWidget { |
|
|
|
|
|
|
|
|
class _PlatEditPageState extends State<PlatEditPage> { |
|
|
class _PlatEditPageState extends State<PlatEditPage> { |
|
|
final _formKey = GlobalKey<FormState>(); |
|
|
final _formKey = GlobalKey<FormState>(); |
|
|
late TextEditingController nomCtrl, descCtrl, prixCtrl, imgCtrl; |
|
|
late TextEditingController nomCtrl, descCtrl, prixCtrl, ingredientsCtrl; |
|
|
late bool disponible; |
|
|
late bool disponible; |
|
|
late List<MenuCategory> selectedCategories; |
|
|
MenuCategory? selectedCategory; // Une seule catégorie pour correspondre à l'API |
|
|
|
|
|
|
|
|
@override |
|
|
@override |
|
|
void initState() { |
|
|
void initState() { |
|
|
@ -88,9 +35,14 @@ class _PlatEditPageState extends State<PlatEditPage> { |
|
|
prixCtrl = TextEditingController( |
|
|
prixCtrl = TextEditingController( |
|
|
text: widget.plat != null ? widget.plat!.prix.toStringAsFixed(2) : "", |
|
|
text: widget.plat != null ? widget.plat!.prix.toStringAsFixed(2) : "", |
|
|
); |
|
|
); |
|
|
imgCtrl = TextEditingController(text: widget.plat?.imageUrl ?? ""); |
|
|
ingredientsCtrl = TextEditingController(text: widget.plat?.ingredients ?? ""); |
|
|
disponible = widget.plat?.disponible ?? true; |
|
|
disponible = widget.plat?.disponible ?? true; |
|
|
selectedCategories = widget.plat?.categories.toList() ?? []; |
|
|
|
|
|
|
|
|
// Utiliser la catégorie unique ou la première des multiples |
|
|
|
|
|
selectedCategory = widget.plat?.category ?? |
|
|
|
|
|
(widget.plat?.categories?.isNotEmpty == true |
|
|
|
|
|
? widget.plat!.categories!.first |
|
|
|
|
|
: null); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@override |
|
|
@override |
|
|
@ -98,56 +50,72 @@ class _PlatEditPageState extends State<PlatEditPage> { |
|
|
nomCtrl.dispose(); |
|
|
nomCtrl.dispose(); |
|
|
descCtrl.dispose(); |
|
|
descCtrl.dispose(); |
|
|
prixCtrl.dispose(); |
|
|
prixCtrl.dispose(); |
|
|
imgCtrl.dispose(); |
|
|
ingredientsCtrl.dispose(); |
|
|
super.dispose(); |
|
|
super.dispose(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void submit() async { |
|
|
Future<void> submit() async { |
|
|
if (!_formKey.currentState!.validate()) return; |
|
|
if (!_formKey.currentState!.validate()) return; |
|
|
if (selectedCategories.isEmpty) { |
|
|
if (selectedCategory == null) { |
|
|
ScaffoldMessenger.of(context).showSnackBar( |
|
|
ScaffoldMessenger.of(context).showSnackBar( |
|
|
const SnackBar(content: Text('Sélectionnez au moins une catégorie.')), |
|
|
const SnackBar(content: Text('Sélectionnez une catégorie.')), |
|
|
); |
|
|
); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Build request data |
|
|
// Build request data selon votre API |
|
|
final body = { |
|
|
final body = { |
|
|
"nom": nomCtrl.text, |
|
|
"nom": nomCtrl.text, |
|
|
"commentaire": descCtrl.text, |
|
|
"commentaire": descCtrl.text, |
|
|
|
|
|
"ingredients": ingredientsCtrl.text, |
|
|
"prix": double.tryParse(prixCtrl.text) ?? 0, |
|
|
"prix": double.tryParse(prixCtrl.text) ?? 0, |
|
|
"categories": selectedCategories.map((c) => c.id).toList(), |
|
|
"categorie_id": selectedCategory!.id, // L'API attend categorie_id |
|
|
"disponible": disponible, |
|
|
"disponible": disponible, |
|
|
"categorie_id": |
|
|
|
|
|
selectedCategories.isNotEmpty |
|
|
|
|
|
? selectedCategories.first.id |
|
|
|
|
|
: null, // Use first category if available |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
final res = await http.post( |
|
|
final isEdit = widget.plat != null; |
|
|
Uri.parse( |
|
|
final url = isEdit |
|
|
'https://restaurant.careeracademy.mg/api/menus', |
|
|
? 'https://restaurant.careeracademy.mg/api/menus/${widget.plat!.id}' |
|
|
), // your API URL here |
|
|
: 'https://restaurant.careeracademy.mg/api/menus'; |
|
|
headers: {"Content-Type": "application/json"}, |
|
|
|
|
|
body: json.encode(body), |
|
|
final res = isEdit |
|
|
); |
|
|
? await http.put( |
|
|
|
|
|
Uri.parse(url), |
|
|
|
|
|
headers: {"Content-Type": "application/json"}, |
|
|
|
|
|
body: json.encode(body), |
|
|
|
|
|
) |
|
|
|
|
|
: await http.post( |
|
|
|
|
|
Uri.parse(url), |
|
|
|
|
|
headers: {"Content-Type": "application/json"}, |
|
|
|
|
|
body: json.encode(body), |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
if (res.statusCode == 200 || res.statusCode == 201) { |
|
|
if (res.statusCode == 200 || res.statusCode == 201) { |
|
|
widget.onSaved?.call(); |
|
|
widget.onSaved?.call(); |
|
|
Navigator.pop(context); |
|
|
Navigator.pop(context); |
|
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar( |
|
|
|
|
|
SnackBar( |
|
|
|
|
|
content: Text(isEdit ? 'Plat modifié avec succès' : 'Plat créé avec succès'), |
|
|
|
|
|
backgroundColor: Colors.green, |
|
|
|
|
|
), |
|
|
|
|
|
); |
|
|
} else { |
|
|
} else { |
|
|
// show error |
|
|
print('Error: ${res.body}\nBody sent: $body'); |
|
|
print('Error creating plat: ${res.body}\n here is body: $body'); |
|
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar( |
|
|
ScaffoldMessenger.of(context).showSnackBar( |
|
|
SnackBar(content: Text('Erreur lors de la création du plat')), |
|
|
SnackBar( |
|
|
|
|
|
content: Text('Erreur lors de ${isEdit ? "la modification" : "la création"} du plat'), |
|
|
|
|
|
backgroundColor: Colors.red, |
|
|
|
|
|
), |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
// show error |
|
|
ScaffoldMessenger.of(context).showSnackBar( |
|
|
ScaffoldMessenger.of( |
|
|
SnackBar( |
|
|
context, |
|
|
content: Text('Erreur réseau: $e'), |
|
|
).showSnackBar(SnackBar(content: Text('Erreur réseau: $e'))); |
|
|
backgroundColor: Colors.red, |
|
|
|
|
|
), |
|
|
|
|
|
); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -155,6 +123,7 @@ class _PlatEditPageState extends State<PlatEditPage> { |
|
|
Widget build(BuildContext context) { |
|
|
Widget build(BuildContext context) { |
|
|
final isEdit = widget.plat != null; |
|
|
final isEdit = widget.plat != null; |
|
|
return Scaffold( |
|
|
return Scaffold( |
|
|
|
|
|
backgroundColor: const Color(0xfffcfbf9), |
|
|
appBar: AppBar( |
|
|
appBar: AppBar( |
|
|
title: Text(isEdit ? 'Éditer le plat' : 'Nouveau plat'), |
|
|
title: Text(isEdit ? 'Éditer le plat' : 'Nouveau plat'), |
|
|
leading: IconButton( |
|
|
leading: IconButton( |
|
|
@ -163,8 +132,8 @@ class _PlatEditPageState extends State<PlatEditPage> { |
|
|
), |
|
|
), |
|
|
centerTitle: true, |
|
|
centerTitle: true, |
|
|
elevation: 0, |
|
|
elevation: 0, |
|
|
backgroundColor: Colors.white, |
|
|
backgroundColor: Colors.transparent, |
|
|
foregroundColor: Colors.black, |
|
|
foregroundColor: Colors.black87, |
|
|
), |
|
|
), |
|
|
body: Center( |
|
|
body: Center( |
|
|
child: ConstrainedBox( |
|
|
child: ConstrainedBox( |
|
|
@ -179,187 +148,179 @@ class _PlatEditPageState extends State<PlatEditPage> { |
|
|
padding: const EdgeInsets.all(28), |
|
|
padding: const EdgeInsets.all(28), |
|
|
child: Form( |
|
|
child: Form( |
|
|
key: _formKey, |
|
|
key: _formKey, |
|
|
child: Column( |
|
|
child: SingleChildScrollView( |
|
|
mainAxisSize: MainAxisSize.min, |
|
|
child: Column( |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
mainAxisSize: MainAxisSize.min, |
|
|
children: [ |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
const Text( |
|
|
children: [ |
|
|
'Informations du plat', |
|
|
Text( |
|
|
style: TextStyle( |
|
|
isEdit ? 'Modifier le plat' : 'Nouveau plat', |
|
|
fontSize: 21, |
|
|
style: const TextStyle( |
|
|
fontWeight: FontWeight.w600, |
|
|
fontSize: 21, |
|
|
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
const SizedBox(height: 20), |
|
|
|
|
|
|
|
|
|
|
|
// Nom du plat |
|
|
|
|
|
TextFormField( |
|
|
|
|
|
controller: nomCtrl, |
|
|
|
|
|
decoration: const InputDecoration( |
|
|
|
|
|
labelText: "Nom du plat *", |
|
|
|
|
|
hintText: "Ex: Steak frites", |
|
|
|
|
|
border: OutlineInputBorder( |
|
|
|
|
|
borderRadius: BorderRadius.all(Radius.circular(8)), |
|
|
|
|
|
), |
|
|
|
|
|
filled: true, |
|
|
|
|
|
fillColor: Color(0xFFF7F7F7), |
|
|
|
|
|
), |
|
|
|
|
|
validator: (v) => (v == null || v.isEmpty) ? "Obligatoire" : null, |
|
|
), |
|
|
), |
|
|
), |
|
|
const SizedBox(height: 16), |
|
|
const SizedBox(height: 14), |
|
|
|
|
|
TextFormField( |
|
|
// Description |
|
|
controller: nomCtrl, |
|
|
TextFormField( |
|
|
decoration: const InputDecoration( |
|
|
controller: descCtrl, |
|
|
labelText: "Nom du plat *", |
|
|
decoration: const InputDecoration( |
|
|
hintText: "Ex: Steak frites", |
|
|
labelText: "Description", |
|
|
|
|
|
hintText: "Description détaillée du plat...", |
|
|
|
|
|
border: OutlineInputBorder( |
|
|
|
|
|
borderRadius: BorderRadius.all(Radius.circular(8)), |
|
|
|
|
|
), |
|
|
|
|
|
filled: true, |
|
|
|
|
|
fillColor: Color(0xFFF7F7F7), |
|
|
|
|
|
), |
|
|
|
|
|
maxLines: 3, |
|
|
), |
|
|
), |
|
|
validator: |
|
|
const SizedBox(height: 16), |
|
|
(v) => |
|
|
|
|
|
(v == null || v.isEmpty) ? "Obligatoire" : null, |
|
|
// Ingrédients |
|
|
), |
|
|
TextFormField( |
|
|
const SizedBox(height: 13), |
|
|
controller: ingredientsCtrl, |
|
|
TextFormField( |
|
|
decoration: const InputDecoration( |
|
|
controller: descCtrl, |
|
|
labelText: "Ingrédients", |
|
|
decoration: const InputDecoration( |
|
|
hintText: "Liste des ingrédients...", |
|
|
labelText: "Description", |
|
|
border: OutlineInputBorder( |
|
|
hintText: "Description détaillée du plat...", |
|
|
borderRadius: BorderRadius.all(Radius.circular(8)), |
|
|
|
|
|
), |
|
|
|
|
|
filled: true, |
|
|
|
|
|
fillColor: Color(0xFFF7F7F7), |
|
|
|
|
|
), |
|
|
|
|
|
maxLines: 2, |
|
|
), |
|
|
), |
|
|
maxLines: 3, |
|
|
const SizedBox(height: 16), |
|
|
), |
|
|
|
|
|
const SizedBox(height: 13), |
|
|
Row( |
|
|
Row( |
|
|
children: [ |
|
|
children: [ |
|
|
// Prix |
|
|
Expanded( |
|
|
Expanded( |
|
|
child: TextFormField( |
|
|
child: TextFormField( |
|
|
controller: prixCtrl, |
|
|
controller: prixCtrl, |
|
|
decoration: const InputDecoration( |
|
|
decoration: const InputDecoration( |
|
|
labelText: "Prix (MGA) *", |
|
|
labelText: "Prix (MGA) *", |
|
|
), |
|
|
border: OutlineInputBorder( |
|
|
validator: |
|
|
borderRadius: BorderRadius.all(Radius.circular(8)), |
|
|
(v) => |
|
|
), |
|
|
(v == null || |
|
|
filled: true, |
|
|
v.isEmpty || |
|
|
fillColor: Color(0xFFF7F7F7), |
|
|
double.tryParse(v) == null) |
|
|
), |
|
|
? "Obligatoire" |
|
|
validator: (v) => |
|
|
: null, |
|
|
(v == null || v.isEmpty || double.tryParse(v) == null) |
|
|
keyboardType: const TextInputType.numberWithOptions( |
|
|
? "Obligatoire" |
|
|
decimal: true, |
|
|
: null, |
|
|
|
|
|
keyboardType: const TextInputType.numberWithOptions( |
|
|
|
|
|
decimal: true, |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
const SizedBox(width: 16), |
|
|
const SizedBox(width: 16), |
|
|
|
|
|
// Multi-category picker |
|
|
// Catégorie |
|
|
Expanded( |
|
|
Expanded( |
|
|
child: InkWell( |
|
|
child: DropdownButtonFormField<MenuCategory>( |
|
|
onTap: () async { |
|
|
value: selectedCategory, |
|
|
final result = await showDialog<MenuCategory?>( |
|
|
|
|
|
context: context, |
|
|
|
|
|
builder: (context) { |
|
|
|
|
|
MenuCategory? temp = |
|
|
|
|
|
selectedCategories.isNotEmpty |
|
|
|
|
|
? selectedCategories.first |
|
|
|
|
|
: null; |
|
|
|
|
|
|
|
|
|
|
|
return StatefulBuilder( |
|
|
|
|
|
builder: (context, setStateDialog) { |
|
|
|
|
|
return AlertDialog( |
|
|
|
|
|
title: const Text("Catégories"), |
|
|
|
|
|
content: SizedBox( |
|
|
|
|
|
width: 330, |
|
|
|
|
|
child: SingleChildScrollView( |
|
|
|
|
|
child: Column( |
|
|
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
|
|
children: |
|
|
|
|
|
widget.categories.map((cat) { |
|
|
|
|
|
return RadioListTile< |
|
|
|
|
|
MenuCategory |
|
|
|
|
|
>( |
|
|
|
|
|
value: cat, |
|
|
|
|
|
groupValue: temp, |
|
|
|
|
|
title: Text(cat.nom), |
|
|
|
|
|
onChanged: (value) { |
|
|
|
|
|
setStateDialog(() { |
|
|
|
|
|
temp = value; |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
|
|
|
); |
|
|
|
|
|
}).toList(), |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
actions: [ |
|
|
|
|
|
TextButton( |
|
|
|
|
|
onPressed: () { |
|
|
|
|
|
if (temp != null) { |
|
|
|
|
|
Navigator.pop(context, temp); |
|
|
|
|
|
} else { |
|
|
|
|
|
Navigator.pop(context, null); |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
child: const Text('OK'), |
|
|
|
|
|
), |
|
|
|
|
|
], |
|
|
|
|
|
); |
|
|
|
|
|
}, |
|
|
|
|
|
); |
|
|
|
|
|
}, |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
if (result != null) { |
|
|
|
|
|
setState(() => selectedCategories = [result]); |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
child: InputDecorator( |
|
|
|
|
|
decoration: const InputDecoration( |
|
|
decoration: const InputDecoration( |
|
|
labelText: "Catégorie *", |
|
|
labelText: "Catégorie *", |
|
|
border: OutlineInputBorder(gapPadding: 2), |
|
|
border: OutlineInputBorder( |
|
|
|
|
|
borderRadius: BorderRadius.all(Radius.circular(8)), |
|
|
|
|
|
), |
|
|
|
|
|
filled: true, |
|
|
|
|
|
fillColor: Color(0xFFF7F7F7), |
|
|
), |
|
|
), |
|
|
child: |
|
|
validator: (v) => v == null ? "Obligatoire" : null, |
|
|
selectedCategories.isEmpty |
|
|
items: widget.categories.map((cat) { |
|
|
? const Text( |
|
|
return DropdownMenuItem( |
|
|
"Aucune sélection", |
|
|
value: cat, |
|
|
style: TextStyle(color: Colors.grey), |
|
|
child: Text(cat.nom), |
|
|
) |
|
|
); |
|
|
: Text(selectedCategories.first.nom), |
|
|
}).toList(), |
|
|
|
|
|
onChanged: (value) { |
|
|
|
|
|
setState(() => selectedCategory = value); |
|
|
|
|
|
}, |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
const SizedBox(height: 20), |
|
|
// const SizedBox(height: 13), |
|
|
|
|
|
// TextFormField( |
|
|
// Switch disponibilité |
|
|
// controller: imgCtrl, |
|
|
Row( |
|
|
// decoration: const InputDecoration( |
|
|
children: [ |
|
|
// labelText: "URL de l'image", |
|
|
Switch( |
|
|
// hintText: "/api/placeholder/300/200", |
|
|
value: disponible, |
|
|
// ), |
|
|
activeColor: Colors.green, |
|
|
// ), |
|
|
onChanged: (v) => setState(() => disponible = v), |
|
|
const SizedBox(height: 13), |
|
|
|
|
|
Row( |
|
|
|
|
|
children: [ |
|
|
|
|
|
Switch( |
|
|
|
|
|
value: disponible, |
|
|
|
|
|
activeColor: Colors.green, |
|
|
|
|
|
onChanged: (v) => setState(() => disponible = v), |
|
|
|
|
|
), |
|
|
|
|
|
const SizedBox(width: 7), |
|
|
|
|
|
const Text('Plat disponible'), |
|
|
|
|
|
], |
|
|
|
|
|
), |
|
|
|
|
|
const SizedBox(height: 22), |
|
|
|
|
|
Row( |
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.end, |
|
|
|
|
|
children: [ |
|
|
|
|
|
OutlinedButton( |
|
|
|
|
|
onPressed: () => Navigator.pop(context), |
|
|
|
|
|
child: const Text( |
|
|
|
|
|
"Annuler", |
|
|
|
|
|
style: TextStyle(color: Colors.black), |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
const SizedBox(width: 8), |
|
|
const SizedBox(width: 18), |
|
|
Text( |
|
|
ElevatedButton.icon( |
|
|
'Plat disponible', |
|
|
style: ElevatedButton.styleFrom( |
|
|
style: TextStyle( |
|
|
backgroundColor: Colors.green, |
|
|
fontSize: 16, |
|
|
|
|
|
color: disponible ? Colors.black87 : Colors.grey, |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
onPressed: submit, |
|
|
], |
|
|
icon: const Icon( |
|
|
), |
|
|
Icons.save, |
|
|
const SizedBox(height: 30), |
|
|
size: 18, |
|
|
|
|
|
color: Colors.white, |
|
|
// Boutons |
|
|
|
|
|
Row( |
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.end, |
|
|
|
|
|
children: [ |
|
|
|
|
|
OutlinedButton( |
|
|
|
|
|
onPressed: () => Navigator.pop(context), |
|
|
|
|
|
style: OutlinedButton.styleFrom( |
|
|
|
|
|
padding: const EdgeInsets.symmetric( |
|
|
|
|
|
horizontal: 24, |
|
|
|
|
|
vertical: 12, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
child: const Text( |
|
|
|
|
|
"Annuler", |
|
|
|
|
|
style: TextStyle(color: Colors.black54), |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
label: Text( |
|
|
const SizedBox(width: 16), |
|
|
isEdit ? "Enregistrer" : "Ajouter", |
|
|
ElevatedButton.icon( |
|
|
style: const TextStyle(color: Colors.white), |
|
|
style: ElevatedButton.styleFrom( |
|
|
|
|
|
backgroundColor: Colors.green[700], |
|
|
|
|
|
foregroundColor: Colors.white, |
|
|
|
|
|
padding: const EdgeInsets.symmetric( |
|
|
|
|
|
horizontal: 24, |
|
|
|
|
|
vertical: 12, |
|
|
|
|
|
), |
|
|
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
|
|
borderRadius: BorderRadius.circular(6), |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
onPressed: submit, |
|
|
|
|
|
icon: const Icon(Icons.save, size: 18), |
|
|
|
|
|
label: Text(isEdit ? "Enregistrer" : "Créer le plat"), |
|
|
), |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
@ -368,4 +329,4 @@ class _PlatEditPageState extends State<PlatEditPage> { |
|
|
), |
|
|
), |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |