diff --git a/frontend-mobile/app/medicine/[id].tsx b/frontend-mobile/app/medicine/[id].tsx new file mode 100644 index 0000000..84d0aa1 --- /dev/null +++ b/frontend-mobile/app/medicine/[id].tsx @@ -0,0 +1,205 @@ +import React, { useEffect, useState } from 'react'; +import { View, Text, ScrollView, StyleSheet, TouchableOpacity } from 'react-native'; +import { useLocalSearchParams, useRouter } from 'expo-router'; +import { getMedicine, getMedicinePharmacies } from '../../services/medicines'; +import { StockBadge } from '../../components/StockBadge'; +import { LoadingSpinner } from '../../components/LoadingSpinner'; +import { colors, spacing, borderRadius } from '../../constants/theme'; +import { Medicine, PharmacyMedicine } from '../../types'; + +export default function MedicineDetailScreen() { + const { id } = useLocalSearchParams<{ id: string }>(); + const router = useRouter(); + const [medicine, setMedicine] = useState(null); + const [pharmacies, setPharmacies] = useState([]); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + if (!id) return; + + const fetchMedicine = async () => { + try { + const [medData, pharmData] = await Promise.all([ + getMedicine(id), + getMedicinePharmacies(id), + ]); + setMedicine(medData); + setPharmacies(pharmData); + } catch (error) { + console.error('Error fetching medicine:', error); + } finally { + setIsLoading(false); + } + }; + + fetchMedicine(); + }, [id]); + + if (isLoading) { + return ; + } + + if (!medicine) { + return ( + + Medicamento no encontrado + + ); + } + + return ( + + + {medicine.nombre} + + + + + + + + + + + + + + Farmacias ({pharmacies.length}) + + + {pharmacies.length === 0 ? ( + No hay farmacias con este medicamento + ) : ( + pharmacies.map((pharm) => ( + router.push(`/pharmacy/${pharm.pharmacy_id}`)} + > + + {pharm.pharmacy?.name} + {pharm.pharmacy?.address} + + + {pharm.price.toFixed(2)} € + Stock: {pharm.stock} + + + )) + )} + + + ); +} + +function InfoRow({ label, value }: { label: string; value: string }) { + return ( + + {label} + {value} + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: colors.background, + }, + header: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'flex-start', + padding: spacing.md, + backgroundColor: colors.card, + }, + name: { + flex: 1, + fontSize: 22, + fontWeight: 'bold', + color: colors.text, + marginRight: spacing.sm, + }, + infoSection: { + backgroundColor: colors.card, + marginTop: spacing.sm, + padding: spacing.md, + }, + infoRow: { + flexDirection: 'row', + justifyContent: 'space-between', + paddingVertical: spacing.sm, + borderBottomWidth: 1, + borderBottomColor: colors.separator, + }, + infoLabel: { + fontSize: 14, + color: colors.textSecondary, + }, + infoValue: { + fontSize: 14, + color: colors.text, + fontWeight: '500', + }, + pharmaciesSection: { + marginTop: spacing.sm, + padding: spacing.md, + }, + sectionTitle: { + fontSize: 18, + fontWeight: '600', + color: colors.text, + marginBottom: spacing.md, + }, + noPharmacies: { + color: colors.textSecondary, + textAlign: 'center', + padding: spacing.xl, + }, + pharmacyCard: { + flexDirection: 'row', + justifyContent: 'space-between', + backgroundColor: colors.card, + borderRadius: borderRadius.md, + padding: spacing.md, + marginBottom: spacing.sm, + }, + pharmacyInfo: { + flex: 1, + }, + pharmacyName: { + fontSize: 16, + fontWeight: '600', + color: colors.text, + }, + pharmacyAddress: { + fontSize: 14, + color: colors.textSecondary, + marginTop: spacing.xs, + }, + pharmacyStock: { + 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, + }, +});