|
@@ -1,9 +1,11 @@
|
|
|
+import 'dart:async';
|
|
|
+
|
|
|
import 'package:flutter/foundation.dart';
|
|
|
import 'package:flutter/material.dart';
|
|
|
import 'package:yoshi_papas_app/widgets/widgets_components.dart';
|
|
|
-import '../../themes/themes.dart'; // Asegúrate de tener este archivo con los temas correctos
|
|
|
-import '../../models/models.dart'; // Tus modelos de datos
|
|
|
-import '../../viewmodels/viewmodels.dart'; // Tus ViewModels
|
|
|
+import '../../themes/themes.dart';
|
|
|
+import '../../models/models.dart';
|
|
|
+import '../../viewmodels/viewmodels.dart';
|
|
|
import 'package:collection/collection.dart';
|
|
|
|
|
|
class PedidoForm extends StatefulWidget {
|
|
@@ -43,11 +45,12 @@ class _PedidoFormState extends State<PedidoForm> {
|
|
|
Map<String, bool> baseOptions = {};
|
|
|
Map<String, bool> sauceOptions = {};
|
|
|
Map<String, bool> dressingOptions = {};
|
|
|
- Map<String, bool> toppingOptions = {};
|
|
|
List<TopingCategoria> categoriasDeTopings = []; // Añade esta línea
|
|
|
TopingCategoria? _currentTopingCategoriaSeleccionada; // Añade esta línea
|
|
|
List<Toping> _topingsFiltrados = []; // Añade esta línea
|
|
|
- Map<int, List<String>> selectedToppingsByCategory = {};
|
|
|
+ Map<int, List<int>> selectedToppingsByCategory = {};
|
|
|
+ Map<String, bool> toppingOptions = {};
|
|
|
+ List<int> _selectedToppings = [];
|
|
|
|
|
|
double calcularTotalPedido() {
|
|
|
double total = 0;
|
|
@@ -104,37 +107,51 @@ class _PedidoFormState extends State<PedidoForm> {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- void _onTopingSelected(Toping toping) {
|
|
|
- print("Topping seleccionado antes de setState: ${toping.nombre}");
|
|
|
- setState(() {
|
|
|
- // Obtiene la lista actual de toppings seleccionados para la categoría
|
|
|
- final currentSelections =
|
|
|
- selectedToppingsByCategory[_currentTopingCategoriaSeleccionada!.id] ??
|
|
|
- [];
|
|
|
-
|
|
|
- if (currentSelections.contains(toping.nombre)) {
|
|
|
- // Si el topping ya está seleccionado, lo deselecciona
|
|
|
- currentSelections.remove(toping.nombre);
|
|
|
+ void _onToppingSelected(Toping topping) {
|
|
|
+ // Verifica si el topping ya está seleccionado
|
|
|
+ bool isSelected = _selectedToppings.contains(topping.id);
|
|
|
+
|
|
|
+ final List<int> currentSelectedToppings =
|
|
|
+ selectedToppingsByCategory[_currentTopingCategoriaSeleccionada!.id] ??
|
|
|
+ [];
|
|
|
+
|
|
|
+ if (isSelected) {
|
|
|
+ // Si ya está seleccionado, lo deseleccionamos
|
|
|
+ setState(() {
|
|
|
+ _selectedToppings.remove(topping.id);
|
|
|
+ currentSelectedToppings.remove(topping.id);
|
|
|
+ selectedToppingsByCategory[_currentTopingCategoriaSeleccionada!.id] =
|
|
|
+ List.from(currentSelectedToppings);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // Si no está seleccionado, verifica las restricciones antes de seleccionar
|
|
|
+ if (_currentTopingCategoriaSeleccionada!.id == 1 &&
|
|
|
+ currentSelectedToppings.isNotEmpty) {
|
|
|
+ // Si es la categoría 'Base', solo permite una selección
|
|
|
+ setState(() {
|
|
|
+ currentSelectedToppings.clear();
|
|
|
+ currentSelectedToppings.add(topping.id);
|
|
|
+ _selectedToppings.clear();
|
|
|
+ _selectedToppings.add(topping.id);
|
|
|
+ });
|
|
|
} else {
|
|
|
- // Comprobar las reglas de selección
|
|
|
- if (_currentTopingCategoriaSeleccionada!.nombre == 'Base' ||
|
|
|
- currentSelections.length < 2) {
|
|
|
- // Si es la categoría 'Base' o hay menos de 2 selecciones, selecciona el topping
|
|
|
- if (_currentTopingCategoriaSeleccionada!.nombre == 'Base') {
|
|
|
- // Si es 'Base', solo permite una selección
|
|
|
- currentSelections.clear();
|
|
|
- }
|
|
|
- currentSelections.add(toping.nombre!);
|
|
|
+ // Si la lista ya tiene dos toppings, quita el primero y agrega el nuevo
|
|
|
+ if (currentSelectedToppings.length >= 2) {
|
|
|
+ setState(() {
|
|
|
+ _selectedToppings.remove(currentSelectedToppings.first);
|
|
|
+ currentSelectedToppings
|
|
|
+ .removeAt(0); // Elimina el primer topping seleccionado
|
|
|
+ });
|
|
|
}
|
|
|
- // De lo contrario, no se permite la selección y puedes mostrar un mensaje o algo similar
|
|
|
+ // Ahora agrega el nuevo topping seleccionado
|
|
|
+ setState(() {
|
|
|
+ currentSelectedToppings.add(topping.id);
|
|
|
+ _selectedToppings.add(topping.id);
|
|
|
+ });
|
|
|
}
|
|
|
-
|
|
|
- // Actualiza el mapa con las nuevas selecciones
|
|
|
selectedToppingsByCategory[_currentTopingCategoriaSeleccionada!.id] =
|
|
|
- currentSelections;
|
|
|
- });
|
|
|
- print(
|
|
|
- "Toppings seleccionados después de setState: ${selectedToppingsByCategory[_currentTopingCategoriaSeleccionada!.id]}");
|
|
|
+ List.from(currentSelectedToppings);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@override
|
|
@@ -197,13 +214,16 @@ class _PedidoFormState extends State<PedidoForm> {
|
|
|
}
|
|
|
|
|
|
void addToCart(Producto producto, {Map<String, dynamic>? customizations}) {
|
|
|
- var existingIndex =
|
|
|
- carrito.indexWhere((item) => item.producto.id == producto.id);
|
|
|
+ // Revisa si hay un producto en el carrito con las mismas customizaciones
|
|
|
+ var existingIndex = carrito.indexWhere((item) =>
|
|
|
+ item.producto.id == producto.id &&
|
|
|
+ mapEquals(item.customizaciones, customizations));
|
|
|
+
|
|
|
if (existingIndex != -1) {
|
|
|
carrito[existingIndex].cantidad++;
|
|
|
} else {
|
|
|
- carrito.add(
|
|
|
- ItemCarrito(producto: producto, customizaciones: customizations));
|
|
|
+ carrito.add(ItemCarrito(
|
|
|
+ producto: producto, cantidad: 1, customizaciones: customizations));
|
|
|
}
|
|
|
setState(() {});
|
|
|
}
|
|
@@ -228,17 +248,43 @@ class _PedidoFormState extends State<PedidoForm> {
|
|
|
|
|
|
void finalizeCustomization() {
|
|
|
if (_productoActual != null) {
|
|
|
- Map<String, dynamic> customizations = {
|
|
|
- 'base': selectedBase,
|
|
|
- 'sauce': selectedSauce,
|
|
|
- 'dressing': selectedDressing,
|
|
|
- 'toppings': selectedToppings,
|
|
|
+ // Prepara el diccionario de customizaciones con listas vacías para cada categoría
|
|
|
+ Map<String, List<String>> customizations = {
|
|
|
+ 'BASE': [],
|
|
|
+ 'SALSA': [],
|
|
|
+ 'ADEREZO': [],
|
|
|
+ 'TOPPINGS': [],
|
|
|
};
|
|
|
- addToCart(_productoActual!, customizations: customizations);
|
|
|
+
|
|
|
+ // Itera sobre los toppings seleccionados, clasificándolos por categoría
|
|
|
+ selectedToppingsByCategory.forEach((categoryId, toppingIds) {
|
|
|
+ var categoryName = _categoriaTopingViewModel.getById(categoryId)?.clave;
|
|
|
+ toppingIds.forEach((toppingId) {
|
|
|
+ var topping = _topingViewModel.getById(toppingId);
|
|
|
+ if (topping != null &&
|
|
|
+ categoryName != null &&
|
|
|
+ customizations.containsKey(categoryName.toUpperCase())) {
|
|
|
+ customizations[categoryName.toUpperCase()]!.add(topping.nombre!);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // Asegúrate de que la customización final se almacene como deseas, por ejemplo, como un solo mapa si es necesario
|
|
|
+ Map<String, dynamic> finalCustomizations = {};
|
|
|
+ customizations.forEach((key, value) {
|
|
|
+ finalCustomizations[key] = value.join(', ');
|
|
|
+ });
|
|
|
+
|
|
|
+ addToCart(_productoActual!, customizations: finalCustomizations);
|
|
|
+
|
|
|
+ // Limpia el estado para la siguiente personalización
|
|
|
setState(() {
|
|
|
- isCustomizingProduct = false; // Salir del modo de customización
|
|
|
- _productoActual = null; // Resetear el producto actual
|
|
|
- // También resetear las opciones de customización aquí si es necesario
|
|
|
+ isCustomizingProduct = false;
|
|
|
+ _productoActual = null;
|
|
|
+ _currentTopingCategoriaSeleccionada = null; // Agrega esta línea
|
|
|
+ _topingsFiltrados.clear(); // Agrega esta línea
|
|
|
+ selectedToppingsByCategory.clear(); // Agrega esta línea
|
|
|
+ _selectedToppings.clear(); // Ya existe, asegúrate de que se llama
|
|
|
});
|
|
|
}
|
|
|
}
|
|
@@ -285,6 +331,23 @@ class _PedidoFormState extends State<PedidoForm> {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+ List<Widget> _buildToppingList(Map<String, dynamic>? customizations) {
|
|
|
+ List<Widget> list = [];
|
|
|
+ customizations?.forEach((category, toppingsAsString) {
|
|
|
+ if (toppingsAsString is String && toppingsAsString.isNotEmpty) {
|
|
|
+ // Divide la string por comas para obtener los nombres individuales de los toppings
|
|
|
+ List<String> toppingNames = toppingsAsString.split(', ');
|
|
|
+ for (var toppingName in toppingNames) {
|
|
|
+ list.add(ListTile(
|
|
|
+ title: Text(toppingName),
|
|
|
+ subtitle: Text(category), // Muestra la categoría como subtítulo
|
|
|
+ ));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
Widget _buildCartSection() {
|
|
|
return Card(
|
|
|
margin: const EdgeInsets.all(8.0),
|
|
@@ -309,34 +372,71 @@ class _PedidoFormState extends State<PedidoForm> {
|
|
|
itemCount: carrito.length,
|
|
|
itemBuilder: (context, index) {
|
|
|
final item = carrito[index];
|
|
|
- return ListTile(
|
|
|
- title: Text(item.producto.nombre!),
|
|
|
- subtitle: Text('\$${item.producto.precio}'),
|
|
|
- trailing: Row(
|
|
|
- mainAxisSize: MainAxisSize.min,
|
|
|
- children: [
|
|
|
- IconButton(
|
|
|
- icon: const Icon(Icons.delete, color: Colors.red),
|
|
|
- onPressed: () => eliminarProductoDelCarrito(index),
|
|
|
+ // Crear una lista de Widgets para las customizaciones.
|
|
|
+ List<Widget> customizationWidgets = [];
|
|
|
+ item.customizaciones?.forEach((category, toppingsAsString) {
|
|
|
+ if (toppingsAsString is String &&
|
|
|
+ toppingsAsString.isNotEmpty) {
|
|
|
+ // Si hay más de un topping en la cadena, sepáralos y muéstralos en la misma línea
|
|
|
+ customizationWidgets.add(
|
|
|
+ Align(
|
|
|
+ alignment: Alignment.centerLeft,
|
|
|
+ child: Padding(
|
|
|
+ padding: const EdgeInsets.only(left: 16.0, top: 4.0),
|
|
|
+ child: Text(
|
|
|
+ '- $category: $toppingsAsString', // Cambio clave aquí
|
|
|
+ style: const TextStyle(
|
|
|
+ fontWeight: FontWeight.w500,
|
|
|
+ fontSize: 14.0,
|
|
|
+ )),
|
|
|
+ ),
|
|
|
),
|
|
|
- IconButton(
|
|
|
- icon: const Icon(Icons.remove),
|
|
|
- onPressed: () => quitarDelCarrito(item.producto),
|
|
|
+ );
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return Column(
|
|
|
+ children: [
|
|
|
+ ListTile(
|
|
|
+ title: Text(
|
|
|
+ item.producto.nombre!,
|
|
|
+ style: const TextStyle(fontWeight: FontWeight.w600),
|
|
|
),
|
|
|
- const SizedBox(width: 5),
|
|
|
- Text(
|
|
|
- '${item.cantidad}',
|
|
|
+ subtitle: Text(
|
|
|
+ '\$${item.producto.precio}',
|
|
|
style: const TextStyle(
|
|
|
- fontWeight: FontWeight.bold, fontSize: 14),
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
+ color: Color(0xFF008000)),
|
|
|
),
|
|
|
- const SizedBox(width: 5),
|
|
|
- IconButton(
|
|
|
- icon: const Icon(Icons.add),
|
|
|
- onPressed: () => agregarAlCarrito(item.producto),
|
|
|
+ trailing: Row(
|
|
|
+ mainAxisSize: MainAxisSize.min,
|
|
|
+ children: [
|
|
|
+ IconButton(
|
|
|
+ icon: const Icon(Icons.delete, color: Colors.red),
|
|
|
+ onPressed: () => eliminarProductoDelCarrito(index),
|
|
|
+ ),
|
|
|
+ IconButton(
|
|
|
+ icon: const Icon(Icons.remove),
|
|
|
+ onPressed: () => quitarDelCarrito(item.producto),
|
|
|
+ ),
|
|
|
+ const SizedBox(width: 5),
|
|
|
+ Text(
|
|
|
+ '${item.cantidad}',
|
|
|
+ style: const TextStyle(
|
|
|
+ fontWeight: FontWeight.bold, fontSize: 14),
|
|
|
+ ),
|
|
|
+ const SizedBox(width: 5),
|
|
|
+ IconButton(
|
|
|
+ icon: const Icon(Icons.add),
|
|
|
+ onPressed: () => agregarAlCarrito(item.producto),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
),
|
|
|
- // Botón para eliminar el producto del carrito
|
|
|
- ],
|
|
|
- ),
|
|
|
+ ),
|
|
|
+ // Coloca aquí las customizaciones directamente.
|
|
|
+ ...customizationWidgets,
|
|
|
+ Divider(), // Opcional: Un divisor visual entre los elementos.
|
|
|
+ ],
|
|
|
);
|
|
|
},
|
|
|
),
|
|
@@ -493,7 +593,7 @@ class _PedidoFormState extends State<PedidoForm> {
|
|
|
return ListTile(
|
|
|
title: Text(
|
|
|
categoria.nombre ?? 'N/A',
|
|
|
- style: TextStyle(
|
|
|
+ style: const TextStyle(
|
|
|
fontSize: 16, fontWeight: FontWeight.bold),
|
|
|
),
|
|
|
selected:
|
|
@@ -501,6 +601,27 @@ class _PedidoFormState extends State<PedidoForm> {
|
|
|
trailing: Image.network(
|
|
|
categoria.mediaTopingCategoria[0].media!.ruta!,
|
|
|
width: 80,
|
|
|
+ loadingBuilder: (BuildContext context, Widget child,
|
|
|
+ ImageChunkEvent? loadingProgress) {
|
|
|
+ if (loadingProgress == null) return child;
|
|
|
+ return Center(
|
|
|
+ child: CircularProgressIndicator(
|
|
|
+ value: loadingProgress.expectedTotalBytes !=
|
|
|
+ null
|
|
|
+ ? loadingProgress.cumulativeBytesLoaded /
|
|
|
+ loadingProgress.expectedTotalBytes!
|
|
|
+ : null,
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ },
|
|
|
+ errorBuilder: (BuildContext context,
|
|
|
+ Object exception, StackTrace? stackTrace) {
|
|
|
+ // Aquí puedes devolver un widget como un ícono o imagen local para indicar el error
|
|
|
+ return const Icon(
|
|
|
+ Icons.menu_book,
|
|
|
+ size: 30,
|
|
|
+ );
|
|
|
+ },
|
|
|
),
|
|
|
onTap: () {
|
|
|
setState(() {
|
|
@@ -522,21 +643,57 @@ class _PedidoFormState extends State<PedidoForm> {
|
|
|
const SliverGridDelegateWithFixedCrossAxisCount(
|
|
|
crossAxisCount: 3,
|
|
|
),
|
|
|
- itemCount: _topingsFiltrados.length,
|
|
|
+ itemCount: _topingsFiltrados
|
|
|
+ .length, // Usando _topingsFiltrados directamente
|
|
|
itemBuilder: (context, index) {
|
|
|
- final toping = _topingsFiltrados[index];
|
|
|
+ final topping = _topingsFiltrados[index];
|
|
|
+ bool isSelected =
|
|
|
+ _selectedToppings.contains(topping.id);
|
|
|
+
|
|
|
return Card(
|
|
|
+ color: isSelected
|
|
|
+ ? const Color(0xFFFC8178)
|
|
|
+ : Colors.white,
|
|
|
child: InkWell(
|
|
|
- onTap: () => _onTopingSelected(toping),
|
|
|
+ onTap: () => _onToppingSelected(topping),
|
|
|
child: Column(
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
children: [
|
|
|
- // Aquí iría la imagen del toping, asegúrate de manejar errores de red.
|
|
|
Image.network(
|
|
|
- toping.mediaToping[0].media!.ruta!,
|
|
|
+ topping.mediaToping[0].media!.ruta!,
|
|
|
width: 80,
|
|
|
+ loadingBuilder: (BuildContext context,
|
|
|
+ Widget child,
|
|
|
+ ImageChunkEvent? loadingProgress) {
|
|
|
+ if (loadingProgress == null) return child;
|
|
|
+ return Center(
|
|
|
+ child: CircularProgressIndicator(
|
|
|
+ value: loadingProgress
|
|
|
+ .expectedTotalBytes !=
|
|
|
+ null
|
|
|
+ ? loadingProgress
|
|
|
+ .cumulativeBytesLoaded /
|
|
|
+ loadingProgress
|
|
|
+ .expectedTotalBytes!
|
|
|
+ : null,
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ },
|
|
|
+ errorBuilder: (BuildContext context,
|
|
|
+ Object exception,
|
|
|
+ StackTrace? stackTrace) {
|
|
|
+ // Aquí puedes devolver un widget como un ícono o imagen local para indicar el error
|
|
|
+ return const Icon(
|
|
|
+ Icons.lunch_dining,
|
|
|
+ size: 60,
|
|
|
+ );
|
|
|
+ },
|
|
|
),
|
|
|
- Text(toping.nombre!),
|
|
|
+ Text(topping.nombre!,
|
|
|
+ style: TextStyle(
|
|
|
+ color: isSelected
|
|
|
+ ? Colors.white
|
|
|
+ : Colors.black)),
|
|
|
],
|
|
|
),
|
|
|
),
|
|
@@ -559,191 +716,6 @@ class _PedidoFormState extends State<PedidoForm> {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- 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.builder(
|
|
|
- key: ValueKey(_topingsFiltrados.length),
|
|
|
- gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
|
|
- crossAxisCount: 3,
|
|
|
- ),
|
|
|
- itemCount: _topingsFiltrados.length,
|
|
|
- itemBuilder: (context, index) {
|
|
|
- final toping = _topingsFiltrados[index];
|
|
|
- // Verifica si el topping está seleccionado consultando el mapa
|
|
|
- final isSelected =
|
|
|
- selectedToppingsByCategory[_currentTopingCategoriaSeleccionada!.id]
|
|
|
- ?.contains(toping.nombre) ??
|
|
|
- false;
|
|
|
-
|
|
|
- return Card(
|
|
|
- color: isSelected
|
|
|
- ? Colors.red
|
|
|
- : Colors.white, // Cambia el color si está seleccionado
|
|
|
- child: InkWell(
|
|
|
- onTap: () => _onTopingSelected(toping),
|
|
|
- child: Column(
|
|
|
- mainAxisAlignment: MainAxisAlignment.center,
|
|
|
- children: [
|
|
|
- Image.network(
|
|
|
- toping.mediaToping[0].media!.ruta!,
|
|
|
- fit: BoxFit.cover,
|
|
|
- width: 80,
|
|
|
- height: 80,
|
|
|
- ),
|
|
|
- Text(
|
|
|
- toping.nombre!,
|
|
|
- style: TextStyle(
|
|
|
- color: isSelected ? Colors.white : Colors.black,
|
|
|
- ),
|
|
|
- ),
|
|
|
- ],
|
|
|
- ),
|
|
|
- ),
|
|
|
- );
|
|
|
- },
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- Widget _buildToppingOptionsForCategory(int idCategoria) {
|
|
|
- var toppingsDeCategoria =
|
|
|
- _topingsDisponibles.where((t) => t.idCategoria == idCategoria).toList();
|
|
|
-
|
|
|
- return GridView.count(
|
|
|
- crossAxisCount: 3,
|
|
|
- children: toppingsDeCategoria.map((topping) {
|
|
|
- return GestureDetector(
|
|
|
- onTap: () {
|
|
|
- // Lógica para seleccionar/deseleccionar topping
|
|
|
- },
|
|
|
- child: Container(
|
|
|
- // Construye tu widget de topping aquí, podrías incluir la imagen y el nombre
|
|
|
- ),
|
|
|
- );
|
|
|
- }).toList(),
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
Widget _buildConfirmButton() {
|
|
|
return ElevatedButton(
|
|
|
style: ElevatedButton.styleFrom(
|