Featured tours working
This commit is contained in:
@@ -26,10 +26,10 @@ const props = defineProps<{
|
||||
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
|
||||
<circle cx="12" cy="10" r="3"></circle>
|
||||
</svg>
|
||||
{{tour.countryName}}, {{tour.continentName}}
|
||||
{{ tour.countries.at(0)?.name }}, {{ tour.countries.at(0)?.continent.name }}
|
||||
</div>
|
||||
<h3 class="tour-title">{{tour.title}}</h3>
|
||||
<p class="tour-description" v-if="tour.description">{{tour.description}}</p>
|
||||
<p class="tour-description" v-if="tour.short_description">{{tour.short_description}}</p>
|
||||
<div class="tour-details">
|
||||
<div class="tour-detail">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
|
||||
@@ -181,5 +181,6 @@ import EdgyButton from "@/components/dredgy/EdgyButton.vue";
|
||||
import GradientText from "@/components/dredgy/GradientText.vue";
|
||||
import SectionContainer from "@/components/dredgy/SectionContainer.vue";
|
||||
import SectionTitle from "@/components/dredgy/SectionTitle.vue";
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -99,10 +99,12 @@ 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[] = [];
|
||||
|
||||
const featuredTours : Tour[] = [
|
||||
{id: 1, length:8, title:"Cantonese Charm", countryId: 1, countryName: "China", continentId:1,continentName:"Asia",description:"Guangdong is known for it's big, global cities, but there is so much more to discover and pristine natural beauty.", internal_name:"cantonese_charm", level: "Beginner", price:1000},
|
||||
{id: 2, length: 7, title:"Fujian Fantasy", countryId: 1, countryName: "China", continentId:1,continentName:"Asia",description:"Experience fresh seafood in Xiamen, and then move rurally for an authentic dive into Hakka culture", internal_name:"fujian_fantasy", level: "Beginner", price:1200},
|
||||
{id: 3, length: 10, title:"Hebei Hijinx", countryId: 1, countryName: "China", continentId:1,continentName:"Asia",description:"The Great Wall, Great Food and ancient treasures in one of China's most underrated provinces.", internal_name:"hebei_hijinx", level: "Moderate", price:1500},
|
||||
]
|
||||
/*
|
||||
import { defineProps } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
featuredTours: Tour[]
|
||||
}>()*/
|
||||
</script>
|
||||
|
||||
38
resources/js/composables/useIntersectionObserver.ts
Normal file
38
resources/js/composables/useIntersectionObserver.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { onMounted, onBeforeUnmount, nextTick } from 'vue';
|
||||
|
||||
/**
|
||||
* useIntersectionObserver
|
||||
*
|
||||
* @param selector - CSS selector for elements to observe
|
||||
* @param callback - called when intersection changes
|
||||
* @param options - IntersectionObserver options
|
||||
*/
|
||||
export const useIntersectionObserver = (
|
||||
selector: string,
|
||||
callback: IntersectionObserverCallback,
|
||||
options: IntersectionObserverInit = {}
|
||||
) => {
|
||||
let observer: IntersectionObserver | null = null;
|
||||
|
||||
const defaultOptions: IntersectionObserverInit = {
|
||||
threshold: 0.3,
|
||||
rootMargin: '0px 0px -50px 0px',
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick(); // wait for DOM to render
|
||||
|
||||
const elements = document.querySelectorAll(selector);
|
||||
if (!elements.length) return;
|
||||
|
||||
observer = new IntersectionObserver(callback, { ...defaultOptions, ...options });
|
||||
elements.forEach(el => observer!.observe(el));
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (observer) {
|
||||
observer.disconnect();
|
||||
observer = null;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -1,9 +1,7 @@
|
||||
<template>
|
||||
<Hero />
|
||||
<!-- About Section -->
|
||||
<About />
|
||||
<!-- Featured Tours Section -->
|
||||
<FeaturedTours />
|
||||
<FeaturedTours :featured-tours="featured_tours" />
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@@ -11,15 +9,21 @@
|
||||
</style>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
|
||||
|
||||
import { onMounted } from 'vue';
|
||||
import {usePage} from "@inertiajs/vue3";
|
||||
import {Tour} from "@/types";
|
||||
|
||||
interface Properties {
|
||||
featured_tours: Tour[]
|
||||
}
|
||||
|
||||
const { featured_tours } = usePage().props as unknown as Properties
|
||||
|
||||
import AppLayout from '../layouts/AppLayout.vue'
|
||||
import Hero from "@/components/home/Hero.vue";
|
||||
import About from "@/components/home/About.vue";
|
||||
import FeaturedTours from "@/components/home/FeaturedTours.vue";
|
||||
|
||||
defineOptions({
|
||||
layout: AppLayout
|
||||
})
|
||||
|
||||
18
resources/js/types/index.d.ts
vendored
18
resources/js/types/index.d.ts
vendored
@@ -46,16 +46,20 @@ export interface Continent {
|
||||
internal_name: string
|
||||
}
|
||||
|
||||
export interface Country {
|
||||
id: number
|
||||
name: string
|
||||
internal_name: string
|
||||
continent: Continent;
|
||||
}
|
||||
|
||||
export interface Tour {
|
||||
id: number
|
||||
title: string
|
||||
internal_name: string
|
||||
continentId: number
|
||||
continentName: string
|
||||
countryId: number
|
||||
countryName: string
|
||||
level: string
|
||||
description?: string
|
||||
price: number
|
||||
length: number
|
||||
price: number
|
||||
level: string
|
||||
short_description: string
|
||||
countries: Country[]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user