瀏覽代碼

Merge branch 'master' into OGdev

OscarGil03 2 月之前
父節點
當前提交
e334a3e9ff

+ 9 - 0
lib/core/models/mesa_model.dart

@@ -1,12 +1,20 @@
 import '../models/basico_model.dart';
 import '../services/services.dart';
 
+enum EstadoPedido {
+  disponible,
+  surtida,
+  preparacion,
+  cobrado,
+}
+
 class Mesa extends Basico {
   int? idSucursal;
   String? nombre;
   String? clave;
   String? posicion;
   bool? activa;
+  EstadoPedido? estado;
 
   Mesa(
       {super.id,
@@ -16,6 +24,7 @@ class Mesa extends Basico {
       this.clave,
       this.posicion,
       this.activa,
+      this.estado = EstadoPedido.disponible,
       super.creado,
       super.modificado,
       super.eliminado});

+ 31 - 31
lib/core/models/mesas_model.dart

@@ -1,6 +1,6 @@
-import 'package:flutter/material.dart';
-import 'package:turquessa_mesas_hoster/core/models/basico_model.dart';
-import 'package:turquessa_mesas_hoster/core/models/mesa_model.dart';
+// import 'package:flutter/material.dart';
+// import 'package:turquessa_mesas_hoster/core/models/basico_model.dart';
+// import 'package:turquessa_mesas_hoster/core/models/mesa_model.dart';
 
 // enum EstadoPedido {
 //   disponible,
@@ -9,35 +9,35 @@ import 'package:turquessa_mesas_hoster/core/models/mesa_model.dart';
 //   cobrado,
 // }
 
-// class Mesas extends Basico {
-//   String? nombre;
-//   EstadoPedido? tipo;
-//   String? folio;
+// // class Mesas extends Basico {
+// //   String? nombre;
+// //   EstadoPedido? tipo;
+// //   String? folio;
 
-//   Mesas({
-//     this.nombre,
-//     this.tipo,
-//     this.folio,
-//   });
+// //   Mesas({
+// //     this.nombre,
+// //     this.tipo,
+// //     this.folio,
+// //   });
 
-//   @override
-//   Map<String, dynamic> toJson() {
-//     return {
-//       'nombre': nombre ?? '',
-//       'tipo': tipo.toString(),
-//       'folio': folio ?? '',
-//     }..addAll(super.toJson());
-//   }
-// }
-class TableItem extends Basico {
-  final int id;
-  final String name;
+// //   @override
+// //   Map<String, dynamic> toJson() {
+// //     return {
+// //       'nombre': nombre ?? '',
+// //       'tipo': tipo.toString(),
+// //       'folio': folio ?? '',
+// //     }..addAll(super.toJson());
+// //   }
+// // }
 
-  final String status;
+// class TableItem extends Basico {
+//   final int id;
+//   final String name;
+//   final EstadoPedido status;
 
-  TableItem({
-    required this.id,
-    required this.name,
-    required this.status,
-  });
-}
+//   TableItem({
+//     required this.id,
+//     required this.name,
+//     required this.status,
+//   });
+// }

+ 19 - 0
lib/mvvm/viewmodels/mesa_view_model.dart

@@ -140,6 +140,25 @@ class MesaViewModel extends ChangeNotifier {
 
     return false;
   }
+  // TODO: Implementar CambiarEstadoMesa, actualizar modelo
+  // void CambiarEstadoPedidoMesa(Mesa mesa) async {
+  //   var db = await DatabaseService().db;
+  //   await db!.update(
+  //     'Mesa',
+  //     {'estado': mesa.estado.toString()},
+  //     where: 'id = ?',
+  //     whereArgs: [mesa.id],
+  //   );
+  //   fetchLocalAll();
+  // }
+
+  //todo: Cambio de estado de mesa provisional
+  void CambiarEstadoPedidoMesa(EstadoPedido nuevoestado) {
+    if (_selectedMesa != null) {
+      _selectedMesa!.estado = nuevoestado;
+      notifyListeners();
+    }
+  }
 
   Future<bool> sincronizarMesas() async {
     String? claveSucursal =

+ 173 - 45
lib/mvvm/views/home/home_screen.dart

@@ -1,8 +1,9 @@
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
+import 'package:turquessa_mesas_hoster/core/models/mesa_model.dart';
 import 'package:turquessa_mesas_hoster/utils/widgets/custom_appbar.dart';
-import 'package:turquessa_mesas_hoster/core/models/mesas_model.dart';
 
+import '../../../utils/widgets/ordenes_card.dart';
 import '../../viewmodels/viewmodels.dart';
 
 class HomeScreen extends StatefulWidget {
@@ -13,6 +14,7 @@ class HomeScreen extends StatefulWidget {
 }
 
 class Formulario extends State<HomeScreen> {
+  int _selectedIndex = 0;
   @override
   void initState() {
     super.initState();
@@ -93,7 +95,9 @@ class Formulario extends State<HomeScreen> {
                   final mesa = mesaViewModel.mesas[index];
                   return GestureDetector(
                     onTap: () {
-                      mesaViewModel.selectMesa(mesa);
+                      setState(() {
+                        mesaViewModel.selectMesa(mesa);
+                      });
                     },
                     child: TableCard(
                       icon: Icons.table_chart,
@@ -106,24 +110,30 @@ class Formulario extends State<HomeScreen> {
               ),
             ),
           ),
-          //if (mesaViewModel.selectedMesa != null)
-          Expanded(
-              flex: 1,
-              child: Container(
-                margin: const EdgeInsets.all(10),
-                decoration: BoxDecoration(
-                  color: Colors.white,
-                  borderRadius: BorderRadius.circular(10),
-                  boxShadow: [
-                    BoxShadow(
-                      color: Colors.grey.withOpacity(0.2),
-                      blurRadius: 5,
-                      spreadRadius: 1,
-                    )
-                  ],
-                ),
-                // child: TablaDetalles(table: selectedTable!),
-              )),
+          if (mesaViewModel.selectedMesa != null)
+            Expanded(
+                child: Container(
+              margin: const EdgeInsets.all(10),
+              decoration: BoxDecoration(
+                color: Colors.white,
+                borderRadius: BorderRadius.circular(10),
+                boxShadow: [
+                  BoxShadow(
+                    color: Colors.grey.withOpacity(0.2),
+                    blurRadius: 5,
+                    spreadRadius: 1,
+                  )
+                ],
+              ),
+              child: TablaDetalles(
+                  status: EstadoPedido.disponible,
+                  table: mesaViewModel.selectedMesa ??
+                      Mesa(
+                          activa: false,
+                          id: 0,
+                          nombre: 'Mesa sin nombre',
+                          estado: EstadoPedido.disponible)),
+            )),
         ],
       ),
     );
@@ -162,42 +172,160 @@ class TableCard extends StatelessWidget {
   }
 }
 
-class TableDetailsPanel extends StatelessWidget {
-  final TableItem table;
+class TablaDetalles extends StatelessWidget {
+  final Mesa table;
+  final EstadoPedido status;
 
-  const TableDetailsPanel({
+  const TablaDetalles({
     Key? key,
     required this.table,
+    required this.status,
   }) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
-    return Column(
-      crossAxisAlignment: CrossAxisAlignment.start,
-      children: [
-        // Encabezado del panel
-        Container(
-          padding: const EdgeInsets.all(16),
-          decoration: BoxDecoration(
-            borderRadius: const BorderRadius.vertical(top: Radius.circular(10)),
+    return Container(
+      margin: const EdgeInsets.all(10),
+      decoration: BoxDecoration(
+        color: Colors.white,
+        borderRadius: BorderRadius.circular(10),
+        boxShadow: [
+          BoxShadow(
+            color: Colors.grey.withOpacity(0.2),
+            blurRadius: 5,
+            spreadRadius: 1,
+          )
+        ],
+      ),
+      child: Column(
+        children: [
+          // Header
+          Container(
+            padding: const EdgeInsets.all(16),
+            decoration: BoxDecoration(
+              color: table.activa! ? Colors.blue : Colors.grey,
+              borderRadius:
+                  const BorderRadius.vertical(top: Radius.circular(10)),
+            ),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              children: [
+                Row(
+                  children: [
+                    const Icon(Icons.table_restaurant,
+                        color: Colors.white, size: 24),
+                    const SizedBox(width: 8),
+                    Text(
+                      table.nombre ?? 'Mesa sin nombre',
+                      style: const TextStyle(
+                        color: Colors.white,
+                        fontSize: 20,
+                        fontWeight: FontWeight.bold,
+                      ),
+                    ),
+                  ],
+                ),
+                Container(
+                  padding:
+                      const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
+                  decoration: BoxDecoration(
+                    color: Colors.white.withOpacity(0.2),
+                    borderRadius: BorderRadius.circular(20),
+                  ),
+                  child: Text(
+                    table.activa! ? 'Activa' : 'Inactiva',
+                    style: const TextStyle(
+                      color: Colors.white,
+                      fontWeight: FontWeight.bold,
+                    ),
+                  ),
+                ),
+              ],
+            ),
           ),
-          child: Row(
-            children: [
-              Icon(Icons.person, color: Colors.white, size: 24),
-              const SizedBox(width: 8),
-              Text(
-                table.name,
-                style: const TextStyle(
-                  color: Colors.white,
-                  fontSize: 20,
-                  fontWeight: FontWeight.bold,
+          // Contenido scrolleable
+          Expanded(
+            child: SingleChildScrollView(
+              child: Padding(
+                padding: const EdgeInsets.all(16),
+                child: Column(
+                  crossAxisAlignment: CrossAxisAlignment.start,
+                  children: [
+                    Text(
+                      'ID: ${table.id}',
+                      style: const TextStyle(fontSize: 16),
+                    ),
+                    const SizedBox(height: 16),
+                    Row(
+                      children: [
+                        const Text('Estado: '),
+                        Text(
+                          status.toString().split('.').last,
+                          style: const TextStyle(
+                            fontWeight: FontWeight.bold,
+                            color: Colors.blue,
+                          ),
+                        ),
+                      ],
+                    ),
+                    const SizedBox(height: 16),
+                    IconDataByStatus(status: status),
+                    const SizedBox(height: 16),
+                    const OrdenesScreen(),
+                  ],
                 ),
               ),
-            ],
+            ),
           ),
-        ),
-        // Contenido específico según el tipo
-      ],
+        ],
+      ),
     );
   }
 }
+
+class IconDataByStatus extends StatelessWidget {
+  final EstadoPedido status;
+  const IconDataByStatus({Key? key, required this.status});
+
+  @override
+  Widget build(BuildContext context) {
+    switch (status) {
+      case EstadoPedido.disponible:
+        return IconButton(
+          onPressed: () {
+            final mesaViewModel =
+                Provider.of<MesaViewModel>(context, listen: false);
+            mesaViewModel.CambiarEstadoPedidoMesa(EstadoPedido.preparacion);
+          },
+          style: ButtonStyle(
+            backgroundColor: MaterialStateProperty.all(
+                const Color.fromARGB(255, 220, 252, 232)),
+          ),
+          icon: const Icon(Icons.table_restaurant_rounded, color: Colors.green),
+        );
+      case EstadoPedido.surtida:
+        return IconButton(
+          onPressed: () {},
+          icon: const Icon(Icons.coffee_rounded,
+              color: Color.fromARGB(255, 220, 234, 254)),
+        );
+      case EstadoPedido.preparacion:
+        return IconButton(
+          onPressed: () {},
+          icon: const Icon(Icons.kitchen_rounded,
+              color: Color.fromARGB(255, 243, 232, 255)),
+        );
+      case EstadoPedido.cobrado:
+        return IconButton(
+          onPressed: () {},
+          icon: const Icon(Icons.money_rounded,
+              color: Color.fromARGB(255, 255, 238, 213)),
+        );
+      default:
+        return IconButton(
+          onPressed: () {},
+          icon: const Icon(Icons.check_circle, color: Colors.grey),
+        );
+    }
+  }
+}

+ 211 - 0
lib/utils/widgets/ordenes_card.dart

@@ -0,0 +1,211 @@
+import 'package:flutter/material.dart';
+
+class OrdenItem {
+  final int cantidad;
+  final String nombre;
+  final String descripcion;
+  final String? notas;
+  final bool isListo;
+
+  OrdenItem({
+    required this.cantidad,
+    required this.nombre,
+    required this.descripcion,
+    this.notas,
+    this.isListo = false,
+  });
+}
+
+class OrdenesScreen extends StatelessWidget {
+  const OrdenesScreen({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    final items = [
+      OrdenItem(
+        cantidad: 1,
+        nombre: 'Chilaquiles Verdes',
+        descripcion: 'Tortillas fritas en salsa verde con pollo',
+        notas: 'Sin cebolla ni tomate',
+      ),
+      OrdenItem(
+        cantidad: 2,
+        nombre: 'Huevos Rancheros',
+        descripcion: 'Huevos fritos sobre tortilla con salsa roja',
+      ),
+    ];
+
+    final items2 = [
+      OrdenItem(
+        cantidad: 1,
+        nombre: 'Club Sandwich',
+        descripcion: 'Sándwich triple con pollo, jamón y tocino',
+        isListo: true,
+      ),
+    ];
+
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      children: [
+        OrdenMesaCard(
+          mesaNumero: '5',
+          ordenNumero: 'A-123',
+          items: items,
+          onLiberarOrden: () {},
+        ),
+        OrdenMesaCard(
+          mesaNumero: '3',
+          ordenNumero: 'A-124',
+          items: items2,
+          tieneItemsListos: true,
+          onLiberarOrden: () {},
+        ),
+      ],
+    );
+  }
+}
+
+class OrdenMesaCard extends StatelessWidget {
+  final String mesaNumero;
+  final String ordenNumero;
+  final List<OrdenItem> items;
+  final bool tieneItemsListos;
+  final VoidCallback onLiberarOrden;
+
+  const OrdenMesaCard({
+    Key? key,
+    required this.mesaNumero,
+    required this.ordenNumero,
+    required this.items,
+    this.tieneItemsListos = false,
+    required this.onLiberarOrden,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Card(
+      margin: const EdgeInsets.all(8.0),
+      child: Column(
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          Padding(
+            padding: const EdgeInsets.all(16.0),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.spaceBetween,
+              children: [
+                Text(
+                  'Mesa $mesaNumero',
+                  style: const TextStyle(
+                    fontSize: 18,
+                    fontWeight: FontWeight.bold,
+                  ),
+                ),
+                Row(
+                  children: [
+                    const Icon(Icons.access_time, size: 16),
+                    const SizedBox(width: 4),
+                    const Text('15:03'),
+                  ],
+                ),
+              ],
+            ),
+          ),
+          const Divider(height: 1),
+          Padding(
+            padding:
+                const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
+            child: Align(
+              alignment: Alignment.centerLeft,
+              child: Text(
+                'Orden #$ordenNumero',
+                style: TextStyle(
+                  color: Colors.grey[600],
+                  fontSize: 14,
+                ),
+              ),
+            ),
+          ),
+          ...items.map((item) => ListTile(
+                contentPadding: const EdgeInsets.symmetric(horizontal: 16.0),
+                leading: Text(
+                  '${item.cantidad}x',
+                  style: const TextStyle(
+                    fontSize: 16,
+                    fontWeight: FontWeight.bold,
+                  ),
+                ),
+                title: Text(
+                  item.nombre,
+                  style: const TextStyle(
+                    fontSize: 16,
+                    fontWeight: FontWeight.w500,
+                  ),
+                ),
+                subtitle: Column(
+                  crossAxisAlignment: CrossAxisAlignment.start,
+                  children: [
+                    Text(
+                      item.descripcion,
+                      style: TextStyle(
+                        color: Colors.grey[600],
+                        fontSize: 14,
+                      ),
+                    ),
+                    if (item.notas != null)
+                      Text(
+                        item.notas!,
+                        style: TextStyle(
+                          color: Colors.red[400],
+                          fontSize: 14,
+                        ),
+                      ),
+                  ],
+                ),
+                trailing: item.isListo
+                    ? Container(
+                        padding: const EdgeInsets.symmetric(
+                            horizontal: 12, vertical: 6),
+                        decoration: BoxDecoration(
+                          color: Colors.black,
+                          borderRadius: BorderRadius.circular(20),
+                        ),
+                        child: const Text(
+                          'Listo',
+                          style: TextStyle(
+                            color: Colors.white,
+                            fontSize: 12,
+                          ),
+                        ),
+                      )
+                    : const Icon(Icons.chevron_right),
+              )),
+          Padding(
+            padding: const EdgeInsets.all(16.0),
+            child: ElevatedButton(
+              onPressed: onLiberarOrden,
+              style: ElevatedButton.styleFrom(
+                backgroundColor: const Color(0xFF4CAF50),
+                padding: const EdgeInsets.symmetric(vertical: 16),
+                shape: RoundedRectangleBorder(
+                  borderRadius: BorderRadius.circular(8),
+                ),
+              ),
+              child: const SizedBox(
+                width: double.infinity,
+                child: Text(
+                  'Liberar Orden Completa',
+                  textAlign: TextAlign.center,
+                  style: TextStyle(
+                    color: Colors.white,
+                    fontSize: 16,
+                    fontWeight: FontWeight.w500,
+                  ),
+                ),
+              ),
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}