feeding_page.dart¶
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class FeedingPage extends StatefulWidget {
final String aquariumId;
const FeedingPage({super.key, required this.aquariumId});
@override
State<FeedingPage> createState() => _FeedingPageState();
}
class _FeedingPageState extends State<FeedingPage> {
bool _isAutoFeedOn = true;
List<TimeOfDay> _feedTimes = [];
bool _loading = true;
late DocumentReference _configRef;
@override
void initState() {
super.initState();
_configRef = FirebaseFirestore.instance
.collection('acuarios')
.doc(widget.aquariumId)
.collection('data')
.doc('config');
_cargarDatos();
}
void _cargarDatos() async {
try {
DocumentSnapshot doc = await _configRef.get();
if (doc.exists) {
Map<String, dynamic> data = doc.data() as Map<String, dynamic>;
bool estadoSwitch = data['sistema_alimentacion_on'] ?? true;
List<dynamic> horasString = data['horarios_comida'] ?? [];
setState(() {
_isAutoFeedOn = estadoSwitch;
_feedTimes = horasString.map((s) {
final parts = s.split(":");
return TimeOfDay(hour: int.parse(parts[0]), minute: int.parse(parts[1]));
}).toList();
_loading = false;
});
} else {
setState(() => _loading = false);
}
} catch (e) { setState(() => _loading = false); }
}
void _guardarCambios() async {
List<String> horasString = _feedTimes.map((t) {
String h = t.hour.toString().padLeft(2, '0');
String m = t.minute.toString().padLeft(2, '0');
return "$h:$m";
}).toList();
await _configRef.update({
'horarios_comida': horasString,
'sistema_alimentacion_on': _isAutoFeedOn
});
}
Future<void> _addTime() async {
final TimeOfDay? newTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (context, child) {
return Theme(
data: ThemeData.dark().copyWith(
colorScheme: const ColorScheme.dark(
primary: Color(0xFFFF5400),
onPrimary: Colors.white,
surface: Color(0xFF001B2E),
),
),
child: child!,
);
},
);
if (newTime != null) {
setState(() {
_feedTimes.add(newTime);
_feedTimes.sort((a, b) => (a.hour * 60 + a.minute).compareTo(b.hour * 60 + b.minute));
});
_guardarCambios();
}
}
void _removeTime(int index) {
setState(() {
_feedTimes.removeAt(index);
});
_guardarCambios();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Alimentación', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white)),
backgroundColor: Colors.transparent,
iconTheme: const IconThemeData(color: Colors.white),
elevation: 0,
),
body: _loading
? const Center(child: CircularProgressIndicator(color: Color(0xFFFF5400)))
: SingleChildScrollView(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
color: _isAutoFeedOn ? const Color(0xFFFF5400) : Colors.grey.shade800,
borderRadius: BorderRadius.circular(20),
border: Border.all(color: Colors.black, width: 3),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.5), blurRadius: 10, offset: const Offset(0, 5))],
),
child: SwitchListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
title: Text(_isAutoFeedOn ? 'Dispensador ACTIVO' : 'Dispensador APAGADO', style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w900, fontSize: 20)),
subtitle: Text(_isAutoFeedOn ? 'El sistema alimentará a las horas indicadas.' : 'El sistema NO alimentará.', style: TextStyle(color: Colors.white.withOpacity(0.8), fontSize: 12)),
activeColor: Colors.white,
activeTrackColor: Colors.black26,
value: _isAutoFeedOn,
onChanged: (bool value) {
setState(() => _isAutoFeedOn = value);
_guardarCambios();
},
secondary: const Icon(Icons.set_meal, color: Colors.white, size: 30),
),
),
const SizedBox(height: 30),
Opacity(
opacity: _isAutoFeedOn ? 1.0 : 0.5,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('Horarios Programados', style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 15),
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: _feedTimes.length,
itemBuilder: (context, index) {
final time = _feedTimes[index];
return Container(
margin: const EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(15), border: Border.all(color: const Color(0xFFFF5400), width: 3)),
child: ListTile(
leading: const Icon(Icons.access_time_filled, color: Colors.black87),
title: Text(time.format(context), style: const TextStyle(color: Colors.black87, fontSize: 20, fontWeight: FontWeight.bold)),
trailing: IconButton(
icon: const Icon(Icons.delete, color: Color(0xFFD32F2F)),
onPressed: _isAutoFeedOn ? () => _removeTime(index) : null,
),
),
);
},
),
const SizedBox(height: 20),
Center(
child: ElevatedButton.icon(
onPressed: _isAutoFeedOn ? _addTime : null,
style: ElevatedButton.styleFrom(backgroundColor: const Color(0xFFFF5400), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 15)),
icon: const Icon(Icons.add_alarm),
label: const Text('Agregar Horario', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16)),
),
),
],
),
)
],
),
),
);
}
}