app_drawer.dart 15 KB

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