From ee1436c6f0881b05b30dc931d5af87cdd88aec17 Mon Sep 17 00:00:00 2001 From: Josh Date: Thu, 18 Sep 2025 17:41:24 +1000 Subject: [PATCH] Added About Page --- app/Models/Tour.php | 6 +++++ app/Models/TourDay.php | 26 +++++++++++++++++++ database/factories/TourDayFactory.php | 22 ++++++++++++++++ ...25_09_18_051804_create_tour_days_table.php | 26 +++++++++++++++++++ database/seeders/DatabaseSeeder.php | 5 +++- resources/js/components/dredgy/ButtonLink.vue | 16 ++++++++++++ resources/js/components/dredgy/TourCard.vue | 10 ++++--- resources/js/components/home/About.vue | 6 ++--- resources/js/pages/AboutUs.vue | 2 ++ resources/js/pages/TourNavigator.vue | 25 ++++++++++++++++++ resources/js/types/index.d.ts | 19 +++++++++++++- routes/web.php | 6 +++++ 12 files changed, 161 insertions(+), 8 deletions(-) create mode 100644 app/Models/TourDay.php create mode 100644 database/factories/TourDayFactory.php create mode 100644 database/migrations/2025_09_18_051804_create_tour_days_table.php create mode 100644 resources/js/components/dredgy/ButtonLink.vue create mode 100644 resources/js/pages/TourNavigator.vue diff --git a/app/Models/Tour.php b/app/Models/Tour.php index 6f37459..9dd3952 100644 --- a/app/Models/Tour.php +++ b/app/Models/Tour.php @@ -15,9 +15,15 @@ class Tour extends Model return $this->belongsToMany(Country::class, 'tour_countries', 'tour_id', 'country_id'); } + public function tour_days() + { + return $this->hasMany(TourDay::class); + } + public static function featuredTours(){ return Tour::whereHas('countries.continent') ->with('countries.continent') + ->with('tour_days') ->inRandomOrder() ->limit(4) ->get(); diff --git a/app/Models/TourDay.php b/app/Models/TourDay.php new file mode 100644 index 0000000..54e864b --- /dev/null +++ b/app/Models/TourDay.php @@ -0,0 +1,26 @@ +belongsTo(Tour::class); + } +} diff --git a/database/factories/TourDayFactory.php b/database/factories/TourDayFactory.php new file mode 100644 index 0000000..7180f58 --- /dev/null +++ b/database/factories/TourDayFactory.php @@ -0,0 +1,22 @@ + Tour::whereInternalName('hebei_harmony')->first()->id, + 'description' => $this->faker->sentence(), + 'content' => $this->faker->paragraphs(3, true), + 'image' => $this->faker->imageUrl(800, 600, 'travel', true, 'Tour Day'), + ]; + } +} diff --git a/database/migrations/2025_09_18_051804_create_tour_days_table.php b/database/migrations/2025_09_18_051804_create_tour_days_table.php new file mode 100644 index 0000000..7aaa69d --- /dev/null +++ b/database/migrations/2025_09_18_051804_create_tour_days_table.php @@ -0,0 +1,26 @@ +id(); + $table->foreignId('tour_id') + ->constrained('tours') + ->onDelete('cascade'); + $table->string('description')->nullable(); + $table->text('content')->nullable(); + $table->string('image')->nullable(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('tour_days'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 99b7514..37fa0df 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -2,6 +2,7 @@ namespace Database\Seeders; +use App\Models\TourDay; use App\Models\User; // use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; @@ -13,7 +14,7 @@ class DatabaseSeeder extends Seeder */ public function run(): void { - // User::factory(10)->create(); + User::factory(10)->create(); $this ->call(ContinentSeeder::class) ->call(CountrySeeder::class) @@ -21,6 +22,8 @@ class DatabaseSeeder extends Seeder ->call(TourCountrySeeder::class) ; + TourDay::factory()->count(5)->create(); + User::factory()->create([ 'name' => 'Test User', 'email' => 'test@example.com', diff --git a/resources/js/components/dredgy/ButtonLink.vue b/resources/js/components/dredgy/ButtonLink.vue new file mode 100644 index 0000000..08740a0 --- /dev/null +++ b/resources/js/components/dredgy/ButtonLink.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/resources/js/components/dredgy/TourCard.vue b/resources/js/components/dredgy/TourCard.vue index 06c4e14..91f2066 100644 --- a/resources/js/components/dredgy/TourCard.vue +++ b/resources/js/components/dredgy/TourCard.vue @@ -3,6 +3,8 @@ import {Tour} from "@/types"; import { defineProps } from 'vue' import EdgyButton from "@/components/dredgy/EdgyButton.vue"; +import {Link} from "@inertiajs/vue3"; +import ButtonLink from "@/components/dredgy/ButtonLink.vue"; const formatPrice = (price: number) => { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(price) } @@ -33,12 +35,12 @@ const props = defineProps<{

{{tour.name}}

{{tour.short_description}}

-
+
- {{tour.length}} Days + {{ tour.tour_days?.length }} Days
@@ -50,7 +52,9 @@ const props = defineProps<{ Maximum 6
- View Details + + Details +
diff --git a/resources/js/components/home/About.vue b/resources/js/components/home/About.vue index 9ad548c..648c23e 100644 --- a/resources/js/components/home/About.vue +++ b/resources/js/components/home/About.vue @@ -33,9 +33,9 @@

Dr Edgy was founded by two close friends who met travelling in North Korea. Both of us love adventure travel with a bit of luxury. One of us is even an actual doctor.

You are in safe hands.

- + GET TO KNOW US - + @@ -149,7 +149,7 @@ import { ref } from 'vue' import EdgyButton from "@/components/dredgy/EdgyButton.vue"; import SectionContainer from "@/components/dredgy/SectionContainer.vue"; import SectionTitle from "@/components/dredgy/SectionTitle.vue"; -import {Link} from "@inertiajs/vue3"; +import ButtonLink from "@/components/dredgy/ButtonLink.vue"; const isVisible = ref(false) diff --git a/resources/js/pages/AboutUs.vue b/resources/js/pages/AboutUs.vue index 967a95d..3ba7162 100644 --- a/resources/js/pages/AboutUs.vue +++ b/resources/js/pages/AboutUs.vue @@ -28,6 +28,7 @@ defineOptions({ or a punchy day tour, we’ll keep it flexible, intimate, and full of good stories.

+
@@ -36,6 +37,7 @@ defineOptions({ +

+import {Tour} from "@/types"; +import {usePage} from "@inertiajs/vue3"; +import AppLayout from "@/layouts/AppLayout.vue"; + +interface Properties { + tour: Tour +} + +const { tour } = usePage().props as unknown as Properties +defineOptions({ + layout: AppLayout +}) + + + + + + diff --git a/resources/js/types/index.d.ts b/resources/js/types/index.d.ts index d5b2ed7..06b2253 100644 --- a/resources/js/types/index.d.ts +++ b/resources/js/types/index.d.ts @@ -53,6 +53,20 @@ export interface Country { continent: Continent; } +/* + 'tour_id', + 'description', + 'content', + 'image', + */ +export interface TourDay { + id: number + tour_id: number + description: string + content: string + image: string | null +} + export interface Tour { id: number name: string @@ -61,5 +75,8 @@ export interface Tour { price: number level: string short_description: string - countries: ?Country[] + countries: Country[] | null + tour_days: TourDay[] | null } + + diff --git a/routes/web.php b/routes/web.php index 133e07c..d07c827 100644 --- a/routes/web.php +++ b/routes/web.php @@ -15,5 +15,11 @@ Route::get('/about', function () { return Inertia::render('AboutUs'); })->name('about'); +Route::get('/adventures/{tour}', function ($tour) { + return Inertia::render('TourNavigator',[ + 'tour' => Tour::where('internal_name', $tour)->with('countries.continent')->first(), + ]); +})->name('tour'); + require __DIR__.'/settings.php'; require __DIR__.'/auth.php';