Initial commit
Some checks failed
Deploy / deploy (push) Has been cancelled

This commit is contained in:
ssww23
2026-03-10 00:55:37 +03:00
parent fc0f28d830
commit 93a655235a
155 changed files with 24768 additions and 0 deletions

1
database/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.sqlite*

View File

@@ -0,0 +1,44 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\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,
]);
}
}

View File

@@ -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');
}
};

View File

@@ -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->integer('expiration')->index();
});
Schema::create('cache_locks', function (Blueprint $table) {
$table->string('key')->primary();
$table->string('owner');
$table->integer('expiration')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('cache');
Schema::dropIfExists('cache_locks');
}
};

View File

@@ -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');
}
};

View File

@@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('is_admin')->default(false)->after('password');
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('is_admin');
});
}
};

View File

@@ -0,0 +1,25 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug')->unique();
$table->text('description')->nullable();
$table->boolean('is_active')->default(true);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('categories');
}
};

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->foreignId('category_id')->constrained()->cascadeOnDelete();
$table->string('name');
$table->string('slug')->unique();
$table->string('sku')->nullable();
$table->decimal('price', 10, 2);
$table->decimal('old_price', 10, 2)->nullable();
$table->unsignedInteger('stock')->default(0);
$table->text('short_description')->nullable();
$table->longText('description')->nullable();
$table->json('specs')->nullable();
$table->boolean('is_active')->default(true);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('products');
}
};

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('orders', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
$table->string('status')->default('new');
$table->decimal('total', 10, 2)->default(0);
$table->unsignedInteger('items_count')->default(0);
$table->string('customer_name');
$table->string('email');
$table->string('phone')->nullable();
$table->string('address')->nullable();
$table->text('comment')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('orders');
}
};

View File

@@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('order_items', function (Blueprint $table) {
$table->id();
$table->foreignId('order_id')->constrained()->cascadeOnDelete();
$table->foreignId('product_id')->nullable()->constrained()->nullOnDelete();
$table->string('name');
$table->decimal('price', 10, 2);
$table->unsignedInteger('quantity');
$table->decimal('subtotal', 10, 2);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('order_items');
}
};

View File

@@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('orders', function (Blueprint $table) {
$table->string('payment_method')->default('card_transfer')->after('status');
});
}
public function down(): void
{
Schema::table('orders', function (Blueprint $table) {
$table->dropColumn('payment_method');
});
}
};

View File

@@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('chat_conversations', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
$table->string('visitor_token')->unique();
$table->string('status')->default('open');
$table->timestamp('last_message_at')->nullable()->index();
$table->timestamps();
});
Schema::create('chat_messages', function (Blueprint $table) {
$table->id();
$table->foreignId('chat_conversation_id')->constrained('chat_conversations')->cascadeOnDelete();
$table->string('sender', 20);
$table->text('body');
$table->boolean('is_read')->default(false);
$table->timestamps();
$table->index(['chat_conversation_id', 'created_at']);
$table->index(['chat_conversation_id', 'sender', 'is_read']);
});
}
public function down(): void
{
Schema::dropIfExists('chat_messages');
Schema::dropIfExists('chat_conversations');
}
};

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('home_slides', function (Blueprint $table) {
$table->id();
$table->string('zone', 10)->index();
$table->string('title', 160)->nullable();
$table->text('subtitle')->nullable();
$table->string('button_text', 60)->nullable();
$table->string('button_url')->nullable();
$table->string('image_path');
$table->unsignedInteger('sort_order')->default(100)->index();
$table->boolean('is_active')->default(true)->index();
$table->timestamps();
$table->index(['zone', 'is_active', 'sort_order']);
});
}
public function down(): void
{
Schema::dropIfExists('home_slides');
}
};

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
if (Schema::hasTable('sessions')) {
return;
}
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();
});
}
public function down(): void
{
if (Schema::hasTable('sessions')) {
Schema::drop('sessions');
}
}
};

View File

@@ -0,0 +1,26 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('products', function (Blueprint $table) {
if (!Schema::hasColumn('products', 'image_path')) {
$table->string('image_path')->nullable()->after('description');
}
});
}
public function down(): void
{
Schema::table('products', function (Blueprint $table) {
if (Schema::hasColumn('products', 'image_path')) {
$table->dropColumn('image_path');
}
});
}
};

View File

@@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('home_slides', function (Blueprint $table) {
if (!Schema::hasColumn('home_slides', 'show_title')) {
$table->boolean('show_title')->default(true)->after('title');
}
if (!Schema::hasColumn('home_slides', 'show_subtitle')) {
$table->boolean('show_subtitle')->default(true)->after('subtitle');
}
if (!Schema::hasColumn('home_slides', 'show_button')) {
$table->boolean('show_button')->default(true)->after('button_url');
}
});
}
public function down(): void
{
Schema::table('home_slides', function (Blueprint $table) {
if (Schema::hasColumn('home_slides', 'show_title')) {
$table->dropColumn('show_title');
}
if (Schema::hasColumn('home_slides', 'show_subtitle')) {
$table->dropColumn('show_subtitle');
}
if (Schema::hasColumn('home_slides', 'show_button')) {
$table->dropColumn('show_button');
}
});
}
};

View File

@@ -0,0 +1,26 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('products', function (Blueprint $table) {
if (!Schema::hasColumn('products', 'gallery_paths')) {
$table->json('gallery_paths')->nullable()->after('image_path');
}
});
}
public function down(): void
{
Schema::table('products', function (Blueprint $table) {
if (Schema::hasColumn('products', 'gallery_paths')) {
$table->dropColumn('gallery_paths');
}
});
}
};

View File

@@ -0,0 +1,27 @@
<?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',
]);
$this->call(ShopCatalogSeeder::class);
}
}

View File

@@ -0,0 +1,545 @@
<?php
namespace Database\Seeders;
use App\Models\Category;
use App\Models\Product;
use Illuminate\Database\Seeder;
use Illuminate\Support\Str;
class ShopCatalogSeeder extends Seeder
{
public function run(): void
{
$categories = [
[
'name' => 'Процессоры',
'slug' => 'processors',
'description' => 'Процессоры для игровых и рабочих сборок.',
'products' => [
[
'name' => 'AMD Ryzen 7 7700X',
'price' => 33990,
'short_description' => '8 ядер, 16 потоков, до 5.4 ГГц.',
'specs' => [
'manufacturer' => 'AMD',
'socket_type' => 'AM5',
'cpu_type' => 'Ryzen 7',
'cores' => '8',
'cache' => '32 МБ',
],
],
[
'name' => 'Intel Core i7-13700K',
'price' => 38990,
'short_description' => '16 ядер, для мощных систем.',
'specs' => [
'manufacturer' => 'Intel',
'socket_type' => 'LGA1700',
'cpu_type' => 'Core i7',
'cores' => '16',
'cache' => '30 МБ',
],
],
[
'name' => 'AMD Ryzen 5 7600',
'price' => 22990,
'short_description' => 'Оптимален для игровых сборок.',
'specs' => [
'manufacturer' => 'AMD',
'socket_type' => 'AM5',
'cpu_type' => 'Ryzen 5',
'cores' => '6',
'cache' => '32 МБ',
],
],
],
],
[
'name' => 'Материнские платы',
'slug' => 'motherboards',
'description' => 'Надежные платы для любых конфигураций.',
'products' => [
[
'name' => 'ASUS TUF B650-PLUS',
'price' => 21990,
'short_description' => 'AM5, усиленное питание, PCIe 4.0.',
'specs' => [
'manufacturer' => 'ASUS',
'form_factor' => 'ATX',
'cpu_socket' => 'AM5',
'chipset' => 'B650',
'memory_type' => 'DDR5',
'max_memory' => '192 ГБ',
'pcie_version' => 'PCIe 4.0',
'wifi_standard' => 'Wi-Fi 6',
],
],
[
'name' => 'MSI MAG Z790 Tomahawk',
'price' => 28990,
'short_description' => 'LGA1700, мощное охлаждение VRM.',
'specs' => [
'manufacturer' => 'MSI',
'form_factor' => 'ATX',
'cpu_socket' => 'LGA1700',
'chipset' => 'Z790',
'memory_type' => 'DDR5',
'max_memory' => '256 ГБ',
'pcie_version' => 'PCIe 5.0',
'wifi_standard' => 'Wi-Fi 6E',
],
],
[
'name' => 'Gigabyte B760M DS3H',
'price' => 13990,
'short_description' => 'Компактная mATX для LGA1700.',
'specs' => [
'manufacturer' => 'Gigabyte',
'form_factor' => 'mATX',
'cpu_socket' => 'LGA1700',
'chipset' => 'B760',
'memory_type' => 'DDR4',
'max_memory' => '128 ГБ',
'pcie_version' => 'PCIe 4.0',
'wifi_standard' => 'Нет',
],
],
],
],
[
'name' => 'Жесткие диски',
'slug' => 'hard-drives',
'description' => 'SSD и HDD для хранения данных.',
'products' => [
[
'name' => 'Samsung 990 PRO 1TB',
'price' => 10990,
'short_description' => 'NVMe SSD с высокой скоростью.',
'specs' => [
'manufacturer' => 'Samsung',
'capacity' => '1 ТБ',
'form_factor' => 'M.2 2280',
],
],
[
'name' => 'WD Blue 2TB',
'price' => 6990,
'short_description' => 'Надежный HDD для хранения.',
'specs' => [
'manufacturer' => 'Western Digital',
'capacity' => '2 ТБ',
'form_factor' => '3.5\"',
],
],
[
'name' => 'Kingston NV2 500GB',
'price' => 3990,
'short_description' => 'Доступный NVMe накопитель.',
'specs' => [
'manufacturer' => 'Kingston',
'capacity' => '500 ГБ',
'form_factor' => 'M.2 2280',
],
],
],
],
[
'name' => 'Видеокарты',
'slug' => 'graphics-cards',
'description' => 'GPU для игр и работы с графикой.',
'products' => [
[
'name' => 'NVIDIA GeForce RTX 4070',
'price' => 69990,
'short_description' => '12 ГБ GDDR6X, DLSS 3.',
'specs' => [
'manufacturer' => 'NVIDIA',
'gpu' => 'GeForce RTX 4070',
'vram' => '12 ГБ',
'vram_type' => 'GDDR6X',
],
],
[
'name' => 'AMD Radeon RX 7800 XT',
'price' => 64990,
'short_description' => '16 ГБ GDDR6, отличная производительность.',
'specs' => [
'manufacturer' => 'AMD',
'gpu' => 'Radeon RX 7800 XT',
'vram' => '16 ГБ',
'vram_type' => 'GDDR6',
],
],
[
'name' => 'NVIDIA GeForce RTX 4060',
'price' => 39990,
'short_description' => '8 ГБ GDDR6 для 1080p.',
'specs' => [
'manufacturer' => 'NVIDIA',
'gpu' => 'GeForce RTX 4060',
'vram' => '8 ГБ',
'vram_type' => 'GDDR6',
],
],
],
],
[
'name' => 'Оперативная память',
'slug' => 'memory',
'description' => 'DDR4/DDR5 комплекты для скорости.',
'products' => [
[
'name' => 'Corsair Vengeance 32GB',
'price' => 10990,
'short_description' => 'DDR5 6000 МГц, 2x16 ГБ.',
'specs' => [
'manufacturer' => 'Corsair',
'memory_type' => 'DDR5',
'form_factor' => 'DIMM',
'kit' => '2 модуля',
'capacity' => '32 ГБ',
'frequency' => '6000 МГц',
],
],
[
'name' => 'Kingston Fury Beast 16GB',
'price' => 4990,
'short_description' => 'DDR4 3200 МГц, 2x8 ГБ.',
'specs' => [
'manufacturer' => 'Kingston',
'memory_type' => 'DDR4',
'form_factor' => 'DIMM',
'kit' => '2 модуля',
'capacity' => '16 ГБ',
'frequency' => '3200 МГц',
],
],
[
'name' => 'G.Skill Ripjaws 32GB',
'price' => 8990,
'short_description' => 'DDR4 3600 МГц, 2x16 ГБ.',
'specs' => [
'manufacturer' => 'G.Skill',
'memory_type' => 'DDR4',
'form_factor' => 'DIMM',
'kit' => '2 модуля',
'capacity' => '32 ГБ',
'frequency' => '3600 МГц',
],
],
],
],
[
'name' => 'Блоки питания',
'slug' => 'psu',
'description' => 'Надежные блоки питания.',
'products' => [
[
'name' => 'Seasonic Focus GX-750',
'price' => 11990,
'short_description' => '750 Вт, 80 Plus Gold.',
'specs' => [
'manufacturer' => 'Seasonic',
'power' => '750 Вт',
'efficiency' => '80 Plus Gold',
],
],
[
'name' => 'Corsair RM850e',
'price' => 13990,
'short_description' => '850 Вт, тихий режим работы.',
'specs' => [
'manufacturer' => 'Corsair',
'power' => '850 Вт',
'efficiency' => '80 Plus Gold',
],
],
[
'name' => 'be quiet! Pure Power 12 M 650',
'price' => 9990,
'short_description' => '650 Вт, стабильная линия питания.',
'specs' => [
'manufacturer' => 'be quiet!',
'power' => '650 Вт',
'efficiency' => '80 Plus Gold',
],
],
],
],
[
'name' => 'Корпуса',
'slug' => 'cases',
'description' => 'Корпуса с отличным airflow.',
'products' => [
[
'name' => 'Lian Li Lancool 216',
'price' => 8990,
'short_description' => 'ATX, сетчатый фронт.',
'specs' => [
'manufacturer' => 'Lian Li',
'size' => 'ATX Mid Tower',
'gpu_length' => '392 мм',
],
],
[
'name' => 'NZXT H5 Flow',
'price' => 9490,
'short_description' => 'Компактный и продуваемый.',
'specs' => [
'manufacturer' => 'NZXT',
'size' => 'ATX Mid Tower',
'gpu_length' => '365 мм',
],
],
[
'name' => 'Cooler Master NR200P',
'price' => 10990,
'short_description' => 'Мини‑корпус для ITX.',
'specs' => [
'manufacturer' => 'Cooler Master',
'size' => 'Mini ITX',
'gpu_length' => '330 мм',
],
],
],
],
[
'name' => 'Системы охлаждения',
'slug' => 'cooling',
'description' => 'Охлаждение для процессора.',
'products' => [
[
'name' => 'Noctua NH-D15',
'price' => 9990,
'short_description' => 'Топовый воздушный кулер.',
'specs' => [
'manufacturer' => 'Noctua',
'intel_socket' => 'LGA1700',
'amd_socket' => 'AM5',
'fan_speed' => '1500 об/мин',
'fans' => '2 вентилятора',
],
],
[
'name' => 'be quiet! Dark Rock 4',
'price' => 7490,
'short_description' => 'Тихая работа и охлаждение.',
'specs' => [
'manufacturer' => 'be quiet!',
'intel_socket' => 'LGA1700',
'amd_socket' => 'AM4/AM5',
'fan_speed' => '1400 об/мин',
'fans' => '1 вентилятор',
],
],
[
'name' => 'DeepCool LS520',
'price' => 10490,
'short_description' => 'Жидкостное охлаждение 240 мм.',
'specs' => [
'manufacturer' => 'DeepCool',
'intel_socket' => 'LGA1700',
'amd_socket' => 'AM5',
'fan_speed' => '2250 об/мин',
'fans' => '2 вентилятора',
],
],
],
],
[
'name' => 'Ноутбуки',
'slug' => 'laptops',
'description' => 'Ноутбуки для работы и игр.',
'products' => [
[
'name' => 'ASUS TUF Gaming A15',
'price' => 99990,
'short_description' => '15.6\", Ryzen 7, RTX 4060.',
'specs' => [
'manufacturer' => 'ASUS',
'type' => 'Игровой',
'screen_size' => '15.6\"',
'cpu_brand' => 'AMD',
'cpu_model' => 'Ryzen 7 7840HS',
'ram' => '16 ГБ',
'storage' => '1 ТБ SSD',
'panel' => 'IPS',
'resolution' => '1920x1080',
'cores' => '8',
'gpu_brand' => 'NVIDIA',
'gpu_model' => 'RTX 4060',
],
],
[
'name' => 'Lenovo IdeaPad 5',
'price' => 64990,
'short_description' => '14\", легкий для работы.',
'specs' => [
'manufacturer' => 'Lenovo',
'type' => 'Для работы',
'screen_size' => '14\"',
'cpu_brand' => 'Intel',
'cpu_model' => 'Core i5-1340P',
'ram' => '16 ГБ',
'storage' => '512 ГБ SSD',
'panel' => 'IPS',
'resolution' => '1920x1200',
'cores' => '12',
'gpu_brand' => 'Intel',
'gpu_model' => 'Iris Xe',
],
],
[
'name' => 'Acer Swift 3',
'price' => 59990,
'short_description' => '13.5\", компактный ультрабук.',
'specs' => [
'manufacturer' => 'Acer',
'type' => 'Ультрабук',
'screen_size' => '13.5\"',
'cpu_brand' => 'Intel',
'cpu_model' => 'Core i5-1235U',
'ram' => '8 ГБ',
'storage' => '512 ГБ SSD',
'panel' => 'IPS',
'resolution' => '2256x1504',
'cores' => '10',
'gpu_brand' => 'Intel',
'gpu_model' => 'Iris Xe',
],
],
],
],
[
'name' => 'Телевизоры',
'slug' => 'televizory',
'description' => 'Телевизоры для дома и офиса.',
'products' => [
[
'name' => 'Samsung UE55CU7100',
'price' => 49990,
'short_description' => '55\", 4K UHD, Smart TV.',
'specs' => [
'manufacturer' => 'Samsung',
'screen_size' => '55\"',
'resolution' => '3840x2160',
'panel' => 'LED',
'refresh_rate' => '60 Гц',
'smart_tv' => 'Да',
],
],
[
'name' => 'LG 50NANO766QA',
'price' => 57990,
'short_description' => '50\", NanoCell, webOS.',
'specs' => [
'manufacturer' => 'LG',
'screen_size' => '50\"',
'resolution' => '3840x2160',
'panel' => 'NanoCell',
'refresh_rate' => '60 Гц',
'smart_tv' => 'Да',
],
],
[
'name' => 'Xiaomi TV A Pro 43',
'price' => 29990,
'short_description' => '43\", 4K UHD, Android TV.',
'specs' => [
'manufacturer' => 'Xiaomi',
'screen_size' => '43\"',
'resolution' => '3840x2160',
'panel' => 'LED',
'refresh_rate' => '60 Гц',
'smart_tv' => 'Да',
],
],
],
],
[
'name' => 'Apple',
'slug' => 'apple',
'description' => 'Устройства Apple: ноутбуки, планшеты и смартфоны.',
'products' => [
[
'name' => 'Apple MacBook Air 13 M2',
'price' => 124990,
'short_description' => '13.6\", чип M2, 8/256 ГБ.',
'specs' => [
'manufacturer' => 'Apple',
'type' => 'Ноутбук',
'model' => 'MacBook Air 13 M2',
'color' => 'Серебристый',
'screen_size' => '13.6\"',
'storage' => '256 ГБ',
'condition' => 'Новое',
],
],
[
'name' => 'Apple iPhone 14 128GB',
'price' => 69990,
'short_description' => '6.1\", 128 ГБ, отличное состояние.',
'specs' => [
'manufacturer' => 'Apple',
'type' => 'Смартфон',
'model' => 'iPhone 14',
'color' => 'Синий',
'screen_size' => '6.1\"',
'storage' => '128 ГБ',
'condition' => 'Б/у',
],
],
[
'name' => 'Apple iPad Air 11 M2',
'price' => 87990,
'short_description' => '11\", чип M2, WiFi.',
'specs' => [
'manufacturer' => 'Apple',
'type' => 'Планшет',
'model' => 'iPad Air 11 M2',
'color' => 'Фиолетовый',
'screen_size' => '11\"',
'storage' => '256 ГБ',
'condition' => 'Новое',
],
],
],
],
];
foreach ($categories as $categoryData) {
$products = $categoryData['products'];
unset($categoryData['products']);
$category = Category::query()->updateOrCreate(
['slug' => $categoryData['slug']],
$categoryData
);
foreach ($products as $productData) {
$slug = Str::slug($productData['name']);
$skuPrefix = strtoupper(Str::replace('-', '', Str::substr($category->slug, 0, 3)));
$sku = $skuPrefix . '-' . strtoupper(Str::substr(sha1($slug), 0, 6));
$specs = (array) ($productData['specs'] ?? []);
if (!isset($specs['condition']) || trim((string) $specs['condition']) === '') {
$specs['condition'] = 'Новое';
}
Product::query()->updateOrCreate(
['slug' => $slug],
array_merge($productData, [
'category_id' => $category->id,
'slug' => $slug,
'sku' => $productData['sku'] ?? $sku,
'stock' => $productData['stock'] ?? 12,
'old_price' => $productData['old_price'] ?? round($productData['price'] * 1.12),
'description' => $productData['description'] ?? ($productData['short_description'] ?? ''),
'specs' => $specs,
'is_active' => true,
])
);
}
}
}
}