Skip to content

Commit 05bab06

Browse files
Update about us carousel to show regions
1 parent 4f567e3 commit 05bab06

File tree

3 files changed

+205
-11
lines changed

3 files changed

+205
-11
lines changed

components/RegionCard.vue

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,6 @@
6565
{{ $t('Coming Soon') }}</span>
6666
</div>
6767
</div>
68-
<!-- CODE FOR CITY NAMES ON REGION CARD -->
69-
<!-- <div
70-
v-if="region._allReferencingCities.length > 0"
71-
class="absolute bottom-32 left-1/2 flex -translate-x-1/2 items-center text-20 font-semibold text-white"
72-
>
73-
<span v-for="(city, index) in region._allReferencingCities" :key="city.id">
74-
<span v-if="index !== 0">, </span>
75-
{{ city.name }}
76-
</span>
77-
</div> -->
7868
</nuxt-link>
7969
</template>
8070

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
<template>
2+
<BlockWrapper
3+
:block-background-color="backgroundColor"
4+
:padding-top="96"
5+
:no-padding-bottom="false"
6+
:overlaps-next-section="false"
7+
>
8+
<div class="widest relative">
9+
<ul
10+
ref="scroller"
11+
role="list"
12+
class="no-scrollbar flex w-full snap-x snap-mandatory gap-16 overflow-x-auto scroll-smooth !px-[max(16px,calc((100vw-370px)/2))] pb-40 pt-12 md:!px-[calc((100vw-2*370px-16px)/2)] xl:gap-32 xl:!px-[calc((100vw-3*370px-2*32px)/2)] xl:pt-16 2xl:!px-[calc((100vw-3*370px-2*32px)/2)]"
13+
:class="{'justify-center': visibleCards > response.allRegions.length }"
14+
@scroll.passive="calculateStep"
15+
>
16+
<li
17+
v-for="(region) in response.allRegions"
18+
:key="`card-${region.id}`"
19+
ref="slides"
20+
class="aspect-square w-[clamp(320px,370px,calc(100vw-40px))] shrink-0 snap-center snap-always"
21+
data-region
22+
>
23+
<RegionCard
24+
class="min-w-full"
25+
:region="region"
26+
compact
27+
/>
28+
</li>
29+
</ul>
30+
31+
<button
32+
v-if="activeIndex > 0"
33+
class="hocus:bg-blue-dark/30 absolute left-32 top-1/2 z-10 -mt-24 hidden size-48 cursor-pointer items-center justify-center rounded bg-blue-dark/20 text-white transition-[background-color] active:bg-blue-dark/40 sm:flex"
34+
@click="goToPrevious"
35+
>
36+
<svg width="16" height="24" fill="none" xmlns="http://www.w3.org/2000/svg">
37+
<path
38+
d="M1 12c0-.66.27-1.3.77-1.73L12.97.43a1.85 1.85 0 0 1 2.6.23c.63.77.56 1.89-.16 2.56l-9.78 8.6a.25.25 0 0 0-.02.35l.02.02 9.77 8.6a1.85 1.85 0 0 1-2.45 2.77L1.77 13.73A2.3 2.3 0 0 1 1 12Z"
39+
fill="currentColor"
40+
/>
41+
</svg>
42+
</button>
43+
44+
<button
45+
v-if="activeIndex < response.allRegions.length - visibleCards"
46+
class="hocus:bg-blue-dark/30 absolute right-32 top-1/2 z-10 -mt-24 hidden size-48 cursor-pointer items-center justify-center rounded bg-blue-dark/20 text-white transition-[background-color] active:bg-blue-dark/40 sm:flex"
47+
@click="goToNext"
48+
>
49+
<svg width="16" height="24" fill="none" xmlns="http://www.w3.org/2000/svg" class="-mr-4 rotate-180">
50+
<path
51+
d="M1 12c0-.66.27-1.3.77-1.73L12.97.43a1.85 1.85 0 0 1 2.6.23c.63.77.56 1.89-.16 2.56l-9.78 8.6a.25.25 0 0 0-.02.35l.02.02 9.77 8.6a1.85 1.85 0 0 1-2.45 2.77L1.77 13.73A2.3 2.3 0 0 1 1 12Z"
52+
fill="currentColor"
53+
/>
54+
</svg>
55+
</button>
56+
</div>
57+
58+
<div v-if="visibleCards <= response.allRegions.length && amountOfItems > 1" class="flex flex-col">
59+
<div class="relative mx-auto mt-48 flex">
60+
<button
61+
v-for="(_, i) in response.allRegions"
62+
:key="i"
63+
class="mx-4 size-8 cursor-pointer rounded bg-blue-dark/10 transition-transform delay-75 after:min-h-[16px] after:min-w-[16px] first:ml-0 last:mr-4"
64+
:class="{
65+
'scale-0': i >= activeIndex && i < activeIndex + visibleCards,
66+
'scale-100': i < activeIndex || i >= activeIndex + visibleCards,
67+
}"
68+
@click="() => slideTo(i)"
69+
/>
70+
<div class="pointer-events-none absolute h-8 w-full rounded">
71+
<div
72+
class="h-full rounded bg-green transition-all duration-300"
73+
:style="`margin-left: ${16 * activeIndex - 2}px; width: ${visibleCards - 0.25}rem;`"
74+
/>
75+
</div>
76+
</div>
77+
</div>
78+
</BlockWrapper>
79+
</template>
80+
81+
<script lang="ts" setup>
82+
import type { AsyncData } from 'nuxt/app'
83+
import type { Region } from '@/types/dato-models/Region'
84+
85+
defineProps({
86+
data: {
87+
type: Object,
88+
required: true
89+
},
90+
index: {
91+
type: Number,
92+
required: true
93+
},
94+
backgroundColor: {
95+
type: String,
96+
required: true,
97+
default: 'white'
98+
}
99+
})
100+
interface AllRegionsResponse {
101+
allRegions: Region[]
102+
}
103+
104+
const { data: { value: response } } = await useGraphqlQuery(`query {
105+
allRegions(orderBy: _createdAt_ASC) {
106+
url
107+
state
108+
name
109+
brandName
110+
subRegion
111+
id
112+
mainImage {
113+
responsiveImage(imgixParams: { fit: max, h: 1000, auto: format }) {
114+
srcSet
115+
webpSrcSet
116+
sizes
117+
src
118+
width
119+
height
120+
aspectRatio
121+
alt
122+
title
123+
base64
124+
}
125+
}
126+
_allReferencingCities {
127+
id
128+
name
129+
}
130+
}
131+
}`) as AsyncData<AllRegionsResponse, RTCError>
132+
133+
const allRegions = computed(() => {
134+
return response.allRegions.filter(x => x.state !== 'hidden')
135+
})
136+
137+
const amountOfItems = computed(() => {
138+
return allRegions.value.length + 1
139+
})
140+
141+
const activeIndex = ref(0)
142+
const scroller = ref<HTMLUListElement | null>(null)
143+
144+
const scrollerStyles = ref<CSSStyleDeclaration | null>(null)
145+
const scrollerPaddingLeft = computed(() => parseFloat(scrollerStyles.value?.paddingLeft || '0'))
146+
const scrollerPaddingRight = computed(() => parseFloat(scrollerStyles.value?.paddingRight || '0'))
147+
const scrollerGap = computed(() => parseFloat(scrollerStyles.value?.gap || '0'))
148+
const visibleCards = ref(1)
149+
150+
function onWindowResize () {
151+
visibleCards.value = window.innerWidth < 768 ? 1 : window.innerWidth < 1152 ? 2 : 3
152+
153+
if (scroller.value) {
154+
scrollerStyles.value = window.getComputedStyle(scroller.value)
155+
}
156+
}
157+
158+
onMounted(() => {
159+
onWindowResize()
160+
window.addEventListener('resize', onWindowResize)
161+
})
162+
163+
onBeforeUnmount(() => {
164+
window.removeEventListener('resize', onWindowResize)
165+
})
166+
167+
function calculateStep (event: Event) {
168+
const target = event.target as HTMLDivElement
169+
170+
const padding = scrollerPaddingLeft.value + scrollerPaddingRight.value
171+
const gap = scrollerGap.value
172+
const cards = visibleCards.value
173+
const cardWidth = (target.offsetWidth - padding) / cards + (gap * 1) / cards
174+
175+
activeIndex.value = Math.round(target.scrollLeft / cardWidth)
176+
}
177+
178+
function slideTo (index: number) {
179+
// Clamp new index
180+
index = Math.min(Math.max(0, index), amountOfItems.value - visibleCards.value)
181+
182+
const card = scroller.value?.querySelectorAll('[data-region]')[index] as HTMLElement
183+
184+
scroller.value!.scrollTo({
185+
top: 0,
186+
left: card.offsetLeft - scrollerPaddingLeft.value,
187+
behavior: 'smooth'
188+
})
189+
}
190+
191+
function goToPrevious () {
192+
slideTo(activeIndex.value - visibleCards.value)
193+
}
194+
195+
function goToNext () {
196+
slideTo(activeIndex.value + visibleCards.value)
197+
}
198+
</script>

pages/about/index.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,13 @@
3131
:page-response="pageData"
3232
:background-color="pageData.backgroundColors?.carouselHeadline"
3333
/>
34-
<BlockAllCitiesCarousel
34+
<!-- <BlockAllCitiesCarousel
35+
:data="pageData.allCitiesCarousel"
36+
:index="1"
37+
:page-response="pageData"
38+
:background-color="pageData.backgroundColors?.allCitiesCarousel"
39+
/> -->
40+
<BlockAllRegionsCarousel
3541
:data="pageData.allCitiesCarousel"
3642
:index="1"
3743
:page-response="pageData"

0 commit comments

Comments
 (0)