home_view.dart 8.9 KB

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