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 { Map baseOptions = {}; Map sauceOptions = {}; Map dressingOptions = {}; Map toppingOptions = {}; bool isCustomizingProduct = false; Map? currentProductForCustomization; String? selectedBase; List selectedSauce = []; List selectedDressing = []; List selectedToppings = []; List> productsInCart = []; String currentCategory = 'Hamburguesa de pollo'; Map>> 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> products = []; CustomizationStep _currentStep = CustomizationStep.Base; late Map _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 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 product) { // Si es un "Cono de papas" y estamos personalizando if (product['category'] == 'Cono de papas' && isCustomizingProduct) { final Map 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 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 product) { List customizationWidgets = []; if (product.containsKey('customizations')) { Map customizations = product['customizations']; customizationWidgets.addAll([ Text(' - Base: ${customizations['base']}'), ...customizations['sauce'] .map((sauce) => Text(' - Salsa: $sauce')) .toList(), ...customizations['dressing'] .map((dressing) => Text(' - Aderezo: $dressing')) .toList(), ...customizations['toppings'] .map((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 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'), ); } }