Later Updates
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled

This commit is contained in:
2025-10-30 11:02:26 +10:00
parent 9b470e07d4
commit ca4569cb8f
4 changed files with 183 additions and 155 deletions

2
.idea/DredgeTours.iml generated
View File

@@ -6,6 +6,8 @@
<sourceFolder url="file://$MODULE_DIR$/database/factories" isTestSource="false" packagePrefix="Database\Factories\" /> <sourceFolder url="file://$MODULE_DIR$/database/factories" isTestSource="false" packagePrefix="Database\Factories\" />
<sourceFolder url="file://$MODULE_DIR$/database/seeders" isTestSource="false" packagePrefix="Database\Seeders\" /> <sourceFolder url="file://$MODULE_DIR$/database/seeders" isTestSource="false" packagePrefix="Database\Seeders\" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="Tests\" /> <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="Tests\" />
<sourceFolder url="file://$MODULE_DIR$/tests/Feature" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/tests/Unit" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/storage/app" /> <excludeFolder url="file://$MODULE_DIR$/storage/app" />
<excludeFolder url="file://$MODULE_DIR$/storage/framework" /> <excludeFolder url="file://$MODULE_DIR$/storage/framework" />
<excludeFolder url="file://$MODULE_DIR$/vendor/_laravel_idea" /> <excludeFolder url="file://$MODULE_DIR$/vendor/_laravel_idea" />

7
package-lock.json generated
View File

@@ -4,6 +4,7 @@
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "DredgeTours",
"dependencies": { "dependencies": {
"@inertiajs/vue3": "^2.1.0", "@inertiajs/vue3": "^2.1.0",
"@mdi/font": "^7.4.47", "@mdi/font": "^7.4.47",
@@ -6098,9 +6099,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "7.1.5", "version": "7.1.11",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.5.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.11.tgz",
"integrity": "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ==", "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"esbuild": "^0.25.0", "esbuild": "^0.25.0",

View File

@@ -0,0 +1,160 @@
<script setup lang="ts">
import type { TourDay } from "@/types";
import { ref } from "vue";
interface Props {
tourDays: TourDay[];
}
const currentStep = ref(1);
const props = defineProps<Props>();
</script>
<template>
<div v-if="tourDays?.length" class="custom-stepper">
<!-- Horizontal Stepper Header -->
<div class="stepper-header">
<button class="stepper-step">
<span class="step-number">Summary</span>
</button>
<button
v-for="(day, index) in tourDays"
:key="day.id"
class="stepper-step"
:class="{
active: currentStep === index + 1,
complete: currentStep > index + 1
}"
@click="currentStep = index + 1"
>
<span class="step-number">Day {{ index + 1 }}</span>
</button>
</div>
<!-- Stepper Content -->
<div class="stepper-content">
<div
v-for="(day, index) in tourDays"
:key="day.id"
v-show="currentStep === index + 1"
class="step-item"
>
<h2 class="text-h3 font-weight-bold mb-2">
Day {{ index + 1 }}
</h2>
<p class="text-h6 text-grey mb-6">
{{ day.description }}
</p>
<div v-if="day.image" class="mb-6">
<v-img
:src="day.image"
:alt="`Day ${index + 1}`"
class="rounded"
height="300"
cover
/>
</div>
<div class="text-body1 line-height-relaxed mb-6">
{{ day.content }}
</div>
<div class="d-flex gap-3">
<v-btn
v-if="index > 0"
variant="outlined"
@click="currentStep = index"
>
Previous
</v-btn>
<v-btn
v-if="index < tourDays.length - 1"
color="primary"
@click="currentStep = index + 2"
>
Next
</v-btn>
<v-btn
v-else
color="success"
disabled
>
Tour Complete
</v-btn>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.custom-stepper {
width: 100%;
display: flex;
flex-direction: column;
gap: 2rem;
}
.stepper-header {
display: flex;
gap: 1rem;
overflow-x: auto;
padding: 1rem 0;
border-bottom: 2px solid rgba(255, 255, 255, 0.1);
}
.stepper-step {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
padding: 0.75rem 1.5rem;
background: transparent;
border: 2px solid rgba(255, 255, 255, 0.3);
color: rgba(255, 255, 255, 0.6);
cursor: pointer;
transition: all 0.3s ease;
white-space: nowrap;
flex-shrink: 0;
}
.stepper-step:hover {
border-color: rgba(255, 255, 255, 0.6);
color: rgba(255, 255, 255, 0.9);
}
.stepper-step.active {
border-color: #1976d2;
background-color: rgba(25, 118, 210, 0.1);
color: #1976d2;
}
.stepper-step.complete {
border-color: #4caf50;
color: #4caf50;
}
.step-number {
font-weight: bold;
font-size: 1.2em;
}
.stepper-content {
flex: 1;
overflow-y: auto;
}
.step-item {
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style>

View File

@@ -2,23 +2,27 @@
import GradientText from "@/components/dredgy/GradientText.vue"; import GradientText from "@/components/dredgy/GradientText.vue";
import TourQuickFacts from "@/components/TourNavigator/TourQuickFacts.vue"; import TourQuickFacts from "@/components/TourNavigator/TourQuickFacts.vue";
import TourOverviewActions from "@/components/TourNavigator/TourOverviewActions.vue"; import TourOverviewActions from "@/components/TourNavigator/TourOverviewActions.vue";
import TourStepper from "@/components/TourNavigator/TourStepper.vue";
import type {Tour, TourDay} from "@/types"; import type {Tour, TourDay} from "@/types";
import {ref} from "vue";
interface Props { interface Props {
tour: Tour; tour: Tour;
tourDay?: TourDay; tourDay?: TourDay;
} }
const currentStep = ref(1)
const props = defineProps<Props>(); const props = defineProps<Props>();
</script> </script>
<template> <template>
<section v-show-on-intersect class="no-gap tour-overview chamfer-tl"> <section v-show-on-intersect class="no-gap tour-overview chamfer-tl">
<div <div
:style="{ backgroundImage: `url('/img/tours/${tour.internal_name}.jpg')` }"
style="background-attachment: scroll; background-size: cover; background-position: center"
class="tour-overview-header" class="tour-overview-header"
:style="{
backgroundImage: `url(/img/tours/${tour.internal_name}.jpg)`,
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
}"
> >
<h1 class="glass chamfer"> <h1 class="glass chamfer">
<GradientText>{{ tour.name }}</GradientText> <GradientText>{{ tour.name }}</GradientText>
@@ -27,78 +31,7 @@ const props = defineProps<Props>();
<div class="tour-overview-body"> <div class="tour-overview-body">
<section class="tour-content"> <section class="tour-content">
<article class="tour-description"> <article class="tour-description">
<div v-if="tour.tour_days?.length" class="custom-stepper"> <TourStepper v-if="tour.tour_days" :tourDays="tour.tour_days" />
<!-- Horizontal Stepper Header -->
<div class="stepper-header">
<button
v-for="(day, index) in tour.tour_days"
:key="day.id"
class="stepper-step"
:class="{
active: currentStep === index + 1,
complete: currentStep > index + 1
}"
@click="currentStep = index + 1"
>
<span class="step-number">Day {{ index + 1 }}</span>
</button>
</div>
<!-- Stepper Content -->
<div class="stepper-content">
<div
v-for="(day, index) in tour.tour_days"
:key="day.id"
v-show="currentStep === index + 1"
class="step-item"
>
<h2 class="text-h3 font-weight-bold mb-2">
Day {{ index + 1 }}
</h2>
<p class="text-h6 text-grey mb-6">
{{ day.description }}
</p>
<div v-if="day.image" class="mb-6">
<v-img
:src="day.image"
:alt="`Day ${index + 1}`"
class="rounded"
height="300"
cover
/>
</div>
<div class="text-body1 line-height-relaxed mb-6">
{{ day.content }}
</div>
<div class="d-flex gap-3">
<v-btn
v-if="index > 0"
variant="outlined"
@click="currentStep = index"
>
Previous
</v-btn>
<v-btn
v-if="index < tour.tour_days.length - 1"
color="primary"
@click="currentStep = index + 2"
>
Next
</v-btn>
<v-btn
v-else
color="success"
disabled
>
Tour Complete
</v-btn>
</div>
</div>
</div>
</div>
</article> </article>
</section> </section>
<aside class="chamfer chamfer-tl"> <aside class="chamfer chamfer-tl">
@@ -123,10 +56,15 @@ const props = defineProps<Props>();
.tour-overview-header { .tour-overview-header {
width: 100%; width: 100%;
height: auto;
flex-shrink: 0; flex-shrink: 0;
position: relative; position: relative;
min-height: 300px; height: 300px;
}
.parallax .v-img__img {
object-fit: contain !important; /* fit the whole image */
object-position: center center !important; /* center it vertically */
background-color: black; /* optional filler color */
} }
.tour-overview-header h1 { .tour-overview-header h1 {
@@ -161,6 +99,7 @@ const props = defineProps<Props>();
width: 100%; width: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: stretch;
} }
.tour-overview-body aside { .tour-overview-body aside {
@@ -223,78 +162,4 @@ const props = defineProps<Props>();
.line-height-relaxed { .line-height-relaxed {
line-height: 1.6; line-height: 1.6;
} }
.custom-stepper {
width: 100%;
display: flex;
flex-direction: column;
gap: 2rem;
}
.stepper-header {
display: flex;
gap: 1rem;
overflow-x: auto;
padding: 1rem 0;
border-bottom: 2px solid rgba(255, 255, 255, 0.1);
}
.stepper-step {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
padding: 0.75rem 1.5rem;
background: transparent;
border: 2px solid rgba(255, 255, 255, 0.3);
color: rgba(255, 255, 255, 0.6);
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
white-space: nowrap;
flex-shrink: 0;
}
.stepper-step:hover {
border-color: rgba(255, 255, 255, 0.6);
color: rgba(255, 255, 255, 0.9);
}
.stepper-step.active {
border-color: #1976d2;
background-color: rgba(25, 118, 210, 0.1);
color: #1976d2;
}
.stepper-step.complete {
border-color: #4caf50;
color: #4caf50;
}
.step-number {
font-weight: bold;
font-size: 1.2em;
}
.step-label {
font-size: 0.875em;
}
.stepper-content {
flex: 1;
overflow-y: auto;
}
.step-item {
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style> </style>