6 Revize 0d72c9ab87 ... 21623b7ccd

Autor SHA1 Zpráva Datum
  BaLa 21623b7ccd importes před 2 měsíci
  BaLa edc3c1bd11 evento onpressed před 2 měsíci
  BaLa 8f787e2b4f se agrego texto al appbar před 2 měsíci
  c90Beretta aa43d3116b Merge branch 'BRNDEV' into desarrollo před 2 měsíci
  c90Beretta 61497976bc Merge branch 'BRNDEV' into desarrollo před 2 měsíci
  c90Beretta f6de571514 Merge branch 'BRNDEV' into desarrollo před 2 měsíci

+ 2 - 1
.vscode/settings.json

@@ -1,3 +1,4 @@
 {
-  "dart.flutterSdkPath": ".fvm/versions/3.16.9"
+  "dart.flutterSdkPath": ".fvm/versions/3.16.9",
+  "java.configuration.updateBuildConfiguration": "interactive"
 }

+ 1 - 0
android/gradle.properties

@@ -1,3 +1,4 @@
 org.gradle.jvmargs=-Xmx4G
 android.useAndroidX=true
 android.enableJetifier=true
+org.gradle.java.home=/opt/homebrew/Cellar/openjdk@17/17.0.14/libexec/openjdk.jdk/Contents/Home

+ 3 - 1
android/gradle/wrapper/gradle-wrapper.properties

@@ -1,5 +1,7 @@
+#Wed Feb 26 19:48:01 MST 2025
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
+org.gradle.java.home=/opt/homebrew/Cellar/openjdk@17/17.0.14/libexec/openjdk.jdk/Contents/Home

+ 1 - 0
devtools_options.yaml

@@ -0,0 +1 @@
+extensions:

+ 5 - 0
lib/main.dart

@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:provider/provider.dart';
 import 'package:sqflite_common_ffi/sqflite_ffi.dart';
+import 'package:turquessa_mesas_hoster/mvvm/views/home/carrito/carrito_screen.dart';
+import 'package:turquessa_mesas_hoster/mvvm/views/home/producto/producto_screen.dart';
 import 'dart:io';
 
 import 'core/models/models.dart';
@@ -82,6 +84,9 @@ class MyApp extends StatelessWidget {
       routes: {
         'login': (context) => const LoginScreen(),
         'home': (context) => const HomeScreen(),
+        'producto': (context) =>
+            ProductScreen(product: Product.staticSandwich()),
+        'carrito': (context) => const CarritoScreen(),
       },
     );
   }

+ 73 - 0
lib/mvvm/views/home/carrito/carrito_screen.dart

@@ -0,0 +1,73 @@
+import 'package:flutter/material.dart';
+
+class CarritoScreen extends StatefulWidget {
+  const CarritoScreen({super.key});
+
+  @override
+  State<CarritoScreen> createState() => _CarritoScreenState();
+}
+
+class _CarritoScreenState extends State<CarritoScreen> {
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      backgroundColor: Colors.white,
+      appBar: AppBar(
+        actions: [],
+        title: const  Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          children: [
+            Text('Atrás'),
+            Column(
+              children: [
+                Text(
+                  'Su carrito',
+                  style:TextStyle(
+                    fontSize: 17,
+                    color: Colors.black54
+                  ),
+                ),
+                Text(
+                  style: TextStyle(
+                    fontSize: 20,
+                    fontWeight: FontWeight.w800
+                  ),
+                  'MXN 69.00',
+                )
+              ],
+            )
+          ],
+        ),
+      ),
+      body: Column(
+        children:[ 
+          Row(
+            mainAxisAlignment: MainAxisAlignment.spaceBetween,
+            children: [
+              Image.network('https://cdn.pixabay.com/photo/2016/03/05/19/02/hamburger-1238246_960_720.jpg',
+              width: 100,
+              height: 100,
+              ),
+              
+             const Column (children: [
+              Text(
+                '1.HAMBURGUESA SENCILLA'
+              ),
+              Text(
+                style: TextStyle(
+                  fontWeight: FontWeight.bold,
+                ),
+                'MXN 115.00'
+              ),
+          ],),
+              
+              
+              
+              
+            ],
+          ),
+        ],
+      ),
+    );
+  }
+}

+ 42 - 4
lib/mvvm/views/home/home_screen.dart

@@ -3,10 +3,12 @@ import 'package:provider/provider.dart';
 import 'package:turquessa_mesas_hoster/core/models/producto_model.dart';
 import 'package:turquessa_mesas_hoster/mvvm/viewmodels/pedido_view_model.dart';
 import 'package:turquessa_mesas_hoster/mvvm/viewmodels/producto_view_model.dart';
+import 'package:turquessa_mesas_hoster/mvvm/views/home/carrito/carrito_screen.dart';
 import 'package:turquessa_mesas_hoster/utils/widgets/custom_appbar.dart';
 import 'package:turquessa_mesas_hoster/mvvm/views/home/categorias_navbar.dart';
 import 'package:turquessa_mesas_hoster/mvvm/viewmodels/home_view_model.dart';
 import 'package:turquessa_mesas_hoster/utils/widgets/modal_infonegaocio.dart';
+import 'package:turquessa_mesas_hoster/mvvm/views/home/producto/producto_screen.dart';
 
 const List<Map<String, dynamic>> items = [
   {
@@ -124,6 +126,34 @@ class _HomeScreenState extends State<HomeScreen> {
     final homeViewModel = Provider.of<HomeViewModel>(context);
     final pedidoViewModel = Provider.of<ProductoViewModel>(context);
     return Scaffold(
+        bottomNavigationBar: BottomAppBar(
+            color: Colors.black,
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.spaceAround,
+              children: [
+                IconButton(
+                  icon: const Icon(Icons.search, color: Colors.white),
+                  onPressed: () {},
+                ),
+                IconButton(
+                  icon: const Icon(Icons.menu, color: Colors.white),
+                  onPressed: () {
+                    Navigator.of(context).pushNamed('carrito');
+                  },
+                ),
+                const Text(
+                  'Producto',
+                  style: TextStyle(
+                    color: Colors.cyanAccent,
+                    fontWeight: FontWeight.bold,
+                  ),
+                ),
+                IconButton(
+                  icon: const Icon(Icons.favorite_border, color: Colors.white),
+                  onPressed: () {},
+                ),
+              ],
+            )),
         backgroundColor: Colors.white,
         body: CustomScrollView(
           slivers: [
@@ -191,7 +221,12 @@ class _HomeScreenState extends State<HomeScreen> {
             ),
             const SliverToBoxAdapter(
               child: Center(
-                child: Text('Coffee', style: TextStyle(fontSize: 30)),
+                child: Text('Coffee',
+                    style: TextStyle(
+                      fontSize: 40,
+                      fontWeight: FontWeight.bold,
+                      fontStyle: FontStyle.italic,
+                    )),
               ),
             ),
             SliverList(
@@ -202,6 +237,7 @@ class _HomeScreenState extends State<HomeScreen> {
                   items[index]['descripcion'],
                   items[index]['precio'],
                   items[index]['imageUrl'],
+                  context,
                 );
               },
               childCount: items.length,
@@ -231,10 +267,12 @@ class CategoriasSliverChild extends SliverPersistentHeaderDelegate {
   }
 }
 
-Widget _buildBurgerItem(
-    String nombre, String descripcion, String precio, String imageUrl) {
+Widget _buildBurgerItem(String nombre, String descripcion, String precio,
+    String imageUrl, BuildContext context) {
   return GestureDetector(
-    onTap: () {},
+    onTap: () {
+      Navigator.of(context).pushNamed('producto');
+    },
     child: Column(
       children: [
         Padding(

+ 633 - 3
lib/mvvm/views/home/producto/producto_screen.dart

@@ -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),
+    );
   }
 }

+ 112 - 107
lib/utils/widgets/modal_infonegaocio.dart

@@ -1,3 +1,4 @@
+import 'package:animate_do/animate_do.dart';
 import 'package:flutter/material.dart';
 
 void mostrarInformacionNegocioBottomSheet(BuildContext context) {
@@ -5,135 +6,139 @@ void mostrarInformacionNegocioBottomSheet(BuildContext context) {
     context: context,
     isScrollControlled: true,
     backgroundColor: Colors.transparent,
-    builder: (context) => Container(
-      height: MediaQuery.of(context).size.height * 0.7,
-      decoration: const BoxDecoration(
-        color: Colors.white,
-        borderRadius: BorderRadius.only(
-          topLeft: Radius.circular(25),
-          topRight: Radius.circular(25),
+    builder: (context) => BounceInUp(
+      duration: const Duration(milliseconds: 450),
+      child: Container(
+        height: MediaQuery.of(context).size.height * 0.7,
+        decoration: const BoxDecoration(
+          color: Colors.white,
+          borderRadius: BorderRadius.only(
+            topLeft: Radius.circular(25),
+            topRight: Radius.circular(25),
+          ),
         ),
-      ),
-      child: SingleChildScrollView(
-        child: Column(
-          crossAxisAlignment: CrossAxisAlignment.start,
-          children: [
-            Container(
-              height: 150,
-              width: double.infinity,
-              decoration: BoxDecoration(
-                borderRadius: const BorderRadius.only(
-                  topLeft: Radius.circular(25),
-                  topRight: Radius.circular(25),
+        child: SingleChildScrollView(
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              Container(
+                height: 150,
+                width: double.infinity,
+                decoration: BoxDecoration(
+                  borderRadius: const BorderRadius.only(
+                    topLeft: Radius.circular(25),
+                    topRight: Radius.circular(25),
+                  ),
+                  image: DecorationImage(
+                    image: const AssetImage('assets/turquessa_prop.jpg'),
+                    fit: BoxFit.cover,
+                    colorFilter: ColorFilter.mode(
+                      Colors.black.withOpacity(0.3),
+                      BlendMode.darken,
+                    ),
+                  ),
                 ),
-                image: DecorationImage(
-                  image: const AssetImage('assets/turquessa_prop.jpg'),
-                  fit: BoxFit.cover,
-                  colorFilter: ColorFilter.mode(
-                    Colors.black.withOpacity(0.3),
-                    BlendMode.darken,
+                child: Center(
+                  child: Column(
+                    mainAxisAlignment: MainAxisAlignment.center,
+                    children: [
+                      Container(
+                        padding: const EdgeInsets.all(8),
+                        decoration: BoxDecoration(
+                          color: Colors.white,
+                          borderRadius: BorderRadius.circular(10),
+                        ),
+                        child: Image.asset('assets/Turquessa.png', height: 50),
+                      ),
+                      const SizedBox(height: 10),
+                      const Text(
+                        'Turquessa-Coffee',
+                        style: TextStyle(
+                          color: Colors.white,
+                          fontSize: 24,
+                          fontWeight: FontWeight.bold,
+                        ),
+                      ),
+                    ],
                   ),
                 ),
               ),
-              child: Center(
+
+              // Sección de información
+              Padding(
+                padding: const EdgeInsets.all(20),
                 child: Column(
-                  mainAxisAlignment: MainAxisAlignment.center,
+                  crossAxisAlignment: CrossAxisAlignment.start,
                   children: [
-                    Container(
-                      padding: const EdgeInsets.all(8),
-                      decoration: BoxDecoration(
-                        color: Colors.white,
-                        borderRadius: BorderRadius.circular(10),
-                      ),
-                      child: Image.asset('assets/Turquessa.png', height: 50),
-                    ),
-                    const SizedBox(height: 10),
                     const Text(
-                      'Turquessa-Coffee',
+                      'Acerca de nosotros',
                       style: TextStyle(
-                        color: Colors.white,
-                        fontSize: 24,
+                        fontSize: 18,
                         fontWeight: FontWeight.bold,
+                        color: Color(0xFF2FD0E5),
                       ),
                     ),
-                  ],
-                ),
-              ),
-            ),
-
-            // Sección de información
-            Padding(
-              padding: const EdgeInsets.all(20),
-              child: Column(
-                crossAxisAlignment: CrossAxisAlignment.start,
-                children: [
-                  const Text(
-                    'Acerca de nosotros',
-                    style: TextStyle(
-                      fontSize: 18,
-                      fontWeight: FontWeight.bold,
-                      color: Color(0xFF2FD0E5),
+                    const SizedBox(height: 8),
+                    const Text(
+                      'Turquessa-Coffee es una cafetería de especialidad con los mejores granos seleccionados. Nuestro compromiso es ofrecer una experiencia única en cada taza.',
+                      style: TextStyle(fontSize: 14, color: Colors.black87),
                     ),
-                  ),
-                  const SizedBox(height: 8),
-                  const Text(
-                    'Turquessa-Coffee es una cafetería de especialidad con los mejores granos seleccionados. Nuestro compromiso es ofrecer una experiencia única en cada taza.',
-                    style: TextStyle(fontSize: 14, color: Colors.black87),
-                  ),
-                  const SizedBox(height: 20),
+                    const SizedBox(height: 20),
 
-                  // Información de contacto
-                  _buildInfoItem(Icons.location_on, 'Dirección',
-                      'Av. Principal #123, Zona Centro'),
-                  _buildInfoItem(Icons.access_time, 'Horario',
-                      'Lun-Vie: 7:00 - 20:00\nSáb-Dom: 8:00 - 18:00'),
-                  _buildInfoItem(Icons.phone, 'Teléfono', '(55) 1234-5678'),
-                  _buildInfoItem(Icons.email, 'Email', 'info@turquessa.com'),
-                  _buildInfoItem(
-                      Icons.language, 'Sitio web', 'www.turquessa.com'),
+                    // Información de contacto
+                    _buildInfoItem(Icons.location_on, 'Dirección',
+                        'C. Quintero Arce 248, El Llano'),
+                    _buildInfoItem(Icons.access_time, 'Horario',
+                        'Lun-Sáb: 8 a.m.- 10 p.m.\nDom: 4:00 p.m - 10 p.m'),
+                    _buildInfoItem(Icons.phone, 'Teléfono', '(662) 466 6626'),
+                    _buildInfoItem(
+                        Icons.email, 'Contacto', 'turquessacoffee@info.com'),
+                    _buildInfoItem(
+                        Icons.language, 'Sitio web', 'turquessacoffee.com'),
 
-                  const SizedBox(height: 20),
+                    const SizedBox(height: 20),
 
-                  // Redes sociales
-                  const Text(
-                    'Síguenos en redes sociales',
-                    style: TextStyle(
-                      fontSize: 18,
-                      fontWeight: FontWeight.bold,
-                      color: Color(0xFF2FD0E5),
+                    // Redes sociales
+                    const Text(
+                      'Síguenos en redes sociales',
+                      style: TextStyle(
+                        fontSize: 18,
+                        fontWeight: FontWeight.bold,
+                        color: Color(0xFF2FD0E5),
+                      ),
+                    ),
+                    const SizedBox(height: 10),
+                    Row(
+                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+                      children: [
+                        _buildSocialButton(Icons.facebook, 'Facebook'),
+                        _buildSocialButton(Icons.camera_alt, 'Instagram'),
+                        _buildSocialButton(Icons.chat_bubble, 'Twitter'),
+                      ],
                     ),
-                  ),
-                  const SizedBox(height: 10),
-                  Row(
-                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
-                    children: [
-                      _buildSocialButton(Icons.facebook, 'Facebook'),
-                      _buildSocialButton(Icons.camera_alt, 'Instagram'),
-                      _buildSocialButton(Icons.chat_bubble, 'Twitter'),
-                    ],
-                  ),
 
-                  const SizedBox(height: 30),
-                  Center(
-                    child: TextButton(
-                      onPressed: () => Navigator.pop(context),
-                      child: Container(
-                        padding: const EdgeInsets.symmetric(
-                            horizontal: 30, vertical: 10),
-                        decoration: BoxDecoration(
-                          color: const Color(0xFF2FD0E5),
-                          borderRadius: BorderRadius.circular(20),
+                    const SizedBox(height: 30),
+                    Center(
+                      child: TextButton(
+                        onPressed: () => Navigator.pop(context),
+                        child: Container(
+                          padding: const EdgeInsets.symmetric(
+                              horizontal: 30, vertical: 10),
+                          decoration: BoxDecoration(
+                            color: const Color(0xFF2FD0E5),
+                            borderRadius: BorderRadius.circular(20),
+                          ),
+                          child: const Text('Cerrar',
+                              style: TextStyle(color: Colors.white)),
                         ),
-                        child: const Text('Cerrar',
-                            style: TextStyle(color: Colors.white)),
                       ),
                     ),
-                  ),
-                  const SizedBox(height: 20),
-                ],
+                    const SizedBox(height: 20),
+                  ],
+                ),
               ),
-            ),
-          ],
+            ],
+          ),
         ),
       ),
     ),

+ 8 - 0
pubspec.lock

@@ -1,6 +1,14 @@
 # Generated by pub
 # See https://dart.dev/tools/pub/glossary#lockfile
 packages:
+  animate_do:
+    dependency: "direct main"
+    description:
+      name: animate_do
+      sha256: e5c8b92e8495cba5adfff17c0b017d50f46b2766226e9faaf68bc08c91aef034
+      url: "https://pub.dev"
+    source: hosted
+    version: "4.2.0"
   async:
     dependency: transitive
     description:

+ 1 - 0
pubspec.yaml

@@ -51,6 +51,7 @@ dependencies:
   url_launcher: ^6.3.0
   otp: ^3.1.4
   universal_html: ^2.2.4
+  animate_do: ^4.2.0
 
 dev_dependencies:
   flutter_test: