creacion_pedido_screen.dart 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. import 'package:flutter/material.dart';
  2. import 'package:provider/provider.dart';
  3. import 'package:turquessa_mesas_hoster/core/models/producto_model.dart';
  4. import 'package:turquessa_mesas_hoster/mvvm/viewmodels/creacion_pedido_view_model.dart';
  5. import 'package:turquessa_mesas_hoster/utils/themes.dart';
  6. import 'package:turquessa_mesas_hoster/utils/widgets/custom_appbar.dart';
  7. import 'package:turquessa_mesas_hoster/utils/widgets/custom_card.dart';
  8. import 'package:turquessa_mesas_hoster/utils/widgets/navigation_rail.dart';
  9. class CreacionPedido extends StatefulWidget {
  10. const CreacionPedido({super.key});
  11. @override
  12. State<CreacionPedido> createState() => _CreacionPedidoState();
  13. }
  14. class _CreacionPedidoState extends State<CreacionPedido> {
  15. @override
  16. void initState() {
  17. // TODO: implement initState
  18. super.initState();
  19. }
  20. final _selectedIndex = 0;
  21. @override
  22. Widget build(BuildContext context) {
  23. CreacionPedidoViewModel creacionPedidoViewModel =
  24. Provider.of<CreacionPedidoViewModel>(context, listen: true);
  25. List<Producto> listaPedido = creacionPedidoViewModel.productosDisponibles;
  26. return Container(
  27. decoration: const BoxDecoration(
  28. gradient: LinearGradient(
  29. begin: Alignment.bottomRight,
  30. end: Alignment.topLeft,
  31. colors: [
  32. Color(0xFF7FD4D4),
  33. Color.fromARGB(255, 141, 225, 225),
  34. Color.fromARGB(255, 74, 156, 156),
  35. ])),
  36. child: Scaffold(
  37. backgroundColor: Colors.transparent,
  38. appBar: AppBar(
  39. title: const CustomAppbar(),
  40. ),
  41. body: Row(
  42. children: [
  43. CustomNavigationRail(selectedIndex: _selectedIndex),
  44. Expanded(
  45. flex: 8,
  46. child: Container(
  47. decoration: const BoxDecoration(
  48. color: Colors.white,
  49. ),
  50. child: const Column(
  51. children: [
  52. CategoryFilters(),
  53. CategoryGrid(),
  54. ],
  55. ),
  56. ),
  57. ),
  58. Expanded(
  59. flex: 4,
  60. child: Container(
  61. decoration: const BoxDecoration(
  62. color: Colors.white,
  63. ),
  64. child: Padding(
  65. padding: const EdgeInsets.all(8.0),
  66. child: Column(
  67. crossAxisAlignment: CrossAxisAlignment.start,
  68. children: [
  69. const Padding(
  70. padding: EdgeInsets.only(left: 10),
  71. child: Text(
  72. "Mesa 3: Palmeras",
  73. textAlign: TextAlign.start,
  74. style: TextStyle(
  75. fontSize: 40,
  76. fontWeight: FontWeight.bold,
  77. color: Colors.black),
  78. ),
  79. ),
  80. const Divider(),
  81. // En el DataTable
  82. SingleChildScrollView(
  83. scrollDirection: Axis.horizontal,
  84. child: SingleChildScrollView(
  85. scrollDirection: Axis.vertical,
  86. child: DataTable(
  87. columnSpacing: 16,
  88. horizontalMargin: 12,
  89. dataRowHeight: 60,
  90. headingRowHeight: 48,
  91. columns: const <DataColumn>[
  92. DataColumn(label: Text('Cant')),
  93. DataColumn(label: Text('Nombre')),
  94. DataColumn(label: Text('SubTotal')),
  95. DataColumn(label: Text('Acciones')),
  96. ],
  97. rows: creacionPedidoViewModel
  98. .carrito // Aquí usamos la lista de carrito
  99. .map(
  100. (e) => DataRow(cells: [
  101. DataCell(
  102. Text(e.venta.toString()),
  103. ),
  104. DataCell(Text(e.nombre!)),
  105. DataCell(
  106. Text((e.precio! * e.venta!)
  107. .toStringAsFixed(2)),
  108. ),
  109. DataCell(IconButton(
  110. color: Colors.grey[600],
  111. icon: const Icon(Icons.edit),
  112. onPressed: () {
  113. creacionPedidoViewModel
  114. .eliminarDelCarrito(e);
  115. },
  116. )),
  117. ]),
  118. )
  119. .toList(),
  120. ),
  121. ),
  122. ),
  123. Expanded(
  124. child: Column(
  125. children: [
  126. const SizedBox(
  127. height: 100,
  128. width: double.infinity,
  129. ),
  130. const Divider(),
  131. Row(
  132. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  133. children: [
  134. const Text(
  135. "Total",
  136. style: TextStyle(
  137. fontSize: 20,
  138. fontWeight: FontWeight.bold),
  139. ),
  140. Text(
  141. "\$${creacionPedidoViewModel.calcularTotalCarrito().toStringAsFixed(2)}",
  142. style: const TextStyle(
  143. fontSize: 20,
  144. fontWeight: FontWeight.bold),
  145. ),
  146. ],
  147. ),
  148. const SizedBox(height: 10),
  149. Row(
  150. children: [
  151. Expanded(
  152. flex: 9,
  153. child: ElevatedButton(
  154. style: const ButtonStyle(
  155. backgroundColor: MaterialStatePropertyAll(
  156. Colors.green),
  157. ),
  158. onPressed: () {},
  159. child: const Text(
  160. "Mandar a Preparacion",
  161. style: TextStyle(color: Colors.white),
  162. ),
  163. ),
  164. ),
  165. Expanded(
  166. flex: 1,
  167. child: IconButton(
  168. style: const ButtonStyle(
  169. backgroundColor:
  170. MaterialStatePropertyAll(
  171. Colors.white),
  172. iconColor: MaterialStatePropertyAll(
  173. Colors.red)),
  174. icon: const Icon(Icons.delete,
  175. color: Colors.red),
  176. onPressed: () {
  177. creacionPedidoViewModel.limpiarCarrito();
  178. },
  179. ),
  180. ),
  181. ],
  182. ),
  183. ],
  184. ),
  185. ),
  186. ],
  187. ),
  188. ),
  189. ),
  190. )
  191. ],
  192. ),
  193. ),
  194. );
  195. }
  196. }
  197. class CategoryGrid extends StatelessWidget {
  198. const CategoryGrid({
  199. super.key,
  200. });
  201. @override
  202. Widget build(BuildContext context) {
  203. CreacionPedidoViewModel creacionPedidoViewModel =
  204. Provider.of<CreacionPedidoViewModel>(context);
  205. List<Producto> listaProductos =
  206. creacionPedidoViewModel.productosDisponibles;
  207. return Expanded(
  208. child: Container(
  209. padding: const EdgeInsets.all(8),
  210. child: GridView.builder(
  211. gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
  212. crossAxisCount: 3,
  213. crossAxisSpacing: 10,
  214. mainAxisSpacing: 15,
  215. ),
  216. itemCount: listaProductos.length,
  217. itemBuilder: (context, index) {
  218. int carritoIndex = creacionPedidoViewModel.carrito
  219. .indexWhere((p) => p.id == listaProductos[index].id);
  220. int cantidad = carritoIndex != -1
  221. ? creacionPedidoViewModel.carrito[carritoIndex].venta!
  222. : 0;
  223. return Card(
  224. shadowColor: Colors.grey.shade700,
  225. surfaceTintColor: Colors.white,
  226. child: Column(children: [
  227. Padding(
  228. padding: const EdgeInsets.all(3),
  229. child: Container(
  230. height: 140,
  231. width: double.infinity,
  232. decoration: BoxDecoration(
  233. color: Colors.white,
  234. image: DecorationImage(
  235. image: NetworkImage(
  236. "https://picsum.photos/200/300?random=$index"),
  237. fit: BoxFit.cover,
  238. ),
  239. ),
  240. ),
  241. ),
  242. Center(
  243. child: Text(
  244. listaProductos[index].nombre ?? "Error",
  245. style: const TextStyle(
  246. fontWeight: FontWeight.bold,
  247. fontSize: 16,
  248. color: Colors.black),
  249. ),
  250. ),
  251. Text(
  252. "\$${listaProductos[index].precio}",
  253. textAlign: TextAlign.left,
  254. style: TextStyle(
  255. color: Colors.green[600],
  256. fontWeight: FontWeight.bold,
  257. ),
  258. ),
  259. const Spacer(),
  260. Padding(
  261. padding: const EdgeInsets.symmetric(horizontal: 10),
  262. child: Row(
  263. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  264. children: [
  265. IconButton(
  266. style: ButtonStyle(
  267. backgroundColor:
  268. MaterialStatePropertyAll(AppTheme.primary)),
  269. onPressed: () {
  270. if (cantidad > 0) {
  271. creacionPedidoViewModel
  272. .reducirDelCarrito(listaProductos[index]);
  273. }
  274. },
  275. icon: const Icon(
  276. Icons.remove,
  277. color: Colors.black,
  278. )),
  279. Text(
  280. "$cantidad",
  281. style: const TextStyle(
  282. fontSize: 20,
  283. fontWeight: FontWeight.bold,
  284. ),
  285. ),
  286. IconButton(
  287. style: ButtonStyle(
  288. backgroundColor:
  289. MaterialStatePropertyAll(AppTheme.primary)),
  290. onPressed: () {
  291. creacionPedidoViewModel
  292. .agregarAlCarrito(listaProductos[index]);
  293. },
  294. icon: const Icon(
  295. Icons.add,
  296. color: Colors.black,
  297. )),
  298. ],
  299. ),
  300. )
  301. ]),
  302. );
  303. },
  304. ),
  305. ),
  306. );
  307. }
  308. }
  309. class CategoryFilters extends StatefulWidget {
  310. const CategoryFilters({super.key});
  311. @override
  312. State<CategoryFilters> createState() => CategoryFiltersState();
  313. }
  314. class CategoryFiltersState extends State<CategoryFilters> {
  315. int _selectedNavIndex = 0;
  316. @override
  317. void initState() {
  318. super.initState();
  319. }
  320. void _closeFilterView() {
  321. setState(() {
  322. _selectedNavIndex = 0;
  323. });
  324. }
  325. @override
  326. Widget build(BuildContext context) {
  327. return Container(
  328. padding: const EdgeInsets.all(8),
  329. decoration: BoxDecoration(
  330. border: Border(bottom: BorderSide(color: Colors.grey.shade300)),
  331. ),
  332. child: Column(
  333. mainAxisSize: MainAxisSize.min,
  334. children: [
  335. Row(
  336. children: [
  337. // Buscador
  338. Expanded(
  339. child: Container(
  340. height: 40,
  341. padding: const EdgeInsets.symmetric(horizontal: 12),
  342. decoration: BoxDecoration(
  343. color: Colors.grey.shade200,
  344. borderRadius: BorderRadius.circular(20),
  345. ),
  346. child: Row(
  347. children: [
  348. Icon(Icons.search, color: Colors.grey.shade600),
  349. const SizedBox(width: 8),
  350. Text('Buscar',
  351. style: TextStyle(color: Colors.grey.shade600)),
  352. ],
  353. ),
  354. ),
  355. ),
  356. const SizedBox(width: 10),
  357. // Botones de filtro
  358. _buildFilterButton(1, 'Categoría'),
  359. const SizedBox(width: 10),
  360. _buildFilterButton(2, 'Topics'),
  361. const SizedBox(width: 10),
  362. _buildFilterButton(3, 'Extras'),
  363. ],
  364. ),
  365. const SizedBox(height: 5),
  366. if (_selectedNavIndex != 0)
  367. Column(
  368. crossAxisAlignment: CrossAxisAlignment.start,
  369. children: [
  370. Row(
  371. children: [
  372. Text(
  373. _getFilterTitle(_selectedNavIndex),
  374. style: const TextStyle(
  375. fontWeight: FontWeight.bold,
  376. fontSize: 16,
  377. ),
  378. ),
  379. const Spacer(),
  380. GestureDetector(
  381. onTap: _closeFilterView,
  382. child: Container(
  383. padding: const EdgeInsets.all(4),
  384. decoration: BoxDecoration(
  385. color: Colors.grey.shade300,
  386. shape: BoxShape.circle,
  387. ),
  388. child: Icon(
  389. Icons.close,
  390. size: 16,
  391. color: Colors.grey.shade800,
  392. ),
  393. ),
  394. ),
  395. ],
  396. ),
  397. const SizedBox(height: 8),
  398. SizedBox(
  399. height: 50,
  400. child: ListView.builder(
  401. scrollDirection: Axis.horizontal,
  402. itemCount: 10,
  403. itemBuilder: (context, index) {
  404. return Container(
  405. margin: const EdgeInsets.only(right: 8),
  406. padding: const EdgeInsets.symmetric(
  407. horizontal: 20, vertical: 10),
  408. decoration: BoxDecoration(
  409. color: Colors.grey.shade200,
  410. borderRadius: BorderRadius.circular(4),
  411. border: Border.all(
  412. color: Colors.grey.shade400,
  413. width: 1,
  414. ),
  415. ),
  416. child: Text(
  417. 'Item $index',
  418. style: const TextStyle(fontSize: 16),
  419. ),
  420. );
  421. },
  422. ),
  423. ),
  424. ],
  425. )
  426. ],
  427. ),
  428. );
  429. }
  430. String _getFilterTitle(int index) {
  431. switch (index) {
  432. case 1:
  433. return 'Categorías';
  434. case 2:
  435. return 'Topics';
  436. case 3:
  437. return 'Extras';
  438. default:
  439. return '';
  440. }
  441. }
  442. Widget _buildFilterButton(int index, String text) {
  443. final bool isSelected = _selectedNavIndex == index;
  444. return GestureDetector(
  445. onTap: () {
  446. setState(() {
  447. if (_selectedNavIndex == index) {
  448. _selectedNavIndex = 0;
  449. } else {
  450. _selectedNavIndex = index;
  451. }
  452. });
  453. },
  454. child: Container(
  455. padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
  456. decoration: BoxDecoration(
  457. color: isSelected ? Colors.blue.shade100 : Colors.grey.shade200,
  458. borderRadius: BorderRadius.circular(16),
  459. border: Border.all(
  460. color: isSelected ? Colors.blue : Colors.transparent,
  461. width: 1,
  462. ),
  463. ),
  464. child: Row(
  465. children: [
  466. Text(
  467. text,
  468. style: TextStyle(
  469. color: isSelected ? Colors.blue.shade800 : Colors.grey.shade800,
  470. fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
  471. ),
  472. ),
  473. if (isSelected) ...[
  474. const SizedBox(width: 4),
  475. Icon(
  476. Icons.keyboard_arrow_down,
  477. size: 16,
  478. color: Colors.blue.shade800,
  479. ),
  480. ],
  481. ],
  482. ),
  483. ),
  484. );
  485. }
  486. }