Ei kuvausta

custom_info_card.dart 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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. imagePath: widget.imagePath,
  45. ),
  46. ),
  47. ),
  48. child: SizedBox(
  49. width: double.infinity,
  50. height: 130,
  51. child: Stack(children: [
  52. Card(
  53. margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
  54. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
  55. color: const Color.fromARGB(255, 254, 242, 221),
  56. child: Padding(
  57. padding: const EdgeInsets.only(right: 8),
  58. child: Row(children: [
  59. Container(
  60. width: 90,
  61. height: 90,
  62. decoration: BoxDecoration(
  63. color: Colors.white,
  64. borderRadius: BorderRadius.circular(36),
  65. ),
  66. child: ClipRRect(
  67. borderRadius: BorderRadius.circular(36),
  68. child: Image.asset(
  69. widget.imagePath,
  70. fit: BoxFit.cover,
  71. width: 90,
  72. height: 90,
  73. ),
  74. ),
  75. ),
  76. const SizedBox(width: 16),
  77. Expanded(
  78. child: Column(
  79. mainAxisAlignment: MainAxisAlignment.center,
  80. crossAxisAlignment: CrossAxisAlignment.start,
  81. children: [
  82. Text(
  83. widget.title,
  84. style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
  85. maxLines: 1,
  86. overflow: TextOverflow.ellipsis,
  87. ),
  88. const SizedBox(height: 4),
  89. Text(
  90. widget.subtitle,
  91. style: TextStyle(fontSize: 14, color: Colors.grey[600]),
  92. maxLines: 2,
  93. overflow: TextOverflow.ellipsis,
  94. ),
  95. const SizedBox(height: 4),
  96. Text(
  97. widget.categoria,
  98. style: TextStyle(
  99. fontSize: 12,
  100. color: _getCategoryColor(widget.categoria),
  101. fontWeight: FontWeight.bold,
  102. ),
  103. ),
  104. ],
  105. ),
  106. ),
  107. ]),
  108. ),
  109. ),
  110. Positioned(
  111. top: 12,
  112. right: 28,
  113. child: IconButton(
  114. icon: Icon(
  115. _isFavorite ? Icons.favorite : Icons.favorite_border,
  116. color: _isFavorite ? Colors.red : Colors.grey[400],
  117. ),
  118. onPressed: _toggleFavorite,
  119. ),
  120. ),
  121. ]),
  122. ),
  123. );
  124. Color _getCategoryColor(String categoria) {
  125. switch (categoria) {
  126. case 'Actividades': return Colors.blue;
  127. case 'Noticias UPR': return Colors.green;
  128. case 'Fechas Importantes': return Colors.purple;
  129. default: return Colors.grey;
  130. }
  131. }
  132. }