Nenhuma descrição

custom_info_card.dart 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import 'package:flutter/material.dart';
  2. import 'package:shared_preferences/shared_preferences.dart';
  3. import 'detail_page.dart';
  4. class CustomInfoCard extends StatefulWidget {
  5. final String imagePath, title, subtitle, texto, categoria;
  6. final bool isFavorite;
  7. const CustomInfoCard({
  8. super.key,
  9. required this.imagePath,
  10. required this.title,
  11. required this.subtitle,
  12. required this.texto,
  13. required this.categoria,
  14. this.isFavorite = false,
  15. });
  16. @override
  17. State<CustomInfoCard> createState() => _CustomInfoCardState();
  18. }
  19. class _CustomInfoCardState extends State<CustomInfoCard> {
  20. late bool _isFavorite;
  21. @override
  22. void initState() {
  23. super.initState();
  24. _isFavorite = widget.isFavorite;
  25. if (!widget.isFavorite) _loadFavorite();
  26. }
  27. Future<void> _loadFavorite() async {
  28. final prefs = await SharedPreferences.getInstance();
  29. if (mounted) setState(() => _isFavorite = prefs.getBool('fav_${widget.title}') ?? false);
  30. }
  31. Future<void> _toggleFavorite() async {
  32. setState(() => _isFavorite = !_isFavorite);
  33. (await SharedPreferences.getInstance()).setBool('fav_${widget.title}', _isFavorite);
  34. }
  35. @override
  36. Widget build(BuildContext context) => GestureDetector(
  37. onTap: () => Navigator.push(
  38. context,
  39. MaterialPageRoute(
  40. builder: (_) => DetailPage(
  41. title: widget.title,
  42. texto: widget.texto,
  43. categoria: widget.categoria,
  44. ),
  45. ),
  46. ),
  47. child: SizedBox(
  48. width: double.infinity,
  49. height: 130,
  50. child: Stack(children: [
  51. Card(
  52. margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
  53. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
  54. color: const Color.fromARGB(255, 254, 242, 221),
  55. child: Padding(
  56. padding: const EdgeInsets.only(right: 8),
  57. child: Row(children: [
  58. Container(
  59. width: 90,
  60. height: 90,
  61. decoration: BoxDecoration(
  62. color: Colors.white,
  63. borderRadius: BorderRadius.circular(36),
  64. ),
  65. child: ClipRRect(
  66. borderRadius: BorderRadius.circular(36),
  67. child: Image.asset(
  68. widget.imagePath,
  69. fit: BoxFit.cover,
  70. width: 90,
  71. height: 90,
  72. ),
  73. ),
  74. ),
  75. const SizedBox(width: 16),
  76. Expanded(
  77. child: Column(
  78. mainAxisAlignment: MainAxisAlignment.center,
  79. crossAxisAlignment: CrossAxisAlignment.start,
  80. children: [
  81. Text(
  82. widget.title,
  83. style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
  84. maxLines: 1,
  85. overflow: TextOverflow.ellipsis,
  86. ),
  87. const SizedBox(height: 4),
  88. Text(
  89. widget.subtitle,
  90. style: TextStyle(fontSize: 14, color: Colors.grey[600]),
  91. maxLines: 2,
  92. overflow: TextOverflow.ellipsis,
  93. ),
  94. const SizedBox(height: 4),
  95. Text(
  96. widget.categoria,
  97. style: TextStyle(
  98. fontSize: 12,
  99. color: _getCategoryColor(widget.categoria),
  100. fontWeight: FontWeight.bold,
  101. ),
  102. ),
  103. ],
  104. ),
  105. ),
  106. ]),
  107. ),
  108. ),
  109. Positioned(
  110. top: 12,
  111. right: 28,
  112. child: IconButton(
  113. icon: Icon(
  114. _isFavorite ? Icons.favorite : Icons.favorite_border,
  115. color: _isFavorite ? Colors.red : Colors.grey[400],
  116. ),
  117. onPressed: _toggleFavorite,
  118. ),
  119. ),
  120. ]),
  121. ),
  122. );
  123. Color _getCategoryColor(String categoria) {
  124. switch (categoria) {
  125. case 'Actividades':
  126. return Colors.blue;
  127. case 'Noticias UPR':
  128. return Colors.green;
  129. case 'Fechas Importantes':
  130. return Colors.purple;
  131. default:
  132. return Colors.grey;
  133. }
  134. }
  135. }