Initial commit from monorepo
This commit is contained in:
198
app/pages/select-location/index.vue
Normal file
198
app/pages/select-location/index.vue
Normal file
@@ -0,0 +1,198 @@
|
||||
<template>
|
||||
<div class="container mx-auto px-4 py-8 max-w-4xl">
|
||||
<PageHeader :title="t('common.selectLocation')">
|
||||
<template #actions>
|
||||
<button class="btn btn-ghost" @click="router.back()">
|
||||
<Icon name="lucide:x" size="20" />
|
||||
</button>
|
||||
</template>
|
||||
</PageHeader>
|
||||
|
||||
<Stack gap="8" class="mt-6">
|
||||
<!-- My addresses -->
|
||||
<Stack v-if="isAuthenticated && teamAddresses?.length" gap="4">
|
||||
<Heading :level="3">{{ t('profileAddresses.header.title') }}</Heading>
|
||||
<Grid :cols="1" :md="2" :gap="4">
|
||||
<Card
|
||||
v-for="addr in teamAddresses"
|
||||
:key="addr.uuid"
|
||||
padding="small"
|
||||
interactive
|
||||
:class="{ 'ring-2 ring-primary': isSelected('address', addr.uuid) }"
|
||||
@click="selectAddress(addr)"
|
||||
>
|
||||
<Stack gap="2">
|
||||
<Stack direction="row" align="center" gap="2">
|
||||
<Icon name="lucide:map-pin" size="18" class="text-primary" />
|
||||
<Text size="base" weight="semibold">{{ addr.name }}</Text>
|
||||
<Pill v-if="addr.isDefault" variant="outline" size="sm">Default</Pill>
|
||||
</Stack>
|
||||
<Text tone="muted" size="sm">{{ addr.address }}</Text>
|
||||
</Stack>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Stack>
|
||||
|
||||
<!-- Hubs -->
|
||||
<Stack gap="4">
|
||||
<Heading :level="3">{{ t('catalogMap.hubsTab') }}</Heading>
|
||||
|
||||
<NuxtLink :to="localePath('/select-location/map')" class="block h-48 rounded-lg overflow-hidden cursor-pointer">
|
||||
<ClientOnly>
|
||||
<MapboxGlobe
|
||||
map-id="select-location-map"
|
||||
:locations="itemsWithCoords"
|
||||
:height="192"
|
||||
/>
|
||||
</ClientOnly>
|
||||
</NuxtLink>
|
||||
|
||||
<CatalogFilters :filters="filters" v-model="selectedFilter" />
|
||||
|
||||
<div v-if="isLoading" class="flex items-center justify-center p-8">
|
||||
<span class="loading loading-spinner loading-lg" />
|
||||
</div>
|
||||
|
||||
<EmptyState
|
||||
v-else-if="!items?.length"
|
||||
:title="t('catalogMap.noHubs')"
|
||||
/>
|
||||
|
||||
<template v-else>
|
||||
<Grid :cols="1" :md="2" :gap="4">
|
||||
<HubCard
|
||||
v-for="hub in items"
|
||||
:key="hub.uuid"
|
||||
:hub="hub"
|
||||
selectable
|
||||
:is-selected="isSelected('hub', hub.uuid)"
|
||||
@select="selectHub(hub)"
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<PaginationLoadMore
|
||||
:shown="items.length"
|
||||
:total="total"
|
||||
:can-load-more="canLoadMore"
|
||||
:loading="isLoadingMore"
|
||||
@load-more="loadMore"
|
||||
/>
|
||||
</template>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useLocationStore } from '~/stores/location'
|
||||
|
||||
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()
|
||||
|
||||
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) => {
|
||||
console.log('[selectHub] called', { hub, isSearchMode: isSearchMode.value })
|
||||
|
||||
if (isSearchMode.value) {
|
||||
searchStore.setLocation(hub.name)
|
||||
searchStore.setLocationUuid(hub.uuid)
|
||||
if (goToRequestIfReady()) return
|
||||
router.back()
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('[selectHub] calling locationStore.select')
|
||||
const success = await locationStore.select('hub', hub.uuid, hub.name, hub.latitude, hub.longitude)
|
||||
console.log('[selectHub] result:', success)
|
||||
if (success) {
|
||||
router.back()
|
||||
} else {
|
||||
console.error('[selectHub] Selection failed - success=false')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[selectHub] Error:', e)
|
||||
}
|
||||
}
|
||||
|
||||
const selectAddress = async (addr: any) => {
|
||||
console.log('[selectAddress] called', { addr, isSearchMode: isSearchMode.value })
|
||||
|
||||
if (isSearchMode.value) {
|
||||
searchStore.setLocation(addr.address || addr.name)
|
||||
searchStore.setLocationUuid(addr.uuid)
|
||||
if (goToRequestIfReady()) return
|
||||
router.back()
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('[selectAddress] calling locationStore.select')
|
||||
const success = await locationStore.select('address', addr.uuid, addr.name, addr.latitude, addr.longitude)
|
||||
console.log('[selectAddress] result:', success)
|
||||
if (success) {
|
||||
router.back()
|
||||
} else {
|
||||
console.error('[selectAddress] Selection failed - success=false')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[selectAddress] Error:', e)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user