Componentalization
This commit is contained in:
@@ -12,18 +12,22 @@
|
||||
|
||||
<div class="tours-grid">
|
||||
<TourCard
|
||||
v-for="tour in featuredTours"
|
||||
v-for="(tour, index) in featuredTours"
|
||||
:key="tour.id ?? index"
|
||||
class="tour-card"
|
||||
:data-index="index"
|
||||
:tour="tour"
|
||||
/>
|
||||
</div>
|
||||
<br/>
|
||||
<EdgyButton classes="btn-primary btn-full">Explore All Tours</EdgyButton>
|
||||
<EdgyButton classes="btn-primary btn-full">Explore All Adventures</EdgyButton>
|
||||
|
||||
</SectionContainer>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
<style scoped>
|
||||
/* Featured Tours Section */
|
||||
.featured-tours {
|
||||
@@ -99,12 +103,77 @@ import SectionTitle from "@/components/dredgy/SectionTitle.vue";
|
||||
import TourCard from "@/components/dredgy/TourCard.vue";
|
||||
import { Tour } from "@/types";
|
||||
import EdgyButton from "@/components/dredgy/EdgyButton.vue";
|
||||
const featuredTours : Tour[] = [];
|
||||
|
||||
/*
|
||||
import { defineProps } from 'vue'
|
||||
|
||||
import { defineProps, onMounted } from 'vue'
|
||||
import {createIntersectionObserver} from "@/composables/useIntersectionObserver";
|
||||
|
||||
const props = defineProps<{
|
||||
featuredTours: Tour[]
|
||||
}>()*/
|
||||
}>()
|
||||
|
||||
onMounted(() => {
|
||||
initToursAnimation()
|
||||
initTourCardInteractions()
|
||||
})
|
||||
|
||||
const initTourCardInteractions = (): void => {
|
||||
const tourCards = document.querySelectorAll('.tour-card') as NodeListOf<HTMLElement>;
|
||||
|
||||
tourCards.forEach((card: HTMLElement) => {
|
||||
// Add hover effects
|
||||
card.addEventListener('mouseenter', () => {
|
||||
card.style.transform = 'translateY(-8px) scale(1.02)';
|
||||
});
|
||||
|
||||
card.addEventListener('mouseleave', () => {
|
||||
if (card.classList.contains('visible')) {
|
||||
card.style.transform = 'translateY(0) rotate(0deg) scale(1)';
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const initToursAnimation = (): void => {
|
||||
const toursHeader = document.querySelector('.tours-header') as HTMLElement | null;
|
||||
const tourCards = document.querySelectorAll('.tour-card') as NodeListOf<HTMLElement>;
|
||||
|
||||
if (!toursHeader || !tourCards.length) return;
|
||||
|
||||
// Header animation
|
||||
const headerObserver = createIntersectionObserver((entries: IntersectionObserverEntry[]) => {
|
||||
entries.forEach((entry: IntersectionObserverEntry) => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add('visible');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
headerObserver.observe(toursHeader);
|
||||
|
||||
// Tour cards animation with staggered effect
|
||||
const cardsObserver = createIntersectionObserver((entries: IntersectionObserverEntry[]) => {
|
||||
entries.forEach((entry: IntersectionObserverEntry) => {
|
||||
const tourCard = entry.target as HTMLElement;
|
||||
const index = parseInt(tourCard.dataset.index || '0');
|
||||
|
||||
if (entry.isIntersecting) {
|
||||
// Staggered animation when scrolling down
|
||||
setTimeout(() => {
|
||||
tourCard.classList.add('visible');
|
||||
}, index * 150);
|
||||
} else {
|
||||
// Reverse staggered animation when scrolling up
|
||||
const reverseIndex = (tourCards.length - 1) - index;
|
||||
setTimeout(() => {
|
||||
tourCard.classList.remove('visible');
|
||||
}, reverseIndex * 100);
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.2 });
|
||||
|
||||
tourCards.forEach((card: HTMLElement) => {
|
||||
cardsObserver.observe(card);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user