id(); $table->string('internal_name')->unique(); $table->string('name'); $table->text('description'); $table->timestamps(); }); DB::table('achievement_difficulties')->insert([ [ 'internal_name' => 'easy', 'name' => 'Easy', 'description' => "As easy as booking a flight somewhere new!", 'created_at' => now(), 'updated_at' => now(), ], [ 'internal_name' => 'moderate', 'name' => 'Moderate', 'description' => 'You might have to reroute your flights a little just to get the achievement!', 'created_at' => now(), 'updated_at' => now(), ], [ 'internal_name' => 'hard', 'name' => 'Hard', 'description' => "You'll need to go quite a bit out of the way to get this achievement!", 'created_at' => now(), 'updated_at' => now(), ], [ 'internal_name' => 'expensive', 'name' => 'Expensive', 'description' => 'It might be hard, but it will be easier if you have a lot of money!', 'created_at' => now(), 'updated_at' => now(), ], [ 'internal_name' => 'near_impossible', 'name' => 'Near-Impossible', 'description' => 'You will actively have to try to get this achievement and they may be very few ways to go about it.', 'created_at' => now(), 'updated_at' => now(), ], [ 'internal_name' => 'impossible', 'name' => 'Impossible', 'description' => 'This achievement is impossible to get if you start today, but was previously possible.', 'created_at' => now(), 'updated_at' => now(), ], ]); // --------------------------------------------------------------- // 2. achievement_categories // --------------------------------------------------------------- Schema::create('achievement_categories', function (Blueprint $table) { $table->id(); $table->string('internal_name')->unique(); $table->string('name'); $table->text('description'); $table->timestamps(); }); DB::table('achievement_categories')->insert([ [ 'internal_name' => 'general_flying', 'name' => 'General Flying', 'description' => 'Achievements earned through everyday flying activity.', 'created_at' => now(), 'updated_at' => now(), ], [ 'internal_name' => 'countries_and_continents', 'name' => 'Countries & Continents', 'description' => 'Achievements for visiting countries, regions, and continents.', 'created_at' => now(), 'updated_at' => now(), ], [ 'internal_name' => 'aircraft', 'name' => 'Aircraft', 'description' => 'Achievements related to specific aircraft types and manufacturers.', 'created_at' => now(), 'updated_at' => now(), ], [ 'internal_name' => 'airlines_and_alliances', 'name' => 'Airlines and Alliances', 'description' => 'Achievements focused on airlines and alliances', 'created_at' => now(), 'updated_at' => now(), ], [ 'internal_name' => 'fun_challenges', 'name' => 'Fun Challenges', 'description' => 'Quirky and creative challenges for the adventurous traveller.', 'created_at' => now(), 'updated_at' => now(), ], ]); // --------------------------------------------------------------- // 3. Alter achievements — add new columns & foreign keys // --------------------------------------------------------------- Schema::table('achievements', function (Blueprint $table) { // Replace description with split fields $table->string('short_description')->after('internal_name'); $table->text('long_description')->after('short_description'); // Progressive tracking $table->boolean('progressive')->default(false)->after('long_description'); // Difficulty flavour text specific to this achievement $table->text('difficulty_description')->nullable()->after('progressive'); $table->unsignedInteger('threshold')->nullable()->after('progressive'); // Foreign keys $table->foreignId('achievement_category_id') ->after('difficulty_description') ->constrained('achievement_categories') ->restrictOnDelete(); $table->foreignId('achievement_difficulty_id') ->after('achievement_category_id') ->constrained('achievement_difficulties') ->restrictOnDelete(); // Drop the old monolithic description column $table->dropColumn('description'); }); // --------------------------------------------------------------- // 4. Alter user_achievements — add nullable progress column // --------------------------------------------------------------- Schema::table('user_achievements', function (Blueprint $table) { $table->unsignedInteger('progress')->nullable()->after('achievement_id'); }); Schema::create('notifications', function (Blueprint $table) { $table->id(); $table->foreignId('user_id') ->constrained('users') ->cascadeOnDelete(); // Content $table->string('title'); $table->text('body'); $table->string('url')->nullable(); // Achievement flag & optional link $table->boolean('is_achievement')->default(false); $table->foreignId('achievement_id') ->nullable() ->constrained('achievements') ->nullOnDelete(); // State $table->timestamp('read_at')->nullable(); $table->timestamp('expires_at')->nullable(); $table->timestamps(); // Common query patterns $table->index(['user_id', 'read_at']); $table->index('expires_at'); }); $this->seedAchievements(); $this->createAlliances(); } public function createAlliances(): void { Schema::create('alliances', function (Blueprint $table) { $table->id(); $table->string('internal_name')->unique(); $table->string('name'); $table->timestamps(); }); Schema::table('airlines', function (Blueprint $table) { $table->foreignId('alliance_id') ->nullable() ->constrained('alliances') ->nullOnDelete(); }); DB::table('alliances')->insert([ ['internal_name' => 'skyteam', 'name' => 'SkyTeam', 'created_at' => now(), 'updated_at' => now()], ['internal_name' => 'oneworld', 'name' => 'Oneworld', 'created_at' => now(), 'updated_at' => now()], ['internal_name' => 'star_alliance', 'name' => 'Star Alliance', 'created_at' => now(), 'updated_at' => now()], ['internal_name' => 'vanilla_alliance','name' => 'Vanilla Alliance', 'created_at' => now(), 'updated_at' => now()], ]); Airline::whereInternalName('xiamen-airlines')->update(['internal_name' => 'xiamen-air', 'name' => 'XiamenAir']); $skyteam = Alliance::where('internal_name', 'skyteam')->first(); $skyteamMembers = [ 'aerolineas-argentinas', 'aeromexico', 'air-europa', 'air-france', 'china-airlines', 'china-eastern', 'delta', 'garuda-indonesia', 'kenya-airways', 'klm', 'korean-air', 'middle-east-airlines', 'saudia', 'sas', 'tarom', 'vietnam-airlines', 'virgin-atlantic', 'xiamen-air' ]; $star = Alliance::where('internal_name', 'star_alliance')->first(); $starMembers = [ 'aegean-airlines', 'air-canada', 'air-china', 'air-india', 'air-new-zealand', 'all-nippon-airways', 'asiana', 'austrian', 'avianca', 'brussels-airlines', 'copa-airlines', 'croatia-airlines', 'egyptair', 'ethiopian-airlines', 'eva-air', 'ita-airways', 'lot-polish-airlines', 'lufthansa', 'shenzhen-airlines', 'singapore-airlines', 'swiss', 'tap-portugal', 'thai-airways-international', 'turkish-airlines', 'united-airlines', ]; $oneworld = Alliance::where('internal_name', 'oneworld')->first(); $oneworldMembers = [ 'alaska-airlines', 'american-airlines', 'british-airways', 'cathay-pacific', 'fiji-airways', 'finnair', 'hawaiian-airlines', 'iberia', 'japan-airlines', 'malaysia-airlines', 'oman-air', 'qantas', 'qatar-airways', 'royal-air-maroc', 'royal-jordanian', 'srilankan' ]; $vanilla = Alliance::where('internal_name', 'vanilla_alliance')->first(); $vanillaMembers = [ 'air-austral', 'air-madagascar', 'air-seychelles', 'air-mauritius' ]; Airline::whereIn('internal_name', $skyteamMembers)->update(['alliance_id' => $skyteam->id]); Airline::whereIn('internal_name', $starMembers)->update(['alliance_id' => $star->id]); Airline::whereIn('internal_name', $oneworldMembers)->update(['alliance_id' => $oneworld->id]); Airline::whereIn('internal_name', $vanillaMembers)->update(['alliance_id' => $vanilla->id]); } private function seedAchievements(): void { $difficulties = DB::table('achievement_difficulties')->pluck('id', 'internal_name'); $categories = DB::table('achievement_categories')->pluck('id', 'internal_name'); $easy = $difficulties['easy']; $moderate = $difficulties['moderate']; $hard = $difficulties['hard']; $expensive = $difficulties['expensive']; $nearImposs = $difficulties['near_impossible']; $impossible = $difficulties['impossible']; $generalFlying = $categories['general_flying']; $countriesAndContinents = $categories['countries_and_continents']; $aircraft = $categories['aircraft']; $airlinesAndAlliances = $categories['airlines_and_alliances']; $funChallenges = $categories['fun_challenges']; $icon = 'standard_achievement.png'; $achievements = [ // ----------------------------------------------------------- // General Flying // ----------------------------------------------------------- [ 'internal_name' => 'general_flying.first_flight', 'name' => 'Off the Ground', 'short_description' => 'Log your very first flight.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $generalFlying, 'achievement_difficulty_id'=> $easy, ], [ 'internal_name' => 'general_flying.domestic_flight', 'name' => 'Home Turf', 'short_description' => 'Take a domestic flight.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $generalFlying, 'achievement_difficulty_id'=> $easy, ], [ 'internal_name' => 'general_flying.international_flight', 'name' => 'Passport Stamp Collector', 'short_description' => 'Take an international flight.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $generalFlying, 'achievement_difficulty_id'=> $easy, ], [ 'internal_name' => 'general_flying.business_class', 'name' => 'Flatbed Fan', 'short_description' => 'Fly in Business Class.', 'long_description' => '', 'icon' => $icon, 'threshold' => null, 'progressive' => false, 'difficulty_description' => null, 'achievement_category_id' => $generalFlying, 'achievement_difficulty_id'=> $expensive, ], [ 'internal_name' => 'general_flying.first_class', 'name' => 'Caviar at 35,000 Feet', 'short_description' => 'Fly in First Class.', 'long_description' => '', 'icon' => $icon, 'threshold' => null, 'progressive' => false, 'difficulty_description' => null, 'achievement_category_id' => $generalFlying, 'achievement_difficulty_id'=> $expensive, ], [ 'internal_name' => 'general_flying.premium_economy', 'name' => 'Legroom Lover', 'short_description' => 'Fly in Premium Economy.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $generalFlying, 'achievement_difficulty_id'=> $expensive, ], [ 'internal_name' => 'general_flying.business_or_first', 'name' => 'Turn Left', 'short_description' => 'Fly in Business or First Class.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $generalFlying, 'achievement_difficulty_id'=> $moderate, ], [ 'internal_name' => 'general_flying.fly_private', 'name' => 'Wheels Up', 'short_description' => 'Fly on a private aircraft.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $generalFlying, 'achievement_difficulty_id'=> $expensive, ], [ 'internal_name' => 'general_flying.general_aviation', 'name' => 'Little Plane, Big Sky', 'short_description' => 'Take a general aviation flight.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $generalFlying, 'achievement_difficulty_id'=> $moderate, ], [ 'internal_name' => 'general_flying.domestic_two_countries', 'name' => 'Local Explorer', 'short_description' => 'Take domestic flights in two different countries.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $generalFlying, 'achievement_difficulty_id'=> $moderate, ], [ 'internal_name' => 'general_flying.10_flights', 'name' => 'Frequent Flyer in Training', 'short_description' => 'Log 10 flights.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 10, 'difficulty_description' => null, 'achievement_category_id' => $generalFlying, 'achievement_difficulty_id'=> $easy, ], [ 'internal_name' => 'general_flying.100_flights', 'name' => 'Century in the Sky', 'short_description' => 'Log 100 flights.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 100, 'difficulty_description' => null, 'achievement_category_id' => $generalFlying, 'achievement_difficulty_id'=> $moderate, ], [ 'internal_name' => 'general_flying.500_flights', 'name' => 'The 500 Club', 'short_description' => 'Log 500 flights.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 500, 'difficulty_description' => null, 'achievement_category_id' => $generalFlying, 'achievement_difficulty_id'=> $hard, ], [ 'internal_name' => 'general_flying.1000_flights', 'name' => 'Skybound for Life', 'short_description' => 'Log 1,000 flights.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 1000, 'difficulty_description' => null, 'achievement_category_id' => $generalFlying, 'achievement_difficulty_id'=> $expensive, ], // ----------------------------------------------------------- // Countries & Continents // ----------------------------------------------------------- [ 'internal_name' => 'countries_continents.intercontinental', 'name' => 'Intercontinental', 'short_description' => 'Fly between two different continents.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $countriesAndContinents, 'achievement_difficulty_id'=> $moderate, ], [ 'internal_name' => 'countries_continents.fly_to_africa', 'name' => 'Safari Bound', 'short_description' => 'Fly to Africa.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $countriesAndContinents, 'achievement_difficulty_id'=> $easy, ], [ 'internal_name' => 'countries_continents.fly_to_asia', 'name' => 'Orient Express (Air Edition)', 'short_description' => 'Fly to Asia.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $countriesAndContinents, 'achievement_difficulty_id'=> $easy, ], [ 'internal_name' => 'countries_continents.fly_to_oceania', 'name' => "G'Day from 35,000 Feet", 'short_description' => 'Fly to Oceania.', 'long_description' => '', 'icon' => $icon, 'threshold' => null, 'progressive' => false, 'difficulty_description' => null, 'achievement_category_id' => $countriesAndContinents, 'achievement_difficulty_id'=> $easy, ], [ 'internal_name' => 'countries_continents.fly_to_antarctica', 'name' => 'Penguin Spotter', 'short_description' => 'Fly to Antarctica.', 'long_description' => '', 'icon' => $icon, 'threshold' => null, 'progressive' => false, 'difficulty_description' => 'Very few commercial or charter services operate to Antarctica, making this extremely difficult to pull off.', 'achievement_category_id' => $countriesAndContinents, 'achievement_difficulty_id'=> $expensive, ], [ 'internal_name' => 'countries_continents.fly_to_europe', 'name' => 'Bonjour from Above', 'short_description' => 'Fly to Europe.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $countriesAndContinents, 'achievement_difficulty_id'=> $easy, ], [ 'internal_name' => 'countries_continents.fly_to_south_america', 'name' => 'Southern Cross', 'short_description' => 'Fly to South America.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $countriesAndContinents, 'achievement_difficulty_id'=> $easy, ], [ 'internal_name' => 'countries_continents.fly_to_north_america', 'name' => 'Stars, Stripes & Contrails', 'short_description' => 'Fly to North America.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $countriesAndContinents, 'achievement_difficulty_id'=> $easy, ], // ----------------------------------------------------------- // Aircraft // ----------------------------------------------------------- [ 'internal_name' => 'aircraft.fly_on_a_plane', 'name' => 'Up, Up and Away', 'short_description' => 'Fly on an aeroplane.', 'long_description' => '', 'icon' => $icon, 'progressive' => false, 'threshold' => null, 'difficulty_description' => null, 'achievement_category_id' => $aircraft, 'achievement_difficulty_id'=> $easy, ], [ 'internal_name' => 'aircraft.fly_on_a_helicopter', 'name' => 'Chop Chop', 'short_description' => 'Fly on a helicopter.', 'long_description' => '', 'icon' => $icon, 'threshold' => null, 'progressive' => false, 'difficulty_description' => null, 'achievement_category_id' => $aircraft, 'achievement_difficulty_id'=> $moderate, ], [ 'internal_name' => 'aircraft.fly_on_a_jet', 'name' => 'Jet Setter', 'short_description' => 'Fly on a jet-powered aircraft.', 'long_description' => '', 'icon' => $icon, 'threshold' => null, 'progressive' => false, 'difficulty_description' => null, 'achievement_category_id' => $aircraft, 'achievement_difficulty_id'=> $easy, ], [ 'internal_name' => 'aircraft.fly_on_a_prop', 'name' => 'Propeller Head', 'short_description' => 'Fly on a propeller driven aircraft.', 'long_description' => '', 'icon' => $icon, 'threshold' => null, 'progressive' => false, 'difficulty_description' => null, 'achievement_category_id' => $aircraft, 'achievement_difficulty_id'=> $moderate, ], [ 'internal_name' => 'aircraft.all_boeing_7x7', 'name' => 'Seven Heaven', 'short_description' => 'Fly every Boeing 7x7 aircraft family.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'difficulty_description' => 'Requires flying the 707, 717, 727, 737, 747, 757, 767, 777, and 787 — some of which are no longer in commercial service.', 'threshold' => 9, 'achievement_category_id' => $aircraft, 'achievement_difficulty_id'=> $impossible, ], [ 'internal_name' => 'aircraft.all_airbus_a3xx', 'name' => 'Airbus Aristocrat', 'short_description' => 'Fly every Airbus A3xx aircraft family.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 10, 'difficulty_description' => 'Covers the A300, A310, A318–A321, A330, A340, A350, and A380 families. You are likely going to have to go to Iran to get this one.', 'achievement_category_id' => $aircraft, 'achievement_difficulty_id'=> $nearImposs, ], [ 'internal_name' => 'aircraft.quad_engine', 'name' => 'Four on the Floor', 'short_description' => 'Fly on a four-engine aircraft.', 'long_description' => '', 'icon' => $icon, 'threshold' => null, 'progressive' => false, 'difficulty_description' => 'Four-engine jets are becoming increasingly rare as twin-engine widebodies dominate long-haul routes.', 'achievement_category_id' => $aircraft, 'achievement_difficulty_id'=> $hard, ], [ 'internal_name' => 'aircraft.double_decker', 'name' => 'Upper Deck Club', 'short_description' => 'Fly on a double-decker aircraft.', 'long_description' => '', 'icon' => $icon, 'threshold' => null, 'progressive' => false, 'difficulty_description' => 'Primarily the A380 and 747, which operate on a limited and shrinking number of routes.', 'achievement_category_id' => $aircraft, 'achievement_difficulty_id'=> $hard, ], [ 'internal_name' => 'aircraft.single_engine', 'name' => 'Solo Spinner', 'short_description' => 'Fly on a single-engine aircraft.', 'long_description' => '', 'icon' => $icon, 'threshold' => null, 'progressive' => false, 'difficulty_description' => null, 'achievement_category_id' => $aircraft, 'achievement_difficulty_id'=> $moderate, ], [ 'internal_name' => 'aircraft.twin_engine', 'name' => 'Twinsies', 'short_description' => 'Fly on a twin-engine aircraft.', 'long_description' => '', 'icon' => $icon, 'threshold' => null, 'progressive' => false, 'difficulty_description' => 'Most planes in service today meet this criteria!', 'achievement_category_id' => $aircraft, 'achievement_difficulty_id'=> $easy, ], [ 'internal_name' => 'aircraft.tri_engine', 'name' => 'Triple Threat', 'short_description' => 'Fly on a tri-engine aircraft.', 'long_description' => '', 'icon' => $icon, 'threshold' => null, 'progressive' => false, 'difficulty_description' => 'Most tri-jets are out of service nowadays, and tri-props even rarer', 'achievement_category_id' => $aircraft, 'achievement_difficulty_id'=> $nearImposs, ], [ 'internal_name' => 'aircraft.smaller_manufacturer', 'name' => 'Break the Duopoly', 'short_description' => 'Fly on a scheduled flight on an aircraft from a manufacturer other than Boeing or Airbus.', 'long_description' => '', 'icon' => $icon, 'threshold' => null, 'progressive' => false, 'difficulty_description' => null, 'achievement_category_id' => $aircraft, 'achievement_difficulty_id'=> $moderate, ], // ----------------------------------------------------------- // Airlines & Alliances // ----------------------------------------------------------- [ 'internal_name' => 'airlines_alliances.all_skyteam', 'name' => 'Team Player', 'short_description' => 'Fly with every airline in the SkyTeam alliance.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 18, 'difficulty_description' => null, 'achievement_category_id' => $airlinesAndAlliances, 'achievement_difficulty_id'=> $hard, ], [ 'internal_name' => 'airlines_alliances.all_oneworld', 'name' => 'One World Wonder', 'short_description' => 'Fly with every airline in the Oneworld alliance.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 16, 'difficulty_description' => null, 'achievement_category_id' => $airlinesAndAlliances, 'achievement_difficulty_id'=> $hard, ], [ 'internal_name' => 'airlines_alliances.all_star_alliance', 'name' => 'Star Collector', 'short_description' => 'Fly with every airline in the Star Alliance.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 26, 'difficulty_description' => null, 'achievement_category_id' => $airlinesAndAlliances, 'achievement_difficulty_id'=> $hard, ], [ 'internal_name' => 'airlines_alliances.all_vanilla_alliance', 'name' => 'Plain Extraordinary', 'short_description' => 'Fly with every airline in the Vanilla Alliance.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 4, 'difficulty_description' => null, 'achievement_category_id' => $airlinesAndAlliances, 'achievement_difficulty_id'=> $hard, ], // --------------------------------------------------------------- // Fun Challenges // --------------------------------------------------------------- [ 'internal_name' => 'fun_challenges.airline_alphabet', 'name' => 'Fly the Alphabet', 'short_description' => 'Fly with an airline whose IATA code starts with every letter of the alphabet.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 26, 'difficulty_description' => 'Some letters have very few airlines with a matching IATA code, requiring creative routing.', 'achievement_category_id' => $funChallenges, 'achievement_difficulty_id' => $hard, ], [ 'internal_name' => 'fun_challenges.airport_alphabet', 'name' => 'Visit the Alphabet', 'short_description' => 'Visit an airport whose IATA code starts with every letter of the alphabet.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 26, 'difficulty_description' => 'Certain letters — particularly Q, X, and Z — have extremely limited airport coverage, making this a serious challenge.', 'achievement_category_id' => $funChallenges, 'achievement_difficulty_id' => $nearImposs, ], // --------------------------------------------------------------- // Countries & Continents // --------------------------------------------------------------- [ 'internal_name' => 'countries_continents.all_inhabited_continents', 'name' => 'Six of One', 'short_description' => 'Fly to all six inhabited continents.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 6, 'difficulty_description' => null, 'achievement_category_id' => $countriesAndContinents, 'achievement_difficulty_id' => $hard, ], [ 'internal_name' => 'countries_continents.all_continents', 'name' => 'Seven Wonders of the Skies', 'short_description' => 'Fly to all seven continents, including Antarctica.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 7, 'difficulty_description' => 'Antarctica has no commercial scheduled service — expect a specialist charter or expedition flight.', 'achievement_category_id' => $countriesAndContinents, 'achievement_difficulty_id' => $nearImposs, ], [ 'internal_name' => 'countries_continents.all_continent_pairs_one_way', 'name' => 'Grand Junction', 'short_description' => 'Fly between every possible pair of continents at least one way.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 21, 'difficulty_description' => 'There are 21 unique continent pairs (excluding Antarctica)', 'achievement_category_id' => $countriesAndContinents, 'achievement_difficulty_id' => $hard, ], [ 'internal_name' => 'countries_continents.all_continent_pairs_both_ways', 'name' => 'There and Back Again', 'short_description' => 'Fly between every possible pair of continents in both directions.', 'long_description' => '', 'icon' => $icon, 'progressive' => true, 'threshold' => 36, 'difficulty_description' => "36 different intercontinental flights required, good luck.", 'achievement_category_id' => $countriesAndContinents, 'achievement_difficulty_id' => $nearImposs, ], ]; DB::table('achievements')->insert($achievements); } public function down(): void { // Reverse user_achievements Schema::table('user_achievements', function (Blueprint $table) { $table->dropColumn('progress'); }); // Reverse achievements Schema::table('achievements', function (Blueprint $table) { $table->text('description')->after('internal_name'); $table->dropForeign(['achievement_difficulty_id']); $table->dropForeign(['achievement_category_id']); $table->dropColumn([ 'short_description', 'long_description', 'progressive', 'difficulty_description', 'achievement_category_id', 'achievement_difficulty_id', ]); }); Schema::dropIfExists('achievement_categories'); Schema::dropIfExists('achievement_difficulties'); Schema::dropIfExists('notifications'); } };