Add grid layout for catalog cards + hover shadow
All checks were successful
Build Docker Image / build (push) Successful in 4m8s

- CatalogPage: added gridColumns prop (1/2/3 columns)
- Card: added hover:shadow-lg on interactive cards
- Products, hubs, suppliers pages now use 3-column grid
- Offers remain full-width (gridColumns=1 default)
This commit is contained in:
Ruslan Bakiev
2026-01-22 08:54:31 +07:00
parent 631effdde4
commit 796204b3cd
6 changed files with 24 additions and 8 deletions

View File

@@ -40,7 +40,7 @@
<slot name="header" /> <slot name="header" />
<slot name="filters" /> <slot name="filters" />
<Stack gap="3"> <div :class="gridClass">
<div <div
v-for="item in displayItems" v-for="item in displayItems"
:key="item.uuid" :key="item.uuid"
@@ -51,7 +51,7 @@
> >
<slot name="card" :item="item" /> <slot name="card" :item="item" />
</div> </div>
</Stack> </div>
<slot name="pagination" /> <slot name="pagination" />
@@ -96,7 +96,7 @@
<slot name="header" /> <slot name="header" />
<slot name="filters" /> <slot name="filters" />
<Stack gap="3"> <div :class="gridClass">
<div <div
v-for="item in displayItems" v-for="item in displayItems"
:key="item.uuid" :key="item.uuid"
@@ -107,7 +107,7 @@
> >
<slot name="card" :item="item" /> <slot name="card" :item="item" />
</div> </div>
</Stack> </div>
<slot name="pagination" /> <slot name="pagination" />
@@ -169,7 +169,7 @@
<slot name="header" /> <slot name="header" />
<slot name="filters" /> <slot name="filters" />
<Stack gap="3"> <div :class="gridClass">
<div <div
v-for="item in items" v-for="item in items"
:key="item.uuid" :key="item.uuid"
@@ -177,7 +177,7 @@
> >
<slot name="card" :item="item" /> <slot name="card" :item="item" />
</div> </div>
</Stack> </div>
<slot name="pagination" /> <slot name="pagination" />
@@ -217,6 +217,7 @@ const props = withDefaults(defineProps<{
hoveredId?: string hoveredId?: string
hasSubNav?: boolean hasSubNav?: boolean
totalCount?: number // Total count for search bar counter (can differ from items.length with pagination) totalCount?: number // Total count for search bar counter (can differ from items.length with pagination)
gridColumns?: number // Number of columns for card grid (1 = stack, 2/3 = grid)
}>(), { }>(), {
loading: false, loading: false,
withMap: true, withMap: true,
@@ -225,7 +226,16 @@ const props = withDefaults(defineProps<{
mapId: 'catalog-map', mapId: 'catalog-map',
pointColor: '#3b82f6', pointColor: '#3b82f6',
hasSubNav: true, hasSubNav: true,
totalCount: 0 totalCount: 0,
gridColumns: 1
})
// Grid class based on gridColumns prop
const gridClass = computed(() => {
if (props.gridColumns === 1) return 'flex flex-col gap-3'
if (props.gridColumns === 2) return 'grid grid-cols-2 gap-3'
if (props.gridColumns === 3) return 'grid grid-cols-3 gap-3'
return 'flex flex-col gap-3'
}) })
// Smooth scroll collapse - pixel values for smooth animation // Smooth scroll collapse - pixel values for smooth animation

View File

@@ -35,7 +35,9 @@ const toneMap: Record<string, string> = {
const cardClass = computed(() => { const cardClass = computed(() => {
const paddingClass = paddingMap[props.padding] || paddingMap.medium const paddingClass = paddingMap[props.padding] || paddingMap.medium
const toneClass = toneMap[props.tone] || toneMap.default const toneClass = toneMap[props.tone] || toneMap.default
const interactiveClass = props.interactive ? 'cursor-pointer' : '' const interactiveClass = props.interactive
? 'cursor-pointer hover:shadow-lg transition-shadow duration-200'
: ''
const baseClass = 'card' const baseClass = 'card'
return [baseClass, paddingClass, toneClass, interactiveClass].filter(Boolean).join(' ') return [baseClass, paddingClass, toneClass, interactiveClass].filter(Boolean).join(' ')
}) })

View File

@@ -3,6 +3,7 @@
:items="displayItems" :items="displayItems"
:map-items="itemsWithCoords" :map-items="itemsWithCoords"
:loading="isLoading" :loading="isLoading"
:grid-columns="3"
with-map with-map
use-server-clustering use-server-clustering
map-id="hubs-map" map-id="hubs-map"

View File

@@ -3,6 +3,7 @@
:items="filteredHubs" :items="filteredHubs"
:loading="isLoading" :loading="isLoading"
:total-count="hubs.length" :total-count="hubs.length"
:grid-columns="3"
with-map with-map
use-server-clustering use-server-clustering
cluster-node-type="logistics" cluster-node-type="logistics"

View File

@@ -3,6 +3,7 @@
:items="filteredProducts" :items="filteredProducts"
:loading="isLoading" :loading="isLoading"
:total-count="products.length" :total-count="products.length"
:grid-columns="3"
with-map with-map
use-server-clustering use-server-clustering
cluster-node-type="offer" cluster-node-type="offer"

View File

@@ -3,6 +3,7 @@
:items="displayItems" :items="displayItems"
:map-items="itemsWithCoords" :map-items="itemsWithCoords"
:loading="isLoading" :loading="isLoading"
:grid-columns="3"
with-map with-map
map-id="suppliers-map" map-id="suppliers-map"
point-color="#3b82f6" point-color="#3b82f6"