Parcourir la source

Merge branch 'BRNDEV' into desarrollo

c90Beretta il y a 2 mois
Parent
commit
aa43d3116b

+ 4 - 1
lib/main.dart

@@ -2,6 +2,7 @@ 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';
 
@@ -83,7 +84,9 @@ class MyApp extends StatelessWidget {
       routes: {
         'login': (context) => const LoginScreen(),
         'home': (context) => const HomeScreen(),
-        'producto': (context) => const ProductScreen(),
+        'producto': (context) =>
+            ProductScreen(product: Product.staticSandwich()),
+        'carrito': (context) => const CarritoScreen(),
       },
     );
   }

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

@@ -0,0 +1,28 @@
+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(
+        title: Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          children: [
+            Text('Atrás'),
+          ],
+        ),
+      ),
+      body: Column(
+        children: [],
+      ),
+    );
+  }
+}

+ 274 - 116
lib/mvvm/views/home/producto/producto_screen.dart

@@ -1,13 +1,95 @@
 import 'package:flutter/material.dart';
 
+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 {
-  const ProductScreen({super.key});
+  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 Scaffold(
@@ -17,12 +99,84 @@ class _ProductScreenState extends State<ProductScreen> {
         actions: [
           IconButton(
             icon: const Icon(Icons.info),
-            onPressed: () => (context) {
+            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(
@@ -50,8 +204,7 @@ class _ProductScreenState extends State<ProductScreen> {
                     topRight: Radius.circular(25),
                   ),
                   image: DecorationImage(
-                    image: NetworkImage(
-                        'https://cdn.pixabay.com/photo/2023/04/02/21/38/sandwich-7895477_1280.jpg'),
+                    image: NetworkImage(widget.product.imageUrl),
                     fit: BoxFit.cover,
                     colorFilter: ColorFilter.mode(
                       Colors.black.withOpacity(0.3),
@@ -62,13 +215,13 @@ class _ProductScreenState extends State<ProductScreen> {
               )
             ]),
             const SizedBox(height: 20),
-            const Padding(
+            Padding(
               padding: EdgeInsets.symmetric(horizontal: 20),
               child: Column(
                 crossAxisAlignment: CrossAxisAlignment.start,
                 children: [
                   Text(
-                    'Sandwich de pollo',
+                    widget.product.nombre,
                     style: TextStyle(
                       color: Colors.black,
                       fontSize: 44,
@@ -77,7 +230,7 @@ class _ProductScreenState extends State<ProductScreen> {
                   ),
                   SizedBox(height: 10),
                   Text(
-                    'Queso, Lechuga, tomate, cebolla, pepinillo, mayonesa, ketchup y moztaza. Acompañado de Papas y Soda',
+                    widget.product.descripcion,
                     style: TextStyle(
                       color: Colors.black,
                       fontSize: 26,
@@ -85,7 +238,7 @@ class _ProductScreenState extends State<ProductScreen> {
                   ),
                   SizedBox(height: 10),
                   Text(
-                    'MXN 115.00',
+                    'MXN ${widget.product.precio.toStringAsFixed(2)}',
                     style: TextStyle(
                       color: Colors.black,
                       fontSize: 36,
@@ -96,7 +249,13 @@ class _ProductScreenState extends State<ProductScreen> {
                     height: 2,
                   ),
                   SizedBox(height: 10),
-                  ToppingsView(),
+                  ToppingsView(
+                    key: _toppingsViewKey,
+                    product: widget.product,
+                    onOptionChanged: () {
+                      _calculateTotalprecio();
+                    },
+                  ),
                 ],
               ),
             ),
@@ -108,7 +267,14 @@ class _ProductScreenState extends State<ProductScreen> {
 }
 
 class ToppingsView extends StatefulWidget {
-  const ToppingsView({super.key});
+  final Product product;
+  final Function() onOptionChanged;
+
+  const ToppingsView({
+    super.key,
+    required this.product,
+    required this.onOptionChanged,
+  });
 
   @override
   State<ToppingsView> createState() => _ToppingsViewState();
@@ -124,31 +290,14 @@ class _ToppingsViewState extends State<ToppingsView> {
   // Estado para la selección de queso
   bool isQuesoSelected = false;
 
-  // Opciones para los dropdowns (como ejemplo)
-  final List<String> toppingsOptions = [
-    'Cebolla',
-    'Pepperoni',
-    'Champiñones',
-    'Tocino',
-    'Pimiento',
-    'Jalapeño'
-  ];
-  final List<String> refrescoOptions = [
-    'Coca-Cola',
-    'Sprite',
-    'Fanta',
-    'Agua mineral'
-  ];
-  final List<String> coccionOptions = [
-    'Término medio',
-    'Tres cuartos',
-    'Bien cocido'
-  ];
-
   // 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) {
@@ -203,19 +352,21 @@ class _ToppingsViewState extends State<ToppingsView> {
               ),
               const Divider(color: Colors.grey),
 
-              // 4. Dropdown de Queso amarillo
-              _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),
+              // 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),
@@ -234,9 +385,12 @@ class _ToppingsViewState extends State<ToppingsView> {
                   border: Border.all(color: Colors.grey),
                 ),
                 height: 80,
-                child: const TextField(
+                child: TextField(
                   style: TextStyle(color: Colors.black),
                   maxLines: 3,
+                  onChanged: (value) {
+                    comments = value;
+                  },
                   decoration: InputDecoration(
                     contentPadding: EdgeInsets.all(12),
                     border: InputBorder.none,
@@ -246,19 +400,8 @@ class _ToppingsViewState extends State<ToppingsView> {
                 ),
               ),
 
-              // 6. Precio
+              // Espaciador final
               const SizedBox(height: 30),
-              const Center(
-                child: Text(
-                  "Precio: MXN 115.00",
-                  style: TextStyle(
-                    color: Colors.white,
-                    fontSize: 24,
-                    fontWeight: FontWeight.bold,
-                  ),
-                ),
-              ),
-              const SizedBox(height: 20),
             ],
           ),
         ),
@@ -278,70 +421,67 @@ class _ToppingsViewState extends State<ToppingsView> {
     return SingleChildScrollView(
       child: Column(
         children: [
-          Row(
-            mainAxisAlignment: MainAxisAlignment.spaceBetween,
-            children: [
-              Expanded(
-                child: Column(
-                  crossAxisAlignment: CrossAxisAlignment.start,
-                  children: [
-                    const SizedBox(height: 16),
+          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(
-                      title,
+                      subtitle,
                       style: const TextStyle(
-                        color: Colors.black,
-                        fontSize: 20,
-                        fontWeight: FontWeight.bold,
+                        color: Colors.grey,
+                        fontSize: 16,
                       ),
                     ),
-                    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 (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),
-                  ),
+            ),
+            if (showObligatorio) ...[
+              Container(
+                padding:
+                    const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
+                decoration: BoxDecoration(
+                  borderRadius: BorderRadius.circular(20),
+                  border: Border.all(color: Colors.grey),
                 ),
-                const SizedBox(width: 10),
-              ],
-              GestureDetector(
-                onTap: onTap,
-                child: Container(
-                  width: 40,
-                  height: 40,
-                  decoration: const BoxDecoration(
-                    color: Color(0xFF333333),
-                    shape: BoxShape.circle,
-                  ),
-                  child: Icon(
-                    isExpanded
-                        ? Icons.keyboard_arrow_up
-                        : Icons.keyboard_arrow_down,
-                    color: Colors.black,
-                  ),
+                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),
         ],
@@ -351,7 +491,7 @@ class _ToppingsViewState extends State<ToppingsView> {
 
   Widget _buildToppingsContent() {
     return Column(
-      children: toppingsOptions.map((topping) {
+      children: widget.product.availableToppings.map((topping) {
         final isSelected = selectedToppings.contains(topping);
         return CheckboxListTile(
           contentPadding: const EdgeInsets.symmetric(horizontal: 8),
@@ -372,6 +512,7 @@ class _ToppingsViewState extends State<ToppingsView> {
               } else {
                 selectedToppings.remove(topping);
               }
+              widget.onOptionChanged();
             });
           },
         );
@@ -382,7 +523,7 @@ class _ToppingsViewState extends State<ToppingsView> {
   // Contenido del dropdown de Refresco
   Widget _buildRefrescoContent() {
     return Column(
-      children: refrescoOptions.map((refresco) {
+      children: widget.product.availableDrinks.map((refresco) {
         return RadioListTile<String>(
           title: Text(
             refresco,
@@ -397,6 +538,7 @@ class _ToppingsViewState extends State<ToppingsView> {
           onChanged: (String? value) {
             setState(() {
               selectedRefresco = value;
+              widget.onOptionChanged();
             });
           },
         );
@@ -407,7 +549,7 @@ class _ToppingsViewState extends State<ToppingsView> {
   // Contenido del dropdown de Cocción
   Widget _buildCoccionContent() {
     return Column(
-      children: coccionOptions.map((coccion) {
+      children: widget.product.availableCookingTerms.map((coccion) {
         return RadioListTile<String>(
           title: Text(
             coccion,
@@ -422,6 +564,7 @@ class _ToppingsViewState extends State<ToppingsView> {
           onChanged: (String? value) {
             setState(() {
               selectedCoccion = value;
+              widget.onOptionChanged();
             });
           },
         );
@@ -438,6 +581,7 @@ class _ToppingsViewState extends State<ToppingsView> {
         onTap: () {
           setState(() {
             isQuesoSelected = !isQuesoSelected;
+            widget.onOptionChanged();
           });
         },
         child: Row(
@@ -454,7 +598,7 @@ class _ToppingsViewState extends State<ToppingsView> {
                   : null,
             ),
             const SizedBox(width: 16),
-            const Column(
+            Column(
               crossAxisAlignment: CrossAxisAlignment.start,
               children: [
                 Text(
@@ -466,7 +610,7 @@ class _ToppingsViewState extends State<ToppingsView> {
                   ),
                 ),
                 Text(
-                  "+ MXN 5.00",
+                  "+ MXN ${widget.product.cheeseprecio.toStringAsFixed(2)}",
                   style: TextStyle(
                     color: Colors.black,
                     fontSize: 16,
@@ -480,3 +624,17 @@ class _ToppingsViewState extends State<ToppingsView> {
     );
   }
 }
+
+// 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),
+    );
+  }
+}

+ 2 - 2
lib/utils/widgets/modal_infonegaocio.dart

@@ -6,8 +6,8 @@ void mostrarInformacionNegocioBottomSheet(BuildContext context) {
     context: context,
     isScrollControlled: true,
     backgroundColor: Colors.transparent,
-    builder: (context) => FadeInRight(
-      duration: const Duration(milliseconds: 300),
+    builder: (context) => BounceInUp(
+      duration: const Duration(milliseconds: 450),
       child: Container(
         height: MediaQuery.of(context).size.height * 0.7,
         decoration: const BoxDecoration(