app_drawer.dart 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. // ignore_for_file: must_be_immutable
  2. import 'package:flutter/material.dart';
  3. import '/views/categoria_producto/categoria_producto_screen.dart';
  4. import '/views/mesa/mesa_screen.dart';
  5. import '/views/pedido/pedido_screen.dart';
  6. import '/views/producto/producto_screen.dart';
  7. import '/views/sucursal/sucursal_screen.dart';
  8. import '/views/variable/variable_screen.dart';
  9. import '/views/venta/venta_screen.dart';
  10. import 'package:provider/provider.dart';
  11. import '../models/models.dart';
  12. import '../services/services.dart';
  13. import '../themes/themes.dart';
  14. import '../viewmodels/login_view_model.dart';
  15. import '../viewmodels/viewmodels.dart';
  16. import '../views/corte_caja/corte_caja_screen.dart';
  17. import '../views/descuento/descuento_screen.dart';
  18. import 'widgets_components.dart';
  19. class AppDrawer extends StatelessWidget {
  20. AppDrawer({super.key});
  21. Future<bool> _showExitConfirmationDialog(BuildContext context) async {
  22. bool shouldPop = false;
  23. await showDialog(
  24. context: context,
  25. builder: (context) => AlertDialog(
  26. surfaceTintColor: AppTheme.secondary,
  27. title: const Text('¿Cerrar sesión?'),
  28. content: const Text('¿Estás seguro de que quieres cerrar la sesión?'),
  29. actions: [
  30. TextButton(
  31. onPressed: () => Navigator.of(context).pop(false),
  32. child: const Text('Cancelar', style: TextStyle(color: Colors.red)),
  33. ),
  34. TextButton(
  35. onPressed: () async {
  36. Provider.of<LoginViewModel>(context, listen: false).logOut();
  37. Navigator.of(context).pushNamedAndRemoveUntil(
  38. 'login',
  39. (route) => false,
  40. );
  41. },
  42. child: const Text('Aceptar'),
  43. ),
  44. ],
  45. ),
  46. );
  47. return shouldPop;
  48. }
  49. @override
  50. Widget build(BuildContext context) {
  51. final permisoViewModel = Provider.of<PermisoViewModel>(context);
  52. List<String> userPermisos = permisoViewModel.userPermisos;
  53. BaseService baseService = BaseService(); // Instancia de BaseService
  54. String prefijoVersion = baseService.prefijoVersion();
  55. return Drawer(
  56. surfaceTintColor: Colors.white,
  57. backgroundColor: Colors.white,
  58. child: Column(
  59. children: [
  60. Container(
  61. width: double.infinity,
  62. decoration: BoxDecoration(
  63. color: AppTheme.primary,
  64. ),
  65. padding: EdgeInsets.only(
  66. top: MediaQuery.of(context).padding.top,
  67. ),
  68. child: const Column(
  69. children: [
  70. Padding(
  71. padding: EdgeInsets.all(8.0),
  72. child: Image(
  73. image: AssetImage('assets/logo-BN.png'),
  74. height: 150,
  75. ),
  76. ),
  77. SizedBox(
  78. height: 10,
  79. ),
  80. SizedBox(
  81. height: 10,
  82. ),
  83. ],
  84. ),
  85. ),
  86. // HEADER
  87. Expanded(
  88. child: ListView(
  89. children: [
  90. ListTile(
  91. leading: circulo(const Icon(Icons.restaurant_menu)),
  92. title: const Text('Pedidos'),
  93. onTap: () => {
  94. Navigator.pop(context),
  95. Navigator.of(context).push(
  96. MaterialPageRoute(
  97. builder: (context) => const PedidoScreen(),
  98. ),
  99. ),
  100. },
  101. ),
  102. ListTile(
  103. leading: circulo(const Icon(Icons.point_of_sale)),
  104. title: const Text('Corte de caja'),
  105. onTap: () => {
  106. Navigator.pop(context),
  107. Navigator.of(context).push(
  108. MaterialPageRoute(
  109. builder: (context) => CorteCajaScreen(),
  110. ),
  111. ),
  112. },
  113. ),
  114. ListTile(
  115. leading: circulo(const Icon(Icons.menu_book_rounded)),
  116. title: const Text('Productos'),
  117. onTap: () => {
  118. Navigator.pop(context),
  119. Navigator.of(context).push(
  120. MaterialPageRoute(
  121. builder: (context) => ProductoScreen(),
  122. ),
  123. ),
  124. },
  125. ),
  126. if (userPermisos.contains(Usuario.VER_CATEGORIAS))
  127. ListTile(
  128. leading:
  129. circulo(const Icon(Icons.format_list_bulleted_rounded)),
  130. title: const Text('Categoría Producto'),
  131. onTap: () => {
  132. Navigator.pop(context),
  133. Navigator.of(context).push(
  134. MaterialPageRoute(
  135. builder: (context) => CategoriaProductoScreen(),
  136. ),
  137. ),
  138. },
  139. ),
  140. ListTile(
  141. leading: circulo(const Icon(Icons.receipt_long_outlined)),
  142. title: const Text('Pedidos Por Día'),
  143. onTap: () => {
  144. Navigator.pop(context),
  145. Navigator.of(context).push(
  146. MaterialPageRoute(
  147. builder: (context) => VentaScreen(),
  148. ),
  149. ),
  150. },
  151. ),
  152. if (userPermisos.contains(Usuario.VER_ADMIN))
  153. ExpansionTile(
  154. leading: circulo(const Icon(Icons.admin_panel_settings)),
  155. title: const Text('Administración'),
  156. children: [
  157. ListTile(
  158. leading: circulo(const Icon(Icons.discount)),
  159. title: const Text('Descuentos'),
  160. onTap: () => {
  161. Navigator.pop(context),
  162. Navigator.of(context).push(
  163. MaterialPageRoute(
  164. builder: (context) => DescuentoScreen(),
  165. ),
  166. ),
  167. },
  168. ),
  169. ListTile(
  170. leading: circulo(const Icon(Icons.discount)),
  171. title: const Text('Variables'),
  172. onTap: () => {
  173. Navigator.pop(context),
  174. Navigator.of(context).push(
  175. MaterialPageRoute(
  176. builder: (context) => VariablesScreen(),
  177. ),
  178. ),
  179. },
  180. ),
  181. ListTile(
  182. leading: circulo(const Icon(Icons.table_bar)),
  183. title: const Text('Mesas'),
  184. onTap: () => {
  185. Navigator.pop(context),
  186. Navigator.of(context).push(
  187. MaterialPageRoute(
  188. builder: (context) => MesasScreen(),
  189. ),
  190. ),
  191. },
  192. ),
  193. if (userPermisos.contains(Usuario.VER_SUCURSALES))
  194. ListTile(
  195. leading:
  196. circulo(const Icon(Icons.storefront_outlined)),
  197. title: const Text('Sucursales'),
  198. onTap: () => {
  199. Navigator.pop(context),
  200. Navigator.of(context).push(
  201. MaterialPageRoute(
  202. builder: (context) => SucursalesPage(),
  203. ),
  204. ),
  205. },
  206. ),
  207. if (userPermisos.contains(Usuario.FORZAR_SINCRONIZACION))
  208. ListTile(
  209. leading: circulo(const Icon(Icons.sync)),
  210. title: const Text('Forzar Sincronización'),
  211. onTap: () async {
  212. bool confirmado = await showDialog(
  213. context: context,
  214. builder: (context) {
  215. return AlertDialog(
  216. title: const Text("Forzar Sincronización",
  217. style: TextStyle(
  218. fontWeight: FontWeight.w500,
  219. fontSize: 22)),
  220. content: const Text(
  221. '¿Estás seguro de que deseas forzar la sincronización?',
  222. style: TextStyle(fontSize: 18)),
  223. actions: [
  224. Row(
  225. mainAxisAlignment:
  226. MainAxisAlignment.spaceBetween,
  227. children: [
  228. TextButton(
  229. onPressed: () =>
  230. Navigator.of(context)
  231. .pop(false),
  232. child: const Text('No',
  233. style:
  234. TextStyle(fontSize: 18)),
  235. style: ButtonStyle(
  236. padding:
  237. MaterialStateProperty.all(
  238. EdgeInsets.fromLTRB(
  239. 20, 10, 20, 10)),
  240. backgroundColor:
  241. MaterialStateProperty.all(
  242. Colors.red),
  243. foregroundColor:
  244. MaterialStateProperty.all(
  245. AppTheme.secondary),
  246. ),
  247. ),
  248. TextButton(
  249. onPressed: () =>
  250. Navigator.of(context)
  251. .pop(true),
  252. child: const Text('Sí',
  253. style:
  254. TextStyle(fontSize: 18)),
  255. style: ButtonStyle(
  256. padding:
  257. MaterialStateProperty.all(
  258. EdgeInsets.fromLTRB(
  259. 20, 10, 20, 10)),
  260. backgroundColor:
  261. MaterialStateProperty.all(
  262. AppTheme.tertiary),
  263. foregroundColor:
  264. MaterialStateProperty.all(
  265. AppTheme.quaternary),
  266. ),
  267. ),
  268. ],
  269. ),
  270. ],
  271. );
  272. },
  273. ) ??
  274. false;
  275. if (confirmado) {
  276. showDialog(
  277. context: context,
  278. barrierDismissible: false,
  279. builder: (context) => AlertDialog(
  280. title: const Text("Sincronizando",
  281. style: TextStyle(
  282. fontWeight: FontWeight.w500,
  283. fontSize: 22)),
  284. content: Padding(
  285. padding:
  286. const EdgeInsetsDirectional.symmetric(
  287. horizontal: 120),
  288. child: const CircularProgressIndicator(),
  289. ),
  290. ),
  291. );
  292. try {
  293. await RepoService().forzarSincronizacion();
  294. Navigator.of(context, rootNavigator: true)
  295. .pop();
  296. Navigator.of(context).pop();
  297. ScaffoldMessenger.of(context).showSnackBar(
  298. SnackBar(
  299. content: const Text(
  300. 'Sincronización completada con éxito'),
  301. backgroundColor: Colors.green,
  302. ),
  303. );
  304. } catch (e) {
  305. Navigator.of(context, rootNavigator: true)
  306. .pop();
  307. Navigator.of(context).pop();
  308. ScaffoldMessenger.of(context).showSnackBar(
  309. SnackBar(
  310. content:
  311. Text('Error en la sincronización: $e'),
  312. backgroundColor: Colors.red,
  313. ),
  314. );
  315. }
  316. }
  317. },
  318. ),
  319. ],
  320. ),
  321. ListTile(
  322. leading: const Icon(Icons.logout),
  323. title: const Text('Cerrar sesión'),
  324. onTap: () {
  325. _showExitConfirmationDialog(context);
  326. },
  327. ),
  328. ],
  329. ),
  330. ),
  331. Padding(
  332. padding: const EdgeInsets.only(bottom: 10),
  333. child: Align(
  334. alignment: Alignment.bottomCenter,
  335. child: Text(
  336. '$prefijoVersion.1.24.12.27',
  337. style: const TextStyle(fontWeight: FontWeight.w300),
  338. ),
  339. ),
  340. ),
  341. ],
  342. ),
  343. );
  344. }
  345. }