|
@@ -1,10 +1,640 @@
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
|
-class ProductScreen extends StatelessWidget {
|
|
|
- const ProductScreen({super.key});
|
|
|
+class Product {
|
|
|
+ final String id;
|
|
|
+ final String nombre;
|
|
|
+ final String descripcion;
|
|
|
+ final double precio;
|
|
|
+ final String imageUrl;
|
|
|
+ final List<String> availableToppings;
|
|
|
+ final List<String> availableDrinks;
|
|
|
+ final List<String> availableCookingTerms;
|
|
|
+ final bool hasCheeseOption;
|
|
|
+ final double cheeseprecio;
|
|
|
+
|
|
|
+ Product({
|
|
|
+ required this.id,
|
|
|
+ required this.nombre,
|
|
|
+ required this.descripcion,
|
|
|
+ required this.precio,
|
|
|
+ required this.imageUrl,
|
|
|
+ required this.availableToppings,
|
|
|
+ required this.availableDrinks,
|
|
|
+ required this.availableCookingTerms,
|
|
|
+ required this.hasCheeseOption,
|
|
|
+ required this.cheeseprecio,
|
|
|
+ });
|
|
|
+
|
|
|
+ factory Product.staticSandwich() {
|
|
|
+ return Product(
|
|
|
+ id: 'p1',
|
|
|
+ nombre: 'Sandwich de pollo',
|
|
|
+ descripcion:
|
|
|
+ 'Queso, Lechuga, tomate, cebolla, pepinillo, mayonesa, ketchup y moztaza. Acompañado de Papas y Soda',
|
|
|
+ precio: 115.00,
|
|
|
+ imageUrl:
|
|
|
+ 'https://cdn.pixabay.com/photo/2023/04/02/21/38/sandwich-7895477_1280.jpg',
|
|
|
+ availableToppings: [
|
|
|
+ 'Cebolla',
|
|
|
+ 'Pepperoni',
|
|
|
+ 'Champiñones',
|
|
|
+ 'Tocino',
|
|
|
+ 'Pimiento',
|
|
|
+ 'Jalapeño'
|
|
|
+ ],
|
|
|
+ availableDrinks: ['Coca-Cola', 'Sprite', 'Fanta', 'Agua mineral'],
|
|
|
+ availableCookingTerms: ['Término medio', 'Tres cuartos', 'Bien cocido'],
|
|
|
+ hasCheeseOption: true,
|
|
|
+ cheeseprecio: 5.00,
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class ProductScreen extends StatefulWidget {
|
|
|
+ final Product product;
|
|
|
+
|
|
|
+ const ProductScreen({super.key, required this.product});
|
|
|
+
|
|
|
+ @override
|
|
|
+ State<ProductScreen> createState() => _ProductScreenState();
|
|
|
+}
|
|
|
+
|
|
|
+class _ProductScreenState extends State<ProductScreen> {
|
|
|
+ int quantity = 1;
|
|
|
+ double totalprecio = 0;
|
|
|
+
|
|
|
+ @override
|
|
|
+ void initState() {
|
|
|
+ super.initState();
|
|
|
+ totalprecio = widget.product.precio;
|
|
|
+ }
|
|
|
+
|
|
|
+ void _updateQuantity(int newQuantity) {
|
|
|
+ if (newQuantity >= 1) {
|
|
|
+ setState(() {
|
|
|
+ quantity = newQuantity;
|
|
|
+ _calculateTotalprecio();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void _calculateTotalprecio() {
|
|
|
+ double baseprecio = widget.product.precio;
|
|
|
+ // Añadir precio del queso si está seleccionado
|
|
|
+ if (_toppingsViewKey.currentState?.isQuesoSelected == true) {
|
|
|
+ baseprecio += widget.product.cheeseprecio;
|
|
|
+ }
|
|
|
+ totalprecio = baseprecio * quantity;
|
|
|
+ }
|
|
|
+
|
|
|
+ final GlobalKey<_ToppingsViewState> _toppingsViewKey =
|
|
|
+ GlobalKey<_ToppingsViewState>();
|
|
|
|
|
|
@override
|
|
|
Widget build(BuildContext context) {
|
|
|
- return Placeholder();
|
|
|
+ return Scaffold(
|
|
|
+ appBar: AppBar(
|
|
|
+ backgroundColor: Colors.transparent,
|
|
|
+ elevation: 0,
|
|
|
+ actions: [
|
|
|
+ IconButton(
|
|
|
+ icon: const Icon(Icons.info),
|
|
|
+ onPressed: () {
|
|
|
+ Navigator.of(context).pop();
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ bottomNavigationBar: SizedBox(
|
|
|
+ height: 110,
|
|
|
+ child: Container(
|
|
|
+ padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: Color.fromARGB(255, 47, 208, 229),
|
|
|
+ borderRadius: const BorderRadius.only(
|
|
|
+ topLeft: Radius.circular(25),
|
|
|
+ topRight: Radius.circular(25),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ child: Row(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
+ children: [
|
|
|
+ ClipRRect(
|
|
|
+ borderRadius: BorderRadius.circular(5),
|
|
|
+ child: Row(
|
|
|
+ mainAxisSize: MainAxisSize.min,
|
|
|
+ children: [
|
|
|
+ Container(
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: Color.fromARGB(255, 200, 214, 232),
|
|
|
+ borderRadius: BorderRadius.circular(2),
|
|
|
+ ),
|
|
|
+ child: IconButton(
|
|
|
+ icon: const Icon(Icons.remove),
|
|
|
+ onPressed: () => _updateQuantity(quantity - 1),
|
|
|
+ color: Colors.black,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Container(
|
|
|
+ width: 48,
|
|
|
+ height: 48,
|
|
|
+ alignment: Alignment.center,
|
|
|
+ color: Colors.white,
|
|
|
+ child: Text(
|
|
|
+ quantity.toString(),
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.black,
|
|
|
+ fontSize: 20,
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Container(
|
|
|
+ color: Color.fromARGB(255, 200, 214, 232),
|
|
|
+ child: IconButton(
|
|
|
+ icon: const Icon(Icons.add),
|
|
|
+ onPressed: () => _updateQuantity(quantity + 1),
|
|
|
+ color: Colors.black,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Container(
|
|
|
+ padding:
|
|
|
+ const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
|
|
+ color: Colors.black,
|
|
|
+ child: Text(
|
|
|
+ "MXN ${totalprecio.toStringAsFixed(2)}",
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.white,
|
|
|
+ fontSize: 20,
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ backgroundColor: Colors.white,
|
|
|
+ body: SingleChildScrollView(
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ Stack(children: [
|
|
|
+ Positioned(
|
|
|
+ top: 20,
|
|
|
+ left: 20,
|
|
|
+ child: IconButton(
|
|
|
+ icon: const Icon(
|
|
|
+ Icons.arrow_back,
|
|
|
+ color: Colors.white,
|
|
|
+ semanticLabel: "Regresar",
|
|
|
+ ),
|
|
|
+ onPressed: () => Navigator.pop(context),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Container(
|
|
|
+ height: 350,
|
|
|
+ width: double.infinity,
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ borderRadius: const BorderRadius.only(
|
|
|
+ topLeft: Radius.circular(25),
|
|
|
+ topRight: Radius.circular(25),
|
|
|
+ ),
|
|
|
+ image: DecorationImage(
|
|
|
+ image: NetworkImage(widget.product.imageUrl),
|
|
|
+ fit: BoxFit.cover,
|
|
|
+ colorFilter: ColorFilter.mode(
|
|
|
+ Colors.black.withOpacity(0.3),
|
|
|
+ BlendMode.darken,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ ]),
|
|
|
+ const SizedBox(height: 20),
|
|
|
+ Padding(
|
|
|
+ padding: EdgeInsets.symmetric(horizontal: 20),
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ Text(
|
|
|
+ widget.product.nombre,
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.black,
|
|
|
+ fontSize: 44,
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ SizedBox(height: 10),
|
|
|
+ Text(
|
|
|
+ widget.product.descripcion,
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.black,
|
|
|
+ fontSize: 26,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ SizedBox(height: 10),
|
|
|
+ Text(
|
|
|
+ 'MXN ${widget.product.precio.toStringAsFixed(2)}',
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.black,
|
|
|
+ fontSize: 36,
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Divider(
|
|
|
+ height: 2,
|
|
|
+ ),
|
|
|
+ SizedBox(height: 10),
|
|
|
+ ToppingsView(
|
|
|
+ key: _toppingsViewKey,
|
|
|
+ product: widget.product,
|
|
|
+ onOptionChanged: () {
|
|
|
+ _calculateTotalprecio();
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class ToppingsView extends StatefulWidget {
|
|
|
+ final Product product;
|
|
|
+ final Function() onOptionChanged;
|
|
|
+
|
|
|
+ const ToppingsView({
|
|
|
+ super.key,
|
|
|
+ required this.product,
|
|
|
+ required this.onOptionChanged,
|
|
|
+ });
|
|
|
+
|
|
|
+ @override
|
|
|
+ State<ToppingsView> createState() => _ToppingsViewState();
|
|
|
+}
|
|
|
+
|
|
|
+class _ToppingsViewState extends State<ToppingsView> {
|
|
|
+ // Estado para controlar la expansión de cada sección
|
|
|
+ bool isToppingsExpanded = false;
|
|
|
+ bool isRefrescoExpanded = false;
|
|
|
+ bool isCoccionExpanded = false;
|
|
|
+ bool isQuesoExpanded = true;
|
|
|
+
|
|
|
+ // Estado para la selección de queso
|
|
|
+ bool isQuesoSelected = false;
|
|
|
+
|
|
|
+ // Selecciones actuales
|
|
|
+ List<String> selectedToppings = [];
|
|
|
+ String? selectedRefresco;
|
|
|
+ String? selectedCoccion;
|
|
|
+ String comments = '';
|
|
|
+
|
|
|
+ // Para calcular el precio total basado en selecciones
|
|
|
+ double additionalprecio = 0.0;
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ return SingleChildScrollView(
|
|
|
+ child: Container(
|
|
|
+ color: Colors.white,
|
|
|
+ child: Padding(
|
|
|
+ padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ // 1. Dropdown de Toppings
|
|
|
+ _buildDropdownSection(
|
|
|
+ title: "SELECCIONA 3 TOPPINGS",
|
|
|
+ subtitle: "Seleccione hasta 3 opciones",
|
|
|
+ isExpanded: isToppingsExpanded,
|
|
|
+ onTap: () {
|
|
|
+ setState(() {
|
|
|
+ isToppingsExpanded = !isToppingsExpanded;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ content: isToppingsExpanded ? _buildToppingsContent() : null,
|
|
|
+ ),
|
|
|
+ const Divider(color: Colors.grey),
|
|
|
+
|
|
|
+ // 2. Dropdown de Refresco
|
|
|
+ _buildDropdownSection(
|
|
|
+ title: "ELIGE UN REFRESCO SIN COSTO",
|
|
|
+ subtitle: "Seleccione hasta 1 opcion",
|
|
|
+ isExpanded: isRefrescoExpanded,
|
|
|
+ onTap: () {
|
|
|
+ setState(() {
|
|
|
+ isRefrescoExpanded = !isRefrescoExpanded;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ content: isRefrescoExpanded ? _buildRefrescoContent() : null,
|
|
|
+ ),
|
|
|
+ const Divider(color: Colors.grey),
|
|
|
+
|
|
|
+ // 3. Dropdown de Término de Cocción
|
|
|
+ _buildDropdownSection(
|
|
|
+ title: "Elige el término de cocción",
|
|
|
+ subtitle: "Seleccione mínimo 1 opciones",
|
|
|
+ isExpanded: isCoccionExpanded,
|
|
|
+ onTap: () {
|
|
|
+ setState(() {
|
|
|
+ isCoccionExpanded = !isCoccionExpanded;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ content: isCoccionExpanded ? _buildCoccionContent() : null,
|
|
|
+ showObligatorio: true,
|
|
|
+ ),
|
|
|
+ const Divider(color: Colors.grey),
|
|
|
+
|
|
|
+ // 4. Dropdown de Queso amarillo - Solo si el producto tiene esta opción
|
|
|
+ if (widget.product.hasCheeseOption) ...[
|
|
|
+ _buildDropdownSection(
|
|
|
+ title: "Queso amarillo para papas",
|
|
|
+ subtitle: null, // Sin subtítulo
|
|
|
+ isExpanded: isQuesoExpanded,
|
|
|
+ onTap: () {
|
|
|
+ setState(() {
|
|
|
+ isQuesoExpanded = !isQuesoExpanded;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ content: isQuesoExpanded ? _buildQuesoContent() : null,
|
|
|
+ ),
|
|
|
+ const Divider(color: Colors.grey),
|
|
|
+ ],
|
|
|
+
|
|
|
+ // 5. Sección de Comentarios
|
|
|
+ const SizedBox(height: 20),
|
|
|
+ const Text(
|
|
|
+ "Comentarios",
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.black,
|
|
|
+ fontSize: 20,
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ const SizedBox(height: 10),
|
|
|
+ Container(
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ borderRadius: BorderRadius.circular(8),
|
|
|
+ border: Border.all(color: Colors.grey),
|
|
|
+ ),
|
|
|
+ height: 80,
|
|
|
+ child: TextField(
|
|
|
+ style: TextStyle(color: Colors.black),
|
|
|
+ maxLines: 3,
|
|
|
+ onChanged: (value) {
|
|
|
+ comments = value;
|
|
|
+ },
|
|
|
+ decoration: InputDecoration(
|
|
|
+ contentPadding: EdgeInsets.all(12),
|
|
|
+ border: InputBorder.none,
|
|
|
+ hintText: "Agrega instrucciones especiales...",
|
|
|
+ hintStyle: TextStyle(color: Colors.grey),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+
|
|
|
+ // Espaciador final
|
|
|
+ const SizedBox(height: 30),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // Construye la estructura base de cada dropdown
|
|
|
+ Widget _buildDropdownSection({
|
|
|
+ required String title,
|
|
|
+ String? subtitle,
|
|
|
+ required bool isExpanded,
|
|
|
+ required VoidCallback onTap,
|
|
|
+ Widget? content,
|
|
|
+ bool showObligatorio = false,
|
|
|
+ }) {
|
|
|
+ return SingleChildScrollView(
|
|
|
+ child: Column(
|
|
|
+ children: [
|
|
|
+ Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
|
|
+ Expanded(
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ const SizedBox(height: 16),
|
|
|
+ Text(
|
|
|
+ title,
|
|
|
+ style: const TextStyle(
|
|
|
+ color: Colors.black,
|
|
|
+ fontSize: 20,
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ if (subtitle != null) ...[
|
|
|
+ const SizedBox(height: 4),
|
|
|
+ Text(
|
|
|
+ subtitle,
|
|
|
+ style: const TextStyle(
|
|
|
+ color: Colors.grey,
|
|
|
+ fontSize: 16,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ if (subtitle == null) const SizedBox(height: 16),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ if (showObligatorio) ...[
|
|
|
+ Container(
|
|
|
+ padding:
|
|
|
+ const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ borderRadius: BorderRadius.circular(20),
|
|
|
+ border: Border.all(color: Colors.grey),
|
|
|
+ ),
|
|
|
+ child: const Text(
|
|
|
+ "Obligatorio",
|
|
|
+ style: TextStyle(color: Colors.grey),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ const SizedBox(width: 10),
|
|
|
+ ],
|
|
|
+ GestureDetector(
|
|
|
+ onTap: onTap,
|
|
|
+ child: Container(
|
|
|
+ width: 40,
|
|
|
+ height: 40,
|
|
|
+ decoration: const BoxDecoration(
|
|
|
+ color: Colors.cyan,
|
|
|
+ shape: BoxShape.circle,
|
|
|
+ ),
|
|
|
+ child: Icon(
|
|
|
+ isExpanded
|
|
|
+ ? Icons.keyboard_arrow_up
|
|
|
+ : Icons.keyboard_arrow_down,
|
|
|
+ color: Colors.white,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ]),
|
|
|
+ if (content != null) content,
|
|
|
+ const SizedBox(height: 8),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget _buildToppingsContent() {
|
|
|
+ return Column(
|
|
|
+ children: widget.product.availableToppings.map((topping) {
|
|
|
+ final isSelected = selectedToppings.contains(topping);
|
|
|
+ return CheckboxListTile(
|
|
|
+ contentPadding: const EdgeInsets.symmetric(horizontal: 8),
|
|
|
+ title: Text(
|
|
|
+ topping,
|
|
|
+ style: const TextStyle(color: Colors.black),
|
|
|
+ ),
|
|
|
+ value: isSelected,
|
|
|
+ activeColor: Colors.blue,
|
|
|
+ checkColor: Colors.black,
|
|
|
+ side: const BorderSide(color: Colors.black),
|
|
|
+ onChanged: (bool? value) {
|
|
|
+ setState(() {
|
|
|
+ if (value == true) {
|
|
|
+ if (selectedToppings.length < 3) {
|
|
|
+ selectedToppings.add(topping);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ selectedToppings.remove(topping);
|
|
|
+ }
|
|
|
+ widget.onOptionChanged();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ );
|
|
|
+ }).toList(),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // Contenido del dropdown de Refresco
|
|
|
+ Widget _buildRefrescoContent() {
|
|
|
+ return Column(
|
|
|
+ children: widget.product.availableDrinks.map((refresco) {
|
|
|
+ return RadioListTile<String>(
|
|
|
+ title: Text(
|
|
|
+ refresco,
|
|
|
+ style: const TextStyle(color: Colors.black),
|
|
|
+ ),
|
|
|
+ value: refresco,
|
|
|
+ groupValue: selectedRefresco,
|
|
|
+ activeColor: Colors.blue,
|
|
|
+ fillColor: MaterialStateProperty.resolveWith<Color>((states) {
|
|
|
+ return Colors.black;
|
|
|
+ }),
|
|
|
+ onChanged: (String? value) {
|
|
|
+ setState(() {
|
|
|
+ selectedRefresco = value;
|
|
|
+ widget.onOptionChanged();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ );
|
|
|
+ }).toList(),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // Contenido del dropdown de Cocción
|
|
|
+ Widget _buildCoccionContent() {
|
|
|
+ return Column(
|
|
|
+ children: widget.product.availableCookingTerms.map((coccion) {
|
|
|
+ return RadioListTile<String>(
|
|
|
+ title: Text(
|
|
|
+ coccion,
|
|
|
+ style: const TextStyle(color: Colors.black),
|
|
|
+ ),
|
|
|
+ value: coccion,
|
|
|
+ groupValue: selectedCoccion,
|
|
|
+ activeColor: Colors.blue,
|
|
|
+ fillColor: MaterialStateProperty.resolveWith<Color>((states) {
|
|
|
+ return Colors.black;
|
|
|
+ }),
|
|
|
+ onChanged: (String? value) {
|
|
|
+ setState(() {
|
|
|
+ selectedCoccion = value;
|
|
|
+ widget.onOptionChanged();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ );
|
|
|
+ }).toList(),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // Contenido del dropdown de Queso
|
|
|
+ Widget _buildQuesoContent() {
|
|
|
+ return Container(
|
|
|
+ margin: const EdgeInsets.only(top: 8, bottom: 8),
|
|
|
+ padding: const EdgeInsets.symmetric(vertical: 8),
|
|
|
+ child: InkWell(
|
|
|
+ onTap: () {
|
|
|
+ setState(() {
|
|
|
+ isQuesoSelected = !isQuesoSelected;
|
|
|
+ widget.onOptionChanged();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ child: Row(
|
|
|
+ children: [
|
|
|
+ Container(
|
|
|
+ width: 24,
|
|
|
+ height: 24,
|
|
|
+ margin: const EdgeInsets.only(left: 12),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ border: Border.all(color: Colors.black),
|
|
|
+ ),
|
|
|
+ child: isQuesoSelected
|
|
|
+ ? const Icon(Icons.check, color: Colors.black, size: 20)
|
|
|
+ : null,
|
|
|
+ ),
|
|
|
+ const SizedBox(width: 16),
|
|
|
+ Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ Text(
|
|
|
+ "Queso amarillo",
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.black,
|
|
|
+ fontSize: 16,
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Text(
|
|
|
+ "+ MXN ${widget.product.cheeseprecio.toStringAsFixed(2)}",
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.black,
|
|
|
+ fontSize: 16,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Ejemplo de cómo se usaría la pantalla con el modelo de producto
|
|
|
+class ExampleUsage extends StatelessWidget {
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ // Crear un producto con datos estáticos
|
|
|
+ final product = Product.staticSandwich();
|
|
|
+
|
|
|
+ // Navegar a la pantalla del producto
|
|
|
+ return MaterialApp(
|
|
|
+ home: ProductScreen(product: product),
|
|
|
+ );
|
|
|
}
|
|
|
}
|