156 lines
4.3 KiB
Vue
156 lines
4.3 KiB
Vue
<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>
|