first commit

This commit is contained in:
Doar Mihai
2026-04-28 16:10:27 +03:00
commit b73f568d90
107 changed files with 18067 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
*.sqlite*
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace Database\Factories;
use App\Models\Attraction;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<Attraction>
*/
class AttractionFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
$categories = ['museum', 'restaurant', 'historic', 'park', 'cultural', 'entertainment', 'other'];
return [
'city_id' => \App\Models\City::factory(),
'name' => fake()->company() . ' ' . fake()->randomElement(['Museum', 'Restaurant', 'Park', 'Theater', 'Gallery']),
'description' => fake()->paragraph(),
'latitude' => fake()->latitude(),
'longitude' => fake()->longitude(),
'category' => fake()->randomElement($categories),
'source' => fake()->randomElement(['opentripmap', 'overpass', 'wikipedia']),
'source_id' => (string) fake()->randomNumber(8),
'rating' => fake()->optional(0.7)->randomFloat(2, 1, 5),
'image_url' => fake()->optional(0.5)->imageUrl(),
'cached_at' => now(),
];
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
namespace Database\Factories;
use App\Models\City;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<City>
*/
class CityFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
$name = fake()->city();
return [
'name' => $name,
'slug' => \Illuminate\Support\Str::slug($name) . '-' . fake()->randomNumber(3),
'country' => fake()->country(),
'latitude' => fake()->latitude(),
'longitude' => fake()->longitude(),
'wikipedia_summary' => fake()->paragraph(3),
'wikipedia_url' => fake()->url(),
'wikipedia_page_id' => fake()->randomNumber(6),
'wikipedia_cached_at' => now(),
];
}
}
+45
View File
@@ -0,0 +1,45 @@
<?php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
/**
* @extends Factory<User>
*/
class UserFactory extends Factory
{
/**
* The current password being used by the factory.
*/
protected static ?string $password;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),
'remember_token' => Str::random(10),
];
}
/**
* Indicate that the model's email address should be unverified.
*/
public function unverified(): static
{
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);
}
}
@@ -0,0 +1,49 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
Schema::dropIfExists('password_reset_tokens');
Schema::dropIfExists('sessions');
}
};
@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('cache', function (Blueprint $table) {
$table->string('key')->primary();
$table->mediumText('value');
$table->bigInteger('expiration')->index();
});
Schema::create('cache_locks', function (Blueprint $table) {
$table->string('key')->primary();
$table->string('owner');
$table->bigInteger('expiration')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('cache');
Schema::dropIfExists('cache_locks');
}
};
@@ -0,0 +1,57 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('jobs', function (Blueprint $table) {
$table->id();
$table->string('queue')->index();
$table->longText('payload');
$table->unsignedTinyInteger('attempts');
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
});
Schema::create('job_batches', function (Blueprint $table) {
$table->string('id')->primary();
$table->string('name');
$table->integer('total_jobs');
$table->integer('pending_jobs');
$table->integer('failed_jobs');
$table->longText('failed_job_ids');
$table->mediumText('options')->nullable();
$table->integer('cancelled_at')->nullable();
$table->integer('created_at');
$table->integer('finished_at')->nullable();
});
Schema::create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('jobs');
Schema::dropIfExists('job_batches');
Schema::dropIfExists('failed_jobs');
}
};
@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->id();
$table->morphs('tokenable');
$table->text('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamp('expires_at')->nullable()->index();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('personal_access_tokens');
}
};
@@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('cities', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('country');
$table->decimal('latitude', 10, 7);
$table->decimal('longitude', 10, 7);
$table->text('wikipedia_summary')->nullable();
$table->string('wikipedia_url')->nullable();
$table->string('wikipedia_page_id')->nullable();
$table->timestamps();
$table->timestamp('wikipedia_cached_at')->nullable();
// Indexes
$table->index(['name', 'country']);
$table->index('wikipedia_cached_at');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('cities');
}
};
@@ -0,0 +1,43 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('attractions', function (Blueprint $table) {
$table->id();
$table->foreignId('city_id')->constrained()->onDelete('cascade');
$table->string('name');
$table->text('description')->nullable();
$table->decimal('latitude', 10, 7);
$table->decimal('longitude', 10, 7);
$table->string('category')->nullable();
$table->enum('source', ['opentripmap', 'overpass', 'wikipedia']);
$table->string('source_id')->nullable();
$table->decimal('rating', 3, 2)->nullable();
$table->string('image_url')->nullable();
$table->timestamps();
$table->timestamp('cached_at')->nullable();
// Indexes
$table->index('city_id');
$table->index('category');
$table->index('cached_at');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('attractions');
}
};
@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('favorites', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->foreignId('city_id')->constrained()->onDelete('cascade');
$table->timestamps();
// Indexes
$table->unique(['user_id', 'city_id']); // Prevent duplicate favorites
$table->index('user_id');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('favorites');
}
};
@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('trips', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->string('name');
$table->text('description')->nullable();
$table->timestamps();
// Indexes
$table->index('user_id');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('trips');
}
};
@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('city_trip', function (Blueprint $table) {
$table->id();
$table->foreignId('trip_id')->constrained()->onDelete('cascade');
$table->foreignId('city_id')->constrained()->onDelete('cascade');
$table->integer('order')->default(0); // Order of cities in trip
$table->timestamps();
// Indexes
$table->index(['trip_id', 'city_id']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('city_trip');
}
};
@@ -0,0 +1,50 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('cities', function (Blueprint $table) {
$table->string('slug')->nullable()->after('name');
});
// Populate slugs for existing cities
$cities = DB::table('cities')->get();
foreach ($cities as $city) {
$slug = \Illuminate\Support\Str::slug($city->name);
$originalSlug = $slug;
$count = 1;
while (DB::table('cities')->where('slug', $slug)->where('id', '!=', $city->id)->exists()) {
$slug = $originalSlug . '-' . $count;
$count++;
}
DB::table('cities')->where('id', $city->id)->update(['slug' => $slug]);
}
// Now make it unique
Schema::table('cities', function (Blueprint $table) {
$table->string('slug')->unique()->change();
$table->index('slug');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('cities', function (Blueprint $table) {
$table->dropIndex(['slug']);
$table->dropColumn('slug');
});
}
};
@@ -0,0 +1,40 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
// Populate slugs for existing cities
$cities = DB::table('cities')->whereNull('slug')->orWhere('slug', '')->get();
foreach ($cities as $city) {
$slug = Str::slug($city->name);
$originalSlug = $slug;
$count = 1;
// Ensure uniqueness
while (DB::table('cities')->where('slug', $slug)->where('id', '!=', $city->id)->exists()) {
$slug = $originalSlug . '-' . $count;
$count++;
}
DB::table('cities')->where('id', $city->id)->update(['slug' => $slug]);
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// No need to reverse - slugs can stay
}
};
@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('cities', function (Blueprint $table) {
$table->string('thumbnail_url')->nullable()->after('wikipedia_url');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('cities', function (Blueprint $table) {
$table->dropColumn('thumbnail_url');
});
}
};
@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('cities', function (Blueprint $table) {
$table->string('image_url')->nullable()->after('thumbnail_url');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('cities', function (Blueprint $table) {
$table->dropColumn('image_url');
});
}
};
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
use WithoutModelEvents;
/**
* Seed the application's database.
*/
public function run(): void
{
// User::factory(10)->create();
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
]);
}
}