Project

General

Profile


history_page.dart feeding_page.dart connection_page.dart config_page.dart

home_page.dart


import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'config_page.dart';
import 'feeding_page.dart';
import 'history_page.dart'; 

class SaveNemoHomePage extends StatefulWidget {
  final String aquariumId; 

  const SaveNemoHomePage({super.key, required this.aquariumId});

  @override
  State<SaveNemoHomePage> createState() => _SaveNemoHomePageState();
}

class _SaveNemoHomePageState extends State<SaveNemoHomePage> {
  late Stream<DocumentSnapshot> _sensorStream;
  String _selectedFish = 'Cargando...';

  @override
  void initState() {
    super.initState();
    _sensorStream = FirebaseFirestore.instance
        .collection('acuarios')
        .doc(widget.aquariumId)
        .collection('data')
        .doc('estado')
        .snapshots();
  }

  void _onTapNavigation(int index) {
    if (index == 0) {
      // Alimentación
      Navigator.push(
        context, 
        MaterialPageRoute(builder: (context) => FeedingPage(aquariumId: widget.aquariumId))
      );
    } else if (index == 1) {
      // Alertas (Historial)
      Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => HistoryPage(aquariumId: widget.aquariumId),
        ),
      );
    } else if (index == 2) {
      // Configuración
      Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => ConfigPage(
            aquariumId: widget.aquariumId, 
            onFishSelected: (name, params) {}, 
            currentFish: _selectedFish,
          ),
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Column(
          children: [
            const Text('SaveNemo', 
              style: TextStyle(fontWeight: FontWeight.w900, letterSpacing: 1.2, color: Colors.white)),
            Text("ID: ${widget.aquariumId}", 
              style: const TextStyle(fontSize: 12, color: Colors.white54, letterSpacing: 1.0)), 
          ],
        ),
        centerTitle: true,
        backgroundColor: Colors.transparent,
        elevation: 0,
        iconTheme: const IconThemeData(color: Colors.white),
      ),

      body: StreamBuilder<DocumentSnapshot>(
        stream: _sensorStream,
        builder: (context, snapshot) {
          if (snapshot.hasError) return const Center(child: Text("Error de conexión", style: TextStyle(color: Colors.white)));
          if (snapshot.connectionState == ConnectionState.waiting) return const Center(child: CircularProgressIndicator(color: Color(0xFFFF5400)));

          Map<String, dynamic> data = snapshot.data!.data() as Map<String, dynamic>? ?? {};

          double currentTemp = (data['temp_actual'] ?? 0.0).toDouble();
          double currentPh = (data['ph_actual'] ?? 7.0).toDouble();
          int currentLight = (data['luz_actual'] ?? 0).toInt();
          int currentWater = (data['agua_nivel'] ?? 0).toInt();

          List<dynamic> alertas = data['alertas'] ?? []; 
          String alertasTexto = alertas.toString(); 
          bool hayProblemas = alertas.isNotEmpty;

          return Column(
            children: [
              Expanded(
                child: SingleChildScrollView(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    children: <Widget>[
                      // TARJETA TEMPERATURA
                      _buildNemoCard(
                        context,
                        icon: Icons.thermostat_rounded,
                        value: '${currentTemp.toStringAsFixed(1)}°C',
                        label: 'Temperatura',
                        alert: alertasTexto.contains("Temp") || alertasTexto.contains("T."), 
                        alertText: "Fuera de Rango",
                      ),
                      const SizedBox(height: 20),

                      // TARJETA PH
                      _buildNemoCard(
                        context,
                        customIcon: Container(
                          alignment: Alignment.center,
                          decoration: BoxDecoration(shape: BoxShape.circle, border: Border.all(color: Colors.black87, width: 2.5)),
                          width: 50, height: 50,
                          child: const Text('pH', style: TextStyle(fontSize: 20, fontWeight: FontWeight.w900, color: Colors.black87)),
                        ),
                        value: currentPh.toStringAsFixed(1),
                        label: 'pH Actual',
                        alert: alertasTexto.contains("pH"),
                        alertText: "Peligro Químico",
                      ),
                      const SizedBox(height: 20),

                      // TARJETA LUZ
                      _buildNemoCard(
                        context,
                        icon: Icons.lightbulb_circle,
                        value: '$currentLight%',
                        label: 'Iluminación',
                        alert: alertasTexto.contains("Luz") || alertasTexto.contains("Iluminación"),
                        alertText: "Problema Luz",
                      ),
                      const SizedBox(height: 20),

                      // TARJETA AGUA
                      _buildNemoCard(
                        context,
                        icon: Icons.waves, 
                        value: '$currentWater%',
                        label: 'Nivel Agua',
                        alert: alertasTexto.contains("Agua"),
                        alertText: "Rellenar Tanque",
                      ),
                    ],
                  ),
                ),
              ),

              // BARRA INFERIOR (CON ALERTAS)
              Container(
                decoration: const BoxDecoration(
                  border: Border(top: BorderSide(color: Colors.white24, width: 0.5))
                ),
                child: BottomNavigationBar(
                  backgroundColor: const Color(0xFF00101C),
                  selectedItemColor: Colors.white,
                  unselectedItemColor: Colors.white54,
                  showSelectedLabels: true,
                  showUnselectedLabels: true,
                  type: BottomNavigationBarType.fixed,
                  onTap: _onTapNavigation,
                  items: <BottomNavigationBarItem>[
                    const BottomNavigationBarItem(
                      icon: Icon(Icons.set_meal_rounded, color: Color(0xFFFF5400)), 
                      label: 'Alimentación'
                    ),

                    // CAMPANA DE ALERTAS (Se marca si hay problemas)
                    BottomNavigationBarItem(
                      icon: Stack(
                        children: [
                          Icon(Icons.notifications, 
                            color: hayProblemas ? Colors.redAccent : Colors.white
                          ),
                          if (hayProblemas)
                            Positioned(
                              right: 0, top: 0,
                              child: Container(
                                padding: const EdgeInsets.all(2),
                                decoration: const BoxDecoration(color: Colors.red, shape: BoxShape.circle),
                                constraints: const BoxConstraints(minWidth: 10, minHeight: 10),
                              ),
                            )
                        ],
                      ),
                      label: 'Alertas',
                    ),

                    const BottomNavigationBarItem(
                      icon: Icon(Icons.settings_rounded, color: Color(0xFFFF5400)), 
                      label: 'Configuración'
                    ),
                  ],
                ),
              ),
            ],
          );
        }
      ),
    );
  }

  Widget _buildNemoCard(BuildContext context, {IconData? icon, Widget? customIcon, required String value, required String label, bool alert = false, String? alertText}) {
    Color mainColor = alert ? const Color(0xFFD32F2F) : const Color(0xFFFF5400); 
    Color stripeColor = Colors.white;
    Color borderColor = Colors.black;

    return AnimatedContainer(
      duration: const Duration(milliseconds: 500),
      height: 100,
      decoration: BoxDecoration(
        color: mainColor,
        borderRadius: BorderRadius.circular(20),
        boxShadow: [BoxShadow(color: alert ? Colors.red.withOpacity(0.6) : Colors.black.withOpacity(0.5), blurRadius: alert ? 20 : 10, offset: const Offset(0, 5))],
        gradient: LinearGradient(
          colors: alert ? [Colors.red.shade900, Colors.red.shade600] : [const Color(0xFFFF5400), const Color(0xFFFF8E00)],
          begin: Alignment.topLeft, end: Alignment.bottomRight,
        ),
      ),
      child: Row(
        children: [
          Container(
            width: 90,
            decoration: BoxDecoration(
              color: stripeColor,
              borderRadius: const BorderRadius.only(topLeft: Radius.circular(20), bottomLeft: Radius.circular(20)),
              border: Border(right: BorderSide(color: borderColor, width: 6)),
            ),
            child: Center(child: customIcon ?? Icon(icon, size: 40, color: Colors.black87)),
          ),
          Expanded(
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(value, style: const TextStyle(fontSize: 34, fontWeight: FontWeight.w900, color: Colors.white, height: 1.0, shadows: [Shadow(color: Colors.black45, offset: Offset(1,1), blurRadius: 2)])),
                  Text(alert ? ' $alertText' : label, style: TextStyle(fontSize: alert ? 14 : 16, fontWeight: FontWeight.bold, color: alert ? Colors.white : Colors.black.withOpacity(0.4))),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}