Fix: offers map coords, map position, orders filter, select-location layout
All checks were successful
Build Docker Image / build (push) Successful in 3m38s
All checks were successful
Build Docker Image / build (push) Successful in 3m38s
This commit is contained in:
@@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
<!-- Right: Map (fixed position) -->
|
<!-- Right: Map (fixed position) -->
|
||||||
<div class="w-3/5 relative">
|
<div class="w-3/5 relative">
|
||||||
<div class="fixed top-28 right-6 w-[calc(60%-3rem)] h-[calc(100vh-8rem)] rounded-lg overflow-hidden">
|
<div class="fixed top-32 right-6 w-[calc(60%-3rem)] h-[calc(100vh-9rem)] rounded-lg overflow-hidden">
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<CatalogMap
|
<CatalogMap
|
||||||
ref="mapRef"
|
ref="mapRef"
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ export function useTeamOrders() {
|
|||||||
const { execute } = useGraphQL()
|
const { execute } = useGraphQL()
|
||||||
|
|
||||||
const filters = computed(() => [
|
const filters = computed(() => [
|
||||||
{ key: 'all', label: t('ordersList.filters.all') },
|
{ id: 'all', label: t('ordersList.filters.all') },
|
||||||
{ key: 'pending', label: t('ordersList.filters.pending') },
|
{ id: 'pending', label: t('ordersList.filters.pending') },
|
||||||
{ key: 'processing', label: t('ordersList.filters.processing') },
|
{ id: 'processing', label: t('ordersList.filters.processing') },
|
||||||
{ key: 'in_transit', label: t('ordersList.filters.in_transit') },
|
{ id: 'in_transit', label: t('ordersList.filters.in_transit') },
|
||||||
{ key: 'delivered', label: t('ordersList.filters.delivered') }
|
{ id: 'delivered', label: t('ordersList.filters.delivered') }
|
||||||
])
|
])
|
||||||
|
|
||||||
const selectedFilter = ref('all')
|
const selectedFilter = ref('all')
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<CatalogPage
|
<CatalogPage
|
||||||
:items="items"
|
:items="itemsForMap"
|
||||||
:loading="isLoading || productsLoading"
|
:loading="isLoading || productsLoading"
|
||||||
map-id="offers-map"
|
map-id="offers-map"
|
||||||
point-color="#f59e0b"
|
point-color="#f59e0b"
|
||||||
@@ -64,6 +64,13 @@ const {
|
|||||||
setProductUuid
|
setProductUuid
|
||||||
} = useCatalogOffers()
|
} = useCatalogOffers()
|
||||||
|
|
||||||
|
// Map items with correct coordinate field names
|
||||||
|
const itemsForMap = computed(() => items.value.map(offer => ({
|
||||||
|
...offer,
|
||||||
|
latitude: offer.locationLatitude,
|
||||||
|
longitude: offer.locationLongitude
|
||||||
|
})))
|
||||||
|
|
||||||
// Product filter options
|
// Product filter options
|
||||||
const productFilters = computed(() => {
|
const productFilters = computed(() => {
|
||||||
const all = [{ id: 'all', label: t('catalogOffersSection.filters.all_products') }]
|
const all = [{ id: 'all', label: t('catalogOffersSection.filters.all_products') }]
|
||||||
|
|||||||
@@ -1,86 +1,78 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container mx-auto px-4 py-8">
|
<CatalogPage
|
||||||
<PageHeader :title="t('common.selectLocation')">
|
:items="itemsWithCoords"
|
||||||
<template #actions>
|
:loading="isLoading"
|
||||||
<button class="btn btn-ghost" @click="router.back()">
|
map-id="select-location-map"
|
||||||
<Icon name="lucide:x" size="20" />
|
point-color="#10b981"
|
||||||
</button>
|
:selected-id="selectedHubId"
|
||||||
</template>
|
v-model:hovered-id="hoveredHubId"
|
||||||
</PageHeader>
|
@select="selectHub"
|
||||||
|
>
|
||||||
<Stack gap="8" class="mt-6">
|
<template #header>
|
||||||
<!-- 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">
|
<Stack gap="4">
|
||||||
<Heading :level="3">{{ t('catalogMap.hubsTab') }}</Heading>
|
<!-- Back button -->
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
<NuxtLink :to="localePath('/select-location/map')" class="block h-48 rounded-lg overflow-hidden cursor-pointer">
|
<Heading :level="2">{{ t('common.selectLocation') }}</Heading>
|
||||||
<ClientOnly>
|
<button class="btn btn-ghost btn-sm" @click="router.back()">
|
||||||
<MapboxGlobe
|
<Icon name="lucide:x" size="20" />
|
||||||
map-id="select-location-map"
|
</button>
|
||||||
: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>
|
</div>
|
||||||
|
|
||||||
<EmptyState
|
<!-- My addresses section -->
|
||||||
v-else-if="!items?.length"
|
<Stack v-if="isAuthenticated && teamAddresses?.length" gap="3">
|
||||||
:title="t('catalogMap.noHubs')"
|
<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>
|
||||||
|
|
||||||
<template v-else>
|
<!-- Hubs section header -->
|
||||||
<Grid :cols="1" :md="2" :gap="4">
|
<Text weight="semibold">{{ t('catalogMap.hubsTab') }}</Text>
|
||||||
<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>
|
||||||
</Stack>
|
</template>
|
||||||
</div>
|
|
||||||
|
<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>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -113,6 +105,10 @@ const {
|
|||||||
init
|
init
|
||||||
} = useCatalogHubs()
|
} = useCatalogHubs()
|
||||||
|
|
||||||
|
// Selected/hovered hub for map
|
||||||
|
const selectedHubId = ref<string>()
|
||||||
|
const hoveredHubId = ref<string>()
|
||||||
|
|
||||||
await init()
|
await init()
|
||||||
|
|
||||||
// Load team addresses
|
// Load team addresses
|
||||||
@@ -151,7 +147,7 @@ const goToRequestIfReady = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const selectHub = async (hub: any) => {
|
const selectHub = async (hub: any) => {
|
||||||
console.log('[selectHub] called', { hub, isSearchMode: isSearchMode.value })
|
selectedHubId.value = hub.uuid
|
||||||
|
|
||||||
if (isSearchMode.value) {
|
if (isSearchMode.value) {
|
||||||
searchStore.setLocation(hub.name)
|
searchStore.setLocation(hub.name)
|
||||||
@@ -162,13 +158,9 @@ const selectHub = async (hub: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('[selectHub] calling locationStore.select')
|
|
||||||
const success = await locationStore.select('hub', hub.uuid, hub.name, hub.latitude, hub.longitude)
|
const success = await locationStore.select('hub', hub.uuid, hub.name, hub.latitude, hub.longitude)
|
||||||
console.log('[selectHub] result:', success)
|
|
||||||
if (success) {
|
if (success) {
|
||||||
router.back()
|
router.back()
|
||||||
} else {
|
|
||||||
console.error('[selectHub] Selection failed - success=false')
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('[selectHub] Error:', e)
|
console.error('[selectHub] Error:', e)
|
||||||
@@ -176,8 +168,6 @@ const selectHub = async (hub: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const selectAddress = async (addr: any) => {
|
const selectAddress = async (addr: any) => {
|
||||||
console.log('[selectAddress] called', { addr, isSearchMode: isSearchMode.value })
|
|
||||||
|
|
||||||
if (isSearchMode.value) {
|
if (isSearchMode.value) {
|
||||||
searchStore.setLocation(addr.address || addr.name)
|
searchStore.setLocation(addr.address || addr.name)
|
||||||
searchStore.setLocationUuid(addr.uuid)
|
searchStore.setLocationUuid(addr.uuid)
|
||||||
@@ -187,13 +177,9 @@ const selectAddress = async (addr: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('[selectAddress] calling locationStore.select')
|
|
||||||
const success = await locationStore.select('address', addr.uuid, addr.name, addr.latitude, addr.longitude)
|
const success = await locationStore.select('address', addr.uuid, addr.name, addr.latitude, addr.longitude)
|
||||||
console.log('[selectAddress] result:', success)
|
|
||||||
if (success) {
|
if (success) {
|
||||||
router.back()
|
router.back()
|
||||||
} else {
|
|
||||||
console.error('[selectAddress] Selection failed - success=false')
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('[selectAddress] Error:', e)
|
console.error('[selectAddress] Error:', e)
|
||||||
|
|||||||
Reference in New Issue
Block a user