Add unified MapPanel component for left map panels
All checks were successful
Build Docker Image / build (push) Successful in 3m25s
All checks were successful
Build Docker Image / build (push) Successful in 3m25s
- Create MapPanel with white glass header, dark content - Refactor SelectionPanel to use MapPanel - Refactor QuotePanel to use MapPanel - Single source of truth for panel styling
This commit is contained in:
13
app/components/catalog/MapPanel.vue
Normal file
13
app/components/catalog/MapPanel.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div class="flex flex-col h-full -m-4">
|
||||
<!-- Header: белое стекло -->
|
||||
<div class="sticky top-0 z-10 p-4 rounded-t-xl bg-white/90 backdrop-blur-md border-b border-white/20">
|
||||
<slot name="header" />
|
||||
</div>
|
||||
|
||||
<!-- Content: тёмный (наследует контейнер) -->
|
||||
<div class="flex-1 px-4 pt-3 pb-4 overflow-y-auto">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<div class="flex flex-col gap-4 h-full">
|
||||
<!-- Header -->
|
||||
<div class="flex items-center justify-between flex-shrink-0">
|
||||
<h3 class="font-semibold text-lg">{{ $t('catalog.headers.offers') }}</h3>
|
||||
<MapPanel>
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="font-semibold text-base text-base-content">{{ $t('catalog.headers.offers') }}</h3>
|
||||
<span class="badge badge-neutral">{{ offers.length }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Results section -->
|
||||
<div class="flex-1 overflow-y-auto -mx-1 px-1">
|
||||
<!-- Content -->
|
||||
<div v-if="loading" class="flex items-center justify-center py-8">
|
||||
<span class="loading loading-spinner loading-md" />
|
||||
</div>
|
||||
|
||||
<div v-else-if="offers.length === 0" class="text-center py-8 text-base-content/60">
|
||||
<div v-else-if="offers.length === 0" class="text-center py-8 text-white/60">
|
||||
<Icon name="lucide:search-x" size="32" class="mb-2" />
|
||||
<p>{{ $t('catalog.empty.noOffers') }}</p>
|
||||
</div>
|
||||
@@ -29,8 +29,7 @@
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</MapPanel>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<template>
|
||||
<div class="flex flex-col h-full -m-4">
|
||||
<!-- Header + Search (dark glass, sticky) -->
|
||||
<div class="sticky top-0 z-10 p-4 rounded-t-xl bg-black/50 backdrop-blur-md border-b border-white/10">
|
||||
<MapPanel>
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<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>
|
||||
@@ -12,12 +11,11 @@
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
:placeholder="searchPlaceholder"
|
||||
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-white/50 border-base-300/50 text-base-content placeholder:text-base-content/50"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- List -->
|
||||
<div class="flex-1 px-4 pt-3 pb-4 overflow-y-auto">
|
||||
<!-- Content -->
|
||||
<div v-if="loading" class="flex items-center justify-center py-8">
|
||||
<span class="loading loading-spinner loading-md" />
|
||||
</div>
|
||||
@@ -89,8 +87,7 @@
|
||||
<span v-if="loadingMore" class="loading loading-spinner loading-sm text-white/60" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</MapPanel>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
Reference in New Issue
Block a user