creacion_pedido_screen.dart 18 KB

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