diff --git a/apps/frontend/src/components/ProductResults.css b/apps/frontend/src/components/ProductResults.css new file mode 100644 index 0000000..fb17ac6 --- /dev/null +++ b/apps/frontend/src/components/ProductResults.css @@ -0,0 +1,163 @@ +.product-results { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 1rem; + margin-top: 0.5rem; + max-height: 70vh; + overflow-y: auto; + overflow-x: hidden; + overscroll-behavior: contain; + animation: fadeInUp 0.5s ease-out; +} + +@media (min-width: 1024px) { + .product-results { + max-height: 76vh; + } +} + +.product-card { + background: var(--surface-container-lowest); + border-radius: var(--radius-md); + padding: 1.25rem; + cursor: pointer; + transition: transform 0.15s, box-shadow 0.15s; + border: 1px solid var(--outline-variant); + display: flex; + flex-direction: column; + justify-content: space-between; + box-shadow: var(--shadow-soft); +} + +.product-card:hover { + transform: translateY(-2px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); + border-color: var(--primary); +} + +.product-card-image { + width: 100%; + height: 120px; + margin-bottom: 1rem; + overflow: hidden; + border-radius: var(--radius-sm); + background: var(--surface-container-low); + display: flex; + align-items: center; + justify-content: center; +} + +.product-card-image img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.product-image-placeholder { + color: var(--outline-variant); + display: flex; + align-items: center; + justify-content: center; +} + +.product-card-content { + display: flex; + flex-direction: column; + flex: 1; +} + +.product-card-badges { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin-bottom: 0.75rem; +} + +.source-badge { + color: white; + padding: 0.25rem 0.5rem; + border-radius: var(--radius-sm); + font-size: 0.7rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.02em; +} + +.category-badge { + background: var(--surface-container-high); + color: var(--on-surface-variant); + padding: 0.25rem 0.5rem; + border-radius: var(--radius-sm); + font-size: 0.7rem; + font-weight: 600; +} + +.nutri-score-badge { + color: white; + padding: 0.25rem 0.5rem; + border-radius: var(--radius-sm); + font-size: 0.7rem; + font-weight: 600; +} + +.product-card-header { + margin-bottom: 0.5rem; +} + +.product-card-header h3 { + color: var(--on-surface); + font-size: 1.15rem; + font-weight: 700; + letter-spacing: -0.01em; + flex: 1; + margin: 0; +} + +.product-card-body { + margin-bottom: 1rem; + flex: 1; +} + +.product-card-body p { + font-size: 0.9rem; + color: var(--on-surface-variant); + line-height: 1.55; + margin-bottom: 0.25rem; +} + +.product-card-body strong { + color: var(--on-surface); + font-weight: 600; +} + +.product-card-footer { + padding-top: 0.75rem; + border-top: 1px solid var(--outline-variant); +} + +.view-details { + color: var(--primary); + font-weight: 600; + font-size: 0.9rem; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.view-details::after { + content: "→"; + transition: transform 0.2s; +} + +.product-card:hover .view-details::after { + transform: translateX(4px); +} + +.no-results { + text-align: center; + padding: 2.5rem 1.5rem; + background: var(--surface-container-low); + border-radius: var(--radius-md); + color: var(--on-surface-variant); + border: 1px dashed var(--outline-variant); +} diff --git a/apps/frontend/src/components/ProductResults.jsx b/apps/frontend/src/components/ProductResults.jsx new file mode 100644 index 0000000..b2d0280 --- /dev/null +++ b/apps/frontend/src/components/ProductResults.jsx @@ -0,0 +1,114 @@ +import React from 'react'; +import './ProductResults.css'; + +const categoryLabels = { + otc: 'Sin Receta', + baby_food: 'Alimentación Infantil', + baby_milk: 'Leche de Fórmula', + baby_cereal: 'Cereales Bebé' +}; + +const sourceColors = { + cima: '#2563eb', + openfoodfacts: '#16a34a' +}; + +const sourceLabels = { + cima: 'CIMA', + openfoodfacts: 'Open Food Facts' +}; + +function ProductResults({ products, onSelect }) { + if (!products || products.length === 0) { + return ( +
+

No se encontraron productos

+
+ ); + } + + return ( +
+ {products.map((product) => ( + + ))} +
+ ); +} + +function ProductCard({ product, onSelect }) { + const nutriScore = product.nutri_score; + const nutriScoreColors = { + a: '#16a34a', + b: '#65a30d', + c: '#eab308', + d: '#f97316', + e: '#dc2626' + }; + + return ( +
onSelect(product)}> +
+ {product.image_url ? ( + {product.name} + ) : ( +
+ + + + + +
+ )} +
+ +
+
+ + {sourceLabels[product.source]} + + + {categoryLabels[product.category] || product.category} + + {product.source === 'openfoodfacts' && nutriScore && ( + + Nutri-Score {nutriScore.toUpperCase()} + + )} +
+ +
+

{product.name}

+
+ +
+ {product.brand && ( +

Marca: {product.brand}

+ )} + {product.source === 'cima' && product.active_ingredient && ( +

Principio Activo: {product.active_ingredient}

+ )} + {product.source === 'cima' && product.dosage && ( +

Dosis: {product.dosage}

+ )} +
+ +
+ Ver detalles → +
+
+
+ ); +} + +export default ProductResults;