diff --git a/app/components/layout/ListMapLayout.vue b/app/components/layout/ListMapLayout.vue
new file mode 100644
index 0000000..85af462
--- /dev/null
+++ b/app/components/layout/ListMapLayout.vue
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/navigation/MainNavigation.vue b/app/components/navigation/MainNavigation.vue
index d892c73..10ec83f 100644
--- a/app/components/navigation/MainNavigation.vue
+++ b/app/components/navigation/MainNavigation.vue
@@ -17,7 +17,6 @@
class="px-4 py-2 rounded-full font-medium text-sm transition-colors hover:bg-base-200"
:class="{ 'bg-base-200 text-primary': isActiveTab(tab.key) }"
>
-
{{ tab.label }}
@@ -137,11 +136,10 @@
v-for="tab in visibleTabs"
:key="tab.key"
:to="localePath(tab.path)"
- class="flex flex-col items-center gap-1 px-4 py-2 rounded-lg hover:bg-base-200"
+ class="px-4 py-2 rounded-full text-sm font-medium hover:bg-base-200"
:class="{ 'bg-base-200 text-primary': isActiveTab(tab.key) }"
>
-
- {{ tab.label }}
+ {{ tab.label }}
@@ -173,9 +171,9 @@ const route = useRoute()
const { t } = useI18n()
const tabs = computed(() => [
- { key: 'catalog', label: t('cabinetNav.catalog'), path: '/catalog/offers', icon: 'lucide:search', auth: false },
- { key: 'orders', label: t('cabinetNav.orders'), path: '/clientarea/orders', icon: 'lucide:package', auth: true },
- { key: 'seller', label: t('cabinetNav.seller'), path: '/clientarea/offers', icon: 'lucide:store', auth: true, seller: true },
+ { key: 'catalog', label: t('cabinetNav.catalog'), path: '/catalog/offers', auth: false },
+ { key: 'orders', label: t('cabinetNav.orders'), path: '/clientarea/orders', auth: true },
+ { key: 'seller', label: t('cabinetNav.seller'), path: '/clientarea/offers', auth: true, seller: true },
])
const visibleTabs = computed(() => {
diff --git a/app/components/navigation/SubNavigation.vue b/app/components/navigation/SubNavigation.vue
index 737eae5..83b0c29 100644
--- a/app/components/navigation/SubNavigation.vue
+++ b/app/components/navigation/SubNavigation.vue
@@ -8,7 +8,6 @@
class="px-4 py-2 rounded-full text-sm font-medium transition-colors whitespace-nowrap text-base-content/70 hover:text-base-content hover:bg-base-200"
:class="{ 'text-primary bg-primary/10': isActive(item.path) }"
>
-
{{ item.label }}
@@ -26,21 +25,21 @@ const { t } = useI18n()
const sectionItems = computed(() => ({
catalog: [
- { label: t('cabinetNav.offers'), path: '/catalog/offers', icon: 'lucide:tag' },
- { label: t('cabinetNav.suppliers'), path: '/catalog/suppliers', icon: 'lucide:users' },
- { label: t('cabinetNav.hubs'), path: '/catalog/hubs', icon: 'lucide:warehouse' },
+ { label: t('cabinetNav.offers'), path: '/catalog/offers' },
+ { label: t('cabinetNav.suppliers'), path: '/catalog/suppliers' },
+ { label: t('cabinetNav.hubs'), path: '/catalog/hubs' },
],
orders: [
- { label: t('cabinetNav.orders'), path: '/clientarea/orders', icon: 'lucide:package' },
- { label: t('cabinetNav.addresses'), path: '/clientarea/addresses', icon: 'lucide:map-pin' },
- { label: t('cabinetNav.billing'), path: '/clientarea/billing', icon: 'lucide:credit-card' },
+ { label: t('cabinetNav.orders'), path: '/clientarea/orders' },
+ { label: t('cabinetNav.addresses'), path: '/clientarea/addresses' },
+ { label: t('cabinetNav.billing'), path: '/clientarea/billing' },
],
seller: [
- { label: t('cabinetNav.myOffers'), path: '/clientarea/offers', icon: 'lucide:tag' },
+ { label: t('cabinetNav.myOffers'), path: '/clientarea/offers' },
],
settings: [
- { label: t('cabinetNav.profile'), path: '/clientarea/profile', icon: 'lucide:user' },
- { label: t('cabinetNav.team'), path: '/clientarea/team', icon: 'lucide:users' },
+ { label: t('cabinetNav.profile'), path: '/clientarea/profile' },
+ { label: t('cabinetNav.team'), path: '/clientarea/team' },
],
}))
diff --git a/app/components/search/GlobalSearchBar.vue b/app/components/search/GlobalSearchBar.vue
index ff3cfec..482123e 100644
--- a/app/components/search/GlobalSearchBar.vue
+++ b/app/components/search/GlobalSearchBar.vue
@@ -5,35 +5,20 @@
@submit.prevent="handleSearch"
class="flex items-center bg-base-100 rounded-full border border-base-300 shadow-sm hover:shadow-md transition-shadow"
>
-
-
+
+
-
-
-
+
+ {{ productDisplay || $t('search.product_placeholder') }}
-
+
-
-
+
+
-
-
-
+
+ {{ locationDisplay || $t('search.destination_placeholder') }}
@@ -96,100 +67,64 @@
-
diff --git a/app/layouts/topnav.vue b/app/layouts/topnav.vue
index 17fb4ff..75b9cbb 100644
--- a/app/layouts/topnav.vue
+++ b/app/layouts/topnav.vue
@@ -16,12 +16,12 @@
@switch-team="switchToTeam"
/>
-
-
-
+
+
+
diff --git a/app/pages/catalog/hubs/index.vue b/app/pages/catalog/hubs/index.vue
index 8e4a207..1a42482 100644
--- a/app/pages/catalog/hubs/index.vue
+++ b/app/pages/catalog/hubs/index.vue
@@ -1,5 +1,5 @@
-
+
-
-
-
-
+
+
+
@@ -29,6 +36,8 @@
v-for="hub in country.hubs"
:key="hub.uuid"
:hub="hub"
+ :class="{ 'ring-2 ring-primary': hub.uuid === selectedHubId }"
+ @click="onSelectHub(hub.uuid)"
/>
@@ -45,19 +54,8 @@
{{ t('catalogHubsSection.empty.no_hubs') }}
-
-
-
-
-
-
-
-
-
+
+
@@ -75,13 +73,20 @@ const {
filters,
isLoading,
isLoadingMore,
- itemsWithCoords,
itemsByCountry,
canLoadMore,
loadMore,
init
} = useCatalogHubs()
+// Selected hub for map highlighting
+const selectedHubId = ref()
+const listMapRef = ref<{ flyToItem: (uuid: string) => void } | null>(null)
+
+const onSelectHub = (uuid: string) => {
+ selectedHubId.value = uuid
+}
+
await init()
useHead(() => ({
diff --git a/app/pages/catalog/offers/index.vue b/app/pages/catalog/offers/index.vue
index 32ebd51..eeabbce 100644
--- a/app/pages/catalog/offers/index.vue
+++ b/app/pages/catalog/offers/index.vue
@@ -1,5 +1,5 @@
-
+
-
-
-
-
+
+
+
@@ -58,6 +65,8 @@
v-for="offer in items"
:key="offer.uuid"
:offer="offer"
+ :class="{ 'ring-2 ring-primary': offer.uuid === selectedOfferId }"
+ @click="onSelectOffer(offer.uuid)"
/>
@@ -73,19 +82,8 @@
{{ t('catalogOffersSection.empty.no_offers') }}
-
-
-
-
-
-
-
-
-
+
+
@@ -114,7 +112,6 @@ const {
filters,
isLoading,
isLoadingMore,
- itemsWithCoords,
canLoadMore,
loadMore,
init: initOffers,
@@ -144,6 +141,15 @@ const selectProduct = (product: any) => {
})
}
+// Selected offer for map highlighting
+const selectedOfferId = ref
()
+const listMapRef = ref<{ flyToItem: (uuid: string) => void } | null>(null)
+
+const onSelectOffer = (uuid: string) => {
+ selectedOfferId.value = uuid
+ // flyToItem will be triggered by ListMapLayout watch
+}
+
// Initialize
await initProducts()
diff --git a/app/pages/catalog/suppliers/index.vue b/app/pages/catalog/suppliers/index.vue
index ac31c9c..8b256b4 100644
--- a/app/pages/catalog/suppliers/index.vue
+++ b/app/pages/catalog/suppliers/index.vue
@@ -1,5 +1,5 @@
-
+
-
-
-
-
+
+
+
@@ -27,6 +34,8 @@
v-for="supplier in items"
:key="supplier.uuid || supplier.teamUuid"
:supplier="supplier"
+ :class="{ 'ring-2 ring-primary': (supplier.uuid || supplier.teamUuid) === selectedSupplierId }"
+ @click="onSelectSupplier(supplier.uuid || supplier.teamUuid)"
/>
@@ -42,19 +51,8 @@
{{ t('catalogSuppliersSection.empty.no_suppliers') }}
-
-
-
-
-
-
-
-
-
+
+
@@ -72,12 +70,19 @@ const {
filters,
isLoading,
isLoadingMore,
- itemsWithCoords,
canLoadMore,
loadMore,
init
} = useCatalogSuppliers()
+// Selected supplier for map highlighting
+const selectedSupplierId = ref
()
+const listMapRef = ref<{ flyToItem: (uuid: string) => void } | null>(null)
+
+const onSelectSupplier = (uuid: string) => {
+ selectedSupplierId.value = uuid
+}
+
await init()
useHead(() => ({