123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704 |
- import 'package:flutter/foundation.dart';
- import 'package:flutter/material.dart';
- import 'package:yoshi_papas_app/widgets/widgets.dart';
- import '../../themes/themes.dart';
- class PedidoForm extends StatefulWidget {
- @override
- _PedidoFormState createState() => _PedidoFormState();
- }
- enum CustomizationStep { Base, Salsa, Aderezo, Toppings }
- class _PedidoFormState extends State<PedidoForm> {
- Map<String, bool> baseOptions = {};
- Map<String, bool> sauceOptions = {};
- Map<String, bool> dressingOptions = {};
- Map<String, bool> toppingOptions = {};
- bool isCustomizingProduct = false;
- Map<String, dynamic>? currentProductForCustomization;
- String? selectedBase;
- List<String> selectedSauce = [];
- List<String> selectedDressing = [];
- List<String> selectedToppings = [];
- List<Map<String, dynamic>> productsInCart = [];
- String currentCategory = 'Hamburguesa de pollo';
- Map<String, List<Map<String, dynamic>>> categoryProducts = {
- 'Hamburguesa de pollo': [
- {
- 'name': 'Rebanada de queso',
- 'price': 25,
- 'category': 'Hamburguesa de pollo'
- },
- {
- 'name': 'Porción de queso',
- 'price': 15,
- 'category': 'Hamburguesa de pollo'
- },
- {
- 'name': 'Hamburguesa de pollo',
- 'price': 110,
- 'category': 'Hamburguesa de pollo'
- },
- ],
- 'Postres': [
- {'name': 'Muffin', 'price': 35, 'category': 'Postres'},
- {'name': 'Rebanada de Pay de Nuez', 'price': 65, 'category': 'Postres'},
- ],
- 'Cono de papas': [
- {
- 'name': 'Cono de papas grande',
- 'price': 120,
- 'category': 'Cono de papas'
- },
- {
- 'name': 'Cono de papas mediano',
- 'price': 85,
- 'category': 'Cono de papas'
- },
- ],
- };
- List<Map<String, dynamic>> products = [];
- CustomizationStep _currentStep = CustomizationStep.Base;
- late Map<CustomizationStep, Widget> _stepWidgets;
- @override
- void initState() {
- super.initState();
- // Inicializa con la categoría actual
- products = categoryProducts[currentCategory]!;
- initializeCheckboxStates();
- _stepWidgets = {
- CustomizationStep.Base: _buildBaseOptions(),
- CustomizationStep.Salsa: _buildSauceOptions(),
- CustomizationStep.Aderezo: _buildDressingOptions(),
- CustomizationStep.Toppings: _buildToppingsOptions(),
- };
- }
- void customizeProduct(Map<String, dynamic> product) {
- if (product['category'] == 'Cono de papas') {
- setState(() {
- isCustomizingProduct = true;
- currentProductForCustomization = product;
- });
- } else {
- addToCart(product);
- }
- }
- void initializeCheckboxStates() {
- // Inicializa los mapas de opciones con valores false
- for (var base in [
- 'Papa Gajo',
- 'Papa Regilla',
- 'Papa Curly',
- 'Papa Smile',
- 'Papa Francesa'
- ]) {
- baseOptions[base] = false;
- }
- for (var sauce in [
- 'BBQ',
- 'HOTBBQ',
- 'BUFFALO',
- 'TERIYAKI',
- 'PARMESAN GARLIC',
- 'MANGO HABANERO'
- ]) {
- sauceOptions[sauce] = false;
- }
- for (var dressing in ['QUESO AMARILLO', 'RANCH', 'CHIPOTLE', 'KETCHUP']) {
- dressingOptions[dressing] = false;
- }
- for (var topping in [
- 'JALAPEÑO',
- 'QUESO BLANCO',
- 'TAKIS',
- 'RUFFLES',
- 'QUESO PARMESANO',
- 'ELOTE'
- ]) {
- toppingOptions[topping] = false;
- }
- }
- void addToCart(Map<String, dynamic> product) {
- // Si es un "Cono de papas" y estamos personalizando
- if (product['category'] == 'Cono de papas' && isCustomizingProduct) {
- final Map<String, dynamic> customizedProduct = {
- ...product,
- 'customizations': {
- 'base': selectedBase,
- 'sauce': selectedSauce,
- 'dressing': selectedDressing,
- 'toppings': selectedToppings,
- },
- 'quantity':
- 1, // Asegúrate de que cada producto personalizado tenga una cantidad inicial de 1
- };
- setState(() {
- productsInCart
- .add(customizedProduct); // Añade el producto personalizado
- isCustomizingProduct = false; // Termina la personalización
- resetCustomizations(); // Llama a un método que restablecerá las personalizaciones
- });
- } else {
- // Si no es un "Cono de papas" o no estamos personalizando, añade directamente al carrito
- setState(() {
- int index = productsInCart.indexWhere((p) =>
- p['name'] == product['name'] &&
- p['customizations'] ==
- product[
- 'customizations']); // Comparar también las personalizaciones
- if (index != -1) {
- productsInCart[index]['quantity'] += 1;
- } else {
- productsInCart.add(
- {...product, 'quantity': 1}); // Añade con cantidad inicial de 1
- }
- });
- }
- }
- void resetCustomizations() {
- // Restablece las variables de estado de las personalizaciones
- selectedBase = null;
- selectedSauce = [];
- selectedDressing = [];
- selectedToppings = [];
- // Restablecer cualquier otro estado de personalización aquí
- }
- void finalizeCustomization() {
- // Aquí debes construir el producto basado en las selecciones de personalización
- selectedBase = baseOptions.entries
- .firstWhere((entry) => entry.value, orElse: () => MapEntry('', false))
- .key;
- selectedSauce = sauceOptions.entries
- .where((entry) => entry.value)
- .map((e) => e.key)
- .toList();
- selectedDressing = dressingOptions.entries
- .where((entry) => entry.value)
- .map((e) => e.key)
- .toList();
- selectedToppings = toppingOptions.entries
- .where((entry) => entry.value)
- .map((e) => e.key)
- .toList();
- Map<String, dynamic> customizedProduct = {
- ...currentProductForCustomization!,
- 'customizations': {
- 'base': selectedBase,
- 'sauce': selectedSauce,
- 'dressing': selectedDressing,
- 'toppings': selectedToppings,
- }
- };
- addToCart(customizedProduct);
- setState(() {
- isCustomizingProduct = false;
- currentProductForCustomization = null;
- initializeCheckboxStates(); // Reinicia los estados de los checkbox
- });
- }
- Widget buildCategoryButtons() {
- return Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: categoryProducts.keys.map((String key) {
- return Padding(
- padding: const EdgeInsets.symmetric(horizontal: 4.0),
- child: OutlinedButton(
- onPressed: () {
- setState(() {
- currentCategory = key;
- products = categoryProducts[key]!;
- });
- },
- style: OutlinedButton.styleFrom(
- backgroundColor: Colors.white,
- foregroundColor: Colors.black,
- side: BorderSide(
- width: 2.0,
- color: currentCategory == key ? AppTheme.primary : Colors.grey,
- ),
- ),
- child: Text(key),
- ),
- );
- }).toList(),
- );
- }
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: encabezado(
- titulo: "CREAR PEDIDO",
- ),
- body: Row(
- children: [
- // Sección izquierda con la lista del carrito - 30%
- Flexible(
- flex: 3,
- child: tarjeta(
- Column(
- children: [
- // Encabezados de la lista
- const Padding(
- padding:
- EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text('Producto',
- style: TextStyle(
- fontWeight: FontWeight.bold, fontSize: 18)),
- Text('Cantidad',
- style: TextStyle(
- fontWeight: FontWeight.bold, fontSize: 18)),
- ],
- ),
- ),
- // Lista de productos
- Expanded(
- child: ListView.builder(
- itemCount: productsInCart.length,
- itemBuilder: (context, index) {
- var product = productsInCart[index];
- return ListTile(
- title: _buildProductItem(product),
- trailing: Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- IconButton(
- icon: const Icon(Icons.remove),
- onPressed: () {
- // Lógica para disminuir la cantidad
- setState(() {
- if (product['quantity'] > 1) {
- productsInCart[index]['quantity'] -= 1;
- } else {
- productsInCart.removeAt(index);
- }
- });
- },
- ),
- Text('${product['quantity'] ?? 1}'),
- IconButton(
- icon: const Icon(Icons.add),
- onPressed: () {
- // Lógica para aumentar la cantidad
- setState(() {
- productsInCart[index]['quantity'] += 1;
- });
- },
- ),
- ],
- ),
- );
- },
- ),
- ),
- ElevatedButton(
- style: ButtonStyle(
- backgroundColor:
- MaterialStatePropertyAll(AppTheme.primary),
- textStyle: const MaterialStatePropertyAll(
- TextStyle(fontSize: 22)),
- foregroundColor:
- const MaterialStatePropertyAll(Colors.black),
- padding: const MaterialStatePropertyAll(
- EdgeInsets.fromLTRB(80, 20, 80, 20))),
- onPressed: () {
- // Aquí agregarías la lógica para guardar el pedido
- },
- child: const Text('Guardar'),
- ),
- ],
- ),
- color: Colors.white,
- padding: 8.0,
- ),
- ),
- const SizedBox(
- width: 35,
- ),
- // Sección derecha con los productos disponibles - 70%
- Flexible(
- flex: 7,
- child: Column(
- children: [
- // Botones de categorías de productos
- buildCategoryButtons(),
- // GridView de productos
- Expanded(
- child: isCustomizingProduct
- ? buildCustomizationOptions()
- : buildProductGrid(),
- ),
- ],
- ),
- ),
- ],
- ),
- );
- }
- Widget _buildProductItem(Map<String, dynamic> product) {
- List<Widget> customizationWidgets = [];
- if (product.containsKey('customizations')) {
- Map customizations = product['customizations'];
- customizationWidgets.addAll([
- Text(' - Base: ${customizations['base']}'),
- ...customizations['sauce']
- .map<Widget>((sauce) => Text(' - Salsa: $sauce'))
- .toList(),
- ...customizations['dressing']
- .map<Widget>((dressing) => Text(' - Aderezo: $dressing'))
- .toList(),
- ...customizations['toppings']
- .map<Widget>((topping) => Text(' - Topping: $topping'))
- .toList(),
- ]);
- }
- return Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(product['name']),
- ...customizationWidgets,
- ],
- );
- }
- Widget buildProductGrid() {
- return tarjeta(
- GridView.builder(
- itemCount: products.length,
- gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
- crossAxisCount: 2, // Número de columnas
- childAspectRatio: 3 / 2, // Proporción de cada tarjeta
- crossAxisSpacing: 10, // Espaciado horizontal
- mainAxisSpacing: 10, // Espaciado vertical
- ),
- itemBuilder: (context, index) {
- final product = products[index];
- return tarjeta(
- InkWell(
- onTap: () => customizeProduct(product),
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- // Añade el ícono aquí
- const Icon(Icons.fastfood,
- size: 80), // Tamaño del ícono ajustable
- const SizedBox(height: 8), // Espacio entre ícono y texto
- Text(
- product['name'],
- style: const TextStyle(fontSize: 16),
- textAlign: TextAlign.center,
- ),
- const SizedBox(height: 8), // Espacio entre texto y precio
- Text(
- '\$${product['price']}',
- style:
- const TextStyle(fontSize: 24, color: Color(0xFF008000)),
- textAlign: TextAlign.center,
- ),
- ],
- ),
- ),
- color: const Color(0xFFF4F4F4),
- padding: 8.0,
- );
- },
- ),
- color: Colors.white,
- padding: 8.0,
- );
- }
- Widget buildCustomizationOptions() {
- Widget currentStepWidget;
- switch (_currentStep) {
- case CustomizationStep.Base:
- currentStepWidget = _buildBaseOptions();
- break;
- case CustomizationStep.Salsa:
- currentStepWidget = _buildSauceOptions();
- break;
- case CustomizationStep.Aderezo:
- currentStepWidget = _buildDressingOptions();
- break;
- case CustomizationStep.Toppings:
- currentStepWidget = _buildToppingsOptions();
- break;
- default:
- currentStepWidget = SizedBox.shrink();
- }
- // Solo muestra el botón de confirmación si isCustomizingProduct es true.
- Widget confirmButton = isCustomizingProduct
- ? Padding(
- padding: const EdgeInsets.symmetric(vertical: 16.0),
- child: _buildConfirmButton(),
- )
- : SizedBox.shrink();
- return tarjeta(
- Column(
- children: [
- Expanded(
- child: Row(
- children: [
- Flexible(
- flex: 3,
- child: ListView(
- children: CustomizationStep.values.map((step) {
- // Verifica si el paso es Salsa, Aderezo o Toppings para añadir el texto " (Max 2)"
- String stepName = describeEnum(step);
- if (step == CustomizationStep.Salsa ||
- step == CustomizationStep.Aderezo ||
- step == CustomizationStep.Toppings) {
- stepName +=
- " (Max 2)"; // Agrega " (Max 2)" al nombre del paso+
- }
- return ListTile(
- title: Text(stepName),
- selected: _currentStep == step,
- onTap: () => setState(() => _currentStep = step),
- );
- }).toList(),
- ),
- ),
- Flexible(
- flex: 7,
- child: currentStepWidget,
- ),
- ],
- ),
- ),
- Padding(
- padding: const EdgeInsets.symmetric(vertical: 16.0),
- child: _buildConfirmButton(),
- ), // Incluir el botón de confirmación aquí
- ],
- ),
- color: Colors.white,
- padding: 8.0,
- );
- }
- Widget buildCheckboxListTile({
- required String title,
- required Map<String, bool> optionsMap,
- required Function(String, bool?) onChanged,
- }) {
- return CheckboxListTile(
- title: Text(title),
- value: optionsMap[title] ?? false,
- onChanged: (bool? value) {
- setState(() {
- onChanged(title, value);
- });
- },
- secondary: Image.asset('assets/JoshiLogo.png', width: 30),
- );
- }
- Widget _buildBaseOptions() {
- return GridView.count(
- crossAxisCount: 3,
- children: baseOptions.keys.map((String key) {
- bool isSelected =
- baseOptions[key] ?? false; // Determina si está seleccionado
- return GestureDetector(
- onTap: () {
- setState(() {
- baseOptions.keys.forEach(
- (k) => baseOptions[k] = false); // Desmarca todos primero
- baseOptions[key] = true; // Marca el seleccionado
- });
- },
- child: Container(
- decoration: BoxDecoration(
- color: isSelected ? AppTheme.primary : const Color(0xFFF4F4F4),
- border: Border.all(color: isSelected ? Colors.red : Colors.grey),
- ),
- child: Center(
- child: Text(key,
- style: TextStyle(
- color: isSelected ? Colors.white : Colors.black)),
- ),
- ),
- );
- }).toList(),
- );
- }
- Widget _buildSauceOptions() {
- return GridView.count(
- crossAxisCount: 3,
- children: sauceOptions.keys.map((String key) {
- bool isSelected = sauceOptions[key] ?? false;
- return GestureDetector(
- onTap: () {
- int selectedCount = sauceOptions.values.where((b) => b).length;
- setState(() {
- // Si la salsa ya está seleccionada, la deselecciona.
- if (isSelected) {
- sauceOptions[key] = false;
- } else {
- // Si se están seleccionando menos de 2 salsas, permite esta selección.
- if (selectedCount < 2) {
- sauceOptions[key] = true;
- } else {
- // Si ya hay 2 salsas seleccionadas, primero deselecciona la primera seleccionada.
- final firstSelected = sauceOptions.keys.firstWhere(
- (k) => sauceOptions[k]!,
- orElse: () => '',
- );
- if (firstSelected.isNotEmpty) {
- sauceOptions[firstSelected] = false;
- sauceOptions[key] = true;
- }
- }
- }
- });
- },
- child: Container(
- decoration: BoxDecoration(
- color: isSelected ? AppTheme.primary : const Color(0xFFF4F4F4),
- border: Border.all(color: Colors.grey),
- ),
- child: Center(
- child: Text(key,
- style: TextStyle(
- color: isSelected ? Colors.white : Colors.black)),
- ),
- ),
- );
- }).toList(),
- );
- }
- Widget _buildDressingOptions() {
- return GridView.count(
- crossAxisCount: 3,
- children: dressingOptions.keys.map((String key) {
- bool isSelected = dressingOptions[key] ?? false;
- return GestureDetector(
- onTap: () {
- int selectedCount = dressingOptions.values.where((b) => b).length;
- setState(() {
- // Si la salsa ya está seleccionada, la deselecciona.
- if (isSelected) {
- dressingOptions[key] = false;
- } else {
- // Si se están seleccionando menos de 2 salsas, permite esta selección.
- if (selectedCount < 2) {
- dressingOptions[key] = true;
- } else {
- // Si ya hay 2 salsas seleccionadas, primero deselecciona la primera seleccionada.
- final firstSelected = dressingOptions.keys.firstWhere(
- (k) => dressingOptions[k]!,
- orElse: () => '',
- );
- if (firstSelected.isNotEmpty) {
- dressingOptions[firstSelected] = false;
- dressingOptions[key] = true;
- }
- }
- }
- });
- },
- child: Container(
- decoration: BoxDecoration(
- color: isSelected ? AppTheme.primary : const Color(0xFFF4F4F4),
- border: Border.all(color: Colors.grey),
- ),
- child: Center(
- child: Text(key,
- style: TextStyle(
- color: isSelected ? Colors.white : Colors.black)),
- ),
- ),
- );
- }).toList(),
- );
- }
- Widget _buildToppingsOptions() {
- return GridView.count(
- crossAxisCount: 3,
- children: toppingOptions.keys.map((String key) {
- bool isSelected = toppingOptions[key] ?? false;
- return GestureDetector(
- onTap: () {
- int selectedCount = toppingOptions.values.where((b) => b).length;
- setState(() {
- // Si la salsa ya está seleccionada, la deselecciona.
- if (isSelected) {
- toppingOptions[key] = false;
- } else {
- // Si se están seleccionando menos de 2 salsas, permite esta selección.
- if (selectedCount < 2) {
- toppingOptions[key] = true;
- } else {
- // Si ya hay 2 salsas seleccionadas, primero deselecciona la primera seleccionada.
- final firstSelected = toppingOptions.keys.firstWhere(
- (k) => toppingOptions[k]!,
- orElse: () => '',
- );
- if (firstSelected.isNotEmpty) {
- toppingOptions[firstSelected] = false;
- toppingOptions[key] = true;
- }
- }
- }
- });
- },
- child: Container(
- decoration: BoxDecoration(
- color: isSelected ? AppTheme.primary : const Color(0xFFF4F4F4),
- border: Border.all(color: Colors.grey),
- ),
- child: Center(
- child: Text(key,
- style: TextStyle(
- color: isSelected ? Colors.white : Colors.black)),
- ),
- ),
- );
- }).toList(),
- );
- }
- Widget _buildConfirmButton() {
- return ElevatedButton(
- style: ElevatedButton.styleFrom(
- primary: AppTheme.primary, // Color del botón
- onPrimary: Colors.black,
- textStyle: const TextStyle(fontSize: 22),
- padding: const EdgeInsets.fromLTRB(80, 20, 80, 20)),
- onPressed: () {
- finalizeCustomization(); // Este método creará el pedido personalizado
- },
- child: Text('Confirmar Pedido'),
- );
- }
- }
|