Files
DredgeTours/resources/js/pages/TourDay.vue
2025-09-19 00:33:32 +10:00

138 lines
5.4 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import SectionContainer from "@/components/dredgy/SectionContainer.vue";
import SectionTitle from "@/components/dredgy/SectionTitle.vue";
import EdgyButton from "@/components/dredgy/EdgyButton.vue";
import ButtonLink from "@/components/dredgy/ButtonLink.vue";
import { computed } from "vue";
import type { TourDay } from "@/types";
interface Props {
day: TourDay
dayNumber?: number
previousHref?: string | null
nextHref?: string | null
}
const props = defineProps<Props>();
const hasPrev = computed(() => !!props.previousHref);
const hasNext = computed(() => !!props.nextHref);
</script>
<template>
<section class="tour-day" id="tour-day">
<div class="tour-decorations">
<div class="tour-decoration tour-decoration-1"></div>
<div class="tour-decoration tour-decoration-2"></div>
<div class="tour-decoration tour-decoration-3"></div>
</div>
<SectionContainer>
<div v-show-on-intersect="'fade-up'" class="tour-content">
<SectionTitle
:title="'Day ' + (dayNumber ?? '')"
gradient="Overview"
:subtitle="day.description"
/>
<div class="tour-card chamfer">
<div class="tour-media chamfer" v-show-on-intersect="{type:'slide-right'}">
<img
v-if="day.image"
:src="day.image"
:alt="`Day ${dayNumber ?? ''} image`"
loading="lazy"
/>
<div v-else class="tour-media__placeholder">
<span>No image available</span>
</div>
</div>
<div class="tour-body" v-show-on-intersect="{type:'slide-left'}">
<div class="tour-description" v-html="day.content || day.description" />
<footer class="tour-actions">
<template v-if="hasPrev">
<EdgyButton classes="btn-secondary chamfer" aria-label="Previous">
<ButtonLink :href="previousHref!"> Previous</ButtonLink>
</EdgyButton>
</template>
<template v-else>
<EdgyButton classes="btn-secondary chamfer" aria-label="Previous" @click="$emit('previous')">
Previous
</EdgyButton>
</template>
<div class="spacer" />
<template v-if="hasNext">
<EdgyButton classes="btn-primary chamfer" aria-label="Next">
<ButtonLink :href="nextHref!">Next </ButtonLink>
</EdgyButton>
</template>
<template v-else>
<EdgyButton classes="btn-primary chamfer" aria-label="Next" @click="$emit('next')">
Next
</EdgyButton>
</template>
</footer>
</div>
</div>
</div>
</SectionContainer>
</section>
</template>
<style scoped>
.tour-day {
position: relative;
padding: 5rem 0;
background: var(--background);
overflow: hidden;
}
.tour-decorations {
position: absolute; inset: 0; pointer-events: none;
}
.tour-decoration {
position: absolute; opacity: 0.05;
clip-path: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 20px 100%, 0 calc(100% - 20px));
}
.tour-decoration-1 { top: 2rem; right: 2rem; width: 100px; height: 100px; background: var(--gradient-adventure); }
.tour-decoration-2 { bottom: 3rem; left: 3rem; width: 80px; height: 80px; background: var(--gradient-accent); }
.tour-decoration-3 { top: 50%; right: 5rem; width: 6px; height: 100px; background: var(--gradient-adventure); }
.tour-card {
display: flex;
gap: 1.5rem;
background: var(--card);
color: var(--foreground);
border: 1px solid color-mix(in oklab, var(--foreground), transparent 85%);
padding: 1.25rem;
min-height: min(60dvh, 680px);
}
.chamfer {
--cut: 20px;
clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, var(--cut) 100%, 0 calc(100% - var(--cut)));
}
.tour-media {
flex: 0 1 44%;
background: color-mix(in oklab, var(--card), black 4%);
border: 1px solid color-mix(in oklab, var(--foreground), transparent 88%);
display: grid; place-items: center; min-height: 260px;
}
.tour-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tour-media__placeholder { color: var(--muted-foreground); font-size: 0.95rem; padding: 1rem; }
.tour-body { flex: 1 1 56%; display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
.tour-description { color: var(--muted-foreground); font-size: 1.08rem; line-height: 1.7; }
.tour-actions { margin-top: auto; display: flex; align-items: center; gap: 0.75rem; }
.spacer { flex: 1; }
@media (max-width: 1023px) {
.tour-card { flex-direction: column; }
.tour-media { min-height: 220px; }
}
@media (max-width: 767px) {
.tour-day { padding: 3rem 0; }
.tour-card { padding: 1rem; }
}
</style>