Explorar el Código

local bd y pedidos

OscarGil03 hace 1 año
padre
commit
2eca21dfd2
Se han modificado 33 ficheros con 2384 adiciones y 2529 borrados
  1. 25 0
      .vscode/launch.json
  2. BIN
      assets/JoshiLogo-BN.png
  3. 22 8
      lib/main.dart
  4. 5 0
      lib/models/categoria_producto_model.dart
  5. 14 0
      lib/models/item_carrito_model.dart
  6. 3 0
      lib/models/models.dart
  7. 18 4
      lib/models/pedido_model.dart
  8. 62 0
      lib/models/pedido_producto_model.dart
  9. 54 0
      lib/models/pedido_producto_toping_model.dart
  10. 33 0
      lib/models/producto_model.dart
  11. 0 1
      lib/models/toping_model.dart
  12. 1 0
      lib/services/producto_service.dart
  13. 47 0
      lib/services/productos_service.dart
  14. 204 0
      lib/services/repo_service.dart
  15. 1 0
      lib/services/services.dart
  16. 69 69
      lib/viewmodels/categoria_producto_view_model.dart
  17. 89 0
      lib/viewmodels/pedido_view_model.dart
  18. 53 67
      lib/viewmodels/producto_view_model.dart
  19. 1 0
      lib/viewmodels/viewmodels.dart
  20. 88 88
      lib/views/categoria_producto/categoria_producto_form.dart
  21. 199 199
      lib/views/categoria_producto/categoria_producto_screen.dart
  22. 0 3
      lib/views/home/home_screen.dart
  23. 22 20
      lib/views/main/main_screen.dart
  24. 44 0
      lib/views/pedido/pedido_csv.dart
  25. 117 0
      lib/views/pedido/pedido_detalle_screen.dart
  26. 0 703
      lib/views/pedido/pedido_form copy.dart
  27. 318 566
      lib/views/pedido/pedido_form.dart
  28. 154 188
      lib/views/pedido/pedido_screen.dart
  29. 289 0
      lib/views/pedido/pedido_ticket.dart
  30. 189 189
      lib/views/producto/producto_form.dart
  31. 229 229
      lib/views/producto/producto_screen.dart
  32. 33 194
      lib/widgets/app_drawer.dart
  33. 1 1
      lib/widgets/widgets_components.dart

+ 25 - 0
.vscode/launch.json

@@ -0,0 +1,25 @@
+{
+    // Use IntelliSense to learn about possible attributes.
+    // Hover to view descriptions of existing attributes.
+    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "name": "yoshi_papas_app",
+            "request": "launch",
+            "type": "dart"
+        },
+        {
+            "name": "yoshi_papas_app (profile mode)",
+            "request": "launch",
+            "type": "dart",
+            "flutterMode": "profile"
+        },
+        {
+            "name": "yoshi_papas_app (release mode)",
+            "request": "launch",
+            "type": "dart",
+            "flutterMode": "release"
+        }
+    ]
+}

BIN
assets/JoshiLogo-BN.png


+ 22 - 8
lib/main.dart

@@ -1,20 +1,34 @@
-//import 'package:fluent_ui/fluent_ui.dart';
 import 'package:flutter/material.dart';
-//import 'package:hermogas_ecosistema_web/viewmodels/codigo_postal_view_model.dart';
-import 'package:yoshi_papas_app/views/perfil/perfil_screen.dart';
-import 'package:provider/provider.dart';
-import '../themes/themes.dart';
 import 'package:flutter/services.dart';
+import 'package:provider/provider.dart';
+import 'package:sqflite_common_ffi/sqflite_ffi.dart';
+import 'dart:io'; // Importa esto para usar Platform.isWindows
 
-import 'viewmodels/viewmodels.dart';
+import 'services/productos_service.dart';
 import 'views/main/main_screen.dart';
 import 'views/home/home_screen.dart';
 import 'views/login/login_screen.dart';
+import 'views/perfil/perfil_screen.dart';
+import 'themes/themes.dart';
+import 'viewmodels/viewmodels.dart';
 import 'package:timezone/data/latest.dart' as tzdata;
 
-void main() {
+void main() async {
   WidgetsFlutterBinding.ensureInitialized();
   tzdata.initializeTimeZones();
+
+  // Inicialización de la base de datos para plataformas de escritorio con FFI
+  if (Platform.isWindows || Platform.isLinux) {
+    sqfliteFfiInit();
+    databaseFactory = databaseFactoryFfi;
+  }
+
+  final productosService = ProductosService();
+  if (await productosService.isDatabaseEmpty()) {
+    await productosService.fillCategoriaBD();
+    await productosService.fillProductoBD();
+  }
+
   SystemChrome.setPreferredOrientations([
     DeviceOrientation.landscapeRight,
     DeviceOrientation.landscapeLeft,
@@ -28,6 +42,7 @@ void main() {
       ChangeNotifierProvider(create: (_) => TopingCategoriaViewModel()),
       ChangeNotifierProvider(create: (_) => MediaViewModel()),
       ChangeNotifierProvider(create: (_) => TopingViewModel()),
+      ChangeNotifierProvider(create: (_) => PedidoViewModel()),
       // Agrega aquí cualquier otro provider que necesites
     ], child: const MyApp()));
   });
@@ -35,7 +50,6 @@ void main() {
 
 class MyApp extends StatelessWidget {
   const MyApp({super.key});
-  //ChangeNotifierProvider(create: (_) => AppTheme()),
 
   @override
   Widget build(BuildContext context) {

+ 5 - 0
lib/models/categoria_producto_model.dart

@@ -1,4 +1,5 @@
 import 'basico_model.dart';
+import '../services/services.dart';
 
 class CategoriaProducto extends Basico {
   String? nombre;
@@ -20,4 +21,8 @@ class CategoriaProducto extends Basico {
     super.parseJson(json);
     nombre = Basico.parseString(json['nombre']);
   }
+
+  Future<void> guardar() async {
+    idLocal = await RepoService().guardar(this);
+  }
 }

+ 14 - 0
lib/models/item_carrito_model.dart

@@ -0,0 +1,14 @@
+import 'toping_model.dart';
+import 'producto_model.dart';
+
+class ItemCarrito {
+  Producto producto;
+  int cantidad;
+  List<Toping> toppings;
+
+  ItemCarrito({
+    required this.producto,
+    this.cantidad = 1,
+    this.toppings = const [],
+  });
+}

+ 3 - 0
lib/models/models.dart

@@ -7,6 +7,9 @@ export '../models/media_toping_model.dart';
 export '../models/profile_model.dart';
 export '../models/categoria_producto_model.dart';
 export '../models/pedido_model.dart';
+export '../models/pedido_producto_model.dart';
+export '../models/pedido_producto_toping_model.dart';
 export '../models/producto_model.dart';
 export '../models/toping_categoria_model.dart';
 export '../models/toping_model.dart';
+export '../models/item_carrito_model.dart';

+ 18 - 4
lib/models/pedido_model.dart

@@ -1,18 +1,21 @@
+import 'package:yoshi_papas_app/models/pedido_producto_model.dart';
+
 import 'basico_model.dart';
 
 class Pedido extends Basico {
   int? folio;
-  int? estatus;
+  String? estatus;
   String? comentarios;
   String? peticion;
   String? nombreCliente;
   int? idCliente;
   int? idMesa;
-  int? terminado;
+  String? terminado;
   int? cerrar;
   int? idUsuario;
   int? idModificador;
   int? idCancelado;
+  List<PedidoProducto> productos = [];
 
   Pedido({
     super.id,
@@ -28,6 +31,7 @@ class Pedido extends Basico {
     this.idUsuario,
     this.idModificador,
     this.idCancelado,
+    this.productos = const [],
   });
 
   @override
@@ -46,22 +50,32 @@ class Pedido extends Basico {
       'idUsuario': idUsuario,
       'idModificador': idModificador,
       'idCancelado': idCancelado,
+      //'productos': productos.map((producto) => producto.toJson()).toList(),
     }..addAll(super.toJson());
   }
 
   Pedido.fromJson(Map<String, dynamic> json) {
     super.parseJson(json);
+    id = (json['id'] as int?)!;
     folio = Basico.parseInt(json['folio']);
-    estatus = Basico.parseInt(json['estatus']);
+    estatus = Basico.parseString(json['estatus']);
     comentarios = Basico.parseString(json['comentarios']);
     peticion = Basico.parseString(json['peticion']);
     nombreCliente = Basico.parseString(json['nombreCliente']);
     idCliente = Basico.parseInt(json['idCliente']);
     idMesa = Basico.parseInt(json['idMesa']);
-    terminado = Basico.parseInt(json['terminado']);
+    terminado = Basico.parseString(json['terminado']);
     cerrar = Basico.parseInt(json['cerrar']);
     idUsuario = Basico.parseInt(json['idUsuario']);
     idModificador = Basico.parseInt(json['idModificador']);
     idCancelado = Basico.parseInt(json['idCancelado']);
+    List<PedidoProducto> _productos = [];
+    if (json["productos"] != null && (json["productos"] as List).isNotEmpty) {
+      for (var i in (json["productos"] as List)) {
+        PedidoProducto m = PedidoProducto.fromJson(i);
+        _productos.add(m);
+      }
+    }
+    productos = _productos;
   }
 }

+ 62 - 0
lib/models/pedido_producto_model.dart

@@ -0,0 +1,62 @@
+import 'package:yoshi_papas_app/models/producto_model.dart';
+import 'package:yoshi_papas_app/models/toping_model.dart';
+
+import 'basico_model.dart';
+
+class PedidoProducto extends Basico {
+  int? idPedido;
+  int? idProducto;
+  Producto? producto;
+  String? costoUnitario;
+  String? descuento;
+  int? cantidad;
+  int? terminar;
+  String? comentario;
+  //List<Map<String, dynamic>>? topings;
+
+  PedidoProducto({
+    super.id,
+    this.idPedido,
+    this.idProducto,
+    this.producto,
+    this.costoUnitario,
+    this.descuento,
+    this.cantidad,
+    this.terminar,
+    this.comentario,
+    //this.topings = const [],
+  });
+
+  @override
+  Map<String, dynamic> toJson() {
+    return {
+      'id': id,
+      'idPedido': idPedido,
+      'idProducto': idProducto,
+      'costoUnitario': costoUnitario,
+      'descuento': descuento,
+      'cantidad': cantidad,
+      'terminar': terminar,
+      'comentario': comentario,
+      //'topings': topings,
+    }..addAll(super.toJson());
+  }
+
+  PedidoProducto.fromJson(Map<String, dynamic> json) {
+    super.parseJson(json);
+    idPedido = Basico.parseInt(json['idPedido']);
+    idProducto = Basico.parseInt(json['idProducto']);
+    producto =
+        json['producto'] != null ? Producto.fromJson(json['producto']) : null;
+    costoUnitario = Basico.parseString(json['costoUnitario']);
+    descuento = Basico.parseString(json['descuento']);
+    cantidad = Basico.parseInt(json['cantidad']);
+    terminar = Basico.parseInt(json['terminar']);
+    comentario = Basico.parseString(json['comentario']);
+    // topings = (json['topings'] as List<dynamic>?)
+    //         ?.map((toping) =>
+    //             {'id': toping['id'], 'cantidad': toping['cantidad']})
+    //         .toList() ??
+    //     [];
+  }
+}

+ 54 - 0
lib/models/pedido_producto_toping_model.dart

@@ -0,0 +1,54 @@
+import 'package:yoshi_papas_app/models/producto_model.dart';
+
+import 'basico_model.dart';
+
+class PedidoProductoToping extends Basico {
+  int? idPedido;
+  int? idProducto;
+  int? idToping;
+  String? costoUnitario;
+  String? descuento;
+  int? cantidad;
+  int? terminar;
+  String? comentario;
+  String? cancelado;
+
+  PedidoProductoToping({
+    super.id,
+    this.idPedido,
+    this.idProducto,
+    this.costoUnitario,
+    this.descuento,
+    this.cantidad,
+    this.terminar,
+    this.comentario,
+    this.cancelado,
+  });
+
+  @override
+  Map<String, dynamic> toJson() {
+    return {
+      'id': id,
+      'idPedido': idPedido,
+      'idProducto': idProducto,
+      'costoUnitario': costoUnitario,
+      'descuento': descuento,
+      'cantidad': cantidad,
+      'terminar': terminar,
+      'comentario': comentario,
+      'cancelado': cancelado,
+    }..addAll(super.toJson());
+  }
+
+  PedidoProductoToping.fromJson(Map<String, dynamic> json) {
+    super.parseJson(json);
+    idPedido = Basico.parseInt(json['idPedido']);
+    idProducto = Basico.parseInt(json['idProducto']);
+    costoUnitario = Basico.parseString(json['costoUnitario']);
+    descuento = Basico.parseString(json['descuento']);
+    cantidad = Basico.parseInt(json['cantidad']);
+    terminar = Basico.parseInt(json['terminar']);
+    comentario = Basico.parseString(json['comentario']);
+    cancelado = Basico.parseString(json['cancelado']);
+  }
+}

+ 33 - 0
lib/models/producto_model.dart

@@ -1,5 +1,6 @@
 import 'package:yoshi_papas_app/models/models.dart';
 
+import '../services/services.dart';
 import 'basico_model.dart';
 
 class Producto extends Basico {
@@ -16,6 +17,7 @@ class Producto extends Basico {
   String? descuento;
   String? venceDescuento;
   int? toping;
+  List<Toping>? topings;
 
   Producto({
     super.id,
@@ -31,6 +33,7 @@ class Producto extends Basico {
     this.descuento,
     this.venceDescuento,
     this.toping,
+    this.topings,
   });
 
   @override
@@ -49,9 +52,30 @@ class Producto extends Basico {
       'descuento': descuento,
       'venceDescuento': venceDescuento,
       'toping': toping,
+      'toppings': topings?.map((toping) => toping.toJson()).toList(),
     }..addAll(super.toJson());
   }
 
+  Map<String, dynamic> toMap() {
+    return {
+      'id': id,
+      'idCategoria': idCategoria,
+      'nombre': nombre,
+      'descripcion': descripcion,
+      'imagen': imagen,
+      'venta': venta,
+      'existencia': existencia,
+      'precio': precio,
+      'verMenu': verMenu,
+      'codigo': codigo,
+      'descuento': descuento,
+      'venceDescuento': venceDescuento,
+      'toping': toping,
+      // Asegúrate de convertir también los toppings si es necesario
+      'toppings': topings?.map((t) => t.toJson()).toList(),
+    };
+  }
+
   Producto.fromJson(Map<String, dynamic> json) {
     super.parseJson(json);
     idCategoria = Basico.parseInt(json['idCategoria']);
@@ -73,5 +97,14 @@ class Producto extends Basico {
     } else {
       toping = Basico.parseInt(json['toping']);
     }
+    if (json['toppings'] != null) {
+      topings = (json['toppings'] as List)
+          .map((topingJson) => Toping.fromJson(topingJson))
+          .toList();
+    }
+  }
+
+  Future<void> guardar() async {
+    idLocal = await RepoService().guardar(this);
   }
 }

+ 0 - 1
lib/models/toping_model.dart

@@ -1,5 +1,4 @@
 import 'package:yoshi_papas_app/models/models.dart';
-import 'media_toping_categoria_model.dart';
 import 'basico_model.dart';
 
 class Toping extends Basico {

+ 1 - 0
lib/services/producto_service.dart

@@ -1,3 +1,4 @@
+import 'package:sqflite/sqflite.dart';
 import 'package:yoshi_papas_app/data/api_response.dart';
 import 'package:yoshi_papas_app/models/models.dart';
 

+ 47 - 0
lib/services/productos_service.dart

@@ -0,0 +1,47 @@
+import 'package:sqflite/sqflite.dart';
+import 'package:yoshi_papas_app/services/repo_service.dart';
+
+import '../models/models.dart';
+
+class ProductosService {
+  Future<bool> isDatabaseEmpty() async {
+    final dbClient = await RepoService().db;
+    final categoriaCount = Sqflite.firstIntValue(
+      await dbClient!.rawQuery('SELECT COUNT(*) FROM CategoriaProducto'),
+    );
+    final productoCount = Sqflite.firstIntValue(
+      await dbClient.rawQuery('SELECT COUNT(*) FROM Producto'),
+    );
+    return categoriaCount == 0 && productoCount == 0;
+  }
+
+  Future<void> fillCategoriaBD() async {
+    final List<CategoriaProducto> categorias = [
+      CategoriaProducto(id: 1, nombre: 'HAMBURGUESA DE POLLO'),
+      CategoriaProducto(id: 2, nombre: 'ESPECIALIDADES'),
+      CategoriaProducto(id: 3, nombre: 'POSTRES'),
+      CategoriaProducto(id: 4, nombre: 'BEBIDAS'),
+    ];
+
+    for (var categoria in categorias) {
+      await categoria.guardar();
+    }
+  }
+
+  Future<void> fillProductoBD() async {
+    List<Producto> productos = [
+      //Snacks
+      Producto(
+          id: 1, idCategoria: 1, nombre: 'HAMBURGUESA DE POLLO', precio: '110'),
+      Producto(
+          id: 2, idCategoria: 2, nombre: 'CONO FIT MEDIANO', precio: '120'),
+      Producto(id: 3, idCategoria: 3, nombre: 'MUFFIN', precio: '35'),
+      Producto(id: 4, idCategoria: 4, nombre: 'COCA COLA 600ML', precio: '25'),
+      Producto(id: 5, idCategoria: 4, nombre: 'AGUA', precio: '20'),
+    ];
+
+    for (var producto in productos) {
+      await producto.guardar();
+    }
+  }
+}

+ 204 - 0
lib/services/repo_service.dart

@@ -0,0 +1,204 @@
+import 'dart:convert';
+import 'package:path/path.dart';
+import 'package:path_provider/path_provider.dart';
+import 'package:sqflite/sqflite.dart';
+import '../models/models.dart';
+
+class RepoService<T> {
+  static int dbVersion = 1;
+  static String dbName = 'joshipos023.db';
+  static const String id = Basico.identificadorWeb;
+  static const String idLocal = Basico.identificadorLocal;
+  static Database? _db;
+  final Map<String, dynamic> contexto = {
+    'Categoria': CategoriaProducto(),
+    'Producto': Producto(),
+    'Pedido': Pedido(productos: []),
+    'PedidoProducto': PedidoProducto(),
+  };
+
+  Future<Database?> get db async {
+    if (_db != null) return _db;
+
+    _db = await databaseInit();
+    return _db;
+  }
+
+  Future<Database> databaseInit() async {
+    String dir = (await getApplicationDocumentsDirectory()).path;
+    String path = join(dir, dbName);
+    return await openDatabase(
+      path,
+      version: dbVersion,
+      onCreate: _onCreate,
+      onUpgrade: _onUpgrade,
+    );
+  }
+
+  /// Crea la base de datos
+  _onCreate(Database db, int version) async {
+    contexto.forEach((String nombre, dynamic modelo) async {
+      Map<String, dynamic> model = json.decode(json.encode(modelo.toJson()));
+      String sql =
+          "CREATE TABLE ${modelo.runtimeType.toString()} (id INTEGER PRIMARY KEY AUTOINCREMENT";
+      model.forEach((String key, dynamic value) {
+        if (key != "id") {
+          // No incluir la columna de identificador local de nuevo
+          String tipo = value.runtimeType.toString();
+          String sqlType = "";
+          if (equals(tipo, 'int')) {
+            sqlType = "INTEGER";
+          } else if (equals(tipo, 'double')) {
+            sqlType = "REAL";
+          } else if (equals(tipo, 'bool')) {
+            sqlType = "BOOLEAN";
+          } else {
+            sqlType = "TEXT";
+          }
+
+          // Añadir cada campo al SQL, asegurándose de no configurar AUTOINCREMENT en folio
+          sql += ", $key $sqlType";
+        }
+      });
+      sql += ")";
+      await db.execute(sql);
+    });
+  }
+
+  /// Actualiza la version de la base de datos
+  _onUpgrade(Database db, int oldVersion, int newVersion) async {
+    while (oldVersion <= newVersion) {
+      switch (oldVersion) {
+        case 100:
+          /* await db.execute("DROP TABLE IF EXISTS Evidencia");
+         await db.execute('CREATE TABLE TABLAA (idLocal INTEGER PRIMARY KEY)');
+          List<String> sueltos = [
+            "ALTER TABLE Evidencia ADD id INTEGER",
+          ];
+          for(int i = 0; i < sueltos.length; i++) {
+            try {
+              String sql = sueltos.elementAt(i);
+              await db.execute(sql);
+            } catch (e) {}
+          } */
+          break;
+      }
+      oldVersion++;
+    }
+  }
+
+  /// Guarda un modelo de datos nuevo o modificado en el repositorio
+  Future<int> guardar(T model) async {
+    var dbClient = await db;
+    String nombreTabla = model.runtimeType.toString();
+    String modelo = json.encode(model, toEncodable: toEncodable);
+    Map<String, dynamic> modelMap = json.decode(modelo);
+
+    // Elimina 'id' si es 0 o null para evitar conflictos con AUTOINCREMENT
+    if (modelMap['id'] == null || modelMap['id'] == 0) {
+      modelMap.remove('id');
+    }
+
+    int resultado;
+    if (modelMap[Basico.identificadorLocal] > 0) {
+      resultado = await dbClient!.update(
+        nombreTabla,
+        modelMap,
+        where: "$idLocal = ?",
+        whereArgs: [modelMap[Basico.identificadorLocal]],
+      );
+    } else {
+      resultado = await dbClient!.insert(nombreTabla, modelMap);
+      var rawQuery =
+          await dbClient.rawQuery("SELECT last_insert_rowid() as id");
+      if (rawQuery.isNotEmpty) {
+        resultado = int.parse(rawQuery.first["id"].toString());
+        modelMap[Basico.identificadorLocal] =
+            resultado; // Actualiza el ID del modelo
+      }
+    }
+
+    if (model is Pedido) {
+      // Asegúrate de actualizar el ID en el objeto Pedido después de guardar
+      model.id = resultado;
+    }
+
+    return resultado;
+  }
+
+  dynamic toEncodable(dynamic item) {
+    Map<String, dynamic> map = {};
+
+    item.toJson().forEach((key, value) {
+      if (value is DateTime) {
+        map[key] = value.toIso8601String();
+      } else {
+        map[key] = value;
+      }
+    });
+
+    return map;
+  }
+
+  Future<List<T>> obtenerTodos() async {
+    var dbClient = await db;
+    String tableName = T
+        .toString(); // Obtiene el nombre del modelo, que asumimos coincide con el nombre de la tabla
+    List<Map<String, dynamic>> result = await dbClient!.query(tableName);
+    return result.map((map) => fromMap<T>(map)).toList();
+  }
+
+// Necesitarás una función que convierta un Map a un objeto de tipo T
+  T fromMap<T>(Map<String, dynamic> map) {
+    switch (T) {
+      case Pedido:
+        return Pedido.fromJson(map) as T;
+      case Producto:
+        return Producto.fromJson(map) as T;
+      // Añade más casos si tienes más tipos
+      default:
+        throw Exception('Tipo no soportado');
+    }
+  }
+
+  Future<Pedido?> obtenerPorId(int id) async {
+    Database? dbClient = await db;
+    List<Map> maps = await dbClient!.query('Pedido',
+        where:
+            'id = ?', // Asegúrate de que el nombre de la columna sea 'id' y no 'idLocal'
+        whereArgs: [id]);
+    if (maps.isNotEmpty) {
+      return Pedido.fromJson(Map<String, dynamic>.from(maps.first));
+    }
+    return null;
+  }
+
+  Future<List<PedidoProducto>> obtenerPorIdPedido(int idPedido) async {
+    Database? dbClient = await db;
+    List<Map> maps = await dbClient!
+        .query('PedidoProducto', where: 'idPedido = ?', whereArgs: [idPedido]);
+    return maps
+        .map((map) => PedidoProducto.fromJson(Map<String, dynamic>.from(map)))
+        .toList();
+  }
+
+  Future<Producto?> obtenerProductoPorId(int idProducto) async {
+    Database? dbClient = await db;
+    List<Map> maps = await dbClient!
+        .query('Producto', where: 'id = ?', whereArgs: [idProducto]);
+    if (maps.isNotEmpty) {
+      return Producto.fromJson(Map<String, dynamic>.from(maps.first));
+    }
+    return null;
+  }
+
+  Future<int> obtenerProximoFolio() async {
+    var dbClient = await db;
+    var result =
+        await dbClient!.rawQuery('SELECT MAX(folio) as last_folio FROM Pedido');
+    if (result.isNotEmpty && result.first["last_folio"] != null) {
+      return int.tryParse(result.first["last_folio"].toString())! + 1;
+    }
+    return 1; // Retorna 1 si no hay registros anteriores
+  }
+}

+ 1 - 0
lib/services/services.dart

@@ -3,3 +3,4 @@ export '../services/login_service.dart';
 export '../services/profile_service.dart';
 export '../services/general_service.dart';
 export '../services/categoria_producto_service.dart';
+export '../services/repo_service.dart';

+ 69 - 69
lib/viewmodels/categoria_producto_view_model.dart

@@ -1,4 +1,5 @@
 import 'package:flutter/material.dart';
+import 'package:sqflite/sqflite.dart';
 import '../services/services.dart';
 
 import '../models/models.dart';
@@ -8,84 +9,83 @@ class CategoriaProductoViewModel extends ChangeNotifier {
   CategoriaProducto? _selectedCategoriaProducto;
   bool _isLoading = true;
 
-  String _busqueda = "";
-  String get busqueda => _busqueda;
-
   List<CategoriaProducto> get categoriaProductos => _categoriaProductos;
   CategoriaProducto? get selectedCategoriaProducto =>
       _selectedCategoriaProducto;
 
   bool get isLoading => _isLoading;
 
-  Future<List<CategoriaProducto>> getCategoriaProducto(
-      {String? q, bool segmentar = false}) async {
-    _categoriaProductos =
-        await CategoriaProductoService().fetchList(q: q, segmentar: segmentar);
-    return _categoriaProductos;
-  }
-
   //Metodo para obtener lista de CategoriaProducto
-  Future<void> fetchCategoriaProductos({bool segmentar = false}) async {
-    _categoriaProductos =
-        await CategoriaProductoService().fetchList(segmentar: segmentar);
-    notifyListeners();
-  }
-
-  int pagina = 1;
-  int totalPaginas = 1;
-  int limite = 10;
-
-  void setLoading(bool loading) {
-    _isLoading = loading;
-    notifyListeners();
-  }
-
-  setBusqueda(String value) {
-    _busqueda = value;
-    notifyListeners();
-  }
-
-  CategoriaProducto selectCategoriaProducto(
-      CategoriaProducto categoriaProducto) {
-    _selectedCategoriaProducto = categoriaProducto;
-    return categoriaProducto;
-  }
-
-  cambiarPagina(int nuevaPagina, {bool segmentar = false}) {
-    pagina = nuevaPagina;
-    fetchCategoriaProductos();
-  }
-
-  Future<void> addCategoriaProducto({
-    required String nombre,
-  }) async {
-    await CategoriaProductoService().postCategoriaProducto(
-      nombre: nombre,
+  Future<void> fetchLocalAll() async {
+    var db = await RepoService().db;
+    var query = await db!.query(
+      'CategoriaProducto',
+      orderBy: 'idLocal asc',
     );
-    await fetchCategoriaProductos();
+    List<CategoriaProducto> aux = [];
+    for (var element in query) {
+      CategoriaProducto categoriaProducto = CategoriaProducto.fromJson(element);
+      aux.add(categoriaProducto);
+    }
+    _categoriaProductos = aux;
     notifyListeners();
   }
 
-  Future<void> editCategoriaProducto({
-    required int id,
-    required String nombre,
-  }) async {
-    await CategoriaProductoService().editCategoriaProducto(
-      id: id,
-      nombre: nombre,
-    );
-    await fetchCategoriaProductos();
-    notifyListeners();
-  }
-
-  setIsLoading(bool loading) {
-    _isLoading = loading;
-    notifyListeners();
-  }
-
-  Future<void> deleteCategoriaProducto(int id) async {
-    await CategoriaProductoService().deleteCategoriaProducto(id: id);
-    await fetchCategoriaProductos();
-    notifyListeners();
-  }
+  // int pagina = 1;
+  // int totalPaginas = 1;
+  // int limite = 10;
+
+  // void setLoading(bool loading) {
+  //   _isLoading = loading;
+  //   notifyListeners();
+  // }
+
+  // setBusqueda(String value) {
+  //   _busqueda = value;
+  //   notifyListeners();
+  // }
+
+  // CategoriaProducto selectCategoriaProducto(
+  //     CategoriaProducto categoriaProducto) {
+  //   _selectedCategoriaProducto = categoriaProducto;
+  //   return categoriaProducto;
+  // }
+
+  // cambiarPagina(int nuevaPagina, {bool segmentar = false}) {
+  //   pagina = nuevaPagina;
+  //   //fetchCategoriaProductos();
+  // }
+
+  // Future<void> addCategoriaProducto({
+  //   required String nombre,
+  // }) async {
+  //   await CategoriaProductoService().postCategoriaProducto(
+  //     nombre: nombre,
+  //   );
+  //   // await fetchCategoriaProductos();
+  //   notifyListeners();
+  // }
+
+  // Future<void> editCategoriaProducto({
+  //   required int id,
+  //   required String nombre,
+  // }) async {
+  //   await CategoriaProductoService().editCategoriaProducto(
+  //     id: id,
+  //     nombre: nombre,
+  //   );
+  //   //await fetchCategoriaProductos();
+  //   notifyListeners();
+  // }
+
+  // setIsLoading(bool loading) {
+  //   _isLoading = loading;
+  //   notifyListeners();
+  // }
+
+  // Future<void> deleteCategoriaProducto(int id) async {
+  //   await CategoriaProductoService().deleteCategoriaProducto(id: id);
+  //   //await fetchCategoriaProductos();
+  //   notifyListeners();
+  // }
 }

+ 89 - 0
lib/viewmodels/pedido_view_model.dart

@@ -0,0 +1,89 @@
+import 'package:flutter/material.dart';
+import 'package:intl/intl.dart';
+import 'package:yoshi_papas_app/services/repo_service.dart';
+
+import '../data/api_response.dart';
+import '../services/base_service.dart';
+import '../models/models.dart';
+
+class PedidoViewModel extends ChangeNotifier {
+  String _busqueda = "";
+  String get busqueda => _busqueda;
+
+  List<Pedido> _pedidos = [];
+  Pedido? _selectedPedido;
+  bool _isLoading = false;
+
+  List<Pedido> get pedidos => _pedidos;
+  Pedido? get selectedPedido => _selectedPedido;
+  bool get isLoading => _isLoading;
+
+  void setIsLoading(bool loading) {
+    _isLoading = loading;
+    notifyListeners();
+  }
+
+  Future<bool> guardarPedidoLocal({required Pedido pedido}) async {
+    RepoService<Pedido> repoPedido = RepoService<Pedido>();
+
+    int nextFolio = await repoPedido.obtenerProximoFolio();
+    pedido.folio = nextFolio;
+
+    int idPedido = await repoPedido.guardar(pedido);
+    if (idPedido > 0) {
+      pedido.id = idPedido;
+      RepoService<PedidoProducto> repoPedidoProducto =
+          RepoService<PedidoProducto>();
+      for (var producto in pedido.productos) {
+        PedidoProducto pedidoProducto = PedidoProducto(
+          idPedido: idPedido,
+          idProducto: producto.idProducto,
+          cantidad: producto.cantidad,
+          costoUnitario: producto.costoUnitario,
+          comentario: producto.comentario,
+        );
+        await repoPedidoProducto.guardar(pedidoProducto);
+      }
+      notifyListeners();
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  Future<void> fetchLocalPedidos() async {
+    setIsLoading(true);
+    RepoService<Pedido> repoPedido = RepoService<Pedido>();
+
+    List<Pedido> localPedidos = await repoPedido.obtenerTodos();
+    _pedidos = localPedidos;
+
+    setIsLoading(false);
+    notifyListeners();
+  }
+
+  Future<Pedido?> fetchPedidoConProductos(int idPedido) async {
+    RepoService<Pedido> repoPedido = RepoService<Pedido>();
+    Pedido? pedido = await repoPedido.obtenerPorId(idPedido);
+
+    if (pedido != null) {
+      RepoService<PedidoProducto> repoProducto = RepoService<PedidoProducto>();
+      RepoService<Producto> repoProductoInfo = RepoService<Producto>();
+      List<PedidoProducto> productos =
+          await repoProducto.obtenerPorIdPedido(idPedido);
+
+      for (var producto in productos) {
+        Producto? prodInfo =
+            await repoProductoInfo.obtenerProductoPorId(producto.idProducto!);
+        if (prodInfo != null) {
+          producto.producto =
+              prodInfo; // Asegúrate de que tu clase PedidoProducto pueda sostener este objeto
+        }
+      }
+
+      pedido.productos = productos;
+    }
+
+    return pedido;
+  }
+}

+ 53 - 67
lib/viewmodels/producto_view_model.dart

@@ -3,16 +3,18 @@ import 'package:flutter/material.dart';
 import '../data/api_response.dart';
 import '../services/base_service.dart';
 import '../models/models.dart';
+import '../services/services.dart';
 
 class ProductoViewModel<T> extends ChangeNotifier {
   String _busqueda = "";
   String get busqueda => _busqueda;
 
-  List<Producto> _registros = [];
+  List<Producto> _productos = [];
   Producto? _selectedModelo;
   bool _isLoading = false;
+  int? _selectedCategoriaId = 0;
 
-  List<Producto> get registros => _registros;
+  List<Producto> get productos => _productos;
   Producto? get selectedProducto => _selectedModelo;
   bool get isLoading => _isLoading;
 
@@ -25,82 +27,66 @@ class ProductoViewModel<T> extends ChangeNotifier {
     notifyListeners();
   }
 
-  Future<List<Producto>> fetchRegistros(
-      {CategoriaProducto? categoriaProducto,
-      String? q,
-      bool segmentar = false,
-      int limitee = 10}) async {
-    Map<String, String> parametros = {
-      "ordenar": "nombre-asc",
-      "pagina": "$pagina",
-      "limite": "$limite",
-      "expand": "categoria"
-    };
-    if (limitee == -1) {
-      parametros['limite'] = limitee.toString();
-    }
-    if (_busqueda.isNotEmpty) {
-      parametros["q"] = _busqueda;
-    }
-    if (categoriaProducto != null) {
-      parametros['idCategoria'] = categoriaProducto.id.toString();
-    }
-    if (segmentar) {
-      parametros['segmentar'] = "1";
-    }
-    var r = ApiResponse(
-        await BaseService().get("admin/producto", queryParameters: parametros));
-    pagina = r.paginacion!.pagina;
-    var total = r.paginacion!.total / r.paginacion!.limite;
-    totalPaginas = total > 0 ? total.ceil() : 1;
+  Future<void> fetchLocalAll() async {
+    _selectedCategoriaId = 0;
+    var db = await RepoService().db;
+    var query = await db!.query(
+      'Producto',
+      orderBy: 'idLocal asc',
+    );
     List<Producto> aux = [];
-    if (r.isOk) {
-      for (var x in r.resultados!) {
-        Producto modelo = Producto.fromJson(x);
-        aux.add(modelo);
-      }
+    for (var element in query) {
+      Producto producto = Producto.fromJson(element);
+      aux.add(producto);
     }
-    _registros = aux;
+    _productos = aux;
     notifyListeners();
-    return _registros;
   }
 
-  selectModelo(Producto Producto) {
-    _selectedModelo = Producto;
-    notifyListeners();
-  }
+  Future<void> fetchLocalByID({required int idCategoria}) async {
+    if (idCategoria == _selectedCategoriaId) {
+      _selectedCategoriaId = 0;
+      fetchLocalAll();
+      return;
+    }
 
-  setIsLoading(bool loading) {
-    _isLoading = loading;
+    //Se utiliza para actualizar la UI del botón
+    _selectedCategoriaId = idCategoria;
+
+    var db = await RepoService().db;
+    var query = await db!.query(
+      'Producto',
+      where: 'idCategoria ==?',
+      whereArgs: ['$idCategoria'],
+      orderBy: 'idLocal asc',
+    );
+    List<Producto> aux = [];
+    for (var element in query) {
+      Producto producto = Producto.fromJson(element);
+      aux.add(producto);
+    }
+    _productos = aux;
     notifyListeners();
   }
 
-  cambiarPagina(int nuevaPagina,
-      {CategoriaProducto? categoriaProducto, bool segmentar = false}) {
-    pagina = nuevaPagina;
-    fetchRegistros(categoriaProducto: categoriaProducto, segmentar: segmentar);
+  Future<void> fetchLocalByName({required String nombre}) async {
+    var db = await RepoService().db;
+    var query = await db!.query(
+      'Producto',
+      where: 'nombre LIKE "%$nombre%"',
+      orderBy: 'idLocal asc',
+    );
+    List<Producto> aux = [];
+    for (var element in query) {
+      Producto producto = Producto.fromJson(element);
+      aux.add(producto);
+    }
+    _productos = aux;
+    notifyListeners();
   }
 
-  Future<void> guardarModelo({
-    required Producto modelo,
-    required String nombre,
-    required String descripcion,
-    String? descuento,
-    required int existencia,
-    required int idCategoria,
-    required String precio,
-    String? venceDescuento,
-  }) async {
-    modelo.nombre = nombre;
-    modelo.descripcion = descripcion;
-    modelo.idCategoria = idCategoria;
-    modelo.descuento = descuento;
-    modelo.existencia = existencia;
-    modelo.precio = precio;
-    modelo.venceDescuento = venceDescuento;
-    var r = await BaseService()
-        .post("admin/producto/guardar", body: modelo.toJson());
-    if (r.statusCode == 200) {}
+  void setIsLoading(bool loading) {
+    _isLoading = loading;
     notifyListeners();
   }
 }

+ 1 - 0
lib/viewmodels/viewmodels.dart

@@ -6,3 +6,4 @@ export '../viewmodels/producto_view_model.dart';
 export '../viewmodels/toping_categoria_view_model.dart';
 export '../viewmodels/toping_view_model.dart';
 export '../viewmodels/media_view_model.dart';
+export '../viewmodels/pedido_view_model.dart';

+ 88 - 88
lib/views/categoria_producto/categoria_producto_form.dart

@@ -1,97 +1,97 @@
-// ignore_for_file: use_build_context_synchronously
+// // ignore_for_file: use_build_context_synchronously
 
-import 'package:flutter/material.dart';
-import 'package:yoshi_papas_app/widgets/widgets.dart';
-import 'package:provider/provider.dart';
+// import 'package:flutter/material.dart';
+// import 'package:yoshi_papas_app/widgets/widgets.dart';
+// import 'package:provider/provider.dart';
 
-import '../../models/models.dart';
-import '../../viewmodels/viewmodels.dart';
+// import '../../models/models.dart';
+// import '../../viewmodels/viewmodels.dart';
 
-class CategoriaProductoForm extends StatefulWidget {
-  const CategoriaProductoForm({Key? key}) : super(key: key);
+// class CategoriaProductoForm extends StatefulWidget {
+//   const CategoriaProductoForm({Key? key}) : super(key: key);
 
-  @override
-  State<CategoriaProductoForm> createState() => Formulario();
-}
+//   @override
+//   State<CategoriaProductoForm> createState() => Formulario();
+// }
 
-class Formulario extends State<CategoriaProductoForm> {
-  final _nombre = TextEditingController();
-  final _busquedaNombre = TextEditingController();
+// class Formulario extends State<CategoriaProductoForm> {
+//   final _nombre = TextEditingController();
+//   final _busquedaNombre = TextEditingController();
 
-  @override
-  void initState() {
-    super.initState();
-    Future(() async {
-      Provider.of<CategoriaProductoViewModel>(context, listen: false)
-          .setIsLoading(true);
-      final mvm =
-          Provider.of<CategoriaProductoViewModel>(context, listen: false);
-      CategoriaProducto? modelo = mvm.selectedCategoriaProducto;
-      if (modelo != null && modelo.id > 0) {
-        setState(() {
-          _nombre.text = modelo.nombre.toString();
-        });
-      }
-      Provider.of<CategoriaProductoViewModel>(context, listen: false)
-          .setIsLoading(false);
-    });
-  }
+//   @override
+//   void initState() {
+//     super.initState();
+//     Future(() async {
+//       Provider.of<CategoriaProductoViewModel>(context, listen: false)
+//           .setIsLoading(true);
+//       final mvm =
+//           Provider.of<CategoriaProductoViewModel>(context, listen: false);
+//       CategoriaProducto? modelo = mvm.selectedCategoriaProducto;
+//       if (modelo != null && modelo.id > 0) {
+//         setState(() {
+//           _nombre.text = modelo.nombre.toString();
+//         });
+//       }
+//       Provider.of<CategoriaProductoViewModel>(context, listen: false)
+//           .setIsLoading(false);
+//     });
+//   }
 
-  @override
-  void dispose() {
-    super.dispose();
-    _nombre.dispose();
-  }
+//   @override
+//   void dispose() {
+//     super.dispose();
+//     _nombre.dispose();
+//   }
 
-  @override
-  Widget build(BuildContext context) {
-    final mvm = Provider.of<CategoriaProductoViewModel>(context);
-    if (mvm.isLoading) return const Cargando();
-    final segmento = mvm.selectedCategoriaProducto;
+//   @override
+//   Widget build(BuildContext context) {
+//     final mvm = Provider.of<CategoriaProductoViewModel>(context);
+//     if (mvm.isLoading) return const Cargando();
+//     final segmento = mvm.selectedCategoriaProducto;
 
-    return Scaffold(
-      appBar: encabezado(titulo: "Agregar categoría producto"),
-      body: SingleChildScrollView(
-        padding: const EdgeInsets.all(8),
-        child: Column(
-          children: [
-            tarjeta(
-              Padding(
-                padding: const EdgeInsets.all(8),
-                child: Column(
-                  children: [
-                    Row(
-                      children: [
-                        Expanded(
-                          child: AppTextField(
-                            maxLength: 100,
-                            etiqueta: 'Nombre',
-                            controller: _nombre,
-                            hintText: 'Nombre de categoría producto',
-                          ),
-                        ),
-                      ],
-                    ),
-                  ],
-                ),
-              ),
-            ),
-            const SizedBox(height: 15),
-            boton("Guardar", () async {
-              Provider.of<CategoriaProductoViewModel>(context, listen: false)
-                  .setIsLoading(true);
-              await mvm.addCategoriaProducto(
-                nombre: _nombre.text,
-              );
-              Provider.of<CategoriaProductoViewModel>(context, listen: false)
-                  .setIsLoading(false);
-              if (context.mounted) {
-                Navigator.pop(context);
-              }
-            }),
-          ],
-        ),
-      ),
-    );
-  }
-}
+//     return Scaffold(
+//       appBar: encabezado(titulo: "Agregar categoría producto"),
+//       body: SingleChildScrollView(
+//         padding: const EdgeInsets.all(8),
+//         child: Column(
+//           children: [
+//             tarjeta(
+//               Padding(
+//                 padding: const EdgeInsets.all(8),
+//                 child: Column(
+//                   children: [
+//                     Row(
+//                       children: [
+//                         Expanded(
+//                           child: AppTextField(
+//                             maxLength: 100,
+//                             etiqueta: 'Nombre',
+//                             controller: _nombre,
+//                             hintText: 'Nombre de categoría producto',
+//                           ),
+//                         ),
+//                       ],
+//                     ),
+//                   ],
+//                 ),
+//               ),
+//             ),
+//             const SizedBox(height: 15),
+//             boton("Guardar", () async {
+//               Provider.of<CategoriaProductoViewModel>(context, listen: false)
+//                   .setIsLoading(true);
+//               await mvm.addCategoriaProducto(
+//                 nombre: _nombre.text,
+//               );
+//               Provider.of<CategoriaProductoViewModel>(context, listen: false)
+//                   .setIsLoading(false);
+//               if (context.mounted) {
+//                 Navigator.pop(context);
+//               }
+//             }),
+//           ],
+//         ),
+//       ),
+//     );
+//   }
+// }

+ 199 - 199
lib/views/categoria_producto/categoria_producto_screen.dart

@@ -1,207 +1,207 @@
-// ignore_for_file: use_build_context_synchronously
+// // ignore_for_file: use_build_context_synchronously
 
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import '../../models/models.dart';
-import '../../themes/themes.dart';
-import '../../viewmodels/viewmodels.dart';
-import '../../widgets/app_textfield.dart';
-import '../../widgets/pagination_buttons.dart';
-import '../../widgets/widgets_components.dart';
-import 'categoria_producto_form.dart';
+// import 'package:flutter/material.dart';
+// import 'package:provider/provider.dart';
+// import '../../models/models.dart';
+// import '../../themes/themes.dart';
+// import '../../viewmodels/viewmodels.dart';
+// import '../../widgets/app_textfield.dart';
+// import '../../widgets/pagination_buttons.dart';
+// import '../../widgets/widgets_components.dart';
+// import 'categoria_producto_form.dart';
 
-class CategoriaProductoScreen extends StatefulWidget {
-  const CategoriaProductoScreen({Key? key}) : super(key: key);
+// class CategoriaProductoScreen extends StatefulWidget {
+//   const CategoriaProductoScreen({Key? key}) : super(key: key);
 
-  @override
-  State<CategoriaProductoScreen> createState() => Formulario();
-}
+//   @override
+//   State<CategoriaProductoScreen> createState() => Formulario();
+// }
 
-class Formulario extends State<CategoriaProductoScreen> {
-  final _busqueda = TextEditingController(text: '');
+// class Formulario extends State<CategoriaProductoScreen> {
+//   final _busqueda = TextEditingController(text: '');
 
-  @override
-  void initState() {
-    super.initState();
-    Future(() async {
-      await Provider.of<CategoriaProductoViewModel>(context, listen: false)
-          .fetchCategoriaProductos();
-    });
-  }
+//   @override
+//   void initState() {
+//     super.initState();
+//     Future(() async {
+//       await Provider.of<CategoriaProductoViewModel>(context, listen: false)
+//           .fetchCategoriaProductos();
+//     });
+//   }
 
-  go(CategoriaProducto item) async {
-    Provider.of<CategoriaProductoViewModel>(context, listen: false)
-        .selectCategoriaProducto(item);
-    Navigator.push(
-      context,
-      MaterialPageRoute(
-        builder: (context) => const CategoriaProductoForm(),
-      ),
-    ).then((value) async {
-      await Provider.of<CategoriaProductoViewModel>(context, listen: false)
-          .fetchCategoriaProductos();
-    });
-  }
+//   go(CategoriaProducto item) async {
+//     Provider.of<CategoriaProductoViewModel>(context, listen: false)
+//         .selectCategoriaProducto(item);
+//     Navigator.push(
+//       context,
+//       MaterialPageRoute(
+//         builder: (context) => const CategoriaProductoForm(),
+//       ),
+//     ).then((value) async {
+//       await Provider.of<CategoriaProductoViewModel>(context, listen: false)
+//           .fetchCategoriaProductos();
+//     });
+//   }
 
-  @override
-  Widget build(BuildContext context) {
-    final mvm = Provider.of<CategoriaProductoViewModel>(context);
-    TextStyle estilo = const TextStyle(fontWeight: FontWeight.bold);
-    int vuelta = 0;
-    List<DataRow> categoriaProductos = [];
-    if (mvm.categoriaProductos.isNotEmpty) {
-      for (CategoriaProducto item in mvm.categoriaProductos) {
-        var _tipo = vuelta % 2;
-        vuelta++;
-        categoriaProductos.add(DataRow(selected: _tipo > 0, cells: [
-          DataCell(
-            Text(item.nombre.toString()),
-            onTap: () => go(item),
-          ),
-          DataCell(
-              Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
-            PopupMenuButton(
-              surfaceTintColor: AppTheme.primary,
-              itemBuilder: (context) => [
-                PopupMenuItem(
-                  child: const Text('Editar'),
-                  onTap: () => go(item),
-                ),
-                PopupMenuItem(
-                  child: const Text(
-                    'Eliminar',
-                  ),
-                  onTap: () async {
-                    return showDialog(
-                      context: context,
-                      builder: (context) {
-                        return AlertDialog(
-                          title: const Text("Eliminar registro"),
-                          content: const Text('¿Desea eliminar el registro?'),
-                          actions: [
-                            Row(children: [
-                              Expanded(
-                                  child: TextButton(
-                                onPressed: () {
-                                  Navigator.pop(context);
-                                },
-                                child: const Text('Cancelar'),
-                              )),
-                              Expanded(
-                                  child: TextButton(
-                                onPressed: () async {
-                                  Navigator.pop(context);
-                                },
-                                child: const Text('Continuar'),
-                              ))
-                            ])
-                          ],
-                        );
-                      },
-                    );
-                  },
-                )
-              ],
-              icon: const Icon(Icons.more_vert),
-              shape: RoundedRectangleBorder(
-                  borderRadius: BorderRadius.circular(15)),
-            )
-          ]))
-        ]));
-      }
-    }
+//   @override
+//   Widget build(BuildContext context) {
+//     final mvm = Provider.of<CategoriaProductoViewModel>(context);
+//     TextStyle estilo = const TextStyle(fontWeight: FontWeight.bold);
+//     int vuelta = 0;
+//     List<DataRow> categoriaProductos = [];
+//     if (mvm.categoriaProductos.isNotEmpty) {
+//       for (CategoriaProducto item in mvm.categoriaProductos) {
+//         var _tipo = vuelta % 2;
+//         vuelta++;
+//         categoriaProductos.add(DataRow(selected: _tipo > 0, cells: [
+//           DataCell(
+//             Text(item.nombre.toString()),
+//             onTap: () => go(item),
+//           ),
+//           DataCell(
+//               Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
+//             PopupMenuButton(
+//               surfaceTintColor: AppTheme.primary,
+//               itemBuilder: (context) => [
+//                 PopupMenuItem(
+//                   child: const Text('Editar'),
+//                   onTap: () => go(item),
+//                 ),
+//                 PopupMenuItem(
+//                   child: const Text(
+//                     'Eliminar',
+//                   ),
+//                   onTap: () async {
+//                     return showDialog(
+//                       context: context,
+//                       builder: (context) {
+//                         return AlertDialog(
+//                           title: const Text("Eliminar registro"),
+//                           content: const Text('¿Desea eliminar el registro?'),
+//                           actions: [
+//                             Row(children: [
+//                               Expanded(
+//                                   child: TextButton(
+//                                 onPressed: () {
+//                                   Navigator.pop(context);
+//                                 },
+//                                 child: const Text('Cancelar'),
+//                               )),
+//                               Expanded(
+//                                   child: TextButton(
+//                                 onPressed: () async {
+//                                   Navigator.pop(context);
+//                                 },
+//                                 child: const Text('Continuar'),
+//                               ))
+//                             ])
+//                           ],
+//                         );
+//                       },
+//                     );
+//                   },
+//                 )
+//               ],
+//               icon: const Icon(Icons.more_vert),
+//               shape: RoundedRectangleBorder(
+//                   borderRadius: BorderRadius.circular(15)),
+//             )
+//           ]))
+//         ]));
+//       }
+//     }
 
-    return Scaffold(
-      appBar: AppBar(
-        title: const Text('Categoría Productos'),
-      ),
-      floatingActionButton: FloatingActionButton(
-        onPressed: () {
-          mvm.selectCategoriaProducto(CategoriaProducto());
-          Navigator.push(
-            context,
-            MaterialPageRoute(
-              builder: (context) => const CategoriaProductoForm(),
-            ),
-          ).then((value) async {
-            await Provider.of<CategoriaProductoViewModel>(context,
-                    listen: false)
-                .fetchCategoriaProductos();
-          });
-        },
-        child: const Icon(Icons.add),
-      ),
-      body: Column(
-        children: [
-          Expanded(
-            child: ListView(
-              padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
-              children: [
-                const SizedBox(height: 8),
-                tarjeta(Padding(
-                    padding: const EdgeInsets.all(10),
-                    child: Row(
-                      children: [
-                        Expanded(
-                          flex: 8,
-                          child: AppTextField(
-                            prefixIcon: const Icon(Icons.search),
-                            maxLength: 100,
-                            etiqueta: 'Búsqueda por nombre...',
-                            controller: _busqueda,
-                            hintText: 'Búsqueda por nombre...',
-                          ),
-                        ),
-                        const SizedBox(width: 5),
-                        Expanded(
-                          flex: 2,
-                          child: botonElevated(
-                            accion: () async {
-                              _busqueda.text = _busqueda.text.trim();
-                              await Provider.of<CategoriaProductoViewModel>(
-                                      context,
-                                      listen: false)
-                                  .setIsLoading(true);
-                              await Provider.of<CategoriaProductoViewModel>(
-                                      context,
-                                      listen: false)
-                                  .setBusqueda(_busqueda.text);
-                              await Provider.of<CategoriaProductoViewModel>(
-                                      context,
-                                      listen: false)
-                                  .fetchCategoriaProductos();
-                              await Provider.of<CategoriaProductoViewModel>(
-                                      context,
-                                      listen: false)
-                                  .setBusqueda("");
-                              await Provider.of<CategoriaProductoViewModel>(
-                                      context,
-                                      listen: false)
-                                  .setIsLoading(false);
-                            },
-                          ),
-                        ),
-                      ],
-                    ))),
-                const SizedBox(height: 8),
-                tarjeta(DataTable(
-                    sortAscending: true,
-                    sortColumnIndex: 1,
-                    columns: [
-                      DataColumn(label: Text("NOMBRE", style: estilo)),
-                      DataColumn(label: Text("", style: estilo)),
-                    ],
-                    rows: categoriaProductos)),
-                PaginationButtons(
-                  currentPage: mvm.pagina,
-                  totalPages: mvm.totalPaginas,
-                  onPageChanged: (i) => mvm.cambiarPagina(i),
-                )
-              ],
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
+//     return Scaffold(
+//       appBar: AppBar(
+//         title: const Text('Categoría Productos'),
+//       ),
+//       floatingActionButton: FloatingActionButton(
+//         onPressed: () {
+//           mvm.selectCategoriaProducto(CategoriaProducto());
+//           Navigator.push(
+//             context,
+//             MaterialPageRoute(
+//               builder: (context) => const CategoriaProductoForm(),
+//             ),
+//           ).then((value) async {
+//             await Provider.of<CategoriaProductoViewModel>(context,
+//                     listen: false)
+//                 .fetchCategoriaProductos();
+//           });
+//         },
+//         child: const Icon(Icons.add),
+//       ),
+//       body: Column(
+//         children: [
+//           Expanded(
+//             child: ListView(
+//               padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
+//               children: [
+//                 const SizedBox(height: 8),
+//                 tarjeta(Padding(
+//                     padding: const EdgeInsets.all(10),
+//                     child: Row(
+//                       children: [
+//                         Expanded(
+//                           flex: 8,
+//                           child: AppTextField(
+//                             prefixIcon: const Icon(Icons.search),
+//                             maxLength: 100,
+//                             etiqueta: 'Búsqueda por nombre...',
+//                             controller: _busqueda,
+//                             hintText: 'Búsqueda por nombre...',
+//                           ),
+//                         ),
+//                         const SizedBox(width: 5),
+//                         Expanded(
+//                           flex: 2,
+//                           child: botonElevated(
+//                             accion: () async {
+//                               _busqueda.text = _busqueda.text.trim();
+//                               await Provider.of<CategoriaProductoViewModel>(
+//                                       context,
+//                                       listen: false)
+//                                   .setIsLoading(true);
+//                               await Provider.of<CategoriaProductoViewModel>(
+//                                       context,
+//                                       listen: false)
+//                                   .setBusqueda(_busqueda.text);
+//                               await Provider.of<CategoriaProductoViewModel>(
+//                                       context,
+//                                       listen: false)
+//                                   .fetchCategoriaProductos();
+//                               await Provider.of<CategoriaProductoViewModel>(
+//                                       context,
+//                                       listen: false)
+//                                   .setBusqueda("");
+//                               await Provider.of<CategoriaProductoViewModel>(
+//                                       context,
+//                                       listen: false)
+//                                   .setIsLoading(false);
+//                             },
+//                           ),
+//                         ),
+//                       ],
+//                     ))),
+//                 const SizedBox(height: 8),
+//                 tarjeta(DataTable(
+//                     sortAscending: true,
+//                     sortColumnIndex: 1,
+//                     columns: [
+//                       DataColumn(label: Text("NOMBRE", style: estilo)),
+//                       DataColumn(label: Text("", style: estilo)),
+//                     ],
+//                     rows: categoriaProductos)),
+//                 PaginationButtons(
+//                   currentPage: mvm.pagina,
+//                   totalPages: mvm.totalPaginas,
+//                   onPageChanged: (i) => mvm.cambiarPagina(i),
+//                 )
+//               ],
+//             ),
+//           ),
+//         ],
+//       ),
+//     );
+//   }
+// }

+ 0 - 3
lib/views/home/home_screen.dart

@@ -22,15 +22,12 @@ class Formulario extends State<HomeScreen> {
 
   @override
   Widget build(BuildContext context) {
-    String nombre = Provider.of<LoginViewModel>(context).nombre;
-    String correo = Provider.of<LoginViewModel>(context).correo;
     return Scaffold(
       backgroundColor: Colors.grey.shade200,
       drawer: AppDrawer(),
       appBar: AppBar(
         elevation: 0,
         title: const Text('Inicio'),
-        actions: [usuarioHeader(nombre, correo)],
       ),
       body: const Center(
         child: Image(

+ 22 - 20
lib/views/main/main_screen.dart

@@ -1,5 +1,6 @@
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
+import 'package:yoshi_papas_app/views/pedido/pedido_screen.dart';
 
 import '../../viewmodels/viewmodels.dart';
 import '../../views/login/login_screen.dart';
@@ -23,25 +24,26 @@ class MainScreenState extends State<MainScreen> {
 
   @override
   Widget build(BuildContext context) {
-    return Consumer(builder: (context, LoginViewModel login, _) {
-      switch (login.status) {
-        case Status.uninitialized:
-          return const Scaffold(
-            body: Center(
-              child: CircularProgressIndicator(),
-            ),
-          );
-        case Status.unauthenticated:
-          return const LoginScreen();
-        case Status.authenticating:
-          return const Scaffold(
-            body: Center(
-              child: CircularProgressIndicator(),
-            ),
-          );
-        case Status.authenticated:
-          return const HomeScreen();
-      }
-    });
+    return const HomeScreen();
+    // return Consumer(builder: (context, LoginViewModel login, _) {
+    //   switch (login.status) {
+    //     case Status.uninitialized:
+    //       return const Scaffold(
+    //         body: Center(
+    //           child: CircularProgressIndicator(),
+    //         ),
+    //       );
+    //     case Status.unauthenticated:
+    //       return const HomeScreen();
+    //     case Status.authenticating:
+    //       return const Scaffold(
+    //         body: Center(
+    //           child: CircularProgressIndicator(),
+    //         ),
+    //       );
+    //     case Status.authenticated:
+    //       return const HomeScreen();
+    //   }
+    // });
   }
 }

+ 44 - 0
lib/views/pedido/pedido_csv.dart

@@ -0,0 +1,44 @@
+import 'package:csv/csv.dart';
+import 'package:path_provider/path_provider.dart';
+import 'dart:io';
+import 'package:path/path.dart'
+    as p; // Importa path como p para evitar conflictos con otros nombres
+
+import '../../models/models.dart';
+
+Future<void> exportarPedidosACSV(List<Pedido> pedidos) async {
+  List<List<dynamic>> rows = [
+    [
+      "Folio",
+      "Cliente",
+      "Producto",
+      "Cantidad",
+      "Precio Unitario",
+      "Comentarios"
+    ]
+  ];
+
+  for (var pedido in pedidos) {
+    for (var producto in pedido.productos) {
+      List<dynamic> row = [
+        pedido.folio,
+        pedido.nombreCliente,
+        producto.producto?.nombre ?? 'No especificado',
+        producto.cantidad,
+        producto.producto?.precio ?? '0.0',
+        pedido.comentarios ?? ''
+      ];
+      rows.add(row);
+    }
+  }
+
+  String csv = const ListToCsvConverter().convert(rows);
+  final directory =
+      await getApplicationDocumentsDirectory(); // Obtiene el directorio de documentos
+  final path = p.join(
+      directory.path, 'pedidos.csv'); // Crea la ruta completa para el archivo
+  final file = File(path);
+
+  await file.writeAsString(csv); // Escribe el CSV en el archivo
+  print('Archivo CSV guardado en $path');
+}

+ 117 - 0
lib/views/pedido/pedido_detalle_screen.dart

@@ -0,0 +1,117 @@
+import 'dart:io';
+
+import 'package:flutter/material.dart';
+import 'package:pdf/pdf.dart';
+import 'package:printing/printing.dart';
+import 'package:provider/provider.dart';
+import 'package:yoshi_papas_app/themes/themes.dart';
+import 'package:yoshi_papas_app/views/pedido/pedido_ticket.dart';
+import '../../models/models.dart';
+
+class PedidoDetalleScreen extends StatelessWidget {
+  final Pedido pedido;
+
+  const PedidoDetalleScreen({Key? key, required this.pedido}) : super(key: key);
+
+  String obtenerEstadoPedido(String? estado) {
+    switch (estado) {
+      case '1':
+        return "NUEVO";
+      case '2':
+        return "EN PROCESO";
+      case '3':
+        return "TERMINADO";
+      case '4':
+        return "CANCELADO";
+      default:
+        return "ESTADO DESCONOCIDO"; // En caso de que se reciba un valor no esperado
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    print("Productos en el pedido: ${pedido.productos.length}");
+    return Scaffold(
+      appBar: AppBar(
+        title: Text('Detalle del Pedido ${pedido.folio}'),
+      ),
+      body: SingleChildScrollView(
+          padding: const EdgeInsets.all(
+              12.0), // Agrega padding al contenedor general
+          child: Column(
+            children: [
+              Card(
+                  elevation: 4, // Sombra de la tarjeta
+                  color: Colors.white, // Fondo blanco de la tarjeta
+                  child: Column(
+                    children: [
+                      ListTile(
+                        title: Text(
+                          'Cliente: ${pedido.nombreCliente}',
+                          style: TextStyle(
+                              fontWeight:
+                                  FontWeight.bold), // Negritas para el título
+                        ),
+                        subtitle: Text('Comentarios: ${pedido.comentarios}'),
+                      ),
+                      // ListTile(
+                      //   title: Text(
+                      //     'Estado del Pedido: ${obtenerEstadoPedido(pedido.estatus)}',
+                      //     style: TextStyle(
+                      //         fontSize: 16,
+                      //         fontWeight: FontWeight.bold,
+                      //         color: Colors
+                      //             .deepOrange), // Estilo para el estado del pedido
+                      //   ),
+                      // )
+                    ],
+                  )),
+              SizedBox(height: 10), // Espacio entre componentes
+              Card(
+                elevation: 4,
+                color: Colors.white,
+                child: Padding(
+                  padding: const EdgeInsets.all(8.0),
+                  child: Column(
+                    crossAxisAlignment: CrossAxisAlignment.start,
+                    children: [
+                      Text('Productos',
+                          style: TextStyle(
+                              fontSize: 18, fontWeight: FontWeight.bold)),
+                      ListView.builder(
+                        shrinkWrap: true,
+                        physics: NeverScrollableScrollPhysics(),
+                        itemCount: pedido.productos.length,
+                        itemBuilder: (context, index) {
+                          final pedidoProducto = pedido.productos[index];
+                          return ListTile(
+                            title: Text(
+                              pedidoProducto.producto?.nombre ??
+                                  "Producto no especificado",
+                              style: TextStyle(
+                                  fontWeight: FontWeight
+                                      .bold), // Negritas para el nombre del producto
+                            ),
+                            subtitle:
+                                Text('Cantidad: ${pedidoProducto.cantidad}'),
+                          );
+                        },
+                      ),
+                      SizedBox(height: 20), // Espacio antes del botón
+                      ElevatedButton(
+                        onPressed: () => printTickets(pedido),
+                        child: Text('Imprimir Ticket'),
+                        style: ElevatedButton.styleFrom(
+                          primary: AppTheme.primary,
+                          onPrimary: Colors.white,
+                        ),
+                      ),
+                    ],
+                  ),
+                ),
+              ),
+            ],
+          )),
+    );
+  }
+}

+ 0 - 703
lib/views/pedido/pedido_form copy.dart

@@ -1,703 +0,0 @@
-import 'package:flutter/foundation.dart';
-import 'package:flutter/material.dart';
-import 'package:yoshi_papas_app/widgets/widgets.dart';
-import '../../themes/themes.dart';
-
-class PedidoForm extends StatefulWidget {
-  @override
-  _PedidoFormState createState() => _PedidoFormState();
-}
-
-enum CustomizationStep { Base, Salsa, Aderezo, Toppings }
-
-class _PedidoFormState extends State<PedidoForm> {
-  Map<String, bool> baseOptions = {};
-  Map<String, bool> sauceOptions = {};
-  Map<String, bool> dressingOptions = {};
-  Map<String, bool> toppingOptions = {};
-  bool isCustomizingProduct = false;
-  Map<String, dynamic>? currentProductForCustomization;
-  String? selectedBase;
-  List<String> selectedSauce = [];
-  List<String> selectedDressing = [];
-  List<String> selectedToppings = [];
-  List<Map<String, dynamic>> productsInCart = [];
-  String currentCategory = 'Hamburguesa de pollo';
-
-  Map<String, List<Map<String, dynamic>>> categoryProducts = {
-    'Hamburguesa de pollo': [
-      {
-        'name': 'Rebanada de queso',
-        'price': 25,
-        'category': 'Hamburguesa de pollo'
-      },
-      {
-        'name': 'Porción de queso',
-        'price': 15,
-        'category': 'Hamburguesa de pollo'
-      },
-      {
-        'name': 'Hamburguesa de pollo',
-        'price': 110,
-        'category': 'Hamburguesa de pollo'
-      },
-    ],
-    'Postres': [
-      {'name': 'Muffin', 'price': 35, 'category': 'Postres'},
-      {'name': 'Rebanada de Pay de Nuez', 'price': 65, 'category': 'Postres'},
-    ],
-    'Cono de papas': [
-      {
-        'name': 'Cono de papas grande',
-        'price': 120,
-        'category': 'Cono de papas'
-      },
-      {
-        'name': 'Cono de papas mediano',
-        'price': 85,
-        'category': 'Cono de papas'
-      },
-    ],
-  };
-  List<Map<String, dynamic>> products = [];
-
-  CustomizationStep _currentStep = CustomizationStep.Base;
-  late Map<CustomizationStep, Widget> _stepWidgets;
-
-  @override
-  void initState() {
-    super.initState();
-    // Inicializa con la categoría actual
-    products = categoryProducts[currentCategory]!;
-    initializeCheckboxStates();
-    _stepWidgets = {
-      CustomizationStep.Base: _buildBaseOptions(),
-      CustomizationStep.Salsa: _buildSauceOptions(),
-      CustomizationStep.Aderezo: _buildDressingOptions(),
-      CustomizationStep.Toppings: _buildToppingsOptions(),
-    };
-  }
-
-  void customizeProduct(Map<String, dynamic> product) {
-    if (product['category'] == 'Cono de papas') {
-      setState(() {
-        isCustomizingProduct = true;
-        currentProductForCustomization = product;
-      });
-    } else {
-      addToCart(product);
-    }
-  }
-
-  void initializeCheckboxStates() {
-    // Inicializa los mapas de opciones con valores false
-    for (var base in [
-      'Papa Gajo',
-      'Papa Regilla',
-      'Papa Curly',
-      'Papa Smile',
-      'Papa Francesa'
-    ]) {
-      baseOptions[base] = false;
-    }
-    for (var sauce in [
-      'BBQ',
-      'HOTBBQ',
-      'BUFFALO',
-      'TERIYAKI',
-      'PARMESAN GARLIC',
-      'MANGO HABANERO'
-    ]) {
-      sauceOptions[sauce] = false;
-    }
-    for (var dressing in ['QUESO AMARILLO', 'RANCH', 'CHIPOTLE', 'KETCHUP']) {
-      dressingOptions[dressing] = false;
-    }
-    for (var topping in [
-      'JALAPEÑO',
-      'QUESO BLANCO',
-      'TAKIS',
-      'RUFFLES',
-      'QUESO PARMESANO',
-      'ELOTE'
-    ]) {
-      toppingOptions[topping] = false;
-    }
-  }
-
-  void addToCart(Map<String, dynamic> product) {
-    // Si es un "Cono de papas" y estamos personalizando
-    if (product['category'] == 'Cono de papas' && isCustomizingProduct) {
-      final Map<String, dynamic> customizedProduct = {
-        ...product,
-        'customizations': {
-          'base': selectedBase,
-          'sauce': selectedSauce,
-          'dressing': selectedDressing,
-          'toppings': selectedToppings,
-        },
-        'quantity':
-            1, // Asegúrate de que cada producto personalizado tenga una cantidad inicial de 1
-      };
-
-      setState(() {
-        productsInCart
-            .add(customizedProduct); // Añade el producto personalizado
-        isCustomizingProduct = false; // Termina la personalización
-        resetCustomizations(); // Llama a un método que restablecerá las personalizaciones
-      });
-    } else {
-      // Si no es un "Cono de papas" o no estamos personalizando, añade directamente al carrito
-      setState(() {
-        int index = productsInCart.indexWhere((p) =>
-            p['name'] == product['name'] &&
-            p['customizations'] ==
-                product[
-                    'customizations']); // Comparar también las personalizaciones
-        if (index != -1) {
-          productsInCart[index]['quantity'] += 1;
-        } else {
-          productsInCart.add(
-              {...product, 'quantity': 1}); // Añade con cantidad inicial de 1
-        }
-      });
-    }
-  }
-
-  void resetCustomizations() {
-    // Restablece las variables de estado de las personalizaciones
-    selectedBase = null;
-    selectedSauce = [];
-    selectedDressing = [];
-    selectedToppings = [];
-    // Restablecer cualquier otro estado de personalización aquí
-  }
-
-  void finalizeCustomization() {
-    // Aquí debes construir el producto basado en las selecciones de personalización
-
-    selectedBase = baseOptions.entries
-        .firstWhere((entry) => entry.value, orElse: () => MapEntry('', false))
-        .key;
-    selectedSauce = sauceOptions.entries
-        .where((entry) => entry.value)
-        .map((e) => e.key)
-        .toList();
-    selectedDressing = dressingOptions.entries
-        .where((entry) => entry.value)
-        .map((e) => e.key)
-        .toList();
-    selectedToppings = toppingOptions.entries
-        .where((entry) => entry.value)
-        .map((e) => e.key)
-        .toList();
-
-    Map<String, dynamic> customizedProduct = {
-      ...currentProductForCustomization!,
-      'customizations': {
-        'base': selectedBase,
-        'sauce': selectedSauce,
-        'dressing': selectedDressing,
-        'toppings': selectedToppings,
-      }
-    };
-
-    addToCart(customizedProduct);
-    setState(() {
-      isCustomizingProduct = false;
-      currentProductForCustomization = null;
-      initializeCheckboxStates(); // Reinicia los estados de los checkbox
-    });
-  }
-
-  Widget buildCategoryButtons() {
-    return Row(
-      mainAxisAlignment: MainAxisAlignment.center,
-      children: categoryProducts.keys.map((String key) {
-        return Padding(
-          padding: const EdgeInsets.symmetric(horizontal: 4.0),
-          child: OutlinedButton(
-            onPressed: () {
-              setState(() {
-                currentCategory = key;
-                products = categoryProducts[key]!;
-              });
-            },
-            style: OutlinedButton.styleFrom(
-              backgroundColor: Colors.white,
-              foregroundColor: Colors.black,
-              side: BorderSide(
-                width: 2.0,
-                color: currentCategory == key ? AppTheme.primary : Colors.grey,
-              ),
-            ),
-            child: Text(key),
-          ),
-        );
-      }).toList(),
-    );
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      appBar: encabezado(
-        titulo: "CREAR PEDIDO",
-      ),
-      body: Row(
-        children: [
-          // Sección izquierda con la lista del carrito - 30%
-          Flexible(
-            flex: 3,
-            child: tarjeta(
-              Column(
-                children: [
-                  // Encabezados de la lista
-                  const Padding(
-                    padding:
-                        EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0),
-                    child: Row(
-                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
-                      children: [
-                        Text('Producto',
-                            style: TextStyle(
-                                fontWeight: FontWeight.bold, fontSize: 18)),
-                        Text('Cantidad',
-                            style: TextStyle(
-                                fontWeight: FontWeight.bold, fontSize: 18)),
-                      ],
-                    ),
-                  ),
-                  // Lista de productos
-                  Expanded(
-                    child: ListView.builder(
-                      itemCount: productsInCart.length,
-                      itemBuilder: (context, index) {
-                        var product = productsInCart[index];
-                        return ListTile(
-                          title: _buildProductItem(product),
-                          trailing: Row(
-                            mainAxisSize: MainAxisSize.min,
-                            children: [
-                              IconButton(
-                                icon: const Icon(Icons.remove),
-                                onPressed: () {
-                                  // Lógica para disminuir la cantidad
-                                  setState(() {
-                                    if (product['quantity'] > 1) {
-                                      productsInCart[index]['quantity'] -= 1;
-                                    } else {
-                                      productsInCart.removeAt(index);
-                                    }
-                                  });
-                                },
-                              ),
-                              Text('${product['quantity'] ?? 1}'),
-                              IconButton(
-                                icon: const Icon(Icons.add),
-                                onPressed: () {
-                                  // Lógica para aumentar la cantidad
-                                  setState(() {
-                                    productsInCart[index]['quantity'] += 1;
-                                  });
-                                },
-                              ),
-                            ],
-                          ),
-                        );
-                      },
-                    ),
-                  ),
-                  ElevatedButton(
-                    style: ButtonStyle(
-                        backgroundColor:
-                            MaterialStatePropertyAll(AppTheme.primary),
-                        textStyle: const MaterialStatePropertyAll(
-                            TextStyle(fontSize: 22)),
-                        foregroundColor:
-                            const MaterialStatePropertyAll(Colors.black),
-                        padding: const MaterialStatePropertyAll(
-                            EdgeInsets.fromLTRB(80, 20, 80, 20))),
-                    onPressed: () {
-                      // Aquí agregarías la lógica para guardar el pedido
-                    },
-                    child: const Text('Guardar'),
-                  ),
-                ],
-              ),
-              color: Colors.white,
-              padding: 8.0,
-            ),
-          ),
-
-          const SizedBox(
-            width: 35,
-          ),
-
-          // Sección derecha con los productos disponibles - 70%
-          Flexible(
-            flex: 7,
-            child: Column(
-              children: [
-                // Botones de categorías de productos
-                buildCategoryButtons(),
-
-                // GridView de productos
-                Expanded(
-                  child: isCustomizingProduct
-                      ? buildCustomizationOptions()
-                      : buildProductGrid(),
-                ),
-              ],
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-
-  Widget _buildProductItem(Map<String, dynamic> product) {
-    List<Widget> customizationWidgets = [];
-    if (product.containsKey('customizations')) {
-      Map customizations = product['customizations'];
-      customizationWidgets.addAll([
-        Text(' - Base: ${customizations['base']}'),
-        ...customizations['sauce']
-            .map<Widget>((sauce) => Text(' - Salsa: $sauce'))
-            .toList(),
-        ...customizations['dressing']
-            .map<Widget>((dressing) => Text(' - Aderezo: $dressing'))
-            .toList(),
-        ...customizations['toppings']
-            .map<Widget>((topping) => Text(' - Topping: $topping'))
-            .toList(),
-      ]);
-    }
-
-    return Column(
-      crossAxisAlignment: CrossAxisAlignment.start,
-      children: [
-        Text(product['name']),
-        ...customizationWidgets,
-      ],
-    );
-  }
-
-  Widget buildProductGrid() {
-    return tarjeta(
-      GridView.builder(
-        itemCount: products.length,
-        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
-          crossAxisCount: 2, // Número de columnas
-          childAspectRatio: 3 / 2, // Proporción de cada tarjeta
-          crossAxisSpacing: 10, // Espaciado horizontal
-          mainAxisSpacing: 10, // Espaciado vertical
-        ),
-        itemBuilder: (context, index) {
-          final product = products[index];
-          return tarjeta(
-            InkWell(
-              onTap: () => customizeProduct(product),
-              child: Column(
-                mainAxisAlignment: MainAxisAlignment.center,
-                children: [
-                  // Añade el ícono aquí
-                  const Icon(Icons.fastfood,
-                      size: 80), // Tamaño del ícono ajustable
-                  const SizedBox(height: 8), // Espacio entre ícono y texto
-                  Text(
-                    product['name'],
-                    style: const TextStyle(fontSize: 16),
-                    textAlign: TextAlign.center,
-                  ),
-                  const SizedBox(height: 8), // Espacio entre texto y precio
-                  Text(
-                    '\$${product['price']}',
-                    style:
-                        const TextStyle(fontSize: 24, color: Color(0xFF008000)),
-                    textAlign: TextAlign.center,
-                  ),
-                ],
-              ),
-            ),
-            color: const Color(0xFFF4F4F4),
-            padding: 8.0,
-          );
-        },
-      ),
-      color: Colors.white,
-      padding: 8.0,
-    );
-  }
-
-  Widget buildCustomizationOptions() {
-    Widget currentStepWidget;
-    switch (_currentStep) {
-      case CustomizationStep.Base:
-        currentStepWidget = _buildBaseOptions();
-        break;
-      case CustomizationStep.Salsa:
-        currentStepWidget = _buildSauceOptions();
-        break;
-      case CustomizationStep.Aderezo:
-        currentStepWidget = _buildDressingOptions();
-        break;
-      case CustomizationStep.Toppings:
-        currentStepWidget = _buildToppingsOptions();
-        break;
-      default:
-        currentStepWidget = SizedBox.shrink();
-    }
-
-    // Solo muestra el botón de confirmación si isCustomizingProduct es true.
-    Widget confirmButton = isCustomizingProduct
-        ? Padding(
-            padding: const EdgeInsets.symmetric(vertical: 16.0),
-            child: _buildConfirmButton(),
-          )
-        : SizedBox.shrink();
-
-    return tarjeta(
-      Column(
-        children: [
-          Expanded(
-            child: Row(
-              children: [
-                Flexible(
-                  flex: 3,
-                  child: ListView(
-                    children: CustomizationStep.values.map((step) {
-                      // Verifica si el paso es Salsa, Aderezo o Toppings para añadir el texto " (Max 2)"
-                      String stepName = describeEnum(step);
-                      if (step == CustomizationStep.Salsa ||
-                          step == CustomizationStep.Aderezo ||
-                          step == CustomizationStep.Toppings) {
-                        stepName +=
-                            " (Max 2)"; // Agrega " (Max 2)" al nombre del paso+
-                      }
-
-                      return ListTile(
-                        title: Text(stepName),
-                        selected: _currentStep == step,
-                        onTap: () => setState(() => _currentStep = step),
-                      );
-                    }).toList(),
-                  ),
-                ),
-                Flexible(
-                  flex: 7,
-                  child: currentStepWidget,
-                ),
-              ],
-            ),
-          ),
-          Padding(
-            padding: const EdgeInsets.symmetric(vertical: 16.0),
-            child: _buildConfirmButton(),
-          ), // Incluir el botón de confirmación aquí
-        ],
-      ),
-      color: Colors.white,
-      padding: 8.0,
-    );
-  }
-
-  Widget buildCheckboxListTile({
-    required String title,
-    required Map<String, bool> optionsMap,
-    required Function(String, bool?) onChanged,
-  }) {
-    return CheckboxListTile(
-      title: Text(title),
-      value: optionsMap[title] ?? false,
-      onChanged: (bool? value) {
-        setState(() {
-          onChanged(title, value);
-        });
-      },
-      secondary: Image.asset('assets/JoshiLogo.png', width: 30),
-    );
-  }
-
-  Widget _buildBaseOptions() {
-    return GridView.count(
-      crossAxisCount: 3,
-      children: baseOptions.keys.map((String key) {
-        bool isSelected =
-            baseOptions[key] ?? false; // Determina si está seleccionado
-        return GestureDetector(
-          onTap: () {
-            setState(() {
-              baseOptions.keys.forEach(
-                  (k) => baseOptions[k] = false); // Desmarca todos primero
-              baseOptions[key] = true; // Marca el seleccionado
-            });
-          },
-          child: Container(
-            decoration: BoxDecoration(
-              color: isSelected ? AppTheme.primary : const Color(0xFFF4F4F4),
-              border: Border.all(color: isSelected ? Colors.red : Colors.grey),
-            ),
-            child: Center(
-              child: Text(key,
-                  style: TextStyle(
-                      color: isSelected ? Colors.white : Colors.black)),
-            ),
-          ),
-        );
-      }).toList(),
-    );
-  }
-
-  Widget _buildSauceOptions() {
-    return GridView.count(
-      crossAxisCount: 3,
-      children: sauceOptions.keys.map((String key) {
-        bool isSelected = sauceOptions[key] ?? false;
-        return GestureDetector(
-          onTap: () {
-            int selectedCount = sauceOptions.values.where((b) => b).length;
-            setState(() {
-              // Si la salsa ya está seleccionada, la deselecciona.
-              if (isSelected) {
-                sauceOptions[key] = false;
-              } else {
-                // Si se están seleccionando menos de 2 salsas, permite esta selección.
-                if (selectedCount < 2) {
-                  sauceOptions[key] = true;
-                } else {
-                  // Si ya hay 2 salsas seleccionadas, primero deselecciona la primera seleccionada.
-                  final firstSelected = sauceOptions.keys.firstWhere(
-                    (k) => sauceOptions[k]!,
-                    orElse: () => '',
-                  );
-                  if (firstSelected.isNotEmpty) {
-                    sauceOptions[firstSelected] = false;
-                    sauceOptions[key] = true;
-                  }
-                }
-              }
-            });
-          },
-          child: Container(
-            decoration: BoxDecoration(
-              color: isSelected ? AppTheme.primary : const Color(0xFFF4F4F4),
-              border: Border.all(color: Colors.grey),
-            ),
-            child: Center(
-              child: Text(key,
-                  style: TextStyle(
-                      color: isSelected ? Colors.white : Colors.black)),
-            ),
-          ),
-        );
-      }).toList(),
-    );
-  }
-
-  Widget _buildDressingOptions() {
-    return GridView.count(
-      crossAxisCount: 3,
-      children: dressingOptions.keys.map((String key) {
-        bool isSelected = dressingOptions[key] ?? false;
-        return GestureDetector(
-          onTap: () {
-            int selectedCount = dressingOptions.values.where((b) => b).length;
-            setState(() {
-              // Si la salsa ya está seleccionada, la deselecciona.
-              if (isSelected) {
-                dressingOptions[key] = false;
-              } else {
-                // Si se están seleccionando menos de 2 salsas, permite esta selección.
-                if (selectedCount < 2) {
-                  dressingOptions[key] = true;
-                } else {
-                  // Si ya hay 2 salsas seleccionadas, primero deselecciona la primera seleccionada.
-                  final firstSelected = dressingOptions.keys.firstWhere(
-                    (k) => dressingOptions[k]!,
-                    orElse: () => '',
-                  );
-                  if (firstSelected.isNotEmpty) {
-                    dressingOptions[firstSelected] = false;
-                    dressingOptions[key] = true;
-                  }
-                }
-              }
-            });
-          },
-          child: Container(
-            decoration: BoxDecoration(
-              color: isSelected ? AppTheme.primary : const Color(0xFFF4F4F4),
-              border: Border.all(color: Colors.grey),
-            ),
-            child: Center(
-              child: Text(key,
-                  style: TextStyle(
-                      color: isSelected ? Colors.white : Colors.black)),
-            ),
-          ),
-        );
-      }).toList(),
-    );
-  }
-
-  Widget _buildToppingsOptions() {
-    return GridView.count(
-      crossAxisCount: 3,
-      children: toppingOptions.keys.map((String key) {
-        bool isSelected = toppingOptions[key] ?? false;
-        return GestureDetector(
-          onTap: () {
-            int selectedCount = toppingOptions.values.where((b) => b).length;
-            setState(() {
-              // Si la salsa ya está seleccionada, la deselecciona.
-              if (isSelected) {
-                toppingOptions[key] = false;
-              } else {
-                // Si se están seleccionando menos de 2 salsas, permite esta selección.
-                if (selectedCount < 2) {
-                  toppingOptions[key] = true;
-                } else {
-                  // Si ya hay 2 salsas seleccionadas, primero deselecciona la primera seleccionada.
-                  final firstSelected = toppingOptions.keys.firstWhere(
-                    (k) => toppingOptions[k]!,
-                    orElse: () => '',
-                  );
-                  if (firstSelected.isNotEmpty) {
-                    toppingOptions[firstSelected] = false;
-                    toppingOptions[key] = true;
-                  }
-                }
-              }
-            });
-          },
-          child: Container(
-            decoration: BoxDecoration(
-              color: isSelected ? AppTheme.primary : const Color(0xFFF4F4F4),
-              border: Border.all(color: Colors.grey),
-            ),
-            child: Center(
-              child: Text(key,
-                  style: TextStyle(
-                      color: isSelected ? Colors.white : Colors.black)),
-            ),
-          ),
-        );
-      }).toList(),
-    );
-  }
-
-  Widget _buildConfirmButton() {
-    return ElevatedButton(
-      style: ElevatedButton.styleFrom(
-          primary: AppTheme.primary, // Color del botón
-          onPrimary: Colors.black,
-          textStyle: const TextStyle(fontSize: 22),
-          padding: const EdgeInsets.fromLTRB(80, 20, 80, 20)),
-      onPressed: () {
-        finalizeCustomization(); // Este método creará el pedido personalizado
-      },
-      child: Text('Confirmar Pedido'),
-    );
-  }
-}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 318 - 566
lib/views/pedido/pedido_form.dart


+ 154 - 188
lib/views/pedido/pedido_screen.dart

@@ -1,199 +1,179 @@
-// ignore_for_file: use_build_context_synchronously
-
 import 'package:flutter/material.dart';
-import 'package:yoshi_papas_app/widgets/widgets.dart';
 import 'package:provider/provider.dart';
-import 'package:intl/intl.dart';
-import '../../viewmodels/viewmodels.dart';
+import 'package:yoshi_papas_app/themes/themes.dart';
+import 'package:yoshi_papas_app/views/pedido/pedido_csv.dart';
+import 'package:yoshi_papas_app/views/pedido/pedido_detalle_screen.dart';
 import '../../models/models.dart';
-import '../../themes/themes.dart';
-import 'pedido_form.dart';
-import '../../services/services.dart' as servicio;
+import '../../viewmodels/viewmodels.dart';
+import '../../widgets/app_textfield.dart';
+import '../../widgets/pagination_buttons.dart';
+import '../../widgets/widgets_components.dart';
+import 'pedido_form.dart'; // Asumiendo que tienes un formulario para los pedidos similar al de los productos.
 
 class PedidoScreen extends StatefulWidget {
   const PedidoScreen({Key? key}) : super(key: key);
+
   @override
-  State<PedidoScreen> createState() => Formulario();
+  State<PedidoScreen> createState() => _PedidoScreenState();
 }
 
-class Formulario extends State<PedidoScreen> {
+class _PedidoScreenState extends State<PedidoScreen> {
   final _busqueda = TextEditingController(text: '');
   ScrollController horizontalScrollController = ScrollController();
-  DateTime? fechaInicio = DateTime.now();
-  DateTime? fechaFin;
-  Size? _size;
+
   @override
   void initState() {
     super.initState();
-    WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
-      // await Provider.of<PedidoViewModel>(context, listen: false)
-      //     .setIsLoading(true);
-      // await Provider.of<PedidoViewModel>(context, listen: false)
-      //     .fetchRegistros();
-      // List<Empresa> lasempresas =
-      //     Provider.of<EmpresaViewModel>(context, listen: false).empresas;
-      // if (lasempresas.isNotEmpty) {
-      //   setState(() {
-      //     empresa = lasempresas.first;
-      //   });
-      // }
-      // await Future.delayed(const Duration(seconds: 1));
-      // await Provider.of<OrdenesViewModel>(context, listen: false)
-      //     .setIsLoading(false);
+    WidgetsBinding.instance.addPostFrameCallback((_) {
+      Provider.of<PedidoViewModel>(context, listen: false).fetchLocalPedidos();
     });
   }
 
-  @override
-  void dispose() {
-    horizontalScrollController.dispose();
-    super.dispose();
+  void exportCSV() async {
+    // Obtiene los pedidos actuales del estado de PedidoViewModel
+    List<Pedido> pedidos =
+        Provider.of<PedidoViewModel>(context, listen: false).pedidos;
+    // Llamada a la función de exportación que debes definir en otro lugar y que crea el CSV
+    exportarPedidosACSV(pedidos);
+    ScaffoldMessenger.of(context).showSnackBar(
+        SnackBar(content: Text('Exportación de CSV completada!')));
   }
 
-  // go(Orden item) async {
-  //   Provider.of<CamaraViewModel>(context, listen: false).limpiarFotos();
-  //   Provider.of<MediaViewModel>(context, listen: false).limpiar();
-  //   Provider.of<OrdenesViewModel>(context, listen: false).selectOrden(item);
-  //   Navigator.push(
-  //     context,
-  //     MaterialPageRoute(
-  //       builder: (context) => const OrdenForm(),
-  //     ),
-  //   ).then((value) async {
-  //     await Provider.of<OrdenesViewModel>(context, listen: false)
-  //         .fetchRegistros();
-  //   });
-  // }
+  void go(Pedido item) async {
+    // Obtener el pedido completo con productos antes de navegar
+    Pedido? pedidoCompleto =
+        await Provider.of<PedidoViewModel>(context, listen: false)
+            .fetchPedidoConProductos(item.id);
+    if (pedidoCompleto != null) {
+      Navigator.push(
+        context,
+        MaterialPageRoute(
+          builder: (context) => PedidoDetalleScreen(pedido: pedidoCompleto),
+        ),
+      );
+    } else {
+      print("Error al cargar el pedido con productos");
+    }
+  }
 
   @override
   Widget build(BuildContext context) {
-    //final mvm = Provider.of<PedidoViewModel>(context);
+    final pvm = Provider.of<PedidoViewModel>(context);
     double screenWidth = MediaQuery.of(context).size.width;
     final isMobile = screenWidth < 1250;
     final double? columnSpacing = isMobile ? null : 0;
-    //final isLoading = mvm.isLoading;
-    // if (isLoading) return const Cargando();
-
     TextStyle estilo = const TextStyle(fontWeight: FontWeight.bold);
     List<DataRow> registros = [];
-    //if (mvm.registros.isNotEmpty) {
-    var vuelta = 0;
-    //for (Orden item in mvm.registros) {
-    var _tipo = vuelta % 2;
-    vuelta++;
-    String fsalida = "";
-    // if (item.fechaSalida != null) {
-    //   fsalida = DateFormat("dd/MM/yyyy HH:mm")
-    //       .format(item.fechaSalida!)
-    //       .toString();
-    // }
-    registros.add(DataRow(selected: _tipo > 0, cells: [
-      DataCell(
-          Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
-        PopupMenuButton(
-          surfaceTintColor: AppTheme.primary,
-          itemBuilder: (context) => [
-            PopupMenuItem(
-              child: const Text('Editar'),
-              onTap: () => {} /*go(item)*/,
-            ),
-            PopupMenuItem(
-              child: const Text(
-                'Eliminar',
+    for (Pedido item in pvm.pedidos) {
+      registros.add(DataRow(cells: [
+        DataCell(
+            Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
+          PopupMenuButton(
+            itemBuilder: (context) => [
+              PopupMenuItem(
+                child: const Text('Editar'),
+                onTap: () => go(item),
               ),
-              onTap: () async {
-                return showDialog(
-                  context: context,
-                  builder: (context) {
-                    return AlertDialog(
-                      title: const Text("Eliminar registro"),
-                      content: const Text('¿Desea eliminar el registro?'),
-                      actions: [
-                        Row(children: [
-                          Expanded(
-                              child: TextButton(
-                            onPressed: () {
-                              Navigator.pop(context);
-                            },
-                            child: const Text('Cancelar'),
-                          )),
-                          Expanded(
-                              child: TextButton(
-                            onPressed: () async {
-                              // //await mvm.eliminar(item);
-                              // await mvm.fetchRegistros();
-                              // if (context.mounted) {
-                              //   Navigator.pop(context);
-                              // }
-                            },
-                            child: const Text('Continuar'),
-                          ))
-                        ])
-                      ],
-                    );
-                  },
-                );
-              },
-            ),
-            PopupMenuItem(
-              child: const Text('Imprimir'),
-              //onTap: () => imprimir(item),
-            ),
-          ],
-          icon: const Icon(Icons.more_vert),
-          shape:
-              RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
+              PopupMenuItem(
+                child: const Text('Cancelar Pedido'),
+                onTap: () async {
+                  bool confirmado = await showDialog<bool>(
+                        context: context,
+                        builder: (context) {
+                          return AlertDialog(
+                            title: const Text("Cancelar Pedido"),
+                            content: const Text(
+                                '¿Estás seguro de que deseas cancelar este pedido?'),
+                            actions: [
+                              TextButton(
+                                onPressed: () =>
+                                    Navigator.of(context).pop(false),
+                                child: const Text('No'),
+                              ),
+                              TextButton(
+                                onPressed: () =>
+                                    Navigator.of(context).pop(false),
+                                child: const Text('Sí'),
+                              ),
+                            ],
+                          );
+                        },
+                      ) ??
+                      false;
+
+                  if (confirmado) {
+                    // bool result = await Provider.of<PedidoViewModel>(context,
+                    //         listen: false)
+                    //     .cancelarPedido(item.id!);
+                    // if (result) {
+                    //   ScaffoldMessenger.of(context).showSnackBar(
+                    //     SnackBar(
+                    //         content: Text("Pedido cancelado correctamente")),
+                    //   );
+                    // } else {
+                    //   ScaffoldMessenger.of(context).showSnackBar(
+                    //     SnackBar(content: Text("Error al cancelar el pedido")),
+                    //   );
+                    // }
+                  }
+                },
+              )
+            ],
+            icon: const Icon(Icons.more_vert),
+          ),
+        ])),
+        DataCell(
+          Text(item.id.toString()), // Ajusta de acuerdo a tu modelo de Pedido.
+          onTap: () => go(item),
         ),
-      ])),
-      DataCell(
-        Text('Pedido'),
-        //Text(item.folio.toString()),
-        // onTap: () => go(item),
-      ),
-      DataCell(
-        Text('Petición'),
-        //Text(item.numeroUnidad.toString()),
-        //onTap: () => go(item),
-      ),
-      DataCell(
-        Text('Cliente'),
-        //Text(item.nombreChofer.toString()),
-        //onTap: () => go(item),
-      ),
-      DataCell(
-        Text('Mesa'),
-        //Text("${item.categoriaFalla.toString()}: ${item.falla.toString()}"),
-        // onTap: () => go(item),
-      ),
-      DataCell(
-        Text('Productos Terminados'),
-        //Text(item.estatus.toString()),
-        //onTap: () => go(item),
-      ),
-      DataCell(
-        Text('Visto'),
-        //Text(item.estatus.toString()),
-        //onTap: () => go(item),
-      ),
-    ]));
-    //}
-    //}
-    _size = MediaQuery.of(context).size;
+        DataCell(
+          Text(item.nombreCliente ??
+              "Sin nombre"), // Ajusta de acuerdo a tu modelo de Pedido.
+          onTap: () => go(item),
+        ),
+        DataCell(
+          Text(item.comentarios ??
+              "Sin comentarios"), // Ajusta de acuerdo a tu modelo de Pedido.
+          onTap: () => go(item),
+        ),
+        // Continúa con las demás celdas que necesites mostrar
+      ]));
+    }
 
     return Scaffold(
-      appBar: encabezado(
-        titulo: "PEDIDOS",
+      appBar: AppBar(
+        title: const Text('Pedidos'),
+        actions: <Widget>[
+          IconButton(
+            icon: const Icon(Icons.save_alt),
+            onPressed: exportCSV,
+            tooltip: 'Exportar a CSV',
+          ),
+        ],
       ),
-      floatingActionButton: FloatingActionButton(
+      floatingActionButton: FloatingActionButton.extended(
         onPressed: () async {
-          // Aquí asumo que quieres navegar a una nueva página cuando se presione el botón
-          await Navigator.of(context).push(
+          await Navigator.push(
+            context,
             MaterialPageRoute(
               builder: (context) => PedidoForm(),
             ),
-          );
+          ).then((_) => Provider.of<PedidoViewModel>(context, listen: false)
+              .fetchLocalPedidos());
         },
-        child: const Icon(Icons
-            .add), // Este es el hijo del FloatingActionButton, que define el ícono que se muestra en el botón.
+        icon: const Icon(Icons.add, size: 30), // Incrementa el tamaño del ícono
+        label: const Text(
+          "Agregar Pedido",
+          style: TextStyle(
+            fontSize: 20, // Incrementa el tamaño del texto
+          ),
+        ),
+        shape: RoundedRectangleBorder(
+          borderRadius: BorderRadius.circular(8),
+        ),
+        materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+        backgroundColor: AppTheme.primary,
+        foregroundColor: AppTheme.tertiary,
       ),
       body: Column(
         children: [
@@ -229,7 +209,6 @@ class Formulario extends State<PedidoScreen> {
                               Row(
                                 children: [BusquedaTextField()],
                               ),
-                              SizedBox(height: 10),
                               SizedBox(height: 15),
                               Row(
                                 children: [BotonBuscar()],
@@ -242,9 +221,9 @@ class Formulario extends State<PedidoScreen> {
                   ),
                 ),
                 const SizedBox(height: 8),
-                // isLoading
-                //     ? const Center(child: CircularProgressIndicator())
-                //     : Container(),
+                pvm.isLoading
+                    ? const Center(child: CircularProgressIndicator())
+                    : Container(),
                 tarjeta(
                   Column(
                     children: [
@@ -272,18 +251,12 @@ class Formulario extends State<PedidoScreen> {
                                   columns: [
                                     DataColumn(label: Text(" ", style: estilo)),
                                     DataColumn(
-                                        label: Text("PEDIDO", style: estilo)),
+                                        label: Text("FOLIO", style: estilo)),
                                     DataColumn(
-                                        label: Text("PETICIÓN", style: estilo)),
+                                        label: Text("NOMBRE", style: estilo)),
                                     DataColumn(
-                                        label: Text("CLIENTE", style: estilo)),
-                                    DataColumn(
-                                        label: Text("MESA", style: estilo)),
-                                    DataColumn(
-                                        label: Text("PRODUCTOS TERMINADOS",
-                                            style: estilo)),
-                                    DataColumn(
-                                        label: Text("VISTO", style: estilo)),
+                                        label:
+                                            Text("COMENTARIOS", style: estilo)),
                                   ],
                                   rows: registros,
                                 ),
@@ -292,15 +265,14 @@ class Formulario extends State<PedidoScreen> {
                           ),
                         );
                       }),
-                      // PaginationButtons(
-                      //   currentPage: mvm.pagina,
-                      //   totalPages: mvm.totalPaginas,
-                      //   onPageChanged: (i) => mvm.cambiarPagina(i,
-                      //       empresa: _selectedEmpresa, falla: _selectedFalla),
-                      // )
                     ],
                   ),
                 ),
+                // PaginationButtons(
+                //   currentPage: pvm.pagina,
+                //   totalPages: pvm.totalPaginas,
+                //   onPageChanged: (i) => pvm.cambiarPagina(i),
+                // )
               ],
             ),
           ),
@@ -326,17 +298,11 @@ class Formulario extends State<PedidoScreen> {
       flex: 2,
       child: botonElevated(
         accion: () async {
-          _busqueda.text = _busqueda.text.trim();
-          /* if (_busqueda.text.isEmpty && _selectedFalla == null) {
-                                return alerta(context);
-                              } */
-
-          // OrdenesViewModel mvm =
-          //     Provider.of<OrdenesViewModel>(context, listen: false);
+          // PedidoViewModel mvm =
+          //     Provider.of<PedidoViewModel>(context, listen: false);
           // await mvm.setIsLoading(true);
           // await mvm.setBusqueda(_busqueda.text);
-          // await mvm.fetchRegistros(
-          //     falla: _selectedFalla, empresa: _selectedEmpresa);
+          // await mvm.fetchPedidos(q: _busqueda.text);
           // await mvm.setBusqueda("");
           // await mvm.setIsLoading(false);
         },

+ 289 - 0
lib/views/pedido/pedido_ticket.dart

@@ -0,0 +1,289 @@
+import 'dart:typed_data';
+import 'package:pdf/pdf.dart';
+import 'package:pdf/widgets.dart' as pw;
+import '../../models/models.dart';
+import 'package:printing/printing.dart';
+import 'package:flutter/services.dart' show rootBundle;
+
+// Future<Uint8List> generateTicket(Pedido pedido) async {
+//   final pdf = pw.Document();
+
+//   final image = pw.MemoryImage(
+//     (await rootBundle.load('assets/JoshiLogo-BN.png')).buffer.asUint8List(),
+//   );
+
+//   pdf.addPage(
+//     pw.Page(
+//       pageFormat: PdfPageFormat.roll57,
+//       build: (pw.Context context) {
+//         return pw.Column(
+//           crossAxisAlignment: pw.CrossAxisAlignment.center,
+//           children: [
+//             pw.Center(child: pw.Image(image, width: 50, height: 50)),
+//             pw.SizedBox(height: 10),
+//             pw.Text('Joshi Papas Tu Sabor tu Estilo',
+//                 style:
+//                     pw.TextStyle(fontSize: 12, fontWeight: pw.FontWeight.bold)),
+//             pw.SizedBox(height: 10),
+//             pw.Text('RFC: XXXX0000', style: pw.TextStyle(fontSize: 9)),
+//             pw.Text('Dirección: Calle Falsa 123',
+//                 style: pw.TextStyle(fontSize: 9)),
+//             pw.Text('Ciudad: Ciudad Ejemplo', style: pw.TextStyle(fontSize: 9)),
+//             pw.Text('Régimen: General de Ley',
+//                 style: pw.TextStyle(fontSize: 9)),
+//             pw.SizedBox(height: 10),
+//             pw.Text('Folio: ${pedido.folio}',
+//                 style:
+//                     pw.TextStyle(fontWeight: pw.FontWeight.bold, fontSize: 10)),
+//             pw.SizedBox(height: 10),
+//             ...pedido.productos.map(
+//               (producto) => pw.Row(
+//                 mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
+//                 children: [
+//                   pw.Expanded(
+//                     flex: 2,
+//                     child: pw.Text(
+//                         producto.producto?.nombre ?? "Producto no especificado",
+//                         style: pw.TextStyle(fontSize: 7)),
+//                   ),
+//                   pw.Expanded(
+//                     flex: 1,
+//                     child: pw.Text('x${producto.cantidad}',
+//                         style: pw.TextStyle(fontSize: 9)),
+//                   ),
+//                   pw.Expanded(
+//                     flex: 1,
+//                     child: pw.Text('\$${producto.producto?.precio}',
+//                         style: pw.TextStyle(fontSize: 9)),
+//                   ),
+//                 ],
+//               ),
+//             ),
+//             pw.Divider(),
+//             pw.Row(
+//               mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
+//               children: [
+//                 pw.Text('Total:',
+//                     style: pw.TextStyle(
+//                         fontWeight: pw.FontWeight.bold, fontSize: 9)),
+//                 pw.Padding(
+//                   padding: pw.EdgeInsets.only(right: 20),
+//                   child: pw.Text(
+//                       '\$${pedido.productos.fold<double>(0.0, (sum, p) => sum + (double.parse(p.producto?.precio ?? '0') * (p.cantidad ?? 1)))}',
+//                       style: pw.TextStyle(
+//                           fontWeight: pw.FontWeight.bold, fontSize: 9)),
+//                 ),
+//               ],
+//             ),
+//             pw.SizedBox(height: 5),
+//             pw.Text('¡GRACIAS POR SU COMPRA!',
+//                 style:
+//                     pw.TextStyle(fontSize: 8, fontWeight: pw.FontWeight.bold)),
+//             pw.SizedBox(height: 20),
+//             pw.Divider(),
+//             pw.SizedBox(height: 10),
+//             // Existing Ticket Content
+//             pw.Text('Folio: ${pedido.folio}',
+//                 style:
+//                     pw.TextStyle(fontWeight: pw.FontWeight.bold, fontSize: 9)),
+//             pw.SizedBox(height: 10),
+//             pw.Text('Cliente: ${pedido.nombreCliente}',
+//                 style:
+//                     pw.TextStyle(fontWeight: pw.FontWeight.bold, fontSize: 9)),
+//             pw.SizedBox(height: 10),
+//             ...pedido.productos.map(
+//               (producto) => pw.Row(
+//                 mainAxisAlignment: pw.MainAxisAlignment.start,
+//                 children: [
+//                   pw.Expanded(
+//                     flex: 3,
+//                     child: pw.Text(
+//                         producto.producto?.nombre ?? "Producto no especificado",
+//                         style: pw.TextStyle(fontSize: 9)),
+//                   ),
+//                   pw.Expanded(
+//                     flex: 1,
+//                     child: pw.Text('x${producto.cantidad}',
+//                         style: pw.TextStyle(fontSize: 9)),
+//                   ),
+//                 ],
+//               ),
+//             ),
+//             pw.SizedBox(height: 80),
+//           ],
+//         );
+//       },
+//     ),
+//   );
+
+//   return Uint8List.fromList(await pdf.save());
+// }
+
+Future<Uint8List> primerTicket(Pedido pedido) async {
+  final pdf = pw.Document();
+
+  final image = pw.MemoryImage(
+    (await rootBundle.load('assets/JoshiLogo-BN.png')).buffer.asUint8List(),
+  );
+
+  pdf.addPage(pw.Page(
+      pageFormat: PdfPageFormat.roll57,
+      build: (pw.Context context) {
+        return pw.Column(
+            crossAxisAlignment: pw.CrossAxisAlignment.center,
+            children: [
+              pw.Padding(
+                  padding: const pw.EdgeInsets.only(right: 20),
+                  child:
+                      pw.Center(child: pw.Image(image, width: 50, height: 50))),
+              pw.SizedBox(height: 10),
+              pw.Padding(
+                  padding: const pw.EdgeInsets.only(right: 15),
+                  child: pw.Column(children: [
+                    pw.Text('Joshi Papas Tu Sabor tu Estilo',
+                        style: pw.TextStyle(
+                            fontSize: 12, fontWeight: pw.FontWeight.bold)),
+                    pw.SizedBox(height: 10),
+                    pw.Text('Fecha: ${pedido.peticion}',
+                        style: const pw.TextStyle(fontSize: 9)),
+                    pw.Text('RFC: XXXX0000',
+                        style: const pw.TextStyle(fontSize: 9)),
+                    pw.Text('Dirección: Calle Falsa 123',
+                        style: const pw.TextStyle(fontSize: 9)),
+                    pw.Text('Ciudad: Ciudad Ejemplo',
+                        style: const pw.TextStyle(fontSize: 9)),
+                    pw.Text('Régimen: General de Ley',
+                        style: const pw.TextStyle(fontSize: 9)),
+                  ])),
+              pw.SizedBox(height: 10),
+              pw.Text('Folio: ${pedido.folio}',
+                  style: pw.TextStyle(
+                      fontWeight: pw.FontWeight.bold, fontSize: 10)),
+              pw.SizedBox(height: 10),
+              ...pedido.productos.map(
+                (producto) => pw.Row(
+                  mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
+                  children: [
+                    pw.Expanded(
+                      flex: 2,
+                      child: pw.Text(
+                          producto.producto?.nombre ??
+                              "Producto no especificado",
+                          style: const pw.TextStyle(fontSize: 7)),
+                    ),
+                    pw.Expanded(
+                      flex: 1,
+                      child: pw.Text('x${producto.cantidad}',
+                          style: const pw.TextStyle(fontSize: 9)),
+                    ),
+                    pw.Expanded(
+                      flex: 1,
+                      child: pw.Text('\$${producto.producto?.precio}',
+                          style: const pw.TextStyle(fontSize: 9)),
+                    ),
+                  ],
+                ),
+              ),
+              pw.Divider(),
+              pw.Row(
+                mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
+                children: [
+                  pw.Text('Total:',
+                      style: pw.TextStyle(
+                          fontWeight: pw.FontWeight.bold, fontSize: 9)),
+                  pw.Padding(
+                    padding: const pw.EdgeInsets.only(right: 20),
+                    child: pw.Text(
+                        '\$${pedido.productos.fold<double>(0.0, (sum, p) => sum + (double.parse(p.producto?.precio ?? '0') * (p.cantidad ?? 1)))}',
+                        style: pw.TextStyle(
+                            fontWeight: pw.FontWeight.bold, fontSize: 9)),
+                  ),
+                ],
+              ),
+              pw.SizedBox(height: 5),
+              pw.Padding(
+                  padding: const pw.EdgeInsets.only(right: 15),
+                  child: pw.Text('¡GRACIAS POR SU COMPRA!',
+                      style: pw.TextStyle(
+                          fontSize: 8, fontWeight: pw.FontWeight.bold))),
+              pw.SizedBox(height: 20),
+              pw.Divider(),
+            ]);
+      }));
+  return Uint8List.fromList(await pdf.save());
+}
+
+Future<Uint8List> segundoTicket(Pedido pedido) async {
+  final pdf = pw.Document();
+
+  pdf.addPage(pw.Page(
+      pageFormat: PdfPageFormat.roll57,
+      build: (pw.Context context) {
+        List<pw.Widget> content = [
+          pw.SizedBox(height: 10),
+          pw.Padding(
+              padding: const pw.EdgeInsets.only(right: 15),
+              child: pw.Text('Fecha: ${pedido.peticion}',
+                  style: pw.TextStyle(
+                      fontSize: 9, fontWeight: pw.FontWeight.bold))),
+          pw.SizedBox(height: 5),
+          pw.Text('Folio: ${pedido.folio}',
+              style: pw.TextStyle(fontWeight: pw.FontWeight.bold, fontSize: 9)),
+          pw.SizedBox(height: 10),
+          pw.Text('Cliente: ${pedido.nombreCliente}',
+              style: pw.TextStyle(fontWeight: pw.FontWeight.bold, fontSize: 9)),
+          pw.SizedBox(height: 10),
+        ];
+
+        content.addAll(pedido.productos.map((producto) => pw.Row(
+              mainAxisAlignment: pw.MainAxisAlignment.start,
+              children: [
+                pw.Expanded(
+                  flex: 3,
+                  child: pw.Text(
+                      producto.producto?.nombre ?? "Producto no especificado",
+                      style: const pw.TextStyle(fontSize: 9)),
+                ),
+                pw.Expanded(
+                  flex: 1,
+                  child: pw.Text('x${producto.cantidad}',
+                      style: const pw.TextStyle(fontSize: 9)),
+                ),
+              ],
+            )));
+
+        if (pedido.comentarios != null && pedido.comentarios!.isNotEmpty) {
+          content.add(pw.SizedBox(height: 10));
+          content.add(pw.Text('Comentarios:',
+              style:
+                  pw.TextStyle(fontWeight: pw.FontWeight.bold, fontSize: 9)));
+          content.add(pw.Padding(
+            padding: const pw.EdgeInsets.only(right: 15),
+            child: pw.Text(pedido.comentarios!,
+                style: const pw.TextStyle(fontSize: 9)),
+          ));
+        }
+
+        content.add(
+            pw.SizedBox(height: 20)); // Some spacing before finalizing the page
+
+        return pw.Column(
+            crossAxisAlignment: pw.CrossAxisAlignment.center,
+            children: content);
+      }));
+
+  return Uint8List.fromList(await pdf.save());
+}
+
+Future<void> printPdf(Uint8List pdfBytes) async {
+  await Printing.layoutPdf(
+    onLayout: (PdfPageFormat format) => pdfBytes,
+  );
+}
+
+void printTickets(Pedido pedido) async {
+  Uint8List firstTicket = await primerTicket(pedido);
+  await printPdf(firstTicket);
+  Uint8List secondTicket = await segundoTicket(pedido);
+  await printPdf(secondTicket);
+}

+ 189 - 189
lib/views/producto/producto_form.dart

@@ -1,198 +1,198 @@
-// ignore_for_file: use_build_context_synchronously
+// // ignore_for_file: use_build_context_synchronously
 
-import 'package:flutter/material.dart';
-import 'package:yoshi_papas_app/widgets/widgets.dart';
-import 'package:provider/provider.dart';
+// import 'package:flutter/material.dart';
+// import 'package:yoshi_papas_app/widgets/widgets.dart';
+// import 'package:provider/provider.dart';
 
-import '../../models/models.dart';
-import '../../viewmodels/viewmodels.dart';
+// import '../../models/models.dart';
+// import '../../viewmodels/viewmodels.dart';
 
-class ProductoForm extends StatefulWidget {
-  const ProductoForm({Key? key}) : super(key: key);
+// class ProductoForm extends StatefulWidget {
+//   const ProductoForm({Key? key}) : super(key: key);
 
-  @override
-  State<ProductoForm> createState() => Formulario();
-}
+//   @override
+//   State<ProductoForm> createState() => Formulario();
+// }
 
-class Formulario extends State<ProductoForm> {
-  final _nombre = TextEditingController();
-  final _descripcion = TextEditingController();
-  final _precio = TextEditingController();
-  final _existencia = TextEditingController();
-  final _descuento = TextEditingController();
-  final _busquedaCategoria = TextEditingController();
-  final _venceDescuento = TextEditingController();
-  CategoriaProducto? categoriaProducto;
+// class Formulario extends State<ProductoForm> {
+//   final _nombre = TextEditingController();
+//   final _descripcion = TextEditingController();
+//   final _precio = TextEditingController();
+//   final _existencia = TextEditingController();
+//   final _descuento = TextEditingController();
+//   final _busquedaCategoria = TextEditingController();
+//   final _venceDescuento = TextEditingController();
+//   CategoriaProducto? categoriaProducto;
 
-  @override
-  void initState() {
-    super.initState();
-    Future(() async {
-      Provider.of<ProductoViewModel>(context, listen: false).setIsLoading(true);
-      final mvm = Provider.of<ProductoViewModel>(context, listen: false);
-      await Provider.of<CategoriaProductoViewModel>(context, listen: false)
-          .fetchCategoriaProductos();
-      List<CategoriaProducto> catProductos =
-          Provider.of<CategoriaProductoViewModel>(context, listen: false)
-              .categoriaProductos;
-      Producto? modelo = mvm.selectedProducto;
-      if (modelo != null && modelo.id > 0) {
-        setState(() {
-          _nombre.text = modelo.nombre.toString();
-          _descripcion.text = modelo.descripcion.toString();
-          _precio.text = modelo.precio.toString();
-          _existencia.text = modelo.existencia.toString();
-          _descuento.text = modelo.descuento.toString();
-          if (modelo.idCategoria != null &&
-              modelo.idCategoria! != "" &&
-              modelo.categoria != null) {
-            categoriaProducto = modelo.categoria;
-          }
-          if (categoriaProducto == null && catProductos.isNotEmpty) {
-            categoriaProducto = catProductos.first;
-          }
-        });
-      }
-      Provider.of<ProductoViewModel>(context, listen: false)
-          .setIsLoading(false);
-    });
-  }
+//   @override
+//   void initState() {
+//     super.initState();
+//     Future(() async {
+//       Provider.of<ProductoViewModel>(context, listen: false).setIsLoading(true);
+//       final mvm = Provider.of<ProductoViewModel>(context, listen: false);
+//       await Provider.of<CategoriaProductoViewModel>(context, listen: false)
+//           .fetchCategoriaProductos();
+//       List<CategoriaProducto> catProductos =
+//           Provider.of<CategoriaProductoViewModel>(context, listen: false)
+//               .categoriaProductos;
+//       Producto? modelo = mvm.selectedProducto;
+//       if (modelo != null && modelo.id > 0) {
+//         setState(() {
+//           _nombre.text = modelo.nombre.toString();
+//           _descripcion.text = modelo.descripcion.toString();
+//           _precio.text = modelo.precio.toString();
+//           _existencia.text = modelo.existencia.toString();
+//           _descuento.text = modelo.descuento.toString();
+//           if (modelo.idCategoria != null &&
+//               modelo.idCategoria! != "" &&
+//               modelo.categoria != null) {
+//             categoriaProducto = modelo.categoria;
+//           }
+//           if (categoriaProducto == null && catProductos.isNotEmpty) {
+//             categoriaProducto = catProductos.first;
+//           }
+//         });
+//       }
+//       Provider.of<ProductoViewModel>(context, listen: false)
+//           .setIsLoading(false);
+//     });
+//   }
 
-  @override
-  void dispose() {
-    super.dispose();
-    _descripcion.dispose();
-    _nombre.dispose();
-  }
+//   @override
+//   void dispose() {
+//     super.dispose();
+//     _descripcion.dispose();
+//     _nombre.dispose();
+//   }
 
-  @override
-  Widget build(BuildContext context) {
-    final mvm = Provider.of<ProductoViewModel>(context);
-    final evm = Provider.of<CategoriaProductoViewModel>(context);
-    if (mvm.isLoading) return const Cargando();
-    final producto = mvm.selectedProducto;
-    List<CategoriaProducto> categoriaProductos = [];
-    if (evm.categoriaProductos.isNotEmpty) {
-      categoriaProductos = evm.categoriaProductos;
-    }
+//   @override
+//   Widget build(BuildContext context) {
+//     final mvm = Provider.of<ProductoViewModel>(context);
+//     final evm = Provider.of<CategoriaProductoViewModel>(context);
+//     if (mvm.isLoading) return const Cargando();
+//     final producto = mvm.selectedProducto;
+//     List<CategoriaProducto> categoriaProductos = [];
+//     if (evm.categoriaProductos.isNotEmpty) {
+//       categoriaProductos = evm.categoriaProductos;
+//     }
 
-    return Scaffold(
-      appBar: encabezado(titulo: "Producto"),
-      body: SingleChildScrollView(
-        padding: const EdgeInsets.all(8),
-        child: Column(
-          children: [
-            tarjeta(
-              Padding(
-                padding: const EdgeInsets.all(8),
-                child: Column(
-                  children: [
-                    categoriaProductos.isNotEmpty
-                        ? AppDropdownSearch(
-                            etiqueta: 'Categoría',
-                            controller: _busquedaCategoria,
-                            selectedItem: categoriaProducto,
-                            onPressedClear: () {
-                              categoriaProducto = null;
-                            },
-                            itemAsString: (item) => '${item.nombre}',
-                            asyncItems: (text) async {
-                              final xregistros = await evm.getCategoriaProducto(
-                                  q: text, segmentar: true);
-                              return xregistros;
-                            },
-                            onChanged: (value) {
-                              categoriaProducto = value;
-                            },
-                            validator: (value) {
-                              if (value == null) {
-                                return 'Seleccione';
-                              }
-                              return null;
-                            },
-                          )
-                        : Container(),
-                    Row(
-                      children: [
-                        Expanded(
-                          child: AppTextField(
-                            maxLength: 100,
-                            etiqueta: 'Nombre',
-                            controller: _nombre,
-                            hintText: 'Nombre producto',
-                          ),
-                        ),
-                      ],
-                    ),
-                    Row(
-                      children: [
-                        Expanded(
-                          child: AppTextField(
-                            maxLength: 100,
-                            etiqueta: 'Precio',
-                            controller: _precio,
-                            hintText: 'Precio del producto',
-                          ),
-                        ),
-                      ],
-                    ),
-                    Row(
-                      children: [
-                        Expanded(
-                          child: AppTextField(
-                            maxLength: 100,
-                            etiqueta: 'Existencia',
-                            controller: _existencia,
-                            hintText: 'Existencia del producto',
-                          ),
-                        ),
-                      ],
-                    ),
-                    Row(
-                      children: [
-                        Expanded(
-                          child: AppTextField(
-                            maxLength: 1000,
-                            maxLines: 3,
-                            etiqueta: 'Descripción',
-                            controller: _descripcion,
-                            hintText: 'descripción del producto',
-                          ),
-                        ),
-                      ],
-                    ),
-                  ],
-                ),
-              ),
-            ),
-            const SizedBox(height: 15),
-            boton("Guardar", () async {
-              if (categoriaProducto == null ||
-                  categoriaProducto!.id == null ||
-                  categoriaProducto!.id == "") {
-                await alerta(context, etiqueta: "Seleccionar categoría");
-                return;
-              }
-              Provider.of<ProductoViewModel>(context, listen: false)
-                  .setIsLoading(true);
-              await mvm.guardarModelo(
-                  modelo: producto!,
-                  nombre: _nombre.text,
-                  descripcion: _descripcion.text,
-                  precio: _precio.text,
-                  descuento: _descuento.text,
-                  existencia: int.tryParse(_existencia.text) ?? 0,
-                  venceDescuento: _venceDescuento.text,
-                  idCategoria: categoriaProducto?.id ?? 0);
-              Provider.of<ProductoViewModel>(context, listen: false)
-                  .setIsLoading(false);
-              if (context.mounted) {
-                Navigator.pop(context);
-              }
-            }),
-          ],
-        ),
-      ),
-    );
-  }
-}
+//     return Scaffold(
+//       appBar: encabezado(titulo: "Producto"),
+//       body: SingleChildScrollView(
+//         padding: const EdgeInsets.all(8),
+//         child: Column(
+//           children: [
+//             tarjeta(
+//               Padding(
+//                 padding: const EdgeInsets.all(8),
+//                 child: Column(
+//                   children: [
+//                     categoriaProductos.isNotEmpty
+//                         ? AppDropdownSearch(
+//                             etiqueta: 'Categoría',
+//                             controller: _busquedaCategoria,
+//                             selectedItem: categoriaProducto,
+//                             onPressedClear: () {
+//                               categoriaProducto = null;
+//                             },
+//                             itemAsString: (item) => '${item.nombre}',
+//                             asyncItems: (text) async {
+//                               final xregistros = await evm.getCategoriaProducto(
+//                                   q: text, segmentar: true);
+//                               return xregistros;
+//                             },
+//                             onChanged: (value) {
+//                               categoriaProducto = value;
+//                             },
+//                             validator: (value) {
+//                               if (value == null) {
+//                                 return 'Seleccione';
+//                               }
+//                               return null;
+//                             },
+//                           )
+//                         : Container(),
+//                     Row(
+//                       children: [
+//                         Expanded(
+//                           child: AppTextField(
+//                             maxLength: 100,
+//                             etiqueta: 'Nombre',
+//                             controller: _nombre,
+//                             hintText: 'Nombre producto',
+//                           ),
+//                         ),
+//                       ],
+//                     ),
+//                     Row(
+//                       children: [
+//                         Expanded(
+//                           child: AppTextField(
+//                             maxLength: 100,
+//                             etiqueta: 'Precio',
+//                             controller: _precio,
+//                             hintText: 'Precio del producto',
+//                           ),
+//                         ),
+//                       ],
+//                     ),
+//                     Row(
+//                       children: [
+//                         Expanded(
+//                           child: AppTextField(
+//                             maxLength: 100,
+//                             etiqueta: 'Existencia',
+//                             controller: _existencia,
+//                             hintText: 'Existencia del producto',
+//                           ),
+//                         ),
+//                       ],
+//                     ),
+//                     Row(
+//                       children: [
+//                         Expanded(
+//                           child: AppTextField(
+//                             maxLength: 1000,
+//                             maxLines: 3,
+//                             etiqueta: 'Descripción',
+//                             controller: _descripcion,
+//                             hintText: 'descripción del producto',
+//                           ),
+//                         ),
+//                       ],
+//                     ),
+//                   ],
+//                 ),
+//               ),
+//             ),
+//             const SizedBox(height: 15),
+//             boton("Guardar", () async {
+//               if (categoriaProducto == null ||
+//                   categoriaProducto!.id == null ||
+//                   categoriaProducto!.id == "") {
+//                 await alerta(context, etiqueta: "Seleccionar categoría");
+//                 return;
+//               }
+//               Provider.of<ProductoViewModel>(context, listen: false)
+//                   .setIsLoading(true);
+//               await mvm.guardarModelo(
+//                   modelo: producto!,
+//                   nombre: _nombre.text,
+//                   descripcion: _descripcion.text,
+//                   precio: _precio.text,
+//                   descuento: _descuento.text,
+//                   existencia: int.tryParse(_existencia.text) ?? 0,
+//                   venceDescuento: _venceDescuento.text,
+//                   idCategoria: categoriaProducto?.id ?? 0);
+//               Provider.of<ProductoViewModel>(context, listen: false)
+//                   .setIsLoading(false);
+//               if (context.mounted) {
+//                 Navigator.pop(context);
+//               }
+//             }),
+//           ],
+//         ),
+//       ),
+//     );
+//   }
+// }

+ 229 - 229
lib/views/producto/producto_screen.dart

@@ -1,239 +1,239 @@
-// ignore_for_file: use_build_context_synchronously
+// // ignore_for_file: use_build_context_synchronously
 
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import '../../models/models.dart';
-import '../../themes/themes.dart';
-import '../../viewmodels/viewmodels.dart';
-import '../../widgets/app_textfield.dart';
-import '../../widgets/pagination_buttons.dart';
-import '../../widgets/widgets_components.dart';
-import 'producto_form.dart';
+// import 'package:flutter/material.dart';
+// import 'package:provider/provider.dart';
+// import '../../models/models.dart';
+// import '../../themes/themes.dart';
+// import '../../viewmodels/viewmodels.dart';
+// import '../../widgets/app_textfield.dart';
+// import '../../widgets/pagination_buttons.dart';
+// import '../../widgets/widgets_components.dart';
+// import 'producto_form.dart';
 
-class ProductoScreen extends StatefulWidget {
-  const ProductoScreen({Key? key}) : super(key: key);
+// class ProductoScreen extends StatefulWidget {
+//   const ProductoScreen({Key? key}) : super(key: key);
 
-  @override
-  State<ProductoScreen> createState() => Formulario();
-}
+//   @override
+//   State<ProductoScreen> createState() => Formulario();
+// }
 
-class Formulario extends State<ProductoScreen> {
-  final _busqueda = TextEditingController(text: '');
+// class Formulario extends State<ProductoScreen> {
+//   final _busqueda = TextEditingController(text: '');
 
-  @override
-  void initState() {
-    super.initState();
-    Future(() async {
-      await Provider.of<ProductoViewModel>(context, listen: false)
-          .fetchRegistros();
-      await Provider.of<CategoriaProductoViewModel>(context, listen: false)
-          .fetchCategoriaProductos(segmentar: true);
-    });
-  }
+//   @override
+//   void initState() {
+//     super.initState();
+//     Future(() async {
+//       await Provider.of<ProductoViewModel>(context, listen: false)
+//           .fetchRegistros();
+//       await Provider.of<CategoriaProductoViewModel>(context, listen: false)
+//           .fetchCategoriaProductos(segmentar: true);
+//     });
+//   }
 
-  go(Producto item) async {
-    Provider.of<ProductoViewModel>(context, listen: false).selectModelo(item);
-    Navigator.push(
-      context,
-      MaterialPageRoute(
-        builder: (context) => const ProductoForm(),
-      ),
-    ).then((value) async {
-      await Provider.of<ProductoViewModel>(context, listen: false)
-          .fetchRegistros();
-    });
-  }
+//   go(Producto item) async {
+//     Provider.of<ProductoViewModel>(context, listen: false).selectModelo(item);
+//     Navigator.push(
+//       context,
+//       MaterialPageRoute(
+//         builder: (context) => const ProductoForm(),
+//       ),
+//     ).then((value) async {
+//       await Provider.of<ProductoViewModel>(context, listen: false)
+//           .fetchRegistros();
+//     });
+//   }
 
-  @override
-  Widget build(BuildContext context) {
-    final evm = Provider.of<CategoriaProductoViewModel>(context);
-    List<CategoriaProducto> categoriaProductos = [];
-    if (evm.categoriaProductos.isNotEmpty) {
-      categoriaProductos = evm.categoriaProductos;
-    }
+//   @override
+//   Widget build(BuildContext context) {
+//     final evm = Provider.of<CategoriaProductoViewModel>(context);
+//     List<CategoriaProducto> categoriaProductos = [];
+//     if (evm.categoriaProductos.isNotEmpty) {
+//       categoriaProductos = evm.categoriaProductos;
+//     }
 
-    final mvm = Provider.of<ProductoViewModel>(context);
-    TextStyle estilo = const TextStyle(fontWeight: FontWeight.bold);
-    int vuelta = 0;
-    List<DataRow> registros = [];
-    if (mvm.registros.isNotEmpty) {
-      for (Producto item in mvm.registros) {
-        String? categoriaProducto = "";
-        if (item.idCategoria != null) {
-          categoriaProducto = item.categoria!.nombre;
-        }
+//     final mvm = Provider.of<ProductoViewModel>(context);
+//     TextStyle estilo = const TextStyle(fontWeight: FontWeight.bold);
+//     int vuelta = 0;
+//     List<DataRow> registros = [];
+//     if (mvm.registros.isNotEmpty) {
+//       for (Producto item in mvm.registros) {
+//         String? categoriaProducto = "";
+//         if (item.idCategoria != null) {
+//           categoriaProducto = item.categoria!.nombre;
+//         }
 
-        var _tipo = vuelta % 2;
-        vuelta++;
-        registros.add(DataRow(selected: _tipo > 0, cells: [
-          DataCell(
-            Text(item.nombre.toString()),
-            onTap: () => go(item),
-          ),
-          DataCell(
-            Text(item.descripcion.toString()),
-            onTap: () => go(item),
-          ),
-          DataCell(
-            Text(categoriaProducto.toString()),
-            onTap: () => go(item),
-          ),
-          DataCell(
-            Text(item.precio.toString()),
-            onTap: () => go(item),
-          ),
-          DataCell(
-            Text(item.venta.toString()),
-            onTap: () => go(item),
-          ),
-          DataCell(
-            Text(item.existencia.toString()),
-            onTap: () => go(item),
-          ),
-          DataCell(
-              Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
-            PopupMenuButton(
-              surfaceTintColor: AppTheme.primary,
-              itemBuilder: (context) => [
-                PopupMenuItem(
-                  child: const Text('Editar'),
-                  onTap: () => go(item),
-                ),
-                PopupMenuItem(
-                  child: const Text(
-                    'Eliminar',
-                  ),
-                  onTap: () async {
-                    return showDialog(
-                      context: context,
-                      builder: (context) {
-                        return AlertDialog(
-                          title: const Text("Eliminar registro"),
-                          content: const Text('¿Desea eliminar el registro?'),
-                          actions: [
-                            Row(children: [
-                              Expanded(
-                                  child: TextButton(
-                                onPressed: () {
-                                  Navigator.pop(context);
-                                },
-                                child: const Text('Cancelar'),
-                              )),
-                              Expanded(
-                                  child: TextButton(
-                                onPressed: () async {
-                                  Navigator.pop(context);
-                                },
-                                child: const Text('Continuar'),
-                              ))
-                            ])
-                          ],
-                        );
-                      },
-                    );
-                  },
-                )
-              ],
-              icon: const Icon(Icons.more_vert),
-              shape: RoundedRectangleBorder(
-                  borderRadius: BorderRadius.circular(15)),
-            )
-          ]))
-        ]));
-      }
-    }
+//         var _tipo = vuelta % 2;
+//         vuelta++;
+//         registros.add(DataRow(selected: _tipo > 0, cells: [
+//           DataCell(
+//             Text(item.nombre.toString()),
+//             onTap: () => go(item),
+//           ),
+//           DataCell(
+//             Text(item.descripcion.toString()),
+//             onTap: () => go(item),
+//           ),
+//           DataCell(
+//             Text(categoriaProducto.toString()),
+//             onTap: () => go(item),
+//           ),
+//           DataCell(
+//             Text(item.precio.toString()),
+//             onTap: () => go(item),
+//           ),
+//           DataCell(
+//             Text(item.venta.toString()),
+//             onTap: () => go(item),
+//           ),
+//           DataCell(
+//             Text(item.existencia.toString()),
+//             onTap: () => go(item),
+//           ),
+//           DataCell(
+//               Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
+//             PopupMenuButton(
+//               surfaceTintColor: AppTheme.primary,
+//               itemBuilder: (context) => [
+//                 PopupMenuItem(
+//                   child: const Text('Editar'),
+//                   onTap: () => go(item),
+//                 ),
+//                 PopupMenuItem(
+//                   child: const Text(
+//                     'Eliminar',
+//                   ),
+//                   onTap: () async {
+//                     return showDialog(
+//                       context: context,
+//                       builder: (context) {
+//                         return AlertDialog(
+//                           title: const Text("Eliminar registro"),
+//                           content: const Text('¿Desea eliminar el registro?'),
+//                           actions: [
+//                             Row(children: [
+//                               Expanded(
+//                                   child: TextButton(
+//                                 onPressed: () {
+//                                   Navigator.pop(context);
+//                                 },
+//                                 child: const Text('Cancelar'),
+//                               )),
+//                               Expanded(
+//                                   child: TextButton(
+//                                 onPressed: () async {
+//                                   Navigator.pop(context);
+//                                 },
+//                                 child: const Text('Continuar'),
+//                               ))
+//                             ])
+//                           ],
+//                         );
+//                       },
+//                     );
+//                   },
+//                 )
+//               ],
+//               icon: const Icon(Icons.more_vert),
+//               shape: RoundedRectangleBorder(
+//                   borderRadius: BorderRadius.circular(15)),
+//             )
+//           ]))
+//         ]));
+//       }
+//     }
 
-    return Scaffold(
-      appBar: AppBar(
-        title: const Text('Productos'),
-      ),
-      floatingActionButton: FloatingActionButton(
-        onPressed: () {
-          mvm.selectModelo(Producto());
-          Navigator.push(
-            context,
-            MaterialPageRoute(
-              builder: (context) => const ProductoForm(),
-            ),
-          ).then((value) async {
-            await Provider.of<ProductoViewModel>(context, listen: false)
-                .fetchRegistros();
-          });
-        },
-        child: const Icon(Icons.add),
-      ),
-      body: Column(
-        children: [
-          Expanded(
-            child: ListView(
-              padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
-              children: [
-                const SizedBox(height: 8),
-                tarjeta(Padding(
-                    padding: const EdgeInsets.all(10),
-                    child: Row(
-                      children: [
-                        Expanded(
-                          flex: 8,
-                          child: AppTextField(
-                            prefixIcon: const Icon(Icons.search),
-                            maxLength: 100,
-                            etiqueta: 'Búsqueda por nombre...',
-                            controller: _busqueda,
-                            hintText: 'Búsqueda por nombre...',
-                          ),
-                        ),
-                        const SizedBox(width: 5),
-                        Expanded(
-                          flex: 2,
-                          child: botonElevated(
-                            accion: () async {
-                              _busqueda.text = _busqueda.text.trim();
-                              await Provider.of<ProductoViewModel>(context,
-                                      listen: false)
-                                  .setIsLoading(true);
-                              await Provider.of<ProductoViewModel>(context,
-                                      listen: false)
-                                  .setBusqueda(_busqueda.text);
-                              await Provider.of<ProductoViewModel>(context,
-                                      listen: false)
-                                  .fetchRegistros();
-                              await Provider.of<ProductoViewModel>(context,
-                                      listen: false)
-                                  .setBusqueda("");
-                              await Provider.of<ProductoViewModel>(context,
-                                      listen: false)
-                                  .setIsLoading(false);
-                            },
-                          ),
-                        ),
-                      ],
-                    ))),
-                const SizedBox(height: 8),
-                tarjeta(DataTable(
-                    sortAscending: true,
-                    sortColumnIndex: 1,
-                    columns: [
-                      DataColumn(label: Text("NOMBRE", style: estilo)),
-                      DataColumn(label: Text("DESCRIPCIÓN", style: estilo)),
-                      DataColumn(
-                          label: Text("CATEGORÍA PRODUCTOS", style: estilo)),
-                      DataColumn(label: Text("PRECIO", style: estilo)),
-                      DataColumn(label: Text("VENTAS", style: estilo)),
-                      DataColumn(label: Text("EN EXISTENCIA", style: estilo)),
-                      DataColumn(label: Text("", style: estilo)),
-                    ],
-                    rows: registros)),
-                PaginationButtons(
-                  currentPage: mvm.pagina,
-                  totalPages: mvm.totalPaginas,
-                  onPageChanged: (i) => mvm.cambiarPagina(i),
-                )
-              ],
-            ),
-          ),
-        ],
-      ),
-    );
-  }
-}
+//     return Scaffold(
+//       appBar: AppBar(
+//         title: const Text('Productos'),
+//       ),
+//       floatingActionButton: FloatingActionButton(
+//         onPressed: () {
+//           mvm.selectModelo(Producto());
+//           Navigator.push(
+//             context,
+//             MaterialPageRoute(
+//               builder: (context) => const ProductoForm(),
+//             ),
+//           ).then((value) async {
+//             await Provider.of<ProductoViewModel>(context, listen: false)
+//                 .fetchRegistros();
+//           });
+//         },
+//         child: const Icon(Icons.add),
+//       ),
+//       body: Column(
+//         children: [
+//           Expanded(
+//             child: ListView(
+//               padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
+//               children: [
+//                 const SizedBox(height: 8),
+//                 tarjeta(Padding(
+//                     padding: const EdgeInsets.all(10),
+//                     child: Row(
+//                       children: [
+//                         Expanded(
+//                           flex: 8,
+//                           child: AppTextField(
+//                             prefixIcon: const Icon(Icons.search),
+//                             maxLength: 100,
+//                             etiqueta: 'Búsqueda por nombre...',
+//                             controller: _busqueda,
+//                             hintText: 'Búsqueda por nombre...',
+//                           ),
+//                         ),
+//                         const SizedBox(width: 5),
+//                         Expanded(
+//                           flex: 2,
+//                           child: botonElevated(
+//                             accion: () async {
+//                               _busqueda.text = _busqueda.text.trim();
+//                               await Provider.of<ProductoViewModel>(context,
+//                                       listen: false)
+//                                   .setIsLoading(true);
+//                               await Provider.of<ProductoViewModel>(context,
+//                                       listen: false)
+//                                   .setBusqueda(_busqueda.text);
+//                               await Provider.of<ProductoViewModel>(context,
+//                                       listen: false)
+//                                   .fetchRegistros();
+//                               await Provider.of<ProductoViewModel>(context,
+//                                       listen: false)
+//                                   .setBusqueda("");
+//                               await Provider.of<ProductoViewModel>(context,
+//                                       listen: false)
+//                                   .setIsLoading(false);
+//                             },
+//                           ),
+//                         ),
+//                       ],
+//                     ))),
+//                 const SizedBox(height: 8),
+//                 tarjeta(DataTable(
+//                     sortAscending: true,
+//                     sortColumnIndex: 1,
+//                     columns: [
+//                       DataColumn(label: Text("NOMBRE", style: estilo)),
+//                       DataColumn(label: Text("DESCRIPCIÓN", style: estilo)),
+//                       DataColumn(
+//                           label: Text("CATEGORÍA PRODUCTOS", style: estilo)),
+//                       DataColumn(label: Text("PRECIO", style: estilo)),
+//                       DataColumn(label: Text("VENTAS", style: estilo)),
+//                       DataColumn(label: Text("EN EXISTENCIA", style: estilo)),
+//                       DataColumn(label: Text("", style: estilo)),
+//                     ],
+//                     rows: registros)),
+//                 PaginationButtons(
+//                   currentPage: mvm.pagina,
+//                   totalPages: mvm.totalPaginas,
+//                   onPageChanged: (i) => mvm.cambiarPagina(i),
+//                 )
+//               ],
+//             ),
+//           ),
+//         ],
+//       ),
+//     );
+//   }
+// }

+ 33 - 194
lib/widgets/app_drawer.dart

@@ -66,36 +66,36 @@ class AppDrawer extends StatelessWidget {
             padding: EdgeInsets.only(
               top: MediaQuery.of(context).padding.top,
             ),
-            child: Column(
+            child: const Column(
               children: [
-                const Padding(
+                Padding(
                   padding: EdgeInsets.all(8.0),
                   child: Image(
                     image: AssetImage('assets/JoshiLogoHorizontal.png'),
                     height: 150,
                   ),
                 ),
-                const SizedBox(
+                SizedBox(
                   height: 10,
                 ),
-                Text(
-                  nombre.toString(),
-                  style: const TextStyle(
-                    fontSize: 18,
-                    fontWeight: FontWeight.bold,
-                  ),
-                ),
-                const SizedBox(
-                  height: 10,
-                ),
-                Text(
-                  correo.toString(),
-                  style: const TextStyle(
-                    fontSize: 15,
-                    fontWeight: FontWeight.bold,
-                  ),
-                ),
-                const SizedBox(
+                // Text(
+                //   nombre.toString(),
+                //   style: const TextStyle(
+                //     fontSize: 18,
+                //     fontWeight: FontWeight.bold,
+                //   ),
+                // ),
+                // const SizedBox(
+                //   height: 10,
+                // ),
+                // Text(
+                //   correo.toString(),
+                //   style: const TextStyle(
+                //     fontSize: 15,
+                //     fontWeight: FontWeight.bold,
+                //   ),
+                // ),
+                SizedBox(
                   height: 10,
                 ),
               ],
@@ -104,18 +104,18 @@ class AppDrawer extends StatelessWidget {
           //HEADER
           Expanded(
               child: ListView(children: [
-            ListTile(
-              leading: circulo(const Icon(Icons.lunch_dining)),
-              title: const Text('Inicio'),
-              onTap: () => {
-                Navigator.pop(context),
-                Navigator.of(context).push(
-                  MaterialPageRoute(
-                    builder: (context) => const HomeScreen(),
-                  ),
-                ),
-              },
-            ),
+            // ListTile(
+            //   leading: circulo(const Icon(Icons.lunch_dining)),
+            //   title: const Text('Inicio'),
+            //   onTap: () => {
+            //     Navigator.pop(context),
+            //     Navigator.of(context).push(
+            //       MaterialPageRoute(
+            //         builder: (context) => const HomeScreen(),
+            //       ),
+            //     ),
+            //   },
+            // ),
             ListTile(
               leading: circulo(const Icon(Icons.restaurant_menu)),
               title: const Text('Pedidos'),
@@ -129,167 +129,6 @@ class AppDrawer extends StatelessWidget {
               },
             ),
             ListTile(
-              leading: circulo(const Icon(Icons.table_bar)),
-              title: const Text('Mesas'),
-              onTap: () => {
-                Navigator.pop(context),
-                Navigator.of(context).push(
-                  MaterialPageRoute(
-                    builder: (context) => const HomeScreen(),
-                  ),
-                ),
-              },
-            ),
-            ListTile(
-              leading: circulo(const Icon(Icons.local_cafe)),
-              title: const Text('Productos'),
-              onTap: () => {
-                Navigator.pop(context),
-                Navigator.of(context).push(
-                  MaterialPageRoute(
-                    builder: (context) => const ProductoScreen(),
-                  ),
-                ),
-              },
-            ),
-            ListTile(
-              leading: circulo(const Icon(Icons.format_list_bulleted)),
-              title: const Text('Caregorías de Producto'),
-              onTap: () => {
-                Navigator.pop(context),
-                Navigator.of(context).push(
-                  MaterialPageRoute(
-                    builder: (context) => const CategoriaProductoScreen(),
-                  ),
-                ),
-              },
-            ),
-            ListTile(
-              leading:
-                  circulo(const Icon(Icons.switch_access_shortcut_add_sharp)),
-              title: const Text('Topings'),
-              onTap: () => {
-                Navigator.pop(context),
-                Navigator.of(context).push(
-                  MaterialPageRoute(
-                    builder: (context) => const TopingScreen(),
-                  ),
-                ),
-              },
-            ),
-            ListTile(
-              leading: circulo(const Icon(Icons.format_list_bulleted)),
-              title: const Text('Categorías de Toping'),
-              onTap: () => {
-                Navigator.pop(context),
-                Navigator.of(context).push(
-                  MaterialPageRoute(
-                    builder: (context) => const TopingCategoriaScreen(),
-                  ),
-                ),
-              },
-            ),
-            ListTile(
-              leading: circulo(const Icon(Icons.discount)),
-              title: const Text('Promociones'),
-              onTap: () => {
-                Navigator.pop(context),
-                Navigator.of(context).push(
-                  MaterialPageRoute(
-                    builder: (context) => const HomeScreen(),
-                  ),
-                ),
-              },
-            ),
-            ListTile(
-              leading: circulo(const Icon(Icons.photo)),
-              title: const Text('Contenidos Web'),
-              onTap: () => {
-                Navigator.pop(context),
-                Navigator.of(context).push(
-                  MaterialPageRoute(
-                    builder: (context) => const HomeScreen(),
-                  ),
-                ),
-              },
-            ),
-            ListTile(
-              leading: circulo(const Icon(Icons.storefront)),
-              title: const Text('Sucursales'),
-              onTap: () => {
-                Navigator.pop(context),
-                Navigator.of(context).push(
-                  MaterialPageRoute(
-                    builder: (context) => const HomeScreen(),
-                  ),
-                ),
-              },
-            ),
-            ListTile(
-              leading: circulo(const Icon(Icons.groups)),
-              title: const Text('Clientes'),
-              onTap: () => {
-                Navigator.pop(context),
-                Navigator.of(context).push(
-                  MaterialPageRoute(
-                    builder: (context) => const HomeScreen(),
-                  ),
-                ),
-              },
-            ),
-            ListTile(
-              leading: circulo(const Icon(Icons.credit_card_rounded)),
-              title: const Text('Tarjetas'),
-              onTap: () => {
-                Navigator.pop(context),
-                Navigator.of(context).push(
-                  MaterialPageRoute(
-                    builder: (context) => const HomeScreen(),
-                  ),
-                ),
-              },
-            ),
-            ListTile(
-              leading: circulo(const Icon(Icons.point_of_sale)),
-              title: const Text('Ventas'),
-              onTap: () => {
-                Navigator.pop(context),
-                Navigator.of(context).push(
-                  MaterialPageRoute(
-                    builder: (context) => const HomeScreen(),
-                  ),
-                ),
-              },
-            ),
-            ExpansionTile(
-                leading: circulo(const Icon(Icons.circle)),
-                title: const Text("ADMINISTRACIÓN"),
-                childrenPadding: const EdgeInsets.only(left: 8),
-                children: [
-                  ListTile(
-                    leading: circulo(const Icon(Icons.person_add_alt)),
-                    title: const Text('USUARIOS'),
-                    onTap: () => {
-                      Navigator.pop(context),
-                      // Navigator.of(context).push(
-                      //   MaterialPageRoute(
-                      //     builder: (context) => const UsuariosScreen(),
-                      //   ),
-                      // ),
-                    },
-                  ),
-                ]),
-            ListTile(
-              leading: const Icon(Icons.person),
-              title: const Text('PERFIL'),
-              onTap: () {
-                Navigator.push(
-                    context,
-                    MaterialPageRoute(
-                        builder: (context) => const PerfilScreen()));
-              },
-            ),
-            ListTile(
               leading: const Icon(Icons.logout),
               title: const Text('Cerrar sesión'),
               onTap: () {

+ 1 - 1
lib/widgets/widgets_components.dart

@@ -633,7 +633,7 @@ Widget usuarioHeader(String nombre, String correo) {
                       color: Colors.black, fontWeight: FontWeight.bold),
                   textAlign: TextAlign.right),
               Text(correo,
-                  style: TextStyle(color: Colors.grey.shade700),
+                  style: TextStyle(color: Colors.grey.shade900),
                   textAlign: TextAlign.right),
             ]),
         Text(" "),