5 Commits

Author SHA1 Message Date
7beac90c05 feat: mejora selector de productos con autocomplete y estética del modal en gestión de imágenes de catálogo 2026-07-11 13:52:35 -05:00
92483a110a Merge pull request 'fix/catalog-image-overlap' (#44) from fix/catalog-image-overlap into main
Reviewed-on: #44
2026-07-03 19:21:40 -05:00
mono
a89af0f0bb #fix: búsqueda insensible a tildes en el catálogo
Normaliza los strings eliminando diacríticos (NFD) antes de comparar,
para que 'cafe' encuentre 'café' y viceversa.
2026-07-03 19:06:40 -05:00
mono
b2a47c44dc #fix: scroll al inicio del grid al cambiar página en el catálogo
El método scrollToTop usaba scrollIntoView en un elemento sticky,
lo que no generaba desplazamiento. Ahora calcula la posición
absoluta del grid de productos y hace scroll suave.
2026-07-03 18:58:00 -05:00
mono
2c2082266e #fix: corregir solapamiento de imagen en tarjetas del catálogo
- Cambiar height: 100% por aspect-ratio: 1 en .product-image-container
- Eliminar media queries duplicados y obsoletos
- El contenedor ahora se ajusta al tamaño real del v-img
2026-07-03 18:52:33 -05:00
3 changed files with 35 additions and 178 deletions

View File

@@ -80,55 +80,67 @@
</v-col>
</v-row>
<v-dialog v-model="dialog.show" max-width="500" persistent>
<v-card>
<v-card-title>
<v-dialog v-model="dialog.show" max-width="520" persistent>
<v-card elevation="2" rounded="lg">
<v-card-title class="text-h6 font-weight-bold pa-6 pb-0">
<v-icon :icon="dialog.isEdit ? 'mdi-pencil' : 'mdi-plus-circle-outline'" class="mr-2" color="primary" />
{{ dialog.isEdit ? 'Editar' : 'Agregar' }} Imagen de Catálogo
</v-card-title>
<v-card-text>
<v-divider class="mt-3" />
<v-card-text class="pa-6">
<v-form ref="formRef">
<v-select
<v-label class="font-weight-medium mb-1 d-block">Producto</v-label>
<v-autocomplete
v-model="form.product"
:items="productOptions"
label="Producto"
placeholder="Buscar producto…"
:rules="[(v) => !!v || 'Seleccione un producto']"
item-title="name"
item-value="id"
variant="outlined"
:disabled="dialog.isEdit"
class="mb-3"
class="mb-5"
clearable
prepend-inner-icon="mdi-package-variant-closed"
density="comfortable"
/>
<v-label class="font-weight-medium mb-1 d-block">Imagen</v-label>
<v-file-input
ref="fileInputRef"
label="Imagen"
accept="image/*"
:rules="[(v) => !!v || 'Seleccione una imagen']"
variant="outlined"
prepend-icon="mdi-camera"
class="mb-3"
prepend-inner-icon="mdi-image-outline"
class="mb-5"
@update:model-value="onFileSelected"
density="comfortable"
hide-details="auto"
/>
<v-img
v-if="form.preview"
:src="form.preview"
max-height="200"
max-height="220"
contain
class="mb-3 rounded"
class="rounded-lg border mt-2"
/>
</v-form>
</v-card-text>
<v-card-actions>
<v-divider />
<v-card-actions class="pa-4">
<v-spacer />
<v-btn variant="text" @click="closeDialog">Cancelar</v-btn>
<v-btn variant="tonal" @click="closeDialog">Cancelar</v-btn>
<v-btn
color="primary"
variant="elevated"
:loading="submitting"
:disabled="submitting"
@click="submitForm"
class="ml-2"
>
<v-icon start :icon="dialog.isEdit ? 'mdi-content-save' : 'mdi-upload'" />
{{ dialog.isEdit ? 'Actualizar' : 'Agregar' }}
</v-btn>
</v-card-actions>

View File

@@ -176,7 +176,6 @@ export default {
.product-image-container {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
background: linear-gradient(135deg, #fafafa 0%, #ffffff 100%);
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
@@ -336,143 +335,6 @@ export default {
/* Móvil estándar (375px - 559px) */
@media (min-width: 375px) and (max-width: 559px) {
.product-name {
font-size: 0.95rem;
}
.price-value {
font-size: 1.05rem;
}
}
/* Tablet (560px - 959px) */
@media (min-width: 560px) and (max-width: 959px) {
.product-content {
padding: 14px;
}
.product-name {
font-size: 1rem;
min-height: 2.6rem;
}
.price-label {
font-size: 0.68rem;
}
.price-value {
font-size: 1.15rem;
}
.price-total-chip {
font-size: 0.95rem;
height: 28px;
}
.quantity-input {
max-width: 70px;
min-width: 70px;
}
}
/* Desktop (≥ 960px) */
@media (min-width: 960px) {
.product-content {
padding: 16px 14px;
}
.product-name {
font-size: 1.05rem;
min-height: 2.7rem;
}
.price-label {
font-size: 0.7rem;
}
.price-value {
font-size: 1.2rem;
}
.price-total-chip {
font-size: 1rem;
height: 30px;
padding: 0 14px;
}
.product-actions {
padding: 8px;
padding-bottom: 12px;
}
.quantity-input {
max-width: 70px;
min-width: 70px;
}
.qty-btn {
width: 36px;
height: 36px;
}
}
/* Desktop Large (≥ 1280px) */
@media (min-width: 1280px) {
.product-content {
padding: 18px 16px;
}
.product-name {
font-size: 1.1rem;
min-height: 2.8rem;
}
.price-value {
font-size: 1.25rem;
}
.price-total-chip {
font-size: 1.05rem;
height: 32px;
}
}
/* Desktop Extra Large (≥ 1920px) */
@media (min-width: 1920px) {
.product-name {
font-size: 1.15rem;
min-height: 3rem;
}
.price-value {
font-size: 1.3rem;
}
.product-content {
padding: 8px;
}
.product-name {
font-size: 0.8rem;
min-height: 1.9rem;
}
.price-value {
font-size: 0.85rem;
}
.quantity-input {
max-width: 50px;
min-width: 50px;
}
}
/* Móvil estándar (375px - 559px) */
@media (min-width: 375px) and (max-width: 559px) {
.product-image-container {
height: 140px;
}
.product-name {
font-size: 0.85rem;
}
@@ -484,10 +346,6 @@ export default {
/* Tablet (560px - 959px) */
@media (min-width: 560px) and (max-width: 959px) {
.product-image-container {
height: 150px;
}
.product-content {
padding: 10px;
}
@@ -518,10 +376,6 @@ export default {
/* Desktop (≥ 960px) */
@media (min-width: 960px) {
.product-image-container {
height: 160px;
}
.product-content {
padding: 12px 10px;
}
@@ -563,10 +417,6 @@ export default {
/* Desktop Large (≥ 1280px) */
@media (min-width: 1280px) {
.product-image-container {
height: 170px;
}
.product-content {
padding: 14px 12px;
}
@@ -588,10 +438,6 @@ export default {
/* Desktop Extra Large (≥ 1920px) */
@media (min-width: 1920px) {
.product-image-container {
height: 180px;
}
.product-name {
font-size: 1.05rem;
min-height: 2.5rem;

View File

@@ -342,9 +342,10 @@ export default {
// Búsqueda
filteredItems() {
if (!this.searchQuery) return this.items;
const query = this.searchQuery.toLowerCase();
const normalize = (s) => s.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
const query = normalize(this.searchQuery);
return this.items.filter((item) =>
item.name.toLowerCase().includes(query),
normalize(item.name).includes(query),
);
},
// Paginación
@@ -541,15 +542,13 @@ export default {
}
},
scrollToTop() {
this.$nextTick(() => {
const catalogHeader = this.$el?.querySelector(".page-header");
if (catalogHeader) {
catalogHeader.scrollIntoView({
behavior: "smooth",
block: "start",
});
}
});
const grid = this.$el?.querySelector(".product-grid");
if (grid) {
const top = grid.getBoundingClientRect().top + window.scrollY - 16;
window.scrollTo({ top, behavior: "smooth" });
} else {
window.scrollTo({ top: 0, behavior: "smooth" });
}
},
openLoginDialog() {
this.$refs.loginDialogRef.open();