import React, { useEffect, useState } from 'react'; import './PharmacyList.css'; import { haversineKm, formatDistance } from '../utils/geo'; import { getOpenStatus } from '../utils/hours'; import { pushSupported, isSubscribedLocally, subscribeToPush, unsubscribeFromPush, } from '../utils/notifications.js'; function PharmacyList({ pharmacies, loading, userPosition, medicine, currentUser, onLoginRequest }) { if (loading) { return (

Cargando farmacias...

); } if (pharmacies.length === 0) { return (

No se encontraron farmacias con este medicamento

); } return (

Disponible en {pharmacies.length} {pharmacies.length === 1 ? 'farmacia' : 'farmacias'}

{pharmacies.map((pharmacy) => { const distanceKm = userPosition && pharmacy.latitude != null && pharmacy.longitude != null ? haversineKm(userPosition.lat, userPosition.lon, pharmacy.latitude, pharmacy.longitude) : null; return ( ); })}
); } function PharmacyCard({ pharmacy, distanceKm, medicine, currentUser, onLoginRequest, userPosition }) { const nregistro = medicine?.nregistro || medicine?.id; const supported = pushSupported(); const outOfStock = pharmacy.stock !== undefined && pharmacy.stock <= 0; const showBell = Boolean(medicine && nregistro && outOfStock); const [subscribed, setSubscribed] = useState(() => showBell ? isSubscribedLocally(nregistro, pharmacy.id) : false ); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); useEffect(() => { if (showBell) setSubscribed(isSubscribedLocally(nregistro, pharmacy.id)); }, [nregistro, pharmacy.id, showBell]); async function handleBell(e) { e.stopPropagation(); if (!currentUser) { onLoginRequest?.(); return; } if (!supported) { setError('Las notificaciones requieren iOS 16.4+ y este sitio instalado como app (Compartir → Añadir a Pantalla de Inicio).'); return; } if (busy) return; setBusy(true); setError(null); try { if (subscribed) { await unsubscribeFromPush(nregistro, pharmacy.id); setSubscribed(false); } else { await subscribeToPush(nregistro, medicine.name, pharmacy.id); setSubscribed(true); } } catch (err) { console.error('[notify] pharmacy toggle failed:', err); setError(err.message || 'No se pudo actualizar la suscripción'); } finally { setBusy(false); } } const openStatus = getOpenStatus(pharmacy.opening_hours); return (

🏥 {pharmacy.name}

{distanceKm != null && ( {formatDistance(distanceKm)} )} {showBell && ( )}
{openStatus && (

{openStatus.label}

)}

📍 {pharmacy.address}

{pharmacy.phone && (

📞 {pharmacy.phone}

)} {error &&

{error}

} {pharmacy.latitude != null && pharmacy.longitude != null && ( Cómo llegar )}
{pharmacy.price && ( €{parseFloat(pharmacy.price).toFixed(2)} )} {pharmacy.stock !== undefined && ( 20 ? 'in-stock' : pharmacy.stock > 0 ? 'low-stock' : 'out-of-stock'}`}> {pharmacy.stock > 20 ? '✓ En Stock' : pharmacy.stock > 0 ? `⚠ Stock Bajo (${pharmacy.stock})` : '✗ Sin Stock'} )}
); } export default PharmacyList;