Initial commit from monorepo
This commit is contained in:
155
app/components/catalog/CatalogMapPanel.vue
Normal file
155
app/components/catalog/CatalogMapPanel.vue
Normal file
@@ -0,0 +1,155 @@
|
||||
<template>
|
||||
<Card class="h-full flex flex-col overflow-hidden">
|
||||
<!-- Tabs -->
|
||||
<div class="flex border-b border-base-300 flex-shrink-0 bg-base-200/70 rounded-t-xl">
|
||||
<button
|
||||
v-for="tab in tabs"
|
||||
:key="tab.id"
|
||||
class="flex-1 px-4 py-3 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring focus-visible:ring-primary/30"
|
||||
:class="[
|
||||
activeTab === tab.id
|
||||
? 'text-primary border-b-2 border-primary bg-primary/10'
|
||||
: 'text-base-content/70 hover:text-base-content hover:bg-base-200'
|
||||
]"
|
||||
@click="activeTab = tab.id"
|
||||
>
|
||||
{{ t(tab.label) }}
|
||||
<span class="ml-1 text-xs text-base-content/60">({{ tab.count }})</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- List -->
|
||||
<div class="flex-1 overflow-y-auto p-3 space-y-2 bg-base-100">
|
||||
<!-- Hubs Tab -->
|
||||
<template v-if="activeTab === 'hubs'">
|
||||
<HubCard
|
||||
v-for="hub in hubs"
|
||||
:key="hub.uuid"
|
||||
:hub="hub"
|
||||
selectable
|
||||
:is-selected="selectedId === hub.uuid"
|
||||
@select="selectHub(hub)"
|
||||
/>
|
||||
<Text v-if="hubs.length === 0" tone="muted" size="sm" class="text-center py-4">
|
||||
{{ t('catalogMap.empty.hubs') }}
|
||||
</Text>
|
||||
</template>
|
||||
|
||||
<!-- Offers Tab -->
|
||||
<template v-if="activeTab === 'offers'">
|
||||
<OfferCard
|
||||
v-for="offer in offers"
|
||||
:key="offer.uuid"
|
||||
:offer="offer"
|
||||
selectable
|
||||
compact
|
||||
:is-selected="selectedId === offer.uuid"
|
||||
@select="selectOffer(offer)"
|
||||
/>
|
||||
<Text v-if="offers.length === 0" tone="muted" size="sm" class="text-center py-4">
|
||||
{{ t('catalogMap.empty.offers') }}
|
||||
</Text>
|
||||
</template>
|
||||
|
||||
<!-- Suppliers Tab -->
|
||||
<template v-if="activeTab === 'suppliers'">
|
||||
<SupplierCard
|
||||
v-for="supplier in suppliers"
|
||||
:key="supplier.uuid"
|
||||
:supplier="supplier"
|
||||
selectable
|
||||
:is-selected="selectedId === supplier.uuid"
|
||||
@select="selectSupplier(supplier)"
|
||||
/>
|
||||
<Text v-if="suppliers.length === 0" tone="muted" size="sm" class="text-center py-4">
|
||||
{{ t('catalogMap.empty.suppliers') }}
|
||||
</Text>
|
||||
</template>
|
||||
</div>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
interface Hub {
|
||||
uuid?: string | null
|
||||
name?: string | null
|
||||
country?: string | null
|
||||
latitude?: number | null
|
||||
longitude?: number | null
|
||||
distance?: string
|
||||
}
|
||||
|
||||
interface Offer {
|
||||
uuid?: string | null
|
||||
title?: string | null
|
||||
locationName?: string | null
|
||||
status?: string | null
|
||||
latitude?: number | null
|
||||
longitude?: number | null
|
||||
lines?: any[] | null
|
||||
}
|
||||
|
||||
interface Supplier {
|
||||
uuid?: string | null
|
||||
name?: string | null
|
||||
country?: string | null
|
||||
offersCount?: number | null
|
||||
isVerified?: boolean | null
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
hubs: Hub[]
|
||||
offers: Offer[]
|
||||
suppliers: Supplier[]
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'fly-to', location: { uuid: string; name: string; latitude: number; longitude: number; country?: string }): void
|
||||
}>()
|
||||
|
||||
type TabId = 'hubs' | 'offers' | 'suppliers'
|
||||
|
||||
const activeTab = ref<TabId>('hubs')
|
||||
const selectedId = ref<string | null>(null)
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const tabs = computed(() => [
|
||||
{ id: 'hubs' as const, label: 'catalogMap.tabs.hubs', count: props.hubs.length },
|
||||
{ id: 'offers' as const, label: 'catalogMap.tabs.offers', count: props.offers.length },
|
||||
{ id: 'suppliers' as const, label: 'catalogMap.tabs.suppliers', count: props.suppliers.length }
|
||||
])
|
||||
|
||||
const selectHub = (hub: Hub) => {
|
||||
selectedId.value = hub.uuid || null
|
||||
|
||||
if (hub.latitude && hub.longitude) {
|
||||
emit('fly-to', {
|
||||
uuid: hub.uuid!,
|
||||
name: hub.name || '',
|
||||
latitude: hub.latitude,
|
||||
longitude: hub.longitude,
|
||||
country: hub.country || undefined
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const selectOffer = (offer: Offer) => {
|
||||
selectedId.value = offer.uuid || null
|
||||
|
||||
if (offer.latitude && offer.longitude) {
|
||||
emit('fly-to', {
|
||||
uuid: offer.uuid!,
|
||||
name: offer.title || '',
|
||||
latitude: offer.latitude,
|
||||
longitude: offer.longitude,
|
||||
country: offer.locationName || undefined
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const selectSupplier = (supplier: Supplier) => {
|
||||
selectedId.value = supplier.uuid || null
|
||||
// Suppliers don't have coordinates currently
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user