diff --git a/apps/frontend/src/views/SearchView.css b/apps/frontend/src/views/SearchView.css index 9101f3a..d7af666 100644 --- a/apps/frontend/src/views/SearchView.css +++ b/apps/frontend/src/views/SearchView.css @@ -356,3 +356,44 @@ color: var(--primary); font-size: 0.85rem; } + +/* Filter tabs */ +.filter-tabs { + display: flex; + gap: 0.5rem; + margin-bottom: 1rem; + flex-wrap: wrap; +} + +.filter-tab { + padding: 0.5rem 1rem; + border-radius: 9999px; + border: none; + font-size: 0.875rem; + font-weight: 500; + cursor: pointer; + background: var(--surface-container-lowest, #f3f4f6); + color: var(--on-surface-variant, #6b7280); + transition: all 0.15s; +} + +.filter-tab:hover { + background: var(--surface-container-low, #e5e7eb); +} + +.filter-tab--active { + background: var(--primary, #2563eb); + color: white; +} + +/* Products section */ +.products-section { + margin-top: 1.5rem; +} + +.section-subtitle { + font-size: 1.125rem; + font-weight: 600; + color: var(--on-surface); + margin-bottom: 0.75rem; +} diff --git a/apps/frontend/src/views/SearchView.jsx b/apps/frontend/src/views/SearchView.jsx index 4149600..fbf72d8 100644 --- a/apps/frontend/src/views/SearchView.jsx +++ b/apps/frontend/src/views/SearchView.jsx @@ -1,6 +1,7 @@ import React, { useState, useEffect, useMemo, useCallback } from 'react'; import SearchBar from '../components/SearchBar'; import MedicineResults from '../components/MedicineResults'; +import ProductResults from '../components/ProductResults'; import PharmacyList from '../components/PharmacyList'; import PharmacyMap from '../components/PharmacyMap'; import { haversineKm, getUserPosition, hasCachedPosition } from '../utils/geo'; @@ -16,6 +17,8 @@ const suggestions = [ function SearchView({ currentUser, onLoginRequest, initialQuery = '' }) { const [searchQuery, setSearchQuery] = useState(initialQuery); const [medicines, setMedicines] = useState([]); + const [products, setProducts] = useState([]); + const [searchMode, setSearchMode] = useState('all'); const [selectedMedicine, setSelectedMedicine] = useState(null); const [pharmacies, setPharmacies] = useState([]); const [loading, setLoading] = useState(false); @@ -76,6 +79,7 @@ function SearchView({ currentUser, onLoginRequest, initialQuery = '' }) { const searchMedicines = async () => { if (searchQuery.trim().length < 2) { setMedicines([]); + setProducts([]); setSelectedMedicine(null); setPharmacies([]); return; @@ -90,6 +94,16 @@ function SearchView({ currentUser, onLoginRequest, initialQuery = '' }) { } finally { setLoading(false); } + + try { + const productsResponse = await fetch(`/api/products/search?q=${encodeURIComponent(searchQuery)}`); + if (productsResponse.ok) { + const productsData = await productsResponse.json(); + setProducts(productsData.results || []); + } + } catch (err) { + console.error('Product search error:', err); + } }; const timeoutId = setTimeout(searchMedicines, 300); return () => clearTimeout(timeoutId); @@ -276,16 +290,53 @@ function SearchView({ currentUser, onLoginRequest, initialQuery = '' }) { )} {searchQuery && !selectedMedicine && ( - { - saveToRecent(m); - setSelectedMedicine(m); - }} - query={searchQuery} - currentUser={currentUser} - onLoginRequest={onLoginRequest} - /> + <> +
+ + + +
+ + {(searchMode === 'all' || searchMode === 'medicines') && ( + { + saveToRecent(m); + setSelectedMedicine(m); + }} + query={searchQuery} + currentUser={currentUser} + onLoginRequest={onLoginRequest} + /> + )} + + {(searchMode === 'all' || searchMode === 'products') && products.length > 0 && ( +
+

Parafarmacia y Bebé

+ { + window.location.href = `/product/${p.source}/${p.id}`; + }} + /> +
+ )} + )} {selectedMedicine && (