pedido_screen.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. import 'package:flutter/material.dart';
  2. import 'package:provider/provider.dart';
  3. import 'package:yoshi_papas_app/themes/themes.dart';
  4. import 'package:yoshi_papas_app/views/pedido/pedido_csv.dart';
  5. import 'package:yoshi_papas_app/views/pedido/pedido_detalle_screen.dart';
  6. import '../../models/models.dart';
  7. import '../../viewmodels/viewmodels.dart';
  8. import '../../widgets/app_textfield.dart';
  9. import '../../widgets/pagination_buttons.dart';
  10. import '../../widgets/widgets_components.dart';
  11. import 'pedido_form.dart'; // Asumiendo que tienes un formulario para los pedidos similar al de los productos.
  12. class PedidoScreen extends StatefulWidget {
  13. const PedidoScreen({Key? key}) : super(key: key);
  14. @override
  15. State<PedidoScreen> createState() => _PedidoScreenState();
  16. }
  17. class _PedidoScreenState extends State<PedidoScreen> {
  18. final _busqueda = TextEditingController(text: '');
  19. ScrollController horizontalScrollController = ScrollController();
  20. @override
  21. void initState() {
  22. super.initState();
  23. WidgetsBinding.instance.addPostFrameCallback((_) {
  24. Provider.of<PedidoViewModel>(context, listen: false).fetchLocalPedidos();
  25. });
  26. }
  27. void exportCSV() async {
  28. // Obtiene los pedidos actuales del estado de PedidoViewModel
  29. List<Pedido> pedidos =
  30. Provider.of<PedidoViewModel>(context, listen: false).pedidos;
  31. // Llamada a la función de exportación que debes definir en otro lugar y que crea el CSV
  32. exportarPedidosACSV(pedidos);
  33. ScaffoldMessenger.of(context).showSnackBar(
  34. SnackBar(content: Text('Exportación de CSV completada!')));
  35. }
  36. void go(Pedido item) async {
  37. // Obtener el pedido completo con productos antes de navegar
  38. Pedido? pedidoCompleto =
  39. await Provider.of<PedidoViewModel>(context, listen: false)
  40. .fetchPedidoConProductos(item.id);
  41. if (pedidoCompleto != null) {
  42. Navigator.push(
  43. context,
  44. MaterialPageRoute(
  45. builder: (context) => PedidoDetalleScreen(pedido: pedidoCompleto),
  46. ),
  47. );
  48. } else {
  49. print("Error al cargar el pedido con productos");
  50. }
  51. }
  52. @override
  53. Widget build(BuildContext context) {
  54. final pvm = Provider.of<PedidoViewModel>(context);
  55. double screenWidth = MediaQuery.of(context).size.width;
  56. final isMobile = screenWidth < 1250;
  57. final double? columnSpacing = isMobile ? null : 0;
  58. TextStyle estilo = const TextStyle(fontWeight: FontWeight.bold);
  59. List<DataRow> registros = [];
  60. for (Pedido item in pvm.pedidos) {
  61. registros.add(DataRow(cells: [
  62. DataCell(
  63. Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
  64. PopupMenuButton(
  65. itemBuilder: (context) => [
  66. PopupMenuItem(
  67. child: const Text('Editar'),
  68. onTap: () => go(item),
  69. ),
  70. PopupMenuItem(
  71. child: const Text('Cancelar Pedido'),
  72. onTap: () async {
  73. bool confirmado = await showDialog<bool>(
  74. context: context,
  75. builder: (context) {
  76. return AlertDialog(
  77. title: const Text("Cancelar Pedido"),
  78. content: const Text(
  79. '¿Estás seguro de que deseas cancelar este pedido?'),
  80. actions: [
  81. TextButton(
  82. onPressed: () =>
  83. Navigator.of(context).pop(false),
  84. child: const Text('No'),
  85. ),
  86. TextButton(
  87. onPressed: () =>
  88. Navigator.of(context).pop(false),
  89. child: const Text('Sí'),
  90. ),
  91. ],
  92. );
  93. },
  94. ) ??
  95. false;
  96. if (confirmado) {
  97. // bool result = await Provider.of<PedidoViewModel>(context,
  98. // listen: false)
  99. // .cancelarPedido(item.id!);
  100. // if (result) {
  101. // ScaffoldMessenger.of(context).showSnackBar(
  102. // SnackBar(
  103. // content: Text("Pedido cancelado correctamente")),
  104. // );
  105. // } else {
  106. // ScaffoldMessenger.of(context).showSnackBar(
  107. // SnackBar(content: Text("Error al cancelar el pedido")),
  108. // );
  109. // }
  110. }
  111. },
  112. )
  113. ],
  114. icon: const Icon(Icons.more_vert),
  115. ),
  116. ])),
  117. DataCell(
  118. Text(item.id.toString()), // Ajusta de acuerdo a tu modelo de Pedido.
  119. onTap: () => go(item),
  120. ),
  121. DataCell(
  122. Text(item.nombreCliente ??
  123. "Sin nombre"), // Ajusta de acuerdo a tu modelo de Pedido.
  124. onTap: () => go(item),
  125. ),
  126. DataCell(
  127. Text(item.comentarios ??
  128. "Sin comentarios"), // Ajusta de acuerdo a tu modelo de Pedido.
  129. onTap: () => go(item),
  130. ),
  131. // Continúa con las demás celdas que necesites mostrar
  132. ]));
  133. }
  134. return Scaffold(
  135. appBar: AppBar(
  136. title: const Text('Pedidos'),
  137. actions: <Widget>[
  138. IconButton(
  139. icon: const Icon(Icons.save_alt),
  140. onPressed: exportCSV,
  141. tooltip: 'Exportar a CSV',
  142. ),
  143. ],
  144. ),
  145. floatingActionButton: FloatingActionButton.extended(
  146. onPressed: () async {
  147. await Navigator.push(
  148. context,
  149. MaterialPageRoute(
  150. builder: (context) => PedidoForm(),
  151. ),
  152. ).then((_) => Provider.of<PedidoViewModel>(context, listen: false)
  153. .fetchLocalPedidos());
  154. },
  155. icon: const Icon(Icons.add, size: 30), // Incrementa el tamaño del ícono
  156. label: const Text(
  157. "Agregar Pedido",
  158. style: TextStyle(
  159. fontSize: 20, // Incrementa el tamaño del texto
  160. ),
  161. ),
  162. shape: RoundedRectangleBorder(
  163. borderRadius: BorderRadius.circular(8),
  164. ),
  165. materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
  166. backgroundColor: AppTheme.primary,
  167. foregroundColor: AppTheme.tertiary,
  168. ),
  169. body: Column(
  170. children: [
  171. Expanded(
  172. child: ListView(
  173. padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
  174. children: [
  175. const SizedBox(height: 8),
  176. tarjeta(
  177. Padding(
  178. padding: const EdgeInsets.all(8.0),
  179. child: LayoutBuilder(
  180. builder: (context, constraints) {
  181. if (screenWidth > 1000) {
  182. return Row(
  183. children: [
  184. Expanded(
  185. flex: 10,
  186. child: Row(
  187. crossAxisAlignment:
  188. CrossAxisAlignment.start,
  189. children: [
  190. BusquedaTextField(),
  191. ],
  192. )),
  193. SizedBox(width: 5),
  194. BotonBuscar()
  195. ],
  196. );
  197. } else {
  198. return Column(
  199. children: [
  200. Row(
  201. children: [BusquedaTextField()],
  202. ),
  203. SizedBox(height: 15),
  204. Row(
  205. children: [BotonBuscar()],
  206. ),
  207. ],
  208. );
  209. }
  210. },
  211. ),
  212. ),
  213. ),
  214. const SizedBox(height: 8),
  215. pvm.isLoading
  216. ? const Center(child: CircularProgressIndicator())
  217. : Container(),
  218. tarjeta(
  219. Column(
  220. children: [
  221. LayoutBuilder(builder: (context, constraints) {
  222. return SingleChildScrollView(
  223. scrollDirection: Axis.vertical,
  224. child: Scrollbar(
  225. controller: horizontalScrollController,
  226. interactive: true,
  227. thumbVisibility: true,
  228. thickness:
  229. 10.0, // Esto es opcional para cambiar el grosor
  230. child: SingleChildScrollView(
  231. controller: horizontalScrollController,
  232. scrollDirection: Axis.horizontal,
  233. child: ConstrainedBox(
  234. constraints: BoxConstraints(
  235. minWidth: isMobile
  236. ? constraints.maxWidth
  237. : screenWidth),
  238. child: DataTable(
  239. columnSpacing: columnSpacing,
  240. sortAscending: true,
  241. sortColumnIndex: 1,
  242. columns: [
  243. DataColumn(label: Text(" ", style: estilo)),
  244. DataColumn(
  245. label: Text("FOLIO", style: estilo)),
  246. DataColumn(
  247. label: Text("NOMBRE", style: estilo)),
  248. DataColumn(
  249. label:
  250. Text("COMENTARIOS", style: estilo)),
  251. ],
  252. rows: registros,
  253. ),
  254. ),
  255. ),
  256. ),
  257. );
  258. }),
  259. ],
  260. ),
  261. ),
  262. // PaginationButtons(
  263. // currentPage: pvm.pagina,
  264. // totalPages: pvm.totalPaginas,
  265. // onPageChanged: (i) => pvm.cambiarPagina(i),
  266. // )
  267. ],
  268. ),
  269. ),
  270. ],
  271. ),
  272. );
  273. }
  274. Widget BusquedaTextField() {
  275. return Expanded(
  276. flex: 4,
  277. child: AppTextField(
  278. prefixIcon: const Icon(Icons.search),
  279. etiqueta: 'Búsqueda por folio...',
  280. controller: _busqueda,
  281. hintText: 'Búsqueda por folio...',
  282. ),
  283. );
  284. }
  285. Widget BotonBuscar() {
  286. return Expanded(
  287. flex: 2,
  288. child: botonElevated(
  289. accion: () async {
  290. // PedidoViewModel mvm =
  291. // Provider.of<PedidoViewModel>(context, listen: false);
  292. // await mvm.setIsLoading(true);
  293. // await mvm.setBusqueda(_busqueda.text);
  294. // await mvm.fetchPedidos(q: _busqueda.text);
  295. // await mvm.setBusqueda("");
  296. // await mvm.setIsLoading(false);
  297. },
  298. ),
  299. );
  300. }
  301. }