feat(orders): open order details in bottom sheet (no page transition)
All checks were successful
Build Docker Image / build (push) Successful in 4m1s

- Created OrderDetailBottomSheet.vue component (like KycBottomSheet)
- Click on order in list opens bottom sheet instead of navigating
- Slide-up animation with backdrop
- Click backdrop or X to close
This commit is contained in:
Ruslan Bakiev
2026-01-29 19:49:21 +07:00
parent de3ec4c39d
commit 1850d255a7
2 changed files with 439 additions and 42 deletions

View File

@@ -1,17 +1,18 @@
<template>
<CatalogPage
:items="mapPoints"
:loading="isLoading"
:use-server-clustering="false"
map-id="orders-map"
point-color="#6366f1"
:hovered-id="hoveredOrderId"
:show-panel="true"
panel-width="w-96"
:hide-view-toggle="true"
@select="onMapSelect"
@update:hovered-id="hoveredOrderId = $event"
>
<div>
<CatalogPage
:items="mapPoints"
:loading="isLoading"
:use-server-clustering="false"
map-id="orders-map"
point-color="#6366f1"
:hovered-id="hoveredOrderId"
:show-panel="true"
panel-width="w-96"
:hide-view-toggle="true"
@select="onMapSelect"
@update:hovered-id="hoveredOrderId = $event"
>
<template #panel>
<!-- Panel header -->
<div class="p-4 border-b border-white/10 flex-shrink-0">
@@ -58,38 +59,35 @@
<!-- Orders list -->
<div class="flex-1 overflow-y-auto p-3 space-y-2">
<template v-if="displayItems.length > 0">
<NuxtLink
<div
v-for="item in displayItems"
:key="item.uuid"
:to="localePath(`/clientarea/orders/${item.uuid}`)"
class="block"
class="bg-white/10 rounded-lg p-3 hover:bg-white/20 transition-colors cursor-pointer"
:class="{ 'ring-2 ring-indigo-500': selectedOrderId === item.uuid }"
@click="selectedOrderId = item.uuid"
@mouseenter="hoveredOrderId = item.uuid"
@mouseleave="hoveredOrderId = undefined"
>
<div
class="bg-white/10 rounded-lg p-3 hover:bg-white/20 transition-colors cursor-pointer"
@mouseenter="hoveredOrderId = item.uuid"
@mouseleave="hoveredOrderId = undefined"
>
<div class="flex items-center justify-between mb-2">
<span class="font-semibold text-sm">#{{ item.name }}</span>
<span class="badge badge-sm" :class="getStatusBadgeClass(item.status)">
{{ getStatusText(item.status) }}
</span>
<div class="flex items-center justify-between mb-2">
<span class="font-semibold text-sm">#{{ item.name }}</span>
<span class="badge badge-sm" :class="getStatusBadgeClass(item.status)">
{{ getStatusText(item.status) }}
</span>
</div>
<div class="text-xs text-white/70 space-y-1">
<div class="flex items-center gap-2">
<Icon name="lucide:map-pin" size="12" class="text-white/40" />
<span class="truncate">{{ item.sourceLocationName }}</span>
</div>
<div class="text-xs text-white/70 space-y-1">
<div class="flex items-center gap-2">
<Icon name="lucide:map-pin" size="12" class="text-white/40" />
<span class="truncate">{{ item.sourceLocationName }}</span>
</div>
<div class="flex items-center gap-2">
<Icon name="lucide:navigation" size="12" class="text-white/40" />
<span class="truncate">{{ item.destinationLocationName }}</span>
</div>
</div>
<div class="text-xs text-white/50 mt-2">
{{ getOrderDate(item) }}
<div class="flex items-center gap-2">
<Icon name="lucide:navigation" size="12" class="text-white/40" />
<span class="truncate">{{ item.destinationLocationName }}</span>
</div>
</div>
</NuxtLink>
<div class="text-xs text-white/50 mt-2">
{{ getOrderDate(item) }}
</div>
</div>
</template>
<template v-else>
<div class="text-center py-8">
@@ -105,7 +103,15 @@
<span class="text-xs text-white/50">{{ displayItems.length }} {{ t('catalog.of') }} {{ filteredItems.length }}</span>
</div>
</template>
</CatalogPage>
</CatalogPage>
<!-- Order Detail Bottom Sheet -->
<OrderDetailBottomSheet
:is-open="!!selectedOrderId"
:order-uuid="selectedOrderId"
@close="selectedOrderId = null"
/>
</div>
</template>
<script setup lang="ts">
@@ -118,7 +124,6 @@ definePageMeta({
middleware: ['auth-oidc']
})
const localePath = useLocalePath()
const { t } = useI18n()
const {
@@ -133,6 +138,7 @@ const {
const hoveredOrderId = ref<string>()
const searchQuery = ref('')
const selectedOrderId = ref<string | null>(null)
// Selected filter label
const selectedFilterLabel = computed(() => {
@@ -170,7 +176,7 @@ const displayItems = computed(() => {
const onMapSelect = (item: { uuid?: string | null }) => {
if (item.uuid) {
navigateTo(localePath(`/clientarea/orders/${item.uuid}`))
selectedOrderId.value = item.uuid
}
}