fix: pin home capsule flow and switch explore panel to white left dock

This commit is contained in:
Ruslan Bakiev
2026-03-12 15:42:56 +07:00
parent 530c97b912
commit c940369c81
8 changed files with 113 additions and 97 deletions

View File

@@ -1,7 +1,7 @@
<template>
<div class="flex flex-col h-full">
<!-- Header with close button -->
<div class="flex-shrink-0 p-4 border-b border-white/10">
<div class="flex-shrink-0 p-4 border-b border-base-300">
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<div
@@ -10,19 +10,19 @@
>
<Icon :name="entityIcon" size="14" class="text-white" />
</div>
<h3 class="font-semibold text-base text-white">{{ entityName }}</h3>
<h3 class="font-semibold text-base text-base-content">{{ entityName }}</h3>
</div>
<div class="flex items-center gap-2">
<button
v-if="(entityType === 'hub' || entityType === 'supplier') && entity?.uuid"
class="rounded-full glass-bright border border-white/30 shadow-lg p-1.5 transition-transform hover:scale-105"
class="rounded-full bg-base-100 border border-base-300 shadow-lg p-1.5 transition-transform hover:scale-105"
@click="emit('pin', entityType, { uuid: entity?.uuid, name: entity?.name })"
aria-label="Pin"
title="Pin"
>
<Icon name="lucide:pin" size="16" class="text-white" />
<Icon name="lucide:pin" size="16" class="text-base-content" />
</button>
<button class="btn btn-ghost btn-xs btn-circle text-white/60 hover:text-white" @click="emit('close')">
<button class="btn btn-ghost btn-xs btn-circle text-base-content/60 hover:text-base-content" @click="emit('close')">
<Icon name="lucide:x" size="16" />
</button>
</div>
@@ -33,7 +33,7 @@
<div class="flex-1 overflow-y-auto p-4">
<!-- Loading state -->
<div v-if="loading" class="flex items-center justify-center py-8">
<span class="loading loading-spinner loading-md text-white" />
<span class="loading loading-spinner loading-md text-base-content" />
</div>
<!-- Content -->
@@ -41,13 +41,13 @@
<!-- Entity Info Header (text, not card) -->
<div class="mb-2">
<!-- Location for hub/supplier -->
<p v-if="entityLocation" class="text-sm text-white/70 flex items-center gap-1">
<p v-if="entityLocation" class="text-sm text-base-content/70 flex items-center gap-1">
<Icon name="lucide:map-pin" size="14" />
{{ entityLocation }}
</p>
<!-- Price for offer -->
<p v-if="entityType === 'offer' && entity?.pricePerUnit" class="text-sm text-white/70 flex items-center gap-1">
<p v-if="entityType === 'offer' && entity?.pricePerUnit" class="text-sm text-base-content/70 flex items-center gap-1">
<Icon name="lucide:tag" size="14" />
{{ formatPrice(entity.pricePerUnit) }} {{ entity.currency || 'RUB' }}/{{ entity.unit || 't' }}
</p>
@@ -65,8 +65,8 @@
</div>
<!-- KYC Teaser Section (for supplier) -->
<section v-if="entityType === 'supplier' && kycTeaser" class="bg-white/5 rounded-lg p-3">
<h3 class="text-sm font-semibold text-white/80 mb-2 flex items-center gap-2">
<section v-if="entityType === 'supplier' && kycTeaser" class="bg-base-200/50 rounded-lg p-3">
<h3 class="text-sm font-semibold text-base-content/80 mb-2 flex items-center gap-2">
<Icon name="lucide:shield-check" size="16" />
{{ $t('catalog.info.kycTeaser') }}
</h3>
@@ -74,19 +74,19 @@
<div class="flex flex-col gap-2 text-sm">
<!-- Company Type -->
<div class="flex items-center justify-between">
<span class="text-white/60">{{ $t('catalog.info.companyType') }}</span>
<span class="text-white">{{ kycTeaser.companyType }}</span>
<span class="text-base-content/60">{{ $t('catalog.info.companyType') }}</span>
<span class="text-base-content">{{ kycTeaser.companyType }}</span>
</div>
<!-- Registration Year -->
<div class="flex items-center justify-between">
<span class="text-white/60">{{ $t('catalog.info.registrationYear') }}</span>
<span class="text-white">{{ kycTeaser.registrationYear }}</span>
<span class="text-base-content/60">{{ $t('catalog.info.registrationYear') }}</span>
<span class="text-base-content">{{ kycTeaser.registrationYear }}</span>
</div>
<!-- Status -->
<div class="flex items-center justify-between">
<span class="text-white/60">{{ $t('catalog.info.status') }}</span>
<span class="text-base-content/60">{{ $t('catalog.info.status') }}</span>
<span :class="kycTeaser.isActive ? 'text-success' : 'text-error'">
{{ kycTeaser.isActive ? $t('catalog.info.active') : $t('catalog.info.inactive') }}
</span>
@@ -94,8 +94,8 @@
<!-- Sources Count -->
<div class="flex items-center justify-between">
<span class="text-white/60">{{ $t('catalog.info.sourcesCount') }}</span>
<span class="text-white">{{ kycTeaser.sourcesCount }}</span>
<span class="text-base-content/60">{{ $t('catalog.info.sourcesCount') }}</span>
<span class="text-base-content">{{ kycTeaser.sourcesCount }}</span>
</div>
</div>
@@ -111,14 +111,14 @@
<!-- Products Section (for hub/supplier) - hide when product selected -->
<section v-if="(entityType === 'hub' || entityType === 'supplier') && !selectedProduct">
<h3 class="text-sm font-semibold text-white/80 mb-2 flex items-center gap-2">
<h3 class="text-sm font-semibold text-base-content/80 mb-2 flex items-center gap-2">
<Icon name="lucide:package" size="16" />
{{ productsSectionTitle }}
<span v-if="loadingProducts" class="loading loading-spinner loading-xs" />
<span v-else-if="relatedProducts.length > 0" class="text-white/50">({{ relatedProducts.length }})</span>
<span v-else-if="relatedProducts.length > 0" class="text-base-content/50">({{ relatedProducts.length }})</span>
</h3>
<div v-if="!loadingProducts && relatedProducts.length === 0" class="text-white/50 text-sm py-2">
<div v-if="!loadingProducts && relatedProducts.length === 0" class="text-base-content/50 text-sm py-2">
{{ $t('catalog.empty.noProducts') }}
</div>
<div v-else-if="!loadingProducts" class="flex flex-col gap-2">
@@ -134,12 +134,12 @@
@select="onProductSelect(product)"
/>
<button
class="absolute -top-2 -right-2 opacity-0 group-hover:opacity-100 transition-opacity rounded-full glass-bright border border-white/30 shadow-lg p-1.5 hover:scale-105"
class="absolute -top-2 -right-2 opacity-0 group-hover:opacity-100 transition-opacity rounded-full bg-base-100 border border-base-300 shadow-lg p-1.5 hover:scale-105"
@click.stop="emit('pin', 'product', product)"
aria-label="Pin product"
title="Pin"
>
<Icon name="lucide:pin" size="16" class="text-white" />
<Icon name="lucide:pin" size="16" class="text-base-content" />
</button>
</div>
</div>
@@ -148,14 +148,14 @@
<!-- Offers Section (after product selected) -->
<section v-if="(entityType === 'hub' || entityType === 'supplier') && selectedProduct">
<div class="flex items-center justify-between mb-2">
<h3 class="text-sm font-semibold text-white/80 flex items-center gap-2">
<h3 class="text-sm font-semibold text-base-content/80 flex items-center gap-2">
<Icon name="lucide:shopping-bag" size="16" />
{{ $t('catalog.headers.offers') }}
<span v-if="loadingOffers" class="loading loading-spinner loading-xs" />
<span v-else-if="offersWithPrice.length > 0" class="text-white/50">({{ offersWithPrice.length }})</span>
<span v-else-if="offersWithPrice.length > 0" class="text-base-content/50">({{ offersWithPrice.length }})</span>
</h3>
<button
class="flex items-center gap-2 px-2 py-1 rounded-full border border-white/15 bg-white/10 text-xs text-white/80 hover:bg-white/20 transition-colors"
class="flex items-center gap-2 px-2 py-1 rounded-full border border-base-300/70 bg-base-200/70 text-xs text-base-content/80 hover:bg-base-200 transition-colors"
@click="emit('select-product', null)"
>
<Icon name="lucide:package" size="12" />
@@ -164,7 +164,7 @@
</button>
</div>
<div v-if="!loadingOffers && offersWithPrice.length === 0" class="text-white/50 text-sm py-2">
<div v-if="!loadingOffers && offersWithPrice.length === 0" class="text-base-content/50 text-sm py-2">
{{ $t('catalog.empty.noOffers') }}
</div>
<div v-else-if="!loadingOffers" class="flex flex-col gap-2">
@@ -187,14 +187,14 @@
<!-- Suppliers Section (for hub only) -->
<section v-if="entityType === 'hub' && !selectedProduct">
<h3 class="text-sm font-semibold text-white/80 mb-2 flex items-center gap-2">
<h3 class="text-sm font-semibold text-base-content/80 mb-2 flex items-center gap-2">
<Icon name="lucide:factory" size="16" />
{{ $t('catalog.info.suppliersNearby') }}
<span v-if="loadingSuppliers" class="loading loading-spinner loading-xs" />
<span v-else-if="relatedSuppliers.length > 0" class="text-white/50">({{ relatedSuppliers.length }})</span>
<span v-else-if="relatedSuppliers.length > 0" class="text-base-content/50">({{ relatedSuppliers.length }})</span>
</h3>
<div v-if="!loadingSuppliers && relatedSuppliers.length === 0" class="text-white/50 text-sm py-2">
<div v-if="!loadingSuppliers && relatedSuppliers.length === 0" class="text-base-content/50 text-sm py-2">
{{ $t('catalog.info.noSuppliers') }}
</div>
<div v-else-if="!loadingSuppliers" class="flex flex-col gap-2">
@@ -209,12 +209,12 @@
@select="onSupplierSelect(supplier)"
/>
<button
class="absolute -top-2 -right-2 opacity-0 group-hover:opacity-100 transition-opacity rounded-full glass-bright border border-white/30 shadow-lg p-1.5 hover:scale-105"
class="absolute -top-2 -right-2 opacity-0 group-hover:opacity-100 transition-opacity rounded-full bg-base-100 border border-base-300 shadow-lg p-1.5 hover:scale-105"
@click.stop="emit('pin', 'supplier', supplier)"
aria-label="Pin supplier"
title="Pin"
>
<Icon name="lucide:pin" size="16" class="text-white" />
<Icon name="lucide:pin" size="16" class="text-base-content" />
</button>
</div>
</div>
@@ -222,25 +222,25 @@
<!-- Hubs Section (for supplier/offer) -->
<section v-if="entityType === 'supplier' || entityType === 'offer'">
<h3 class="text-sm font-semibold text-white/80 mb-2 flex items-center gap-2">
<h3 class="text-sm font-semibold text-base-content/80 mb-2 flex items-center gap-2">
<Icon name="lucide:warehouse" size="16" />
{{ $t('catalog.info.nearestHubs') }}
<span v-if="loadingHubs" class="loading loading-spinner loading-xs" />
<span v-else-if="relatedHubs.length > 0" class="text-white/50">({{ relatedHubs.length }})</span>
<span v-else-if="relatedHubs.length > 0" class="text-base-content/50">({{ relatedHubs.length }})</span>
</h3>
<div v-if="!loadingHubs && relatedHubs.length === 0" class="text-white/50 text-sm py-2">
<div v-if="!loadingHubs && relatedHubs.length === 0" class="text-base-content/50 text-sm py-2">
{{ $t('catalog.info.noHubs') }}
</div>
<div v-else-if="!loadingHubs" class="space-y-4">
<template v-if="railHubs.length">
<div class="grid grid-cols-2 gap-2">
<Card padding="small" class="border border-white/10 bg-white/5">
<Card padding="small" class="border border-base-300 bg-base-200/50">
<div class="flex items-center gap-2">
<div class="w-8 h-8 rounded-lg bg-white/10 flex items-center justify-center">
<Icon name="lucide:train-front" size="16" class="text-white/80" />
<div class="w-8 h-8 rounded-lg bg-base-200/70 flex items-center justify-center">
<Icon name="lucide:train-front" size="16" class="text-base-content/80" />
</div>
<div class="text-sm text-white/80">{{ $t('catalog.info.railHubs') }}</div>
<div class="text-sm text-base-content/80">{{ $t('catalog.info.railHubs') }}</div>
</div>
</Card>
<div
@@ -255,12 +255,12 @@
@select="onHubSelect(hub)"
/>
<button
class="absolute -top-2 -right-2 opacity-0 group-hover:opacity-100 transition-opacity rounded-full glass-bright border border-white/30 shadow-lg p-1.5 hover:scale-105"
class="absolute -top-2 -right-2 opacity-0 group-hover:opacity-100 transition-opacity rounded-full bg-base-100 border border-base-300 shadow-lg p-1.5 hover:scale-105"
@click.stop="emit('pin', 'hub', hub)"
aria-label="Pin hub"
title="Pin"
>
<Icon name="lucide:pin" size="16" class="text-white" />
<Icon name="lucide:pin" size="16" class="text-base-content" />
</button>
</div>
</div>
@@ -268,12 +268,12 @@
<template v-if="seaHubs.length">
<div class="grid grid-cols-2 gap-2">
<Card padding="small" class="border border-white/10 bg-white/5">
<Card padding="small" class="border border-base-300 bg-base-200/50">
<div class="flex items-center gap-2">
<div class="w-8 h-8 rounded-lg bg-white/10 flex items-center justify-center">
<Icon name="lucide:ship" size="16" class="text-white/80" />
<div class="w-8 h-8 rounded-lg bg-base-200/70 flex items-center justify-center">
<Icon name="lucide:ship" size="16" class="text-base-content/80" />
</div>
<div class="text-sm text-white/80">{{ $t('catalog.info.seaHubs') }}</div>
<div class="text-sm text-base-content/80">{{ $t('catalog.info.seaHubs') }}</div>
</div>
</Card>
<div
@@ -288,12 +288,12 @@
@select="onHubSelect(hub)"
/>
<button
class="absolute -top-2 -right-2 opacity-0 group-hover:opacity-100 transition-opacity rounded-full glass-bright border border-white/30 shadow-lg p-1.5 hover:scale-105"
class="absolute -top-2 -right-2 opacity-0 group-hover:opacity-100 transition-opacity rounded-full bg-base-100 border border-base-300 shadow-lg p-1.5 hover:scale-105"
@click.stop="emit('pin', 'hub', hub)"
aria-label="Pin hub"
title="Pin"
>
<Icon name="lucide:pin" size="16" class="text-white" />
<Icon name="lucide:pin" size="16" class="text-base-content" />
</button>
</div>
</div>

View File

@@ -1,9 +1,9 @@
<template>
<div class="flex flex-col h-full">
<!-- Header -->
<div class="flex-shrink-0 p-4 border-b border-white/10">
<div class="flex-shrink-0 p-4 border-b border-base-300">
<div class="flex items-center justify-between">
<h3 class="font-semibold text-base text-white">{{ $t('catalog.headers.offers') }}</h3>
<h3 class="font-semibold text-base text-base-content">{{ $t('catalog.headers.offers') }}</h3>
<span class="badge badge-neutral">{{ totalOffers }}</span>
</div>
</div>
@@ -11,10 +11,10 @@
<!-- Content (scrollable) -->
<div class="flex-1 overflow-y-auto p-4">
<div v-if="loading" class="flex items-center justify-center py-8">
<span class="loading loading-spinner loading-md text-white" />
<span class="loading loading-spinner loading-md text-base-content" />
</div>
<div v-else-if="offersWithPrice.length === 0" class="text-center py-8 text-white/60">
<div v-else-if="offersWithPrice.length === 0" class="text-center py-8 text-base-content/60">
<Icon name="lucide:search-x" size="32" class="mb-2" />
<p>{{ $t('catalog.empty.noOffers') }}</p>
</div>

View File

@@ -1,10 +1,10 @@
<template>
<div class="flex flex-col h-full">
<!-- Header -->
<div class="flex-shrink-0 p-4 border-b border-white/10">
<div class="flex-shrink-0 p-4 border-b border-base-300">
<div class="flex items-center justify-between mb-3">
<h3 class="font-semibold text-base text-white">{{ title }}</h3>
<button class="btn btn-ghost btn-xs btn-circle text-white/60 hover:text-white" @click="emit('close')">
<h3 class="font-semibold text-base text-base-content">{{ title }}</h3>
<button class="btn btn-ghost btn-xs btn-circle text-base-content/60 hover:text-base-content" @click="emit('close')">
<Icon name="lucide:x" size="16" />
</button>
</div>
@@ -13,10 +13,10 @@
<!-- Content (scrollable) -->
<div class="flex-1 overflow-y-auto p-4">
<div v-if="loading" class="flex items-center justify-center py-8">
<span class="loading loading-spinner loading-md text-white" />
<span class="loading loading-spinner loading-md text-base-content" />
</div>
<div v-else-if="items.length === 0" class="text-center py-8 text-white/60">
<div v-else-if="items.length === 0" class="text-center py-8 text-base-content/60">
<Icon name="lucide:search-x" size="32" class="mb-2" />
<p>{{ $t('catalog.empty.noResults') }}</p>
</div>
@@ -38,12 +38,12 @@
@select="onSelect(item)"
/>
<button
class="absolute -top-2 -right-2 opacity-0 group-hover:opacity-100 transition-opacity rounded-full glass-bright border border-white/30 shadow-lg p-1.5 hover:scale-105"
class="absolute -top-2 -right-2 opacity-0 group-hover:opacity-100 transition-opacity rounded-full bg-base-100 border border-base-300 shadow-lg p-1.5 hover:scale-105"
@click.stop="emit('pin', 'product', item)"
aria-label="Pin product"
title="Pin"
>
<Icon name="lucide:pin" size="16" class="text-white" />
<Icon name="lucide:pin" size="16" class="text-base-content" />
</button>
</div>
</template>
@@ -63,12 +63,12 @@
@select="onSelect(item)"
/>
<button
class="absolute -top-2 -right-2 opacity-0 group-hover:opacity-100 transition-opacity rounded-full glass-bright border border-white/30 shadow-lg p-1.5 hover:scale-105"
class="absolute -top-2 -right-2 opacity-0 group-hover:opacity-100 transition-opacity rounded-full bg-base-100 border border-base-300 shadow-lg p-1.5 hover:scale-105"
@click.stop="emit('pin', 'hub', item)"
aria-label="Pin hub"
title="Pin"
>
<Icon name="lucide:pin" size="16" class="text-white" />
<Icon name="lucide:pin" size="16" class="text-base-content" />
</button>
</div>
</template>
@@ -88,12 +88,12 @@
@select="onSelect(item)"
/>
<button
class="absolute -top-2 -right-2 opacity-0 group-hover:opacity-100 transition-opacity rounded-full glass-bright border border-white/30 shadow-lg p-1.5 hover:scale-105"
class="absolute -top-2 -right-2 opacity-0 group-hover:opacity-100 transition-opacity rounded-full bg-base-100 border border-base-300 shadow-lg p-1.5 hover:scale-105"
@click.stop="emit('pin', 'supplier', item)"
aria-label="Pin supplier"
title="Pin"
>
<Icon name="lucide:pin" size="16" class="text-white" />
<Icon name="lucide:pin" size="16" class="text-base-content" />
</button>
</div>
</template>
@@ -104,7 +104,7 @@
ref="loadMoreSentinel"
class="flex items-center justify-center py-4"
>
<span v-if="loadingMore" class="loading loading-spinner loading-sm text-white/60" />
<span v-if="loadingMore" class="loading loading-spinner loading-sm text-base-content/60" />
</div>
</div>
</div>

View File

@@ -102,10 +102,11 @@
:class="[
isHeroLayout ? 'w-full max-w-none justify-start' : 'max-w-2xl justify-center'
]"
:style="centerStyle"
>
<!-- Hero slot for home page title -->
<slot name="hero" />
<div :style="heroTitleStyle">
<slot name="hero" />
</div>
<!-- Client Area tabs -->
<template v-if="isClientArea">
@@ -419,10 +420,13 @@ const props = withDefaults(defineProps<{
collapseProgress?: number
// Home scroll position for floating center capsule
heroScrollY?: number
// Initial hero height for stable landing capsule start position
heroBaseHeight?: number
}>(), {
height: 100,
collapseProgress: 1,
heroScrollY: 0
heroScrollY: 0,
heroBaseHeight: 0
})
defineEmits([
@@ -527,7 +531,6 @@ const getTokenIcon = (type: string) => {
const isHeroLayout = computed(() => props.isHomePage && !props.isClientArea)
const topRowHeight = 100
const LANDING_CAPSULE_TOP_START = 450
const LANDING_CAPSULE_TOP_STOP = 2
const rowStyle = computed(() => {
@@ -537,7 +540,7 @@ const rowStyle = computed(() => {
return { height: `${props.height}px` }
})
const centerStyle = computed(() => {
const heroTitleStyle = computed(() => {
if (!isHeroLayout.value) return {}
const heroHeight = props.height || topRowHeight
const minTop = 0
@@ -549,15 +552,21 @@ const centerStyle = computed(() => {
const isFloatingHomeCapsule = computed(() => isHeroLayout.value)
const landingCapsuleTopStart = computed(() => {
const base = props.heroBaseHeight || props.height || 0
if (!base) return 420
return Math.max(300, Math.min(520, Math.round(base * 0.52)))
})
const landingCapsuleTop = computed(() => {
if (!isFloatingHomeCapsule.value) return LANDING_CAPSULE_TOP_STOP
const y = Math.max(0, props.heroScrollY || 0)
return Math.max(LANDING_CAPSULE_TOP_STOP, LANDING_CAPSULE_TOP_START - y)
return Math.max(LANDING_CAPSULE_TOP_STOP, landingCapsuleTopStart.value - y)
})
const searchCapsuleClass = computed(() => {
if (!isFloatingHomeCapsule.value) return 'w-full'
return 'w-full lg:fixed lg:left-1/2 lg:z-40 lg:w-[min(1120px,calc(100%-1.5rem))] lg:-translate-x-1/2 transition-[top] duration-200 ease-out'
return 'w-full lg:absolute lg:left-1/2 lg:z-20 lg:w-[min(1120px,calc(100%-1.5rem))] lg:-translate-x-1/2 transition-[top] duration-200 ease-out'
})
const searchCapsuleStyle = computed(() => {

View File

@@ -45,7 +45,8 @@
<!-- Filter by bounds checkbox (LEFT, next to panel when open) - only in selection mode -->
<label
v-if="selectMode !== null"
class="absolute top-[116px] left-[calc(1rem+32rem+1rem)] z-20 hidden lg:flex items-center gap-2 map-chip rounded-full px-3 py-1.5 cursor-pointer text-base-content text-sm hover:bg-base-200 transition-colors"
class="absolute top-[116px] z-20 hidden lg:flex items-center gap-2 map-chip rounded-full px-3 py-1.5 cursor-pointer text-base-content text-sm hover:bg-base-200 transition-colors"
:style="boundsFilterStyle"
>
<input
type="checkbox"
@@ -101,10 +102,10 @@
<Transition name="slide-left">
<div
v-if="isPanelOpen"
class="absolute top-[116px] left-4 bottom-4 z-30 max-w-[calc(100vw-2rem)] hidden lg:block"
class="absolute top-[116px] left-0 bottom-0 z-30 max-w-[calc(100vw-1rem)] hidden lg:block"
:class="panelWidth"
>
<div class="bg-neutral text-neutral-content border border-neutral/70 rounded-[1.1rem] shadow-2xl h-full flex flex-col">
<div class="bg-base-100 text-base-content border border-base-300 border-l-0 rounded-none rounded-tr-[1.1rem] rounded-bl-[1.1rem] shadow-2xl h-full flex flex-col">
<slot name="panel" />
</div>
</div>
@@ -162,7 +163,7 @@
<Transition name="slide-up">
<div
v-if="isPanelOpen"
class="bg-neutral text-neutral-content rounded-t-3xl border-t border-neutral/70 shadow-[0_-8px_40px_rgba(0,0,0,0.35)] transition-all duration-300 h-[60vh]"
class="bg-base-100 text-base-content rounded-t-3xl border-t border-base-300 shadow-[0_-8px_40px_rgba(0,0,0,0.12)] transition-all duration-300 h-[60vh]"
>
<!-- Drag handle / close -->
<div
@@ -212,11 +213,16 @@ const panelWidthPx = computed(() => {
const fitPaddingLeft = computed(() => {
if (!isPanelOpen.value || !isDesktop.value || panelWidthPx.value === 0) return 0
const leftInset = 16
const leftInset = 0
const rightInset = 16
return leftInset + panelWidthPx.value + rightInset
})
const boundsFilterStyle = computed(() => {
if (!isDesktop.value || panelWidthPx.value === 0) return { left: '1rem' }
return { left: `${panelWidthPx.value + 16}px` }
})
// Open panel based on current mapViewMode
const openPanel = () => {
const newSelectMode = mapViewMode.value === 'hubs' ? 'hub'

View File

@@ -19,6 +19,7 @@
:height="isHomePage ? heroHeight : 100"
:collapse-progress="isHomePage ? collapseProgress : 1"
:hero-scroll-y="isHomePage ? heroScrollY : 0"
:hero-base-height="isHomePage ? heroBaseHeight : 0"
:session-checked="sessionChecked"
:logged-in="isLoggedIn"
:user-avatar-svg="userAvatarSvg"

View File

@@ -15,7 +15,7 @@
>
<template #panel>
<!-- Panel header -->
<div class="p-4 border-b border-white/10 flex-shrink-0">
<div class="p-4 border-b border-base-300 flex-shrink-0">
<div class="flex items-center justify-between mb-3">
<span class="font-semibold">{{ t('cabinetNav.addresses') }}</span>
</div>
@@ -26,14 +26,14 @@
v-model="searchQuery"
type="text"
:placeholder="t('common.search')"
class="input input-sm w-full bg-white/10 border-white/20 text-white placeholder:text-white/50"
class="input input-sm w-full bg-base-200 border-base-300 text-base-content placeholder:text-base-content/50"
/>
<Icon name="lucide:search" size="16" class="absolute right-3 top-1/2 -translate-y-1/2 text-white/50" />
<Icon name="lucide:search" size="16" class="absolute right-3 top-1/2 -translate-y-1/2 text-base-content/50" />
</div>
<!-- Add button -->
<NuxtLink :to="localePath('/clientarea/addresses/new')">
<button class="btn btn-sm w-full bg-white/10 border-white/20 text-white hover:bg-white/20">
<button class="btn btn-sm w-full bg-base-200 border-base-300 text-base-content hover:bg-base-200">
<Icon name="lucide:plus" size="14" class="mr-1" />
{{ t('profileAddresses.actions.add') }}
</button>
@@ -46,7 +46,7 @@
<div
v-for="item in displayItems"
:key="item.uuid"
class="bg-white/10 rounded-lg p-3 hover:bg-white/20 transition-colors cursor-pointer"
class="bg-base-200 rounded-lg p-3 hover:bg-base-200 transition-colors cursor-pointer"
:class="{ 'ring-2 ring-emerald-500': selectedAddressId === item.uuid }"
@click="selectedAddressId = item.uuid"
@mouseenter="hoveredAddressId = item.uuid"
@@ -56,7 +56,7 @@
<span class="text-xl">{{ isoToEmoji(item.countryCode) }}</span>
<div class="flex-1 min-w-0">
<div class="font-semibold text-sm truncate">{{ item.name }}</div>
<div class="text-xs text-white/60 line-clamp-2">{{ item.address }}</div>
<div class="text-xs text-base-content/60 line-clamp-2">{{ item.address }}</div>
</div>
</div>
</div>
@@ -65,9 +65,9 @@
<div class="text-center py-8">
<div class="text-3xl mb-2">📍</div>
<div class="font-semibold text-sm mb-1">{{ t('profileAddresses.empty.title') }}</div>
<div class="text-xs text-white/60 mb-3">{{ t('profileAddresses.empty.description') }}</div>
<div class="text-xs text-base-content/60 mb-3">{{ t('profileAddresses.empty.description') }}</div>
<NuxtLink :to="localePath('/clientarea/addresses/new')">
<button class="btn btn-sm bg-white/10 border-white/20 text-white hover:bg-white/20">
<button class="btn btn-sm bg-base-200 border-base-300 text-base-content hover:bg-base-200">
<Icon name="lucide:plus" size="14" class="mr-1" />
{{ t('profileAddresses.empty.cta') }}
</button>
@@ -77,8 +77,8 @@
</div>
<!-- Footer -->
<div class="p-3 border-t border-white/10 flex-shrink-0">
<span class="text-xs text-white/50">{{ displayItems.length }} {{ t('catalog.of') }} {{ items.length }}</span>
<div class="p-3 border-t border-base-300 flex-shrink-0">
<span class="text-xs text-base-content/50">{{ displayItems.length }} {{ t('catalog.of') }} {{ items.length }}</span>
</div>
</template>
</CatalogPage>

View File

@@ -15,7 +15,7 @@
>
<template #panel>
<!-- Panel header -->
<div class="p-4 border-b border-white/10 flex-shrink-0">
<div class="p-4 border-b border-base-300 flex-shrink-0">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-2">
<div class="w-8 h-8 rounded-lg bg-indigo-500/20 flex items-center justify-center">
@@ -23,7 +23,7 @@
</div>
<div>
<span class="font-semibold text-sm">{{ t('cabinetNav.orders') }}</span>
<div class="text-xs text-white/50">{{ filteredItems.length }} {{ t('orders.total', 'total') }}</div>
<div class="text-xs text-base-content/50">{{ filteredItems.length }} {{ t('orders.total', 'total') }}</div>
</div>
</div>
</div>
@@ -34,14 +34,14 @@
v-model="searchQuery"
type="text"
:placeholder="t('common.search')"
class="input input-sm w-full bg-white/10 border-white/20 text-white placeholder:text-white/50"
class="input input-sm w-full bg-base-200 border-base-300 text-base-content placeholder:text-base-content/50"
/>
<Icon name="lucide:search" size="16" class="absolute right-3 top-1/2 -translate-y-1/2 text-white/50" />
<Icon name="lucide:search" size="16" class="absolute right-3 top-1/2 -translate-y-1/2 text-base-content/50" />
</div>
<!-- Filter dropdown -->
<div class="dropdown dropdown-end w-full">
<label tabindex="0" class="btn btn-sm w-full bg-white/10 border-white/20 text-white hover:bg-white/20 justify-between">
<label tabindex="0" class="btn btn-sm w-full bg-base-200 border-base-300 text-base-content hover:bg-base-200 justify-between">
<span>{{ selectedFilterLabel }}</span>
<Icon name="lucide:chevron-down" size="14" />
</label>
@@ -62,7 +62,7 @@
<div
v-for="item in displayItems"
:key="item.uuid"
class="bg-white/10 rounded-lg p-3 hover:bg-white/20 transition-colors cursor-pointer"
class="bg-base-200 rounded-lg p-3 hover:bg-base-200 transition-colors cursor-pointer"
:class="{ 'ring-2 ring-indigo-500': selectedOrderId === item.uuid }"
@click="selectedOrderId = item.uuid"
@mouseenter="hoveredOrderId = item.uuid"
@@ -74,17 +74,17 @@
{{ getStatusText(item.status) }}
</span>
</div>
<div class="text-xs text-white/70 space-y-1">
<div class="text-xs text-base-content/70 space-y-1">
<div class="flex items-center gap-2">
<Icon name="lucide:map-pin" size="12" class="text-white/40" />
<Icon name="lucide:map-pin" size="12" class="text-base-content/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" />
<Icon name="lucide:navigation" size="12" class="text-base-content/40" />
<span class="truncate">{{ item.destinationLocationName }}</span>
</div>
</div>
<div class="text-xs text-white/50 mt-2">
<div class="text-xs text-base-content/50 mt-2">
{{ getOrderDate(item) }}
</div>
</div>
@@ -93,14 +93,14 @@
<div class="text-center py-8">
<div class="text-3xl mb-2">📦</div>
<div class="font-semibold text-sm mb-1">{{ t('orders.no_orders') }}</div>
<div class="text-xs text-white/60">{{ t('orders.no_orders_desc') }}</div>
<div class="text-xs text-base-content/60">{{ t('orders.no_orders_desc') }}</div>
</div>
</template>
</div>
<!-- Footer -->
<div class="p-3 border-t border-white/10 flex-shrink-0">
<span class="text-xs text-white/50">{{ displayItems.length }} {{ t('catalog.of') }} {{ filteredItems.length }}</span>
<div class="p-3 border-t border-base-300 flex-shrink-0">
<span class="text-xs text-base-content/50">{{ displayItems.length }} {{ t('catalog.of') }} {{ filteredItems.length }}</span>
</div>
</template>
</CatalogPage>