import React, { useState, useEffect, useMemo } from 'react'; import PharmacyMap from '../components/PharmacyMap'; import PharmacyList from '../components/PharmacyList'; import { haversineKm, getUserPosition, hasCachedPosition } from '../utils/geo'; import './ProductView.css'; export default function ProductView({ source, id, onBack }) { const [product, setProduct] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [pharmacies, setPharmacies] = useState([]); const [loadingPharmacies, setLoadingPharmacies] = useState(false); const [sortByDistance, setSortByDistance] = useState(false); const [userPosition, setUserPosition] = useState(null); const [positionSource, setPositionSource] = useState(null); const [locating, setLocating] = useState(false); const [locationError, setLocationError] = useState(''); const hasSavedCoords = product?.latitude != null && product?.longitude != null; const displayedPharmacies = useMemo(() => { if (!sortByDistance || !userPosition) return pharmacies; return [...pharmacies].sort((a, b) => { if (a.latitude == null || a.longitude == null) return 1; if (b.latitude == null || b.longitude == null) return -1; return ( haversineKm(userPosition.lat, userPosition.lon, a.latitude, a.longitude) - haversineKm(userPosition.lat, userPosition.lon, b.latitude, b.longitude) ); }); }, [pharmacies, sortByDistance, userPosition]); const handleSortByDistance = async () => { if (sortByDistance) { setSortByDistance(false); return; } setLocationError(''); setLocating(true); try { const pos = await getUserPosition(); setUserPosition(pos); setPositionSource('browser'); setSortByDistance(true); } catch (err) { let msg = 'No se pudo obtener tu ubicación'; if (err && typeof err.code === 'number') { if (err.code === 1) msg = 'Permiso de ubicación denegado.'; else if (err.code === 2) msg = 'Ubicación no disponible.'; else if (err.code === 3) msg = 'La ubicación tardó demasiado.'; } setLocationError(msg); } finally { setLocating(false); } }; useEffect(() => { loadProduct(); }, [source, id]); async function loadProduct() { setLoading(true); setError(null); setPharmacies([]); try { // Use parapharmacy endpoint for all non-CIMA sources const isCima = source === 'cima'; const apiUrl = isCima ? `/api/products/${source}/${id}` : `/api/products/parapharmacy/${id}`; const response = await fetch(apiUrl); if (!response.ok) { throw new Error('Producto no encontrado'); } const data = await response.json(); setProduct(data); loadPharmacies(source, data.id || data._id); } catch (err) { setError(err.message); } finally { setLoading(false); } } async function loadPharmacies(productSource, productId) { setLoadingPharmacies(true); try { const response = await fetch(`/api/products/${productSource}/${productId}/pharmacies`); if (response.ok) { const data = await response.json(); setPharmacies(data); } } catch { // Pharmacies are optional — don't block on failure } finally { setLoadingPharmacies(false); } } if (loading) { return (
{product.brand}