Add Info panel for catalog with tabbed interface
Implemented Info mode для детального просмотра объектов каталога (hub/supplier/offer) с навигацией между связанными объектами. Новые компоненты: - InfoPanel.vue - панель с детальной информацией и табами для связанных объектов - useCatalogInfo.ts - composable для управления Info state и загрузки данных Изменения: - useCatalogSearch.ts - добавлен infoId state и функции openInfo/closeInfo - catalog/index.vue - интеграция InfoPanel, обработчики событий, relatedPoints для карты - CatalogPage.vue - проброс relatedPoints в CatalogMap - CatalogMap.vue - related points layer (cyan circles) для отображения связанных объектов Флоу: 1. Клик на чип → Selection → Выбор → Info открывается 2. Клик на карту → Info открывается напрямую 3. В Info показываются табы со связанными объектами (top-12) 4. Клик на связанный объект → навигация к его Info 5. Кнопка "Добавить в фильтр" - добавляет объект в chips URL sharing: ?info=type:uuid для шаринга ссылок Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import type { LocationQuery } from 'vue-router'
|
||||
export type SelectMode = 'product' | 'supplier' | 'hub' | null
|
||||
export type MapViewMode = 'offers' | 'hubs' | 'suppliers'
|
||||
export type CatalogMode = 'explore' | 'quote'
|
||||
export type InfoEntityType = 'hub' | 'supplier' | 'offer'
|
||||
export type DisplayMode =
|
||||
| 'map-default'
|
||||
| 'grid-products'
|
||||
@@ -13,6 +14,11 @@ export type DisplayMode =
|
||||
| 'grid-products-in-hub'
|
||||
| 'grid-offers'
|
||||
|
||||
export interface InfoId {
|
||||
type: InfoEntityType
|
||||
uuid: string
|
||||
}
|
||||
|
||||
export interface SearchFilter {
|
||||
type: 'product' | 'supplier' | 'hub' | 'quantity'
|
||||
id: string
|
||||
@@ -56,6 +62,17 @@ export function useCatalogSearch() {
|
||||
return null
|
||||
})
|
||||
|
||||
// Parse info state from query param (format: "type:uuid")
|
||||
const infoId = computed<InfoId | null>(() => {
|
||||
const info = route.query.info as string | undefined
|
||||
if (!info) return null
|
||||
const [type, uuid] = info.split(':')
|
||||
if (['hub', 'supplier', 'offer'].includes(type) && uuid) {
|
||||
return { type: type as InfoEntityType, uuid }
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
const productId = computed(() => route.query.product as string | undefined)
|
||||
const supplierId = computed(() => route.query.supplier as string | undefined)
|
||||
const hubId = computed(() => route.query.hub as string | undefined)
|
||||
@@ -210,6 +227,14 @@ export function useCatalogSearch() {
|
||||
updateQuery({ qty })
|
||||
}
|
||||
|
||||
const openInfo = (type: InfoEntityType, uuid: string) => {
|
||||
updateQuery({ info: `${type}:${uuid}`, select: null })
|
||||
}
|
||||
|
||||
const closeInfo = () => {
|
||||
updateQuery({ info: null })
|
||||
}
|
||||
|
||||
const clearAll = () => {
|
||||
if (isMainPage.value) {
|
||||
router.push({ path: localePath('/catalog'), query: {} })
|
||||
@@ -256,6 +281,7 @@ export function useCatalogSearch() {
|
||||
return {
|
||||
// State
|
||||
selectMode,
|
||||
infoId,
|
||||
displayMode,
|
||||
catalogMode,
|
||||
productId,
|
||||
@@ -283,6 +309,8 @@ export function useCatalogSearch() {
|
||||
removeFilter,
|
||||
editFilter,
|
||||
setQuantity,
|
||||
openInfo,
|
||||
closeInfo,
|
||||
clearAll,
|
||||
setLabel,
|
||||
setMapViewMode,
|
||||
|
||||
Reference in New Issue
Block a user