import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; import 'custom_info_card.dart'; import 'favorites_page.dart'; // Nuevo import void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); static const Color primaryColor = Color.fromARGB(255, 254, 100, 91); static const Color secondaryColor = Colors.orange; @override Widget build(BuildContext context) { return MaterialApp( title: 'Custom Info Cards', theme: ThemeData( primaryColor: primaryColor, appBarTheme: const AppBarTheme( backgroundColor: primaryColor, elevation: 0, ), ), home: const HomePage(), debugShowCheckedModeBanner: false, ); } } class HomePage extends StatefulWidget { const HomePage({super.key}); @override State createState() => _HomePageState(); } class _HomePageState extends State { List> infoCards = []; List> favoriteCards = []; int _currentIndex = 0; static const String googleSheetUrl = 'https://script.google.com/macros/s/AKfycbw1htmk7rlwLMOkOrpZ9ED-7ErWgMlYNtLKxoQ9QO-FopqTAhJuQkR7Gs1LxTJakbMT/exec'; @override void initState() { super.initState(); _loadInfoCards(); } Future _loadInfoCards() async { final prefs = await SharedPreferences.getInstance(); String? savedData = prefs.getString('infoCardsData'); setState(() { infoCards = savedData != null ? List>.from(json.decode(savedData)) : _defaultInfoCards(); }); await _fetchUpdatedData(); } Future _loadFavorites() async { final prefs = await SharedPreferences.getInstance(); final allKeys = prefs.getKeys().where((key) => key.startsWith('fav_')).toList(); setState(() { favoriteCards = infoCards.where((card) { return allKeys.contains('fav_${card['title']}') && (prefs.getBool('fav_${card['title']}') ?? false); }).toList(); }); } List> _defaultInfoCards() { return [ { 'image': 'assets/icons/icono1.jpg', 'title': 'Tutorias de programación', 'subtitle': '8:00am a 11:30am En biblioteca Lázaro', 'texto': 'Detalles completos sobre tutorías...', }, ]; } Future _fetchUpdatedData() async { try { final response = await http.get(Uri.parse(googleSheetUrl)); if (response.statusCode == 200) { final List> newData = List>.from(json.decode(response.body)); if (json.encode(newData) != json.encode(infoCards)) { setState(() => infoCards = newData); final prefs = await SharedPreferences.getInstance(); await prefs.setString('infoCardsData', json.encode(newData)); } } } catch (e) { if (kDebugMode) print('Error fetching data: $e'); } } @override Widget build(BuildContext context) { return Scaffold( appBar: _currentIndex == 0 ? AppBar( flexibleSpace: Padding( padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top - 20), child: Image.asset( 'assets/header_image.png', fit: BoxFit.cover, ), ), toolbarHeight: MediaQuery.of(context).size.height * 0.19, ) : null, body: Container( decoration: const BoxDecoration( gradient: LinearGradient( colors: [MyApp.primaryColor, MyApp.secondaryColor], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), child: _currentIndex == 0 ? RefreshIndicator( onRefresh: _fetchUpdatedData, child: _buildMainContent(), ) : FavoritesPage(favoriteCards: favoriteCards), ), bottomNavigationBar: BottomNavigationBar( currentIndex: _currentIndex, selectedItemColor: Colors.white, unselectedItemColor: Colors.white70, backgroundColor: MyApp.primaryColor, items: const [ BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Inicio'), BottomNavigationBarItem(icon: Icon(Icons.favorite), label: 'Favoritos'), ], onTap: (index) { if (index == 1) _loadFavorites(); setState(() => _currentIndex = index); }, ), ); } Widget _buildMainContent() { return SafeArea( child: Column( children: [ Expanded( child: ListView.builder( itemCount: infoCards.isEmpty ? 1 : infoCards.length, itemBuilder: (context, index) { if (infoCards.isEmpty) { return _buildErrorWidget(); } final card = infoCards[index]; return CustomInfoCard( imagePath: "assets/icons/${card['image']}", title: card['title'], subtitle: card['subtitle'], texto: card['texto'], ); }, ), ), ], ), ); } Widget _buildErrorWidget() { return Card( margin: const EdgeInsets.all(16), color: Colors.white, child: Padding( padding: const EdgeInsets.all(16), child: Column( children: [ const Icon(Icons.warning_amber_rounded, size: 48, color: Colors.orange), const SizedBox(height: 16), const Text('No se pudo cargar la información', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), const SizedBox(height: 8), const Text('Desliza hacia abajo para intentar de nuevo', textAlign: TextAlign.center), const SizedBox(height: 16), ElevatedButton( onPressed: _fetchUpdatedData, style: ElevatedButton.styleFrom(backgroundColor: MyApp.primaryColor), child: const Text('Reintentar'), ), ], ), ), ); } }