Files
webapp/app/pages/select-location/index.vue
Ruslan Bakiev 53904ead05
All checks were successful
Build Docker Image / build (push) Successful in 3m38s
Fix: offers map coords, map position, orders filter, select-location layout
2026-01-08 13:01:54 +07:00

189 lines
5.1 KiB
Vue

<template>
<CatalogPage
:items="itemsWithCoords"
:loading="isLoading"
map-id="select-location-map"
point-color="#10b981"
:selected-id="selectedHubId"
v-model:hovered-id="hoveredHubId"
@select="selectHub"
>
<template #header>
<Stack gap="4">
<!-- Back button -->
<div class="flex justify-between items-center">
<Heading :level="2">{{ t('common.selectLocation') }}</Heading>
<button class="btn btn-ghost btn-sm" @click="router.back()">
<Icon name="lucide:x" size="20" />
</button>
</div>
<!-- My addresses section -->
<Stack v-if="isAuthenticated && teamAddresses?.length" gap="3">
<Text weight="semibold">{{ t('profileAddresses.header.title') }}</Text>
<Stack gap="2">
<Card
v-for="addr in teamAddresses"
:key="addr.uuid"
padding="sm"
interactive
:class="{ 'ring-2 ring-primary': isSelected('address', addr.uuid) }"
@click="selectAddress(addr)"
>
<Stack gap="1">
<Stack direction="row" align="center" gap="2">
<Icon name="lucide:map-pin" size="16" class="text-primary" />
<Text size="sm" weight="semibold">{{ addr.name }}</Text>
<Pill v-if="addr.isDefault" variant="outline" size="sm">Default</Pill>
</Stack>
<Text tone="muted" size="xs">{{ addr.address }}</Text>
</Stack>
</Card>
</Stack>
</Stack>
<!-- Hubs section header -->
<Text weight="semibold">{{ t('catalogMap.hubsTab') }}</Text>
</Stack>
</template>
<template #filters>
<CatalogFilterSelect :filters="filters" v-model="selectedFilter" />
</template>
<template #card="{ item }">
<HubCard
:hub="item"
selectable
:is-selected="isSelected('hub', item.uuid)"
/>
</template>
<template #pagination>
<PaginationLoadMore
:shown="items.length"
:total="total"
:can-load-more="canLoadMore"
:loading="isLoadingMore"
@load-more="loadMore"
/>
</template>
<template #empty>
<EmptyState :title="t('catalogMap.noHubs')" />
</template>
</CatalogPage>
</template>
<script setup lang="ts">
import { useLocationStore } from '~/stores/location'
definePageMeta({
layout: 'topnav'
})
const router = useRouter()
const route = useRoute()
const { t } = useI18n()
const localePath = useLocalePath()
const { isAuthenticated } = useAuth()
const locationStore = useLocationStore()
const searchStore = useSearchStore()
const isSearchMode = computed(() => route.query.mode === 'search')
// Use shared composable for hubs
const {
items,
total,
selectedFilter,
filters,
isLoading,
isLoadingMore,
itemsWithCoords,
canLoadMore,
loadMore,
init
} = useCatalogHubs()
// Selected/hovered hub for map
const selectedHubId = ref<string>()
const hoveredHubId = ref<string>()
await init()
// Load team addresses
const teamAddresses = ref<any[]>([])
if (isAuthenticated.value) {
try {
const { execute } = useGraphQL()
const { GetTeamAddressesDocument } = await import('~/composables/graphql/team/teams-generated')
const data = await execute(GetTeamAddressesDocument, {}, 'team', 'teams')
teamAddresses.value = data?.teamAddresses || []
} catch {
// Not critical
}
}
const isSelected = (type: 'address' | 'hub', uuid: string) => {
return locationStore.selectedLocation?.type === type && locationStore.selectedLocation?.uuid === uuid
}
const goToRequestIfReady = () => {
if (route.query.after === 'request' && searchStore.searchForm.productUuid && searchStore.searchForm.locationUuid) {
router.push({
path: '/request',
query: {
productUuid: searchStore.searchForm.productUuid,
product: searchStore.searchForm.product,
locationUuid: searchStore.searchForm.locationUuid,
location: searchStore.searchForm.location,
quantity: searchStore.searchForm.quantity || undefined
}
})
return true
}
return false
}
const selectHub = async (hub: any) => {
selectedHubId.value = hub.uuid
if (isSearchMode.value) {
searchStore.setLocation(hub.name)
searchStore.setLocationUuid(hub.uuid)
if (goToRequestIfReady()) return
router.back()
return
}
try {
const success = await locationStore.select('hub', hub.uuid, hub.name, hub.latitude, hub.longitude)
if (success) {
router.back()
}
} catch (e) {
console.error('[selectHub] Error:', e)
}
}
const selectAddress = async (addr: any) => {
if (isSearchMode.value) {
searchStore.setLocation(addr.address || addr.name)
searchStore.setLocationUuid(addr.uuid)
if (goToRequestIfReady()) return
router.back()
return
}
try {
const success = await locationStore.select('address', addr.uuid, addr.name, addr.latitude, addr.longitude)
if (success) {
router.back()
}
} catch (e) {
console.error('[selectAddress] Error:', e)
}
}
</script>