search and filtering

This commit is contained in:
Doar Mihai
2026-02-07 14:36:33 +02:00
parent 7a99c3eb59
commit 89be4d4329
10 changed files with 1506 additions and 23 deletions
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace Database\Factories;
use App\Models\Category;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Category>
*/
class CategoryFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Category::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
$name = $this->faker->unique()->words(2, true);
return [
'name' => ucfirst($name),
'slug' => Str::slug($name),
'description' => $this->faker->sentence(),
];
}
}
+77
View File
@@ -0,0 +1,77 @@
<?php
namespace Database\Factories;
use App\Models\Category;
use App\Models\Product;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Product>
*/
class ProductFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Product::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'title' => $this->faker->sentence(3),
'description' => $this->faker->paragraph(),
'website_url' => $this->faker->url(),
'thumbnail' => null,
'user_id' => User::factory(),
'category_id' => Category::factory(),
'status' => 'pending',
'approved_at' => null,
'rejected_at' => null,
];
}
/**
* Indicate that the product is approved.
*/
public function approved(): static
{
return $this->state(fn (array $attributes) => [
'status' => 'approved',
'approved_at' => now(),
'rejected_at' => null,
]);
}
/**
* Indicate that the product is pending.
*/
public function pending(): static
{
return $this->state(fn (array $attributes) => [
'status' => 'pending',
'approved_at' => null,
'rejected_at' => null,
]);
}
/**
* Indicate that the product is rejected.
*/
public function rejected(): static
{
return $this->state(fn (array $attributes) => [
'status' => 'rejected',
'approved_at' => null,
'rejected_at' => now(),
]);
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
namespace Database\Factories;
use App\Models\Product;
use App\Models\Upvote;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Upvote>
*/
class UpvoteFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Upvote::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'user_id' => User::factory(),
'product_id' => Product::factory(),
];
}
}
@@ -0,0 +1,36 @@
<?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('products', function (Blueprint $table) {
// Add fulltext index for search functionality
$table->fullText(['title', 'description'], 'products_search_fulltext');
// Add index on created_at for date range filtering
$table->index('created_at');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('products', function (Blueprint $table) {
// Drop fulltext index
$table->dropFullText('products_search_fulltext');
// Drop created_at index
$table->dropIndex(['created_at']);
});
}
};