// src/screens/VaccinationScreen.js
import React, { useState, useEffect } from 'react';
import {
View,
Text,
StyleSheet,
ScrollView,
TextInput,
TouchableOpacity,
Alert,
Modal,
FlatList,
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import DateTimePicker from '@react-native-community/datetimepicker';
import { executeQuery } from '../database';
// Lista de vacunas comunes
const COMMON_VACCINES = [
'Fiebre Aftosa',
'Brucelosis',
'Carbón',
'Leptospirosis',
'Clostridiales',
'Rabia',
'IBR',
'DVB',
'Parainfluenza',
'Rinotraqueítis',
];
// Lista de responsables
const RESPONSABLES = ['Juan', 'Pedro', 'Carlos', 'Miguel', 'Papá', 'Tú'];
export default function VaccinationScreen({ navigation }) {
const [animalId, setAnimalId] = useState('');
const [vaccineName, setVaccineName] = useState('');
const [date, setDate] = useState(new Date());
const [nextDate, setNextDate] = useState(new Date());
const [responsable, setResponsable] = useState('');
const [observations, setObservations] = useState('');
// Estados para modales
const [showDatePicker, setShowDatePicker] = useState(false);
const [datePickerFor, setDatePickerFor] = useState(''); // 'date' o 'nextDate'
const [showVaccineModal, setShowVaccineModal] = useState(false);
const [showAnimalModal, setShowAnimalModal] = useState(false);
const [showResponsableModal, setShowResponsableModal] = useState(false);
// Lista de animales para búsqueda
const [animals, setAnimals] = useState([]);
const [filteredAnimals, setFilteredAnimals] = useState([]);
// Cargar animales al iniciar
useEffect(() => {
loadAnimals();
}, []);
const loadAnimals = async () => {
try {
const result = await executeQuery(
'SELECT id, nombre, categoria FROM animales WHERE activo = 1 ORDER BY id'
);
const animalsList = [];
for (let i = 0; i < result.rows.length; i++) {
animalsList.push(result.rows.item(i));
}
setAnimals(animalsList);
setFilteredAnimals(animalsList);
} catch (error) {
console.error('Error cargando animales:', error);
}
};
const handleSearchAnimal = (text) => {
setAnimalId(text);
if (text.length > 0) {
const filtered = animals.filter(animal =>
animal.id.toLowerCase().includes(text.toLowerCase()) ||
(animal.nombre && animal.nombre.toLowerCase().includes(text.toLowerCase()))
);
setFilteredAnimals(filtered);
} else {
setFilteredAnimals(animals);
}
};
const handleDateChange = (event, selectedDate) => {
setShowDatePicker(false);
if (selectedDate) {
if (datePickerFor === 'date') {
setDate(selectedDate);
} else {
setNextDate(selectedDate);
}
}
};
const formatDate = (dateObj) => {
return dateObj.toISOString().split('T')[0];
};
const handleSave = async () => {
// Validaciones
if (!animalId.trim()) {
Alert.alert('Error', 'Por favor ingrese el número o lote del animal');
return;
}
if (!vaccineName.trim()) {
Alert.alert('Error', 'Por favor seleccione una vacuna');
return;
}
const vaccinationData = {
id: `vac_${Date.now()}`,
animal_id: animalId.toUpperCase(),
tipo_evento: 'VACUNACION',
producto: vaccineName,
fecha_aplicacion: formatDate(date),
fecha_proxima: formatDate(nextDate),
responsable: responsable || 'No especificado',
observaciones: observations,
};
try {
// Guardar en eventos_sanitarios
await executeQuery(
`INSERT INTO eventos_sanitarios
(id, animal_id, tipo_evento, producto, fecha_aplicacion, fecha_proxima, responsable, observaciones)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
[
vaccinationData.id,
vaccinationData.animal_id,
vaccinationData.tipo_evento,
vaccinationData.producto,
vaccinationData.fecha_aplicacion,
vaccinationData.fecha_proxima,
vaccinationData.responsable,
vaccinationData.observaciones,
]
);
// Crear alerta para próxima vacunación si hay fecha próxima
if (vaccinationData.fecha_proxima) {
const alertId = `alert_${Date.now()}`;
await executeQuery(
`INSERT INTO alertas_pendientes
(id, tipo, animal_id, descripcion, fecha_vencimiento, prioridad)
VALUES (?, ?, ?, ?, ?, ?)`,
[
alertId,
'VACUNACION',
vaccinationData.animal_id,
`Próxima dosis: ${vaccinationData.producto}`,
vaccinationData.fecha_proxima,
2,
]
);
}
Alert.alert(
'¡Éxito!',
`Vacunación registrada correctamente para ${vaccinationData.animal_id}`,
[
{
text: 'Registrar otra',
onPress: () => {
setAnimalId('');
setVaccineName('');
setObservations('');
},
},
{
text: 'Volver al inicio',
onPress: () => navigation.navigate('Home'),
},
]
);
} catch (error) {
console.error('Error guardando vacunación:', error);
Alert.alert('Error', 'No se pudo guardar la vacunación');
}
};
const renderAnimalItem = ({ item }) => (
{
setAnimalId(item.nombre ? `${item.id} - ${item.nombre}` : item.id);
setShowAnimalModal(false);
}}
>
{item.id}
{item.nombre && (
{item.nombre}
)}
{item.categoria}
);
return (
{/* Campo: Animal/Lote */}
Animal o Lote *
setShowAnimalModal(true)}
>
Presione para buscar animal existente o escriba nuevo
{/* Campo: Vacuna */}
Vacuna *
setShowVaccineModal(true)}
>
{/* Campo: Fecha de aplicación */}
Fecha de aplicación
{
setDatePickerFor('date');
setShowDatePicker(true);
}}
>
{/* Campo: Próxima fecha */}
Próxima dosis (opcional)
{
setDatePickerFor('nextDate');
setShowDatePicker(true);
}}
>
El sistema creará una alerta automática
{/* Campo: Responsable */}
Responsable
setShowResponsableModal(true)}
>
{/* Campo: Observaciones */}
Observaciones
{/* Botones de acción */}
navigation.goBack()}
>
CANCELAR
GUARDAR VACUNACIÓN
{/* Recordatorio */}
Este registro quedará guardado en el dispositivo. No se requiere internet.
{/* Modal: Seleccionar animal */}
Seleccionar Animal
setShowAnimalModal(false)}>
item.id}
style={styles.animalList}
/>
{
setShowAnimalModal(false);
// Habilitar edición directa
// (necesitarías un estado adicional para esto)
}}
>
Escribir manualmente
{/* Modal: Seleccionar vacuna */}
Seleccionar Vacuna
setShowVaccineModal(false)}>
(
{
setVaccineName(item);
setShowVaccineModal(false);
}}
>
{item}
)}
keyExtractor={(item) => item}
/>
{
setShowVaccineModal(false);
// Aquí podrías activar un TextInput manual
}}
>
Escribir manualmente
{/* Modal: Seleccionar responsable */}
Seleccionar Responsable
setShowResponsableModal(false)}>
(
{
setResponsable(item);
setShowResponsableModal(false);
}}
>
{item}
)}
keyExtractor={(item) => item}
/>
{
setShowResponsableModal(false);
// Activar TextInput manual
}}
>
Escribir manualmente
{/* Date Picker */}
{showDatePicker && (
)}
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5F5F5',
},
form: {
padding: 16,
},
field: {
marginBottom: 20,
},
label: {
fontSize: 16,
fontWeight: '600',
color: '#333',
marginBottom: 8,
},
input: {
backgroundColor: 'white',
borderWidth: 1,
borderColor: '#DDD',
borderRadius: 8,
paddingHorizontal: 12,
paddingVertical: 12,
fontSize: 16,
flex: 1,
},
inputWithIcon: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'white',
borderWidth: 1,
borderColor: '#DDD',
borderRadius: 8,
paddingHorizontal: 12,
},
textArea: {
minHeight: 80,
textAlignVertical: 'top',
},
helperText: {
fontSize: 12,
color: '#666',
marginTop: 4,
fontStyle: 'italic',
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
marginTop: 24,
marginBottom: 16,
},
cancelButton: {
flex: 1,
backgroundColor: '#F5F5F5',
borderWidth: 1,
borderColor: '#DDD',
borderRadius: 8,
paddingVertical: 14,
alignItems: 'center',
marginRight: 8,
},
cancelButtonText: {
color: '#666',
fontWeight: '600',
fontSize: 16,
},
saveButton: {
flex: 2,
backgroundColor: '#4CAF50',
borderRadius: 8,
paddingVertical: 14,
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'center',
marginLeft: 8,
},
saveButtonText: {
color: 'white',
fontWeight: 'bold',
fontSize: 16,
marginLeft: 8,
},
reminderBox: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#E8F5E9',
padding: 12,
borderRadius: 8,
marginTop: 16,
},
reminderText: {
flex: 1,
fontSize: 14,
color: '#2E7D32',
marginLeft: 12,
},
// Estilos para modales
modalContainer: {
flex: 1,
backgroundColor: 'rgba(0,0,0,0.5)',
justifyContent: 'flex-end',
},
modalContent: {
backgroundColor: 'white',
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
maxHeight: '80%',
},
modalHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
padding: 16,
borderBottomWidth: 1,
borderBottomColor: '#EEE',
},
modalTitle: {
fontSize: 18,
fontWeight: 'bold',
color: '#333',
},
searchInput: {
backgroundColor: '#F5F5F5',
marginHorizontal: 16,
marginVertical: 12,
padding: 12,
borderRadius: 8,
fontSize: 16,
},
animalList: {
maxHeight: 300,
},
animalItem: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 16,
paddingVertical: 12,
borderBottomWidth: 1,
borderBottomColor: '#EEE',
},
animalInfo: {
marginLeft: 12,
},
animalId: {
fontSize: 16,
fontWeight: '600',
color: '#333',
},
animalName: {
fontSize: 14,
color: '#666',
},
animalCategory: {
fontSize: 12,
color: '#999',
},
vaccineItem: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 16,
paddingVertical: 14,
borderBottomWidth: 1,
borderBottomColor: '#EEE',
},
vaccineItemText: {
fontSize: 16,
marginLeft: 12,
color: '#333',
},
responsableItem: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 16,
paddingVertical: 14,
borderBottomWidth: 1,
borderBottomColor: '#EEE',
},
responsableItemText: {
fontSize: 16,
marginLeft: 12,
color: '#333',
},
useTextButton: {
padding: 16,
alignItems: 'center',
borderTopWidth: 1,
borderTopColor: '#EEE',
},
useTextButtonText: {
color: '#2196F3',
fontSize: 16,
fontWeight: '600',
},
});