#49 feat: panel lateral izquierdo de productos junto al mapa de provenance

This commit is contained in:
2026-08-16 12:42:52 -05:00
parent 798a9bba15
commit 6966c4180a
2 changed files with 92 additions and 56 deletions

View File

@@ -1,63 +1,71 @@
<template>
<div>
<template v-if="productRows.length">
<v-card class="mb-3" data-test="map-product-box" variant="tonal">
<v-list density="compact">
<v-list-item
v-for="row in productRows"
:key="row.product.id"
data-test="map-product-row"
:prepend-avatar="row.image"
role="button"
:subtitle="row.locationLabel"
:title="row.product.name"
@click="onRowClick(row)"
>
<template #append>
<v-icon v-if="row.position" color="primary" size="small">
mdi-map-marker
</v-icon>
<v-icon v-else color="medium-emphasis" size="small">
mdi-map-marker-off
</v-icon>
</template>
</v-list-item>
</v-list>
</v-card>
<div class="map-layout">
<v-card class="product-panel" data-test="map-product-box" variant="tonal">
<v-card-title class="text-subtitle-1 font-weight-bold py-2">
Productos ({{ productRows.length }})
</v-card-title>
<v-divider />
<v-list density="compact">
<v-list-item
v-for="row in productRows"
:key="row.product.id"
data-test="map-product-row"
:prepend-avatar="row.image"
role="button"
:subtitle="row.locationLabel"
:title="row.product.name"
@click="onRowClick(row)"
>
<template #append>
<v-icon v-if="row.position" color="primary" size="small">
mdi-map-marker
</v-icon>
<v-icon v-else color="medium-emphasis" size="small">
mdi-map-marker-off
</v-icon>
</template>
</v-list-item>
</v-list>
</v-card>
<template v-if="hasMarkers">
<div class="map-container">
<div ref="mapEl" class="map-wrapper" />
<v-btn
class="map-reset-zoom"
data-test="map-reset-zoom"
density="comfortable"
icon="mdi-fit-to-page"
size="small"
variant="flat"
@click="resetZoom"
/>
<div class="map-area">
<template v-if="hasMarkers">
<div class="map-container">
<div ref="mapEl" class="map-wrapper" />
<v-btn
class="map-reset-zoom"
data-test="map-reset-zoom"
density="comfortable"
icon="mdi-fit-to-page"
size="small"
variant="flat"
@click="resetZoom"
/>
</div>
<v-alert
v-if="!storePosition"
class="mt-2"
type="warning"
variant="tonal"
>
La ubicación de la tienda no está configurada, por lo que no se mostrará su recorrido.
</v-alert>
<p class="text-caption text-medium-emphasis mt-2 mb-0">
Pasa el cursor sobre un producto para ver su recorrido hasta la tienda.
</p>
</template>
<v-alert
v-else
class="my-2"
type="info"
variant="tonal"
>
Las coordenadas geográficas de los municipios de origen aún no están disponibles.
</v-alert>
</div>
<v-alert
v-if="!storePosition"
class="mt-2"
type="warning"
variant="tonal"
>
La ubicación de la tienda no está configurada, por lo que no se mostrará su recorrido.
</v-alert>
<p class="text-caption text-medium-emphasis mt-2 mb-0">
Pasa el cursor sobre un producto para ver su recorrido hasta la tienda.
</p>
</template>
<v-alert
v-else
class="my-2"
type="info"
variant="tonal"
>
Las coordenadas geográficas de los municipios de origen aún no están disponibles.
</v-alert>
</div>
</template>
<ProvenanceRelationModal
@@ -328,6 +336,23 @@
</script>
<style scoped>
.map-layout {
display: flex;
gap: 12px;
align-items: stretch;
}
.product-panel {
flex: 0 0 300px;
max-height: 480px;
overflow-y: auto;
}
.map-area {
flex: 1;
min-width: 0;
}
.map-container {
position: relative;
}
@@ -348,6 +373,17 @@
z-index: 1000;
}
@media (max-width: 900px) {
.map-layout {
flex-direction: column;
}
.product-panel {
flex-basis: auto;
max-height: none;
}
}
.map-wrapper :deep(.provenance-product-pin) {
display: flex;
align-items: center;