diff --git a/frontend-mobile/app/pharmacy/[id].tsx b/frontend-mobile/app/pharmacy/[id].tsx new file mode 100644 index 0000000..03c8d06 --- /dev/null +++ b/frontend-mobile/app/pharmacy/[id].tsx @@ -0,0 +1,260 @@ +import React, { useEffect, useState } from 'react'; +import { View, Text, ScrollView, StyleSheet, TouchableOpacity, Linking } from 'react-native'; +import { useLocalSearchParams, useRouter } from 'expo-router'; +import { Ionicons } from '@expo/vector-icons'; +import MapView, { Marker } from 'react-native-maps'; +import { getPharmacy, getPharmacyMedicines } from '../../services/pharmacies'; +import { LoadingSpinner } from '../../components/LoadingSpinner'; +import { colors, spacing, borderRadius } from '../../constants/theme'; +import { Pharmacy, PharmacyMedicine } from '../../types'; + +export default function PharmacyDetailScreen() { + const { id } = useLocalSearchParams<{ id: string }>(); + const router = useRouter(); + const [pharmacy, setPharmacy] = useState(null); + const [medicines, setMedicines] = useState([]); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + if (!id) return; + + const fetchPharmacy = async () => { + try { + const [pharmData, medData] = await Promise.all([ + getPharmacy(Number(id)), + getPharmacyMedicines(Number(id)), + ]); + setPharmacy(pharmData); + setMedicines(medData as PharmacyMedicine[]); + } catch (error) { + console.error('Error fetching pharmacy:', error); + } finally { + setIsLoading(false); + } + }; + + fetchPharmacy(); + }, [id]); + + const handleCall = () => { + if (pharmacy?.phone) { + Linking.openURL(`tel:${pharmacy.phone}`); + } + }; + + const handleDirections = () => { + if (pharmacy) { + const url = `https://www.google.com/maps/dir/?api=1&destination=${pharmacy.latitude},${pharmacy.longitude}`; + Linking.openURL(url); + } + }; + + if (isLoading) { + return ; + } + + if (!pharmacy) { + return ( + + Farmacia no encontrada + + ); + } + + return ( + + + {pharmacy.name} + + + + + + Llamar + + + + + Cómo llegar + + + + + + + {pharmacy.address} + + + {pharmacy.phone && ( + + + {pharmacy.phone} + + )} + + + + + + + + + + + Medicamentos ({medicines.length}) + + + {medicines.length === 0 ? ( + No hay medicamentos disponibles + ) : ( + medicines.map((med) => ( + router.push(`/medicine/${med.medicine_nregistro}`)} + > + + {med.medicine_name} + Reg: {med.medicine_nregistro} + + + {med.price.toFixed(2)} € + Stock: {med.stock} + + + )) + )} + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: colors.background, + }, + header: { + padding: spacing.md, + backgroundColor: colors.card, + }, + name: { + fontSize: 22, + fontWeight: 'bold', + color: colors.text, + }, + actionsRow: { + flexDirection: 'row', + justifyContent: 'space-around', + padding: spacing.md, + backgroundColor: colors.card, + borderBottomWidth: 1, + borderBottomColor: colors.separator, + }, + actionButton: { + flexDirection: 'row', + alignItems: 'center', + padding: spacing.sm, + }, + actionText: { + marginLeft: spacing.xs, + color: colors.primary, + fontWeight: '500', + }, + infoSection: { + padding: spacing.md, + backgroundColor: colors.card, + marginTop: spacing.sm, + }, + infoRow: { + flexDirection: 'row', + alignItems: 'flex-start', + marginBottom: spacing.sm, + }, + infoText: { + flex: 1, + marginLeft: spacing.sm, + fontSize: 16, + color: colors.text, + }, + mapContainer: { + height: 200, + marginTop: spacing.sm, + }, + map: { + flex: 1, + }, + medicinesSection: { + marginTop: spacing.sm, + padding: spacing.md, + }, + sectionTitle: { + fontSize: 18, + fontWeight: '600', + color: colors.text, + marginBottom: spacing.md, + }, + noMedicines: { + color: colors.textSecondary, + textAlign: 'center', + padding: spacing.xl, + }, + medicineCard: { + flexDirection: 'row', + justifyContent: 'space-between', + backgroundColor: colors.card, + borderRadius: borderRadius.md, + padding: spacing.md, + marginBottom: spacing.sm, + }, + medicineInfo: { + flex: 1, + }, + medicineName: { + fontSize: 16, + fontWeight: '500', + color: colors.text, + }, + medicineNregistro: { + fontSize: 12, + color: colors.textSecondary, + marginTop: spacing.xs, + }, + medicineStock: { + alignItems: 'flex-end', + }, + price: { + fontSize: 16, + fontWeight: '600', + color: colors.primary, + }, + stock: { + fontSize: 12, + color: colors.textSecondary, + marginTop: spacing.xs, + }, + errorContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + errorText: { + fontSize: 16, + color: colors.textSecondary, + }, +});