import React, { useState, useEffect, useMemo, useRef } from 'react'; import { useTranslation } from '../../i18n'; import './AdminComponents.css'; const MAX_PHARMACY_RESULTS = 25; function normalize(s) { return (s || '').toString().toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, ''); } function PharmacyMedicineLink() { const { t } = useTranslation(); const [pharmacies, setPharmacies] = useState([]); const [medicineSearch, setMedicineSearch] = useState(''); const [medicineResults, setMedicineResults] = useState([]); const [selectedPharmacy, setSelectedPharmacy] = useState(null); const [selectedMedicine, setSelectedMedicine] = useState(null); const [pharmacyMedicines, setPharmacyMedicines] = useState([]); const [loading, setLoading] = useState(false); const [searching, setSearching] = useState(false); const [pharmacyQuery, setPharmacyQuery] = useState(''); const [pharmacyDropdownOpen, setPharmacyDropdownOpen] = useState(false); const pharmacyInputRef = useRef(null); const [formData, setFormData] = useState({ pharmacy_id: '', price: '', stock: '' }); const filteredPharmacies = useMemo(() => { const q = normalize(pharmacyQuery).trim(); if (!q) return pharmacies.slice(0, MAX_PHARMACY_RESULTS); const tokens = q.split(/\s+/).filter(Boolean); return pharmacies .filter(p => { const hay = `${normalize(p.name)} ${normalize(p.address)}`; return tokens.every(tok => hay.includes(tok)); }) .slice(0, MAX_PHARMACY_RESULTS); }, [pharmacies, pharmacyQuery]); useEffect(() => { fetchPharmacies(); }, []); useEffect(() => { if (selectedPharmacy) { fetchPharmacyMedicines(selectedPharmacy.id); } }, [selectedPharmacy]); // Buscar medicamentos en la API de CIMA mientras el usuario escribe useEffect(() => { const q = medicineSearch.trim(); if (q.length < 2) { setMedicineResults([]); setSearching(false); return; } const controller = new AbortController(); const timeoutId = setTimeout(async () => { setSearching(true); try { const response = await fetch(`/api/medicines/search?q=${encodeURIComponent(q)}`, { credentials: 'include', signal: controller.signal, }); const data = await response.json(); setMedicineResults(Array.isArray(data) ? data : []); } catch (error) { if (error.name === 'AbortError') return; console.error('Error searching medicines:', error); } finally { if (!controller.signal.aborted) setSearching(false); } }, 500); return () => { clearTimeout(timeoutId); controller.abort(); }; }, [medicineSearch]); const fetchPharmacies = async () => { try { const response = await fetch('/api/pharmacies', { credentials: 'include', }); const data = await response.json(); setPharmacies(data); } catch (error) { console.error('Error fetching pharmacies:', error); } }; const fetchPharmacyMedicines = async (pharmacyId) => { setLoading(true); try { const response = await fetch(`/api/admin/pharmacies/${pharmacyId}/medicines`, { credentials: 'include', }); const data = await response.json(); setPharmacyMedicines(data); } catch (error) { console.error('Error fetching pharmacy medicines:', error); } finally { setLoading(false); } }; const handleSubmit = async (e) => { e.preventDefault(); if (!selectedMedicine) { alert(t('admin.linkMedicine.selectMedicineFirst')); return; } try { const payload = { pharmacy_id: parseInt(formData.pharmacy_id), medicine_nregistro: selectedMedicine.nregistro, medicine_name: selectedMedicine.name, price: formData.price ? parseFloat(formData.price) : null, stock: formData.stock ? parseInt(formData.stock) : 0 }; const response = await fetch('/api/admin/pharmacy-medicines', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify(payload) }); if (!response.ok) throw new Error(t('admin.linkMedicine.linkError')); resetForm(); if (selectedPharmacy) { fetchPharmacyMedicines(selectedPharmacy.id); } alert(t('admin.linkMedicine.linkSuccess')); } catch (error) { console.error('Error linking medicine:', error); alert(t('admin.linkMedicine.linkError')); } }; const handleUpdate = async (id, price, stock) => { try { const response = await fetch(`/api/admin/pharmacy-medicines/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ price, stock }) }); if (!response.ok) throw new Error(t('admin.linkMedicine.updateError')); fetchPharmacyMedicines(selectedPharmacy.id); alert(t('admin.linkMedicine.updateSuccess')); } catch (error) { console.error('Error updating:', error); alert(t('admin.linkMedicine.updateError')); } }; const handleDelete = async (id) => { if (!confirm(t('admin.linkMedicine.deleteConfirm'))) return; try { const response = await fetch(`/api/admin/pharmacy-medicines/${id}`, { method: 'DELETE', credentials: 'include' }); if (!response.ok) throw new Error(t('admin.linkMedicine.deleteError')); fetchPharmacyMedicines(selectedPharmacy.id); alert(t('admin.linkMedicine.deleteSuccess')); } catch (error) { console.error('Error deleting:', error); alert(t('admin.linkMedicine.deleteError')); } }; const resetForm = () => { setFormData({ pharmacy_id: selectedPharmacy ? selectedPharmacy.id.toString() : '', price: '', stock: '' }); setSelectedMedicine(null); setMedicineSearch(''); setMedicineResults([]); }; const selectMedicine = (medicine) => { setSelectedMedicine(medicine); setMedicineSearch(medicine.name); setMedicineResults([]); }; const pickPharmacy = (pharmacy) => { setSelectedPharmacy(pharmacy); setFormData(prev => ({ ...prev, pharmacy_id: pharmacy.id.toString() })); setPharmacyQuery(`${pharmacy.name} — ${pharmacy.address}`); setPharmacyDropdownOpen(false); }; const clearPharmacy = () => { setSelectedPharmacy(null); setFormData(prev => ({ ...prev, pharmacy_id: '' })); setPharmacyQuery(''); setPharmacyDropdownOpen(true); setTimeout(() => pharmacyInputRef.current?.focus(), 0); }; return (

{t('admin.linkMedicine.title')}

{ setPharmacyQuery(e.target.value); if (selectedPharmacy) { setSelectedPharmacy(null); setFormData(prev => ({ ...prev, pharmacy_id: '' })); } setPharmacyDropdownOpen(true); }} onFocus={() => setPharmacyDropdownOpen(true)} onBlur={() => setTimeout(() => setPharmacyDropdownOpen(false), 150)} placeholder={pharmacies.length ? `${t('admin.linkMedicine.searchPharmacy')} ${pharmacies.length} ${t('admin.linkMedicine.pharmacies')}` : t('admin.linkMedicine.loadingPharmacies')} autoComplete="off" required={!selectedPharmacy} /> {!selectedPharmacy && pharmacyDropdownOpen && (
{filteredPharmacies.length === 0 ? (
{t('admin.linkMedicine.noPharmacies')} "{pharmacyQuery}"
) : ( filteredPharmacies.map((pharmacy) => (
{ e.preventDefault(); pickPharmacy(pharmacy); }} > {pharmacy.name} {pharmacy.address}
)) )}
)} {selectedPharmacy && (

✅ Selected: {selectedPharmacy.name}

{selectedPharmacy.address}

)}
{ setMedicineSearch(e.target.value); setSelectedMedicine(null); }} placeholder={t('admin.linkMedicine.searchMedicine')} required /> {searching &&

{t('admin.linkMedicine.searching')}

} {medicineResults.length > 0 && !selectedMedicine && (
{medicineResults.slice(0, 10).map((medicine) => (
selectMedicine(medicine)} > {medicine.name} {medicine.active_ingredient && - {medicine.active_ingredient}} {medicine.dosage && ({medicine.dosage})}
))}
)} {selectedMedicine && (

✅ Selected: {selectedMedicine.name}

{selectedMedicine.active_ingredient && `${t('admin.linkMedicine.activeIngredient')} ${selectedMedicine.active_ingredient} • `} {selectedMedicine.dosage && `${t('admin.linkMedicine.dosage')} ${selectedMedicine.dosage} • `} {t('admin.linkMedicine.registrationNumber')} {selectedMedicine.nregistro}

)}
setFormData({ ...formData, price: e.target.value })} placeholder="e.g., 12.50" />
setFormData({ ...formData, stock: e.target.value })} placeholder="e.g., 50" />
{selectedPharmacy && (

{t('admin.linkMedicine.medicationsIn')} {selectedPharmacy.name}

{loading ? (
{t('admin.linkMedicine.loading')}
) : pharmacyMedicines.length === 0 ? (

{t('admin.linkMedicine.empty')}

) : (
{pharmacyMedicines.map((pm) => (

{pm.medicine_name}

{t('admin.linkMedicine.priceLabel')} {pm.price ? `€${parseFloat(pm.price).toFixed(2)}` : t('admin.linkMedicine.undefined')} • Stock: {pm.stock || 0}

))}
)}
)}
); } export default PharmacyMedicineLink;