diff --git a/app/Models/Continent.php b/app/Models/Continent.php
new file mode 100644
index 0000000..dcdb25b
--- /dev/null
+++ b/app/Models/Continent.php
@@ -0,0 +1,27 @@
+orderBy('name')
+ ->get();
+ }
+
+ public function countries(): HasMany
+ {
+ return $this->hasMany(Country::class);
+ }
+
+}
diff --git a/app/Models/Country.php b/app/Models/Country.php
new file mode 100644
index 0000000..45b754f
--- /dev/null
+++ b/app/Models/Country.php
@@ -0,0 +1,28 @@
+belongsTo(Continent::class);
+ }
+
+ public function tours(): BelongsToMany
+ {
+ return $this->belongsToMany(Tour::class, 'tour_countries', 'country_id', 'tour_id');
+ }
+}
diff --git a/app/Models/Tour.php b/app/Models/Tour.php
new file mode 100644
index 0000000..3e6fb3b
--- /dev/null
+++ b/app/Models/Tour.php
@@ -0,0 +1,17 @@
+belongsToMany(Country::class, 'tour_countries', 'tour_id', 'country_id');
+ }
+}
diff --git a/app/Models/TourCountry.php b/app/Models/TourCountry.php
new file mode 100644
index 0000000..2fe926d
--- /dev/null
+++ b/app/Models/TourCountry.php
@@ -0,0 +1,12 @@
+id();
+ $table->string('name');
+ $table->string('internal_name')->unique();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('continents');
+ }
+};
diff --git a/database/migrations/2025_09_15_013414_create_countries_table.php b/database/migrations/2025_09_15_013414_create_countries_table.php
new file mode 100644
index 0000000..a53fe02
--- /dev/null
+++ b/database/migrations/2025_09_15_013414_create_countries_table.php
@@ -0,0 +1,32 @@
+id();
+ $table->string('internal_name')->unique();
+ $table->string('name');
+ $table->string('country_code', 2)->unique();
+ $table->foreignId('continent_id')
+ ->constrained('continents')
+ ->onDelete('restrict'); // or ->onDelete('cascade') if you prefer
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('countries');
+ }
+};
diff --git a/database/migrations/2025_09_15_014700_create_tours_table.php b/database/migrations/2025_09_15_014700_create_tours_table.php
new file mode 100644
index 0000000..a6941ca
--- /dev/null
+++ b/database/migrations/2025_09_15_014700_create_tours_table.php
@@ -0,0 +1,32 @@
+id();
+ $table->string('name');
+ $table->string('internal_name');
+ $table->string('short_description');
+ $table->integer('length');
+ $table->integer('price');
+ $table->string('level');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('tours');
+ }
+};
diff --git a/database/migrations/2025_09_15_021144_create_tour_countries_table.php b/database/migrations/2025_09_15_021144_create_tour_countries_table.php
new file mode 100644
index 0000000..995c0ae
--- /dev/null
+++ b/database/migrations/2025_09_15_021144_create_tour_countries_table.php
@@ -0,0 +1,28 @@
+id();
+ $table->foreignId('country_id')->constrained();
+ $table->foreignId('tour_id')->constrained();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('tour_countries');
+ }
+};
diff --git a/database/seeders/ContinentSeeder.php b/database/seeders/ContinentSeeder.php
new file mode 100644
index 0000000..56e9e4e
--- /dev/null
+++ b/database/seeders/ContinentSeeder.php
@@ -0,0 +1,24 @@
+insert([
+ ['id' => 1, 'name' => 'Australia & Oceania', 'internal_name' => 'oceania'],
+ ['id' => 2, 'name' => 'Africa', 'internal_name' => 'africa'],
+ ['id' => 3, 'name' => 'Asia', 'internal_name' => 'asia'],
+ ['id' => 4, 'name' => 'Europe', 'internal_name' => 'europe'],
+ ['id' => 5, 'name' => 'North America', 'internal_name' => 'north_america'],
+ ['id' => 6, 'name' => 'South America', 'internal_name' => 'south_america'],
+ ['id' => 7, 'name' => 'Antarctica', 'internal_name' => 'antarctica'],
+ ]);
+ }
+
+}
diff --git a/database/seeders/CountrySeeder.php b/database/seeders/CountrySeeder.php
new file mode 100644
index 0000000..f137ed0
--- /dev/null
+++ b/database/seeders/CountrySeeder.php
@@ -0,0 +1,29 @@
+pluck('id', 'internal_name')->toArray();
+
+ \DB::table('countries')->insert([
+ ['internal_name'=>'comoros','name'=>'Comoros','country_code'=>'km','continent_id'=>$map['africa']],
+ ['internal_name'=>'madagascar','name'=>'Madagascar','country_code'=>'mg','continent_id'=>$map['africa']],
+ ['internal_name'=>'suriname','name'=>'Suriname','country_code'=>'sn','continent_id'=>$map['south_america']],
+ ['internal_name'=>'mauritania','name'=>'Mauritania','country_code'=>'mr','continent_id'=>$map['africa']],
+ ['internal_name'=>'china','name'=>'China','country_code'=>'cn','continent_id'=>$map['asia']],
+ ['internal_name'=>'tajikistan','name'=>'Tajikistan','country_code'=>'tj','continent_id'=>$map['asia']],
+ ['internal_name'=>'gabon','name'=>'Gabon','country_code'=>'ga','continent_id'=>$map['africa']],
+ ]);
+ }
+
+}
diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php
index a121999..99b7514 100644
--- a/database/seeders/DatabaseSeeder.php
+++ b/database/seeders/DatabaseSeeder.php
@@ -14,9 +14,12 @@ class DatabaseSeeder extends Seeder
public function run(): void
{
// User::factory(10)->create();
- $this->call(ContinentSeeder::class);
-
- $this->call(CountrySeeder::class);
+ $this
+ ->call(ContinentSeeder::class)
+ ->call(CountrySeeder::class)
+ ->call(TourSeeder::class)
+ ->call(TourCountrySeeder::class)
+ ;
User::factory()->create([
'name' => 'Test User',
diff --git a/database/seeders/TourCountrySeeder.php b/database/seeders/TourCountrySeeder.php
new file mode 100644
index 0000000..b2ad21c
--- /dev/null
+++ b/database/seeders/TourCountrySeeder.php
@@ -0,0 +1,27 @@
+pluck('id', 'internal_name')->toArray();
+ $countryMap= Country::all()->pluck('id', 'internal_name')->toArray();
+ \DB::table('tour_countries')->insert([
+ ['tour_id' => $tourMap['cantonese_charm'], 'country_id' => $countryMap['china']],
+ ['tour_id' => $tourMap['fujianese_fantasy'], 'country_id' => $countryMap['china']],
+ ['tour_id' => $tourMap['hebei_hijinx'], 'country_id' => $countryMap['china']],
+ ]);
+
+ }
+}
diff --git a/database/seeders/TourSeeder.php b/database/seeders/TourSeeder.php
new file mode 100644
index 0000000..f64b92e
--- /dev/null
+++ b/database/seeders/TourSeeder.php
@@ -0,0 +1,23 @@
+insert([
+ ['length' => 8, 'name' => "Cantonese Charm", 'short_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],
+ ['length' => 7, 'name' => "Fujianese Fantasy", 'short_description' => "Experience fresh seafood in Xiamen, and then move rurally for an authentic dive into Hakka culture", 'internal_name' => "fujianese_fantasy", 'level' => "Beginner", 'price' => 1200],
+ ['length' => 10, 'name' => "Hebei Hijinx", 'short_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],
+ ]);
+
+
+ }
+}
diff --git a/public/img/hero.jpg b/public/img/hero.jpg
new file mode 100644
index 0000000..84ca916
Binary files /dev/null and b/public/img/hero.jpg differ
diff --git a/public/img/tours/cantonese_charm.jpg b/public/img/tours/cantonese_charm.jpg
new file mode 100644
index 0000000..bf657ab
Binary files /dev/null and b/public/img/tours/cantonese_charm.jpg differ
diff --git a/public/img/tours/fujianese_fantasy.jpg b/public/img/tours/fujianese_fantasy.jpg
new file mode 100644
index 0000000..3055dd3
Binary files /dev/null and b/public/img/tours/fujianese_fantasy.jpg differ
diff --git a/public/img/tours/hebei_hijinx.jpg b/public/img/tours/hebei_hijinx.jpg
new file mode 100644
index 0000000..c9aedcd
Binary files /dev/null and b/public/img/tours/hebei_hijinx.jpg differ
diff --git a/resources/js/components/dredgy/TourCard.vue b/resources/js/components/dredgy/TourCard.vue
index 1da3a80..bd00b99 100644
--- a/resources/js/components/dredgy/TourCard.vue
+++ b/resources/js/components/dredgy/TourCard.vue
@@ -26,10 +26,10 @@ const props = defineProps<{
{{tour.description}}
+{{tour.short_description}}