widgets_components.dart 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. // ignore_for_file: use_build_context_synchronously, prefer_if_null_operators, prefer_conditional_assignment
  2. import 'dart:io';
  3. import 'dart:typed_data';
  4. import 'package:camera/camera.dart';
  5. import 'package:flutter/material.dart';
  6. //import 'package:yoshi_papas_app/viewmodels/media_view_model.dart';
  7. import 'package:intl/intl.dart';
  8. import 'package:omni_datetime_picker/omni_datetime_picker.dart';
  9. import 'package:flutter/material.dart' as d;
  10. import 'package:datetime_picker_formfield/datetime_picker_formfield.dart' as d2;
  11. import 'package:provider/provider.dart';
  12. import 'package:url_launcher/url_launcher.dart';
  13. import 'package:flutter/foundation.dart' show kIsWeb;
  14. import 'package:path_provider/path_provider.dart';
  15. import '../data/session/session_storage.dart';
  16. //import '../models/media_model.dart';
  17. import '../themes/themes.dart';
  18. import 'package:timezone/timezone.dart' as tz;
  19. import 'package:http/http.dart' as http;
  20. import "package:universal_html/html.dart" as html;
  21. //import '../viewmodels/ordenes_view_model.dart';
  22. //import 'dart:html';
  23. //import 'dart:html' as html;
  24. encabezado(
  25. {double elevacion = 1,
  26. List<Widget>? acciones,
  27. PreferredSize? bottom,
  28. Color? backgroundColor,
  29. String? nombre,
  30. Widget? leading = null,
  31. String? titulo,
  32. bool centerTitle = true}) {
  33. TextStyle estilo = const TextStyle(fontWeight: FontWeight.bold);
  34. if (acciones == null) {
  35. acciones = [];
  36. }
  37. return AppBar(
  38. leading: leading,
  39. elevation: elevacion,
  40. backgroundColor: Colors.white,
  41. foregroundColor: Colors.white,
  42. centerTitle: centerTitle,
  43. title: titulo == null
  44. ? Image.asset("assets/logo_iee.png", width: 100)
  45. : Text(titulo.toString(), style: estilo),
  46. actions: [
  47. ...acciones,
  48. Image.asset("assets/logo_iee.png", width: 100),
  49. ],
  50. bottom: bottom);
  51. }
  52. tarjeta(Widget item, {Color color = Colors.white, double padding = 0}) {
  53. if (padding > 0) {
  54. return Padding(
  55. padding: const EdgeInsets.all(0),
  56. child: Card(
  57. color: color,
  58. shape:
  59. RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
  60. margin: const EdgeInsets.only(bottom: 16),
  61. elevation: 0,
  62. borderOnForeground: true,
  63. child: Padding(padding: EdgeInsets.all(padding), child: item)));
  64. }
  65. return Card(
  66. color: color,
  67. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
  68. margin: const EdgeInsets.only(bottom: 8),
  69. elevation: 0,
  70. borderOnForeground: true,
  71. child: Padding(
  72. padding: const EdgeInsets.all(8),
  73. child: item,
  74. ));
  75. }
  76. class Cargando extends StatelessWidget {
  77. const Cargando({super.key});
  78. @override
  79. Widget build(BuildContext context) {
  80. return Scaffold(
  81. backgroundColor: const Color(0xFFE0E0E0),
  82. body: Center(
  83. child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
  84. Padding(
  85. padding: const EdgeInsets.fromLTRB(16, 0, 16, 10),
  86. child: Image.asset("assets/Elecciones2024.png", height: 200)),
  87. const CircularProgressIndicator(backgroundColor: Colors.grey),
  88. Container(margin: const EdgeInsets.only(bottom: 8.0)),
  89. const Text("Cargando contenido...",
  90. style: TextStyle(
  91. fontWeight: FontWeight.bold,
  92. fontSize: 16,
  93. color: Colors.black)),
  94. const Text("Por favor espere.",
  95. style: TextStyle(
  96. fontWeight: FontWeight.bold,
  97. fontSize: 16,
  98. color: Colors.black),
  99. textAlign: TextAlign.center)
  100. ]),
  101. ));
  102. }
  103. }
  104. boton(String etiqueta, Function()? accion,
  105. {double height = 75, double width = 380}) {
  106. return Align(
  107. alignment: Alignment.topLeft,
  108. child: SizedBox(
  109. height: height,
  110. width: 380,
  111. child: ElevatedButton(
  112. style: ButtonStyle(
  113. shape: MaterialStatePropertyAll(
  114. RoundedRectangleBorder(
  115. borderRadius: BorderRadius.circular(10),
  116. ),
  117. ),
  118. backgroundColor: MaterialStatePropertyAll(AppTheme.primary),
  119. ),
  120. onPressed: accion,
  121. child: Row(
  122. mainAxisAlignment: MainAxisAlignment.center,
  123. children: [
  124. Text(etiqueta,
  125. style: TextStyle(fontSize: 18, color: AppTheme.secondary)),
  126. ],
  127. ),
  128. ),
  129. ),
  130. );
  131. }
  132. Future<DateTime?> showHora(BuildContext context, DateTime? fecha) async {
  133. if (fecha == null) {
  134. return fecha;
  135. }
  136. final tiempo = await showTimePicker(
  137. useRootNavigator: false,
  138. helpText: "CAPTURAR HORA",
  139. confirmText: "ACEPTAR",
  140. cancelText: "CANCELAR",
  141. hourLabelText: "HORA",
  142. minuteLabelText: "MINUTO",
  143. initialEntryMode: TimePickerEntryMode.input,
  144. context: context,
  145. initialTime: TimeOfDay.fromDateTime(fecha),
  146. builder: (context, childs) {
  147. return MediaQuery(
  148. data: MediaQuery.of(context).copyWith(
  149. alwaysUse24HourFormat: true,
  150. padding: const EdgeInsets.all(1),
  151. size: const Size.square(1),
  152. textScaler: const TextScaler.linear(.8)),
  153. child: childs!);
  154. },
  155. );
  156. return d2.DateTimeField.combine(fecha!, tiempo);
  157. }
  158. Future<DateTime?> showDatetimePicker(BuildContext context, DateTime? fecha,
  159. {DateTime? inicia,
  160. DateTime? termina,
  161. OmniDateTimePickerType tipo = OmniDateTimePickerType.dateAndTime,
  162. bool solofecha = false}) async {
  163. if (termina == null) {
  164. termina = DateTime(2030);
  165. }
  166. final f = await d.showDatePicker(
  167. context: context,
  168. initialDate: fecha != null ? DateTime.now() : fecha,
  169. firstDate: inicia == null ? DateTime(2023) : inicia, // DateTime(2023),
  170. lastDate: termina,
  171. cancelText: "CANCELAR", confirmText: "ACEPTAR",
  172. );
  173. if (f == null) {
  174. return fecha;
  175. }
  176. if (solofecha) {
  177. return f;
  178. }
  179. final tiempo = await showTimePicker(
  180. useRootNavigator: false,
  181. helpText: "CAPTURAR HORA",
  182. confirmText: "ACEPTAR",
  183. cancelText: "CANCELAR",
  184. hourLabelText: "HORA",
  185. minuteLabelText: "MINUTO",
  186. initialEntryMode: TimePickerEntryMode.input,
  187. context: context,
  188. initialTime: TimeOfDay.fromDateTime(f),
  189. builder: (context, childs) {
  190. return MediaQuery(
  191. data: MediaQuery.of(context).copyWith(
  192. alwaysUse24HourFormat: true,
  193. padding: const EdgeInsets.all(1),
  194. size: const Size.square(1),
  195. textScaler: const TextScaler.linear(.8)),
  196. child: childs!);
  197. },
  198. );
  199. return d2.DateTimeField.combine(f, tiempo);
  200. }
  201. Widget circulo(Widget item, {Function()? accion, Color? color}) {
  202. color ??= Colors.black;
  203. return InkWell(
  204. onTap: accion,
  205. child: Container(
  206. decoration: BoxDecoration(
  207. border: Border.all(
  208. color: color, // <--- border color
  209. width: 2.0,
  210. ),
  211. borderRadius: const BorderRadius.all(
  212. Radius.circular(50) // <--- border radius here
  213. ),
  214. ),
  215. child: item));
  216. }
  217. alerta(BuildContext context, {String? etiqueta = "Capturar búsqueda"}) {
  218. return showDialog(
  219. context: context,
  220. builder: (context) {
  221. return AlertDialog(
  222. title: Text(etiqueta.toString()),
  223. actions: [
  224. Row(children: [
  225. Expanded(
  226. child: TextButton(
  227. onPressed: () async {
  228. Navigator.pop(context);
  229. },
  230. child: const Text('Continuar'),
  231. ))
  232. ])
  233. ],
  234. );
  235. });
  236. }
  237. botonElevated(
  238. {Function()? accion,
  239. String? titulo = "Buscar",
  240. Color color = Colors.black}) {
  241. return ElevatedButton(
  242. style: ElevatedButton.styleFrom(
  243. backgroundColor: color,
  244. shape: RoundedRectangleBorder(
  245. borderRadius: BorderRadius.circular(12), // <-- Radius
  246. )),
  247. onPressed: accion,
  248. child: Text(
  249. titulo.toString(),
  250. style: const TextStyle(color: Colors.white),
  251. ),
  252. );
  253. }
  254. Widget xMedia(XFile m) {
  255. bool archivo = false;
  256. Widget icono = const Icon(Icons.file_copy, size: 50);
  257. int lastIndex = m.name.lastIndexOf('.');
  258. String extension = "";
  259. if (lastIndex != -1 && lastIndex < m.name.length - 1) {
  260. extension = m.name.substring(lastIndex + 1);
  261. }
  262. switch (extension) {
  263. case "mp4":
  264. archivo = true;
  265. icono = const Icon(Icons.video_file, size: 50);
  266. break;
  267. case "wav":
  268. archivo = true;
  269. icono = Image.asset("assets/audio-file.png");
  270. archivo = true;
  271. break;
  272. case "jpeg":
  273. case "jpg":
  274. case "png":
  275. break;
  276. case "pdf":
  277. icono = Image.asset("assets/pdf-file.png");
  278. archivo = true;
  279. break;
  280. case "csv":
  281. case "docx":
  282. icono = Image.asset("assets/word.png");
  283. archivo = true;
  284. break;
  285. case "xlsx":
  286. icono = Image.asset("assets/excel.png");
  287. archivo = true;
  288. break;
  289. }
  290. String nombre = m.name.toString();
  291. if (nombre.length > 25) {
  292. nombre = "${m.name.toString().substring(0, 24)}...";
  293. }
  294. return InkWell(
  295. onTap: () async {
  296. String url = m.path.toString();
  297. await canLaunch(url)
  298. ? await launch(url, forceSafariVC: false, forceWebView: false)
  299. : print('Could not launch '); //aqui
  300. },
  301. child: Stack(alignment: Alignment.center, children: [
  302. Container(
  303. height: 100.0,
  304. width: 100.0,
  305. clipBehavior: Clip.antiAlias,
  306. decoration: BoxDecoration(
  307. border: Border.all(color: Colors.black, width: 1.0),
  308. borderRadius: const BorderRadius.all(Radius.circular(15.0)),
  309. ),
  310. child: archivo
  311. ? icono
  312. : Image.network(m.path.toString(),
  313. scale:
  314. 1) // _firma == null?const Icon(Icons.pages, size: 30, color: Colors.black): contenedorFirma,
  315. ),
  316. Positioned(
  317. bottom: 0,
  318. child: Container(
  319. width: 200,
  320. height: 40,
  321. color: Colors.grey.shade800,
  322. child: Column(
  323. mainAxisAlignment: MainAxisAlignment.center,
  324. children: [
  325. Text(
  326. nombre,
  327. textAlign: TextAlign.center,
  328. textScaler: const TextScaler.linear(.8),
  329. style: const TextStyle(color: Colors.white),
  330. ),
  331. ]),
  332. )),
  333. ]));
  334. }
  335. // Widget wMedia(Media m, {Function()? eliminar}) {
  336. // bool archivo = false;
  337. // Widget icono = const Icon(Icons.file_copy, size: 50);
  338. // switch (m.extension) {
  339. // case "mp4":
  340. // archivo = true;
  341. // icono = const Icon(Icons.video_file, size: 50);
  342. // break;
  343. // case "wav":
  344. // archivo = true;
  345. // icono = Image.asset("assets/audio-file.png");
  346. // archivo = true;
  347. // break;
  348. // case "jpeg":
  349. // case "jpg":
  350. // case "png":
  351. // break;
  352. // case "pdf":
  353. // icono = Image.asset("assets/pdf-file.png");
  354. // archivo = true;
  355. // break;
  356. // case "csv":
  357. // case "docx":
  358. // icono = Image.asset("assets/word.png");
  359. // archivo = true;
  360. // break;
  361. // case "xlsx":
  362. // icono = Image.asset("assets/excel.png");
  363. // archivo = true;
  364. // break;
  365. // }
  366. // String fecha = "";
  367. // if (m.creado != null) {
  368. // String timeZone = 'America/Hermosillo';
  369. // fecha = formatFechaConZonaHoraria(m.creado!, timeZone);
  370. // }
  371. // String nombre = m.nombre.toString();
  372. // if (nombre.length > 25) {
  373. // nombre = "${m.nombre.toString().substring(0, 24)}...";
  374. // }
  375. // return InkWell(
  376. // onTap: () async {
  377. // String url = m.ruta.toString();
  378. // await canLaunch(url)
  379. // ? await launch(url, forceSafariVC: false, forceWebView: false)
  380. // : print('Could not launch '); //aqui
  381. // },
  382. // child: Stack(alignment: Alignment.center, children: [
  383. // Container(
  384. // height: 160.0,
  385. // width: 160.0,
  386. // clipBehavior: Clip.antiAlias,
  387. // decoration: BoxDecoration(
  388. // border: Border.all(color: Colors.black, width: 1.0),
  389. // borderRadius: const BorderRadius.all(Radius.circular(15.0)),
  390. // ),
  391. // child: archivo
  392. // ? icono
  393. // : Image.network(m.ruta.toString(),
  394. // scale:
  395. // 1) // _firma == null?const Icon(Icons.pages, size: 30, color: Colors.black): contenedorFirma,
  396. // ),
  397. // Positioned(
  398. // bottom: 0,
  399. // child: Container(
  400. // width: 500,
  401. // height: 40,
  402. // color: Colors.grey.shade800,
  403. // child: Column(
  404. // mainAxisAlignment: MainAxisAlignment.center,
  405. // children: [
  406. // Text(
  407. // nombre,
  408. // textAlign: TextAlign.center,
  409. // textScaler: const TextScaler.linear(.8),
  410. // style: const TextStyle(color: Colors.white),
  411. // ),
  412. // Text(
  413. // fecha,
  414. // textAlign: TextAlign.center,
  415. // textScaler: const TextScaler.linear(.8),
  416. // style: const TextStyle(color: Colors.white),
  417. // ),
  418. // ]),
  419. // )),
  420. // Positioned(
  421. // left: 0,
  422. // top: 0,
  423. // child: ElevatedButton(
  424. // onPressed: eliminar,
  425. // style: ElevatedButton.styleFrom(
  426. // shape: CircleBorder(),
  427. // padding: EdgeInsets.all(16),
  428. // ),
  429. // child: Icon(
  430. // Icons.delete,
  431. // color: Colors.red.shade800,
  432. // ),
  433. // ),
  434. // ),
  435. // ]));
  436. // }
  437. Widget agregarMedia(
  438. {Color color = Colors.green,
  439. Function()? accion,
  440. String titulo = "Agregar Media",
  441. Icon? icono,
  442. double tamano = 160}) {
  443. if (icono == null) {
  444. icono = Icon(
  445. Icons.add,
  446. size: tamano < 100 ? 60 : 100,
  447. color: Colors.white,
  448. );
  449. }
  450. return InkWell(
  451. onTap: accion,
  452. child: Stack(alignment: Alignment.center, children: [
  453. // Contenedor con un color de fondo y dimensiones específicas
  454. Container(
  455. width: tamano,
  456. height: tamano,
  457. color: color,
  458. ),
  459. // Texto flotante
  460. Positioned(
  461. child:
  462. Column(mainAxisAlignment: MainAxisAlignment.center, children: [
  463. icono,
  464. titulo.isEmpty
  465. ? Container()
  466. : Text(
  467. titulo,
  468. style: const TextStyle(
  469. color: Colors.white,
  470. fontSize: 16,
  471. ),
  472. ),
  473. ])),
  474. ]));
  475. }
  476. String formatFechaConZonaHoraria(DateTime dateTime, String timeZone) {
  477. // Obtiene la ubicación de la zona horaria
  478. tz.Location location = tz.getLocation(timeZone);
  479. // Convierte la fecha a la zona horaria deseada
  480. tz.TZDateTime fechaConZona = tz.TZDateTime.from(dateTime, location);
  481. // Formatea la fecha con la zona horaria
  482. //String formattedFecha = DateFormat("dd/MM/yyyy HH:mm '($timeZone)'").format(fechaConZona);
  483. String formattedFecha = DateFormat("dd/MM/yyyy HH:mm").format(fechaConZona);
  484. return formattedFecha;
  485. }
  486. html.Location getLocation(String timeZone) {
  487. // Obtiene la ubicación de la zona horaria
  488. return getLocation(timeZone);
  489. }
  490. int obtenerAxiscount(Size s) {
  491. int axiscount = 8;
  492. if (s.width > 1300) {
  493. axiscount = 8;
  494. }
  495. if (s.width > 900 && s.width < 1300) {
  496. axiscount = 5;
  497. }
  498. if (s.width > 700 && s.width < 900) {
  499. axiscount = 4;
  500. }
  501. if (s.width > 600 && s.width < 700) {
  502. axiscount = 3;
  503. }
  504. if (s.width < 600) {
  505. axiscount = 2;
  506. }
  507. return axiscount;
  508. }
  509. imprimirExcel(String url, String nombre) async {
  510. var t = await SessionStorage().getToken();
  511. Map<String, String> headers = {
  512. 'Authorization': 'Bearer $t',
  513. 'Content-Type': 'application/json', // Puedes ajustar según sea necesario
  514. };
  515. http.Response response = await http.get(
  516. Uri.parse(url),
  517. headers: headers,
  518. );
  519. if (response.statusCode == 200) {
  520. // Obtener el contenido del archivo como Uint8List
  521. Uint8List fileBytes = response.bodyBytes;
  522. if (!kIsWeb) {
  523. // Lógica para dispositivos móviles y escritorio
  524. final directory = await getApplicationDocumentsDirectory();
  525. final path = '${directory.path}/$nombre.xlsx';
  526. final file = File(path);
  527. await file.writeAsBytes(fileBytes);
  528. final Uri fileUri = Uri.file(path);
  529. if (await canLaunchUrl(fileUri)) {
  530. await launchUrl(fileUri);
  531. } else {
  532. throw 'No se pudo abrir el archivo';
  533. }
  534. return; // Retorna después de manejar la lógica de dispositivos móviles
  535. }
  536. // Lógica específica para la web sigue aquí
  537. // Asegúrate de que este código solo se ejecute en la web
  538. if (kIsWeb) {
  539. // Crea y descarga el archivo para la web
  540. final blob = html.Blob([fileBytes]);
  541. final url = html.Url.createObjectUrlFromBlob(blob);
  542. final anchor = html.AnchorElement(href: url)
  543. ..setAttribute('download', '$nombre.xlsx')
  544. ..click();
  545. html.Url.revokeObjectUrl(url);
  546. }
  547. } else {
  548. print(
  549. 'Error al descargar el archivo. Código de estado: ${response.statusCode}');
  550. }
  551. }
  552. imprimirPdf(String url, String nombre) async {
  553. var t = await SessionStorage().getToken();
  554. Map<String, String> headers = {
  555. 'Authorization': 'Bearer $t',
  556. 'Content-Type': 'application/json', // Puedes ajustar según sea necesario
  557. };
  558. http.Response response = await http.get(
  559. Uri.parse(url),
  560. headers: headers,
  561. );
  562. if (response.statusCode == 200) {
  563. // Obtener el contenido del archivo como Uint8List
  564. Uint8List fileBytes = response.bodyBytes;
  565. // Crear un blob con los bytes del archivo
  566. final blob = html.Blob([fileBytes]);
  567. // Crear un objeto URL para el blob
  568. final url = html.Url.createObjectUrlFromBlob(blob);
  569. // Crear un enlace de descarga y hacer clic en él para descargar el archivo
  570. final anchor = html.AnchorElement(href: url)
  571. ..target = 'blank'
  572. ..download =
  573. '$nombre.pdf'; // Ajustar el nombre y la extensión del archivo
  574. anchor.click();
  575. // Liberar el objeto URL
  576. html.Url.revokeObjectUrl(url);
  577. } else {
  578. print(
  579. 'Error al descargar el archivo. Código de estado: ${response.statusCode}');
  580. }
  581. }
  582. Widget usuarioHeader(String correo) {
  583. return Row(
  584. mainAxisAlignment: MainAxisAlignment.center,
  585. crossAxisAlignment: CrossAxisAlignment.center,
  586. children: [
  587. Column(
  588. mainAxisAlignment: MainAxisAlignment.center,
  589. crossAxisAlignment: CrossAxisAlignment.end,
  590. children: [
  591. Text(correo,
  592. style: TextStyle(color: Colors.white),
  593. textAlign: TextAlign.right),
  594. ]),
  595. Text(" "),
  596. CircleAvatar(
  597. child: Icon(Icons.verified_user, color: Colors.white),
  598. backgroundColor: Colors.grey.shade700),
  599. Text(" "),
  600. ]);
  601. }
  602. // Future eliminarMedia(
  603. // BuildContext context, Media m, Function()? confirmacion) async {
  604. // return await showDialog(
  605. // context: context,
  606. // builder: (context) {
  607. // return AlertDialog(
  608. // surfaceTintColor: AppTheme.secondary,
  609. // title: const Text('¿Desea eliminar esta archivo?'),
  610. // actions: [
  611. // TextButton(
  612. // onPressed: () {
  613. // Navigator.pop(context);
  614. // },
  615. // child: const Text('Cancelar'),
  616. // ),
  617. // TextButton(
  618. // onPressed: confirmacion,
  619. // child: const Text(
  620. // 'Sí, estoy seguro',
  621. // style: TextStyle(color: Colors.red),
  622. // ),
  623. // ),
  624. // ],
  625. // );
  626. // },
  627. // );
  628. // }