152 lines
4.7 KiB
Vue
152 lines
4.7 KiB
Vue
<template>
|
|
<div class="fixed inset-0">
|
|
<ClientOnly>
|
|
<CatalogMap
|
|
map-id="step-quantity-map"
|
|
:items="mapPoints"
|
|
:use-server-clustering="false"
|
|
point-color="#22c55e"
|
|
entity-type="hub"
|
|
:related-points="relatedPoints"
|
|
:info-loading="false"
|
|
:fit-padding-left="460"
|
|
/>
|
|
</ClientOnly>
|
|
|
|
<MapSidePanel
|
|
:title="t('catalog.steps.setQuantity')"
|
|
:initial-collapsed="false"
|
|
width-class="w-[min(calc(100vw-1rem),440px)] md:w-[420px] xl:w-[460px]"
|
|
>
|
|
<div class="space-y-4">
|
|
<p class="text-xs font-bold uppercase tracking-wider text-[#8a7761]">{{ $t('catalog.step', { n: 3 }) }}</p>
|
|
|
|
<div class="flex flex-wrap gap-2">
|
|
<div v-if="productName" class="inline-flex items-center gap-2 rounded-full border border-[#ded3c2] bg-white px-3 py-1.5 text-xs font-medium text-[#6f6353]">
|
|
<Icon name="lucide:package" size="14" />
|
|
<span class="truncate">{{ productName }}</span>
|
|
</div>
|
|
<div v-if="hubName" class="inline-flex items-center gap-2 rounded-full border border-[#ded3c2] bg-white px-3 py-1.5 text-xs font-medium text-[#6f6353]">
|
|
<Icon name="lucide:warehouse" size="14" />
|
|
<span class="truncate">{{ hubName }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="space-y-2">
|
|
<label class="text-sm font-semibold text-[#4a3b2a]">{{ $t('catalog.filters.quantity') }}</label>
|
|
<label class="input w-full rounded-2xl bg-white border-[#dccfbf] flex items-center gap-2">
|
|
<input
|
|
v-model="qty"
|
|
type="number"
|
|
min="0"
|
|
step="0.1"
|
|
placeholder="100"
|
|
class="grow bg-transparent [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
|
>
|
|
<span class="text-[#8a7761] text-sm">{{ $t('units.t') }}</span>
|
|
</label>
|
|
</div>
|
|
|
|
<button
|
|
class="btn w-full rounded-full border-0 bg-[#10223b] text-white hover:bg-[#1b3552]"
|
|
:disabled="!canSearch"
|
|
@click="goSearch"
|
|
>
|
|
<Icon name="lucide:search" size="18" />
|
|
{{ $t('catalog.quote.findOffers') }}
|
|
</button>
|
|
</div>
|
|
|
|
<template #footer>
|
|
<button
|
|
class="btn btn-sm rounded-full border-[#d7c9b7] bg-white text-[#2f2418] hover:bg-[#f7f1e8]"
|
|
@click="goBack"
|
|
>
|
|
<Icon name="lucide:arrow-left" size="14" />
|
|
{{ $t('common.back') }}
|
|
</button>
|
|
</template>
|
|
</MapSidePanel>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { GetNodeDocument } from '~/composables/graphql/public/geo-generated'
|
|
|
|
definePageMeta({ layout: 'topnav' })
|
|
|
|
const { t } = useI18n()
|
|
const router = useRouter()
|
|
const localePath = useLocalePath()
|
|
const route = useRoute()
|
|
const { execute } = useGraphQL()
|
|
|
|
const qty = ref(typeof route.query.qty === 'string' ? route.query.qty : '100')
|
|
|
|
const productUuid = computed(() => route.query.product as string | undefined)
|
|
const productName = computed(() => route.query.productName as string | undefined)
|
|
const hubUuid = computed(() => route.query.hub as string | undefined)
|
|
const hubName = computed(() => route.query.hubName as string | undefined)
|
|
|
|
const canSearch = computed(() => !!(productUuid.value && hubUuid.value && Number(qty.value) > 0))
|
|
|
|
const hubPoint = ref<{ uuid: string; name: string; latitude: number; longitude: number } | null>(null)
|
|
|
|
const loadHubPoint = async () => {
|
|
if (!hubUuid.value) return
|
|
|
|
const data = await execute(GetNodeDocument, { uuid: hubUuid.value }, 'public', 'geo')
|
|
const node = data?.node
|
|
|
|
if (node?.latitude != null && node?.longitude != null) {
|
|
hubPoint.value = {
|
|
uuid: node.uuid,
|
|
name: node.name || hubName.value || '',
|
|
latitude: Number(node.latitude),
|
|
longitude: Number(node.longitude),
|
|
}
|
|
}
|
|
}
|
|
|
|
const mapPoints = computed(() => hubPoint.value ? [hubPoint.value] : [])
|
|
|
|
const relatedPoints = computed(() => {
|
|
if (!hubPoint.value) return []
|
|
return [{
|
|
uuid: hubPoint.value.uuid,
|
|
name: hubPoint.value.name,
|
|
latitude: hubPoint.value.latitude,
|
|
longitude: hubPoint.value.longitude,
|
|
type: 'hub' as const,
|
|
}]
|
|
})
|
|
|
|
const goSearch = () => {
|
|
const query: Record<string, string> = {
|
|
...route.query as Record<string, string>,
|
|
}
|
|
|
|
if (qty.value) query.qty = qty.value
|
|
|
|
router.push({
|
|
path: localePath('/catalog/results'),
|
|
query,
|
|
})
|
|
}
|
|
|
|
const goBack = () => {
|
|
router.push({
|
|
path: localePath('/catalog/destination'),
|
|
query: route.query,
|
|
})
|
|
}
|
|
|
|
onMounted(() => {
|
|
loadHubPoint()
|
|
})
|
|
|
|
useHead(() => ({
|
|
title: t('catalog.steps.setQuantity')
|
|
}))
|
|
</script>
|