home_view.dart 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. import 'package:flutter/cupertino.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_linkify/flutter_linkify.dart';
  4. import 'package:provider/provider.dart';
  5. import 'package:sis_flutter/data/session/session_storage.dart';
  6. import 'package:sis_flutter/models/usuario_model.dart';
  7. import 'package:sis_flutter/services/usuario_session_service.dart';
  8. import 'package:sis_flutter/viewmodels/login_view_model.dart';
  9. import 'package:sis_flutter/viewmodels/actividad_view_model.dart';
  10. import 'package:sis_flutter/viewmodels/viewmodels.dart';
  11. import 'package:sis_flutter/widgets/app_dropdown_search.dart';
  12. import 'package:sis_flutter/widgets/app_loader.dart';
  13. import 'package:url_launcher/url_launcher.dart';
  14. import 'package:url_launcher/url_launcher_string.dart';
  15. import '../../models/actividad_model.dart';
  16. import '../../themes/themes.dart';
  17. class HomeBody extends StatefulWidget {
  18. const HomeBody({
  19. super.key,
  20. });
  21. @override
  22. State<HomeBody> createState() => _HomeBodyState();
  23. }
  24. class _HomeBodyState extends State<HomeBody> {
  25. Usuario? _usuario;
  26. List<Usuario> _usuariosList = [];
  27. TextEditingController _usuariosController = TextEditingController();
  28. @override
  29. void initState() {
  30. super.initState();
  31. final idUsuario =
  32. Provider.of<LoginViewModel>(context, listen: false).idUsuario;
  33. _fetchActividad(idUsuario);
  34. _loadUsuarios();
  35. }
  36. @override
  37. void dispose() {
  38. super.dispose();
  39. }
  40. Future<void> _loadUsuarios() async {
  41. final usuario = await getUsuarioFromSessionStorage();
  42. final idUsuario = usuario.id;
  43. final usuariosList =
  44. await Provider.of<UsuariosViewModel>(context, listen: false)
  45. .fetchUsuarios(idUsuario, 20, 0);
  46. setState(() {
  47. _usuario = usuario;
  48. _usuariosList = usuariosList;
  49. });
  50. }
  51. Future _fetchActividad(String? idUsuario) async {
  52. idUsuario ??= Provider.of<LoginViewModel>(context, listen: false).idUsuario;
  53. Provider.of<PrioridadesViewMode>(context, listen: false)
  54. .fetchActividad(idUsuario);
  55. }
  56. @override
  57. Widget build(BuildContext context) {
  58. var vm = Provider.of<PrioridadesViewMode>(context);
  59. var actividadDetalle = vm.actividadList;
  60. var usuario = Provider.of<LoginViewModel>(context, listen: false);
  61. final height = MediaQuery.of(context).size.height;
  62. return SafeArea(
  63. child: SingleChildScrollView(
  64. child: Column(
  65. children: [
  66. Container(
  67. padding: const EdgeInsets.all(10),
  68. decoration: const BoxDecoration(
  69. color: Colors.white,
  70. borderRadius:
  71. BorderRadius.vertical(bottom: Radius.circular(15))),
  72. child: Padding(
  73. padding: const EdgeInsets.all(8.0),
  74. child: Column(
  75. mainAxisAlignment: MainAxisAlignment.start,
  76. crossAxisAlignment: CrossAxisAlignment.start,
  77. children: [
  78. const Text("Bienvenido ",
  79. style: TextStyle(
  80. fontSize: 25,
  81. )),
  82. Text(_usuario?.name! ?? "Cargando...",
  83. style: const TextStyle(
  84. fontSize: 45,
  85. fontWeight: FontWeight.bold,
  86. height: -1)),
  87. const SizedBox(height: 10),
  88. Container(
  89. decoration: BoxDecoration(
  90. borderRadius: BorderRadius.circular(10),
  91. ),
  92. child: AppDropdownSearch<Usuario>(
  93. controller: _usuariosController,
  94. itemAsString: (u) => u.name!,
  95. selectedItem: _usuario,
  96. compareFn: (item1, item2) {
  97. return item1.id == item2.id;
  98. },
  99. onChanged: (selectedUsuario) {
  100. if (selectedUsuario != null) {
  101. _fetchActividad(selectedUsuario.id);
  102. }
  103. },
  104. items: _usuariosList,
  105. etiqueta: "Actividades",
  106. )),
  107. ]),
  108. ),
  109. ),
  110. const SizedBox(height: 10),
  111. SizedBox(
  112. width: double.infinity,
  113. height: height * 0.9,
  114. child: ListView.builder(
  115. itemCount: actividadDetalle.length,
  116. itemBuilder: (context, index) {
  117. var actividad = actividadDetalle[index];
  118. return _infoCard(actividad);
  119. }),
  120. ),
  121. ],
  122. )),
  123. );
  124. }
  125. Card _infoCard(Actividad actividad) {
  126. List<Widget> tareaWidgets = [];
  127. for (var tarea in actividad.tareas!) {
  128. // final posicion = (actividad.tareas!.indexOf(tarea) + 1).toString();
  129. final Color color = getPrioridadColors(tarea.prioridad!);
  130. tareaWidgets.add(
  131. Column(
  132. children: [
  133. const FractionallySizedBox(
  134. widthFactor: 0.75, // 80% of the parent width
  135. child: Divider(
  136. color: Colors.grey,
  137. ),
  138. ),
  139. ListTile(
  140. leading: CircleAvatar(
  141. backgroundColor: color,
  142. child: Text(tarea.prioridad.toString()),
  143. ),
  144. title: Linkify(
  145. text: tarea.contenido!,
  146. onOpen: (link) async {
  147. if (await canLaunchUrlString(link.url)) {
  148. await launchUrlString(link.url);
  149. } else {
  150. throw CupertinoAlertDialog(
  151. title: const Text("Error"),
  152. content: const Text("No se puede abrir el link"),
  153. actions: [
  154. CupertinoDialogAction(
  155. child: const Text("OK"),
  156. onPressed: () {
  157. Navigator.of(context).pop();
  158. },
  159. )
  160. ],
  161. );
  162. }
  163. }),
  164. subtitle: Text(tarea.urgencia!),
  165. ),
  166. ],
  167. ),
  168. );
  169. }
  170. return Card(
  171. margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 8),
  172. elevation: 4,
  173. shape: BeveledRectangleBorder(borderRadius: BorderRadius.circular(6.0)),
  174. child: ExpansionTile(
  175. backgroundColor: Colors.white24,
  176. leading: SizedBox(
  177. width: 60,
  178. child: Row(
  179. mainAxisAlignment: MainAxisAlignment.spaceAround,
  180. crossAxisAlignment: CrossAxisAlignment.center,
  181. children: [
  182. Text(
  183. actividad.prioridad!.toString(),
  184. style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
  185. ),
  186. const Icon(Icons.local_fire_department_rounded),
  187. ],
  188. ),
  189. ),
  190. title: Text(
  191. "${actividad.nombreProyecto!} - ${actividad.nombre!} ",
  192. style: const TextStyle(
  193. fontSize: 20, fontWeight: FontWeight.bold, color: Colors.black54),
  194. strutStyle: const StrutStyle(fontWeight: FontWeight.bold),
  195. ),
  196. trailing: const Icon(Icons.arrow_drop_down),
  197. subtitle: Row(
  198. mainAxisAlignment: MainAxisAlignment.start,
  199. crossAxisAlignment: CrossAxisAlignment.center,
  200. children: [
  201. Text(actividad.avance!),
  202. const SizedBox(width: 10),
  203. Expanded(
  204. child: ClipRRect(
  205. borderRadius: const BorderRadius.all(Radius.circular(10)),
  206. child: LinearProgressIndicator(
  207. value: double.parse(actividad.avance!) / 100,
  208. backgroundColor: Colors.grey,
  209. valueColor: const AlwaysStoppedAnimation(AppTheme.primary)),
  210. ),
  211. ),
  212. ],
  213. ),
  214. children: tareaWidgets,
  215. ),
  216. );
  217. }
  218. Color getPrioridadColors(tarea) {
  219. return tarea == 1
  220. ? Colors.red
  221. : tarea == 2
  222. ? Color.fromARGB(255, 253, 211, 1)
  223. : tarea == 3
  224. ? Colors.green
  225. : tarea == 4
  226. ? Colors.purple
  227. : Colors.grey;
  228. }
  229. }