update deploy
This commit is contained in:
1
database/.gitignore
vendored
Normal file
1
database/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.sqlite*
|
||||
42
database/factories/AnnouncementFactory.php
Normal file
42
database/factories/AnnouncementFactory.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Enums\AnnouncementCategory;
|
||||
use App\Models\Announcement;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @extends Factory<Announcement>
|
||||
*/
|
||||
class AnnouncementFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$title = fake()->unique()->sentence(4);
|
||||
|
||||
return [
|
||||
'slug' => Str::slug($title),
|
||||
'title' => $title,
|
||||
'category' => fake()->randomElement(AnnouncementCategory::cases()),
|
||||
'excerpt' => fake()->paragraph(),
|
||||
'content' => fake()->paragraphs(5, true),
|
||||
'image' => null,
|
||||
'is_featured' => fake()->boolean(20),
|
||||
'meta_title' => fake()->sentence(4),
|
||||
'meta_description' => fake()->sentence(10),
|
||||
'published_at' => fake()->dateTimeBetween('-6 months', 'now'),
|
||||
];
|
||||
}
|
||||
|
||||
public function featured(): static
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'is_featured' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
30
database/factories/CategoryFactory.php
Normal file
30
database/factories/CategoryFactory.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\Category;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @extends Factory<Category>
|
||||
*/
|
||||
class CategoryFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$label = fake()->unique()->words(2, true);
|
||||
|
||||
return [
|
||||
'slug' => Str::slug($label),
|
||||
'label' => ucfirst($label),
|
||||
'desc' => fake()->paragraph(),
|
||||
'image' => null,
|
||||
'meta_title' => fake()->sentence(4),
|
||||
'meta_description' => fake()->sentence(10),
|
||||
];
|
||||
}
|
||||
}
|
||||
44
database/factories/CommentFactory.php
Normal file
44
database/factories/CommentFactory.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\Comment;
|
||||
use App\Models\Course;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<Comment>
|
||||
*/
|
||||
class CommentFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'commentable_id' => Course::factory(),
|
||||
'commentable_type' => Course::class,
|
||||
'name_surname' => fake()->name(),
|
||||
'phone' => fake()->phoneNumber(),
|
||||
'body' => fake()->paragraph(),
|
||||
'admin_reply' => null,
|
||||
'is_approved' => false,
|
||||
];
|
||||
}
|
||||
|
||||
public function approved(): static
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'is_approved' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function withReply(): static
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'admin_reply' => fake()->paragraph(),
|
||||
'is_approved' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
27
database/factories/CourseBlockFactory.php
Normal file
27
database/factories/CourseBlockFactory.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\Course;
|
||||
use App\Models\CourseBlock;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<CourseBlock>
|
||||
*/
|
||||
class CourseBlockFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'course_id' => Course::factory(),
|
||||
'type' => fake()->randomElement(['hero', 'text', 'cards', 'stats_grid', 'cta', 'faq', 'gallery']),
|
||||
'content' => ['title' => fake()->sentence()],
|
||||
'order_index' => fake()->numberBetween(0, 10),
|
||||
'is_active' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
45
database/factories/CourseFactory.php
Normal file
45
database/factories/CourseFactory.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\Category;
|
||||
use App\Models\Course;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @extends Factory<Course>
|
||||
*/
|
||||
class CourseFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$title = fake()->unique()->words(3, true);
|
||||
|
||||
return [
|
||||
'category_id' => Category::factory(),
|
||||
'slug' => Str::slug($title),
|
||||
'title' => ucfirst($title),
|
||||
'sub' => fake()->optional()->word(),
|
||||
'desc' => fake()->paragraph(),
|
||||
'long_desc' => fake()->paragraphs(3, true),
|
||||
'duration' => fake()->randomElement(['3 Gün', '5 Gün', '10 Gün', '2 Hafta']),
|
||||
'students' => fake()->numberBetween(0, 500),
|
||||
'rating' => fake()->randomFloat(1, 3.0, 5.0),
|
||||
'badge' => fake()->optional()->randomElement(['Simülatör', 'Online', 'Yüz Yüze']),
|
||||
'image' => null,
|
||||
'price' => fake()->optional()->randomElement(['2.500 TL', '5.000 TL', '7.500 TL', '10.000 TL']),
|
||||
'includes' => fake()->words(4),
|
||||
'requirements' => fake()->words(3),
|
||||
'meta_title' => fake()->sentence(4),
|
||||
'meta_description' => fake()->sentence(10),
|
||||
'scope' => fake()->words(5),
|
||||
'standard' => fake()->optional()->randomElement(['STCW Uyumlu', 'IMO Uyumlu', 'STCW / IMO Uyumlu']),
|
||||
'language' => 'Türkçe',
|
||||
'location' => fake()->optional()->randomElement(['Kadıköy, İstanbul', 'Tuzla, İstanbul', 'Beşiktaş, İstanbul']),
|
||||
];
|
||||
}
|
||||
}
|
||||
33
database/factories/CourseScheduleFactory.php
Normal file
33
database/factories/CourseScheduleFactory.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\Course;
|
||||
use App\Models\CourseSchedule;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<CourseSchedule>
|
||||
*/
|
||||
class CourseScheduleFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$startDate = fake()->dateTimeBetween('+1 week', '+3 months');
|
||||
$endDate = (clone $startDate)->modify('+'.fake()->numberBetween(3, 14).' days');
|
||||
$quota = fake()->numberBetween(10, 30);
|
||||
|
||||
return [
|
||||
'course_id' => Course::factory(),
|
||||
'start_date' => $startDate,
|
||||
'end_date' => $endDate,
|
||||
'location' => fake()->randomElement(['Kadıköy', 'Tuzla', 'Online']),
|
||||
'quota' => $quota,
|
||||
'available_seats' => fake()->numberBetween(0, $quota),
|
||||
'is_urgent' => fake()->boolean(20),
|
||||
];
|
||||
}
|
||||
}
|
||||
34
database/factories/FaqFactory.php
Normal file
34
database/factories/FaqFactory.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Enums\FaqCategory;
|
||||
use App\Models\Faq;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<Faq>
|
||||
*/
|
||||
class FaqFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'category' => fake()->randomElement(FaqCategory::cases()),
|
||||
'question' => fake()->sentence().'?',
|
||||
'answer' => fake()->paragraph(),
|
||||
'order_index' => fake()->numberBetween(0, 10),
|
||||
'is_active' => true,
|
||||
];
|
||||
}
|
||||
|
||||
public function inactive(): static
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'is_active' => false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
28
database/factories/GuideCardFactory.php
Normal file
28
database/factories/GuideCardFactory.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\GuideCard;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<GuideCard>
|
||||
*/
|
||||
class GuideCardFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'title' => fake()->words(2, true),
|
||||
'description' => fake()->paragraph(),
|
||||
'icon' => fake()->randomElement(['anchor', 'compass', 'shield', 'briefcase', 'ship', 'navigation']),
|
||||
'color' => fake()->randomElement(['from-blue-500 to-blue-700', 'from-emerald-500 to-emerald-700', 'from-orange-500 to-orange-700', 'from-rose-500 to-rose-700']),
|
||||
'link' => '/'.fake()->slug(2),
|
||||
'order' => fake()->numberBetween(0, 10),
|
||||
'is_active' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
34
database/factories/HeroSlideFactory.php
Normal file
34
database/factories/HeroSlideFactory.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\HeroSlide;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<HeroSlide>
|
||||
*/
|
||||
class HeroSlideFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'label' => fake()->words(3, true),
|
||||
'title' => fake()->sentence(5),
|
||||
'description' => fake()->paragraph(),
|
||||
'image' => null,
|
||||
'order_index' => fake()->numberBetween(0, 10),
|
||||
'is_active' => true,
|
||||
];
|
||||
}
|
||||
|
||||
public function inactive(): static
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'is_active' => false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
44
database/factories/LeadFactory.php
Normal file
44
database/factories/LeadFactory.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Enums\LeadSource;
|
||||
use App\Enums\LeadStatus;
|
||||
use App\Models\Lead;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<Lead>
|
||||
*/
|
||||
class LeadFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'name' => fake()->name(),
|
||||
'phone' => fake()->phoneNumber(),
|
||||
'target_course' => fake()->optional()->words(2, true),
|
||||
'education_level' => fake()->optional()->randomElement(['Lise', 'Üniversite', 'Lisans', 'Yüksek Lisans']),
|
||||
'subject' => fake()->optional()->randomElement(['stcw', 'kaptanlik', 'belge', 'diger']),
|
||||
'message' => fake()->optional()->paragraph(),
|
||||
'status' => fake()->randomElement(LeadStatus::cases()),
|
||||
'notes' => null,
|
||||
'is_read' => fake()->boolean(30),
|
||||
'source' => fake()->randomElement(LeadSource::cases()),
|
||||
'utm' => null,
|
||||
'consent_kvkk' => true,
|
||||
'consent_text_version' => 'v1.0',
|
||||
];
|
||||
}
|
||||
|
||||
public function unread(): static
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'is_read' => false,
|
||||
'status' => LeadStatus::New,
|
||||
]);
|
||||
}
|
||||
}
|
||||
30
database/factories/MenuFactory.php
Normal file
30
database/factories/MenuFactory.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Enums\MenuLocation;
|
||||
use App\Enums\MenuType;
|
||||
use App\Models\Menu;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<Menu>
|
||||
*/
|
||||
class MenuFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'location' => fake()->randomElement(MenuLocation::cases()),
|
||||
'label' => fake()->words(2, true),
|
||||
'url' => '/'.fake()->slug(2),
|
||||
'type' => MenuType::Link,
|
||||
'parent_id' => null,
|
||||
'order' => fake()->numberBetween(0, 10),
|
||||
'is_active' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
30
database/factories/PageBlockFactory.php
Normal file
30
database/factories/PageBlockFactory.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\Page;
|
||||
use App\Models\PageBlock;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<PageBlock>
|
||||
*/
|
||||
class PageBlockFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'page_id' => Page::factory(),
|
||||
'type' => fake()->randomElement(['hero', 'text_image', 'stats_grid', 'cta', 'gallery']),
|
||||
'content' => [
|
||||
'title' => fake()->sentence(3),
|
||||
'text' => fake()->paragraph(),
|
||||
],
|
||||
'order_index' => fake()->numberBetween(0, 10),
|
||||
'is_active' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
29
database/factories/PageFactory.php
Normal file
29
database/factories/PageFactory.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\Page;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @extends Factory<Page>
|
||||
*/
|
||||
class PageFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$title = fake()->unique()->words(3, true);
|
||||
|
||||
return [
|
||||
'slug' => Str::slug($title),
|
||||
'title' => ucfirst($title),
|
||||
'meta_title' => fake()->sentence(4),
|
||||
'meta_description' => fake()->sentence(10),
|
||||
'is_active' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
29
database/factories/StoryFactory.php
Normal file
29
database/factories/StoryFactory.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\Story;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<Story>
|
||||
*/
|
||||
class StoryFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'title' => fake()->sentence(4),
|
||||
'badge' => fake()->randomElement(['Tanıtım', 'Yeni Dönem', null]),
|
||||
'content' => fake()->paragraphs(2, true),
|
||||
'image' => null,
|
||||
'cta_text' => fake()->randomElement(['Detaylı Bilgi', 'Hakkımızda', null]),
|
||||
'cta_url' => fake()->randomElement(['/kurumsal/hakkimizda', '/egitimler', null]),
|
||||
'order_index' => fake()->numberBetween(0, 10),
|
||||
'is_active' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
45
database/factories/UserFactory.php
Normal file
45
database/factories/UserFactory.php
Normal 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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
49
database/migrations/0001_01_01_000000_create_users_table.php
Normal file
49
database/migrations/0001_01_01_000000_create_users_table.php
Normal 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');
|
||||
}
|
||||
};
|
||||
35
database/migrations/0001_01_01_000001_create_cache_table.php
Normal file
35
database/migrations/0001_01_01_000001_create_cache_table.php
Normal 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');
|
||||
}
|
||||
};
|
||||
57
database/migrations/0001_01_01_000002_create_jobs_table.php
Normal file
57
database/migrations/0001_01_01_000002_create_jobs_table.php
Normal 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');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
<?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
|
||||
{
|
||||
$teams = config('permission.teams');
|
||||
$tableNames = config('permission.table_names');
|
||||
$columnNames = config('permission.column_names');
|
||||
$pivotRole = $columnNames['role_pivot_key'] ?? 'role_id';
|
||||
$pivotPermission = $columnNames['permission_pivot_key'] ?? 'permission_id';
|
||||
|
||||
throw_if(empty($tableNames), 'Error: config/permission.php not loaded. Run [php artisan config:clear] and try again.');
|
||||
throw_if($teams && empty($columnNames['team_foreign_key'] ?? null), 'Error: team_foreign_key on config/permission.php not loaded. Run [php artisan config:clear] and try again.');
|
||||
|
||||
/**
|
||||
* See `docs/prerequisites.md` for suggested lengths on 'name' and 'guard_name' if "1071 Specified key was too long" errors are encountered.
|
||||
*/
|
||||
Schema::create($tableNames['permissions'], static function (Blueprint $table) {
|
||||
$table->id(); // permission id
|
||||
$table->string('name');
|
||||
$table->string('guard_name');
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['name', 'guard_name']);
|
||||
});
|
||||
|
||||
/**
|
||||
* See `docs/prerequisites.md` for suggested lengths on 'name' and 'guard_name' if "1071 Specified key was too long" errors are encountered.
|
||||
*/
|
||||
Schema::create($tableNames['roles'], static function (Blueprint $table) use ($teams, $columnNames) {
|
||||
$table->id(); // role id
|
||||
if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing
|
||||
$table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable();
|
||||
$table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index');
|
||||
}
|
||||
$table->string('name');
|
||||
$table->string('guard_name');
|
||||
$table->timestamps();
|
||||
if ($teams || config('permission.testing')) {
|
||||
$table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']);
|
||||
} else {
|
||||
$table->unique(['name', 'guard_name']);
|
||||
}
|
||||
});
|
||||
|
||||
Schema::create($tableNames['model_has_permissions'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) {
|
||||
$table->unsignedBigInteger($pivotPermission);
|
||||
|
||||
$table->string('model_type');
|
||||
$table->unsignedBigInteger($columnNames['model_morph_key']);
|
||||
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index');
|
||||
|
||||
$table->foreign($pivotPermission)
|
||||
->references('id') // permission id
|
||||
->on($tableNames['permissions'])
|
||||
->cascadeOnDelete();
|
||||
if ($teams) {
|
||||
$table->unsignedBigInteger($columnNames['team_foreign_key']);
|
||||
$table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index');
|
||||
|
||||
$table->primary([$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_permissions_permission_model_type_primary');
|
||||
} else {
|
||||
$table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_permissions_permission_model_type_primary');
|
||||
}
|
||||
});
|
||||
|
||||
Schema::create($tableNames['model_has_roles'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) {
|
||||
$table->unsignedBigInteger($pivotRole);
|
||||
|
||||
$table->string('model_type');
|
||||
$table->unsignedBigInteger($columnNames['model_morph_key']);
|
||||
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index');
|
||||
|
||||
$table->foreign($pivotRole)
|
||||
->references('id') // role id
|
||||
->on($tableNames['roles'])
|
||||
->cascadeOnDelete();
|
||||
if ($teams) {
|
||||
$table->unsignedBigInteger($columnNames['team_foreign_key']);
|
||||
$table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index');
|
||||
|
||||
$table->primary([$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_roles_role_model_type_primary');
|
||||
} else {
|
||||
$table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_roles_role_model_type_primary');
|
||||
}
|
||||
});
|
||||
|
||||
Schema::create($tableNames['role_has_permissions'], static function (Blueprint $table) use ($tableNames, $pivotRole, $pivotPermission) {
|
||||
$table->unsignedBigInteger($pivotPermission);
|
||||
$table->unsignedBigInteger($pivotRole);
|
||||
|
||||
$table->foreign($pivotPermission)
|
||||
->references('id') // permission id
|
||||
->on($tableNames['permissions'])
|
||||
->cascadeOnDelete();
|
||||
|
||||
$table->foreign($pivotRole)
|
||||
->references('id') // role id
|
||||
->on($tableNames['roles'])
|
||||
->cascadeOnDelete();
|
||||
|
||||
$table->primary([$pivotPermission, $pivotRole], 'role_has_permissions_permission_id_role_id_primary');
|
||||
});
|
||||
|
||||
app('cache')
|
||||
->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null)
|
||||
->forget(config('permission.cache.key'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
$tableNames = config('permission.table_names');
|
||||
|
||||
throw_if(empty($tableNames), 'Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.');
|
||||
|
||||
Schema::dropIfExists($tableNames['role_has_permissions']);
|
||||
Schema::dropIfExists($tableNames['model_has_roles']);
|
||||
Schema::dropIfExists($tableNames['model_has_permissions']);
|
||||
Schema::dropIfExists($tableNames['roles']);
|
||||
Schema::dropIfExists($tableNames['permissions']);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateActivityLogTable extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::connection(config('activitylog.database_connection'))->create(config('activitylog.table_name'), function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('log_name')->nullable();
|
||||
$table->text('description');
|
||||
$table->nullableMorphs('subject', 'subject');
|
||||
$table->nullableMorphs('causer', 'causer');
|
||||
$table->json('properties')->nullable();
|
||||
$table->timestamps();
|
||||
$table->index('log_name');
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::connection(config('activitylog.database_connection'))->dropIfExists(config('activitylog.table_name'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddEventColumnToActivityLogTable extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) {
|
||||
$table->string('event')->nullable()->after('subject_type');
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) {
|
||||
$table->dropColumn('event');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddBatchUuidColumnToActivityLogTable extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) {
|
||||
$table->uuid('batch_uuid')->nullable()->after('properties');
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::connection(config('activitylog.database_connection'))->table(config('activitylog.table_name'), function (Blueprint $table) {
|
||||
$table->dropColumn('batch_uuid');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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,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('users', function (Blueprint $table) {
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropSoftDeletes();
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
<?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('categories', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('slug')->unique();
|
||||
$table->string('label');
|
||||
$table->text('desc')->nullable();
|
||||
$table->string('image')->nullable();
|
||||
$table->string('meta_title')->nullable();
|
||||
$table->text('meta_description')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('categories');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
<?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('courses', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('category_id')->constrained()->cascadeOnDelete();
|
||||
$table->string('slug')->unique();
|
||||
$table->string('title');
|
||||
$table->string('sub')->nullable();
|
||||
$table->text('desc');
|
||||
$table->longText('long_desc');
|
||||
$table->string('duration');
|
||||
$table->unsignedInteger('students')->default(0);
|
||||
$table->decimal('rating', 2, 1)->default(5.0);
|
||||
$table->string('badge')->nullable();
|
||||
$table->string('image')->nullable();
|
||||
$table->string('price')->nullable();
|
||||
$table->json('includes')->nullable();
|
||||
$table->json('requirements')->nullable();
|
||||
$table->string('meta_title')->nullable();
|
||||
$table->text('meta_description')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('courses');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
<?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('course_schedules', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('course_id')->constrained()->cascadeOnDelete();
|
||||
$table->date('start_date');
|
||||
$table->date('end_date');
|
||||
$table->string('location');
|
||||
$table->unsignedInteger('quota');
|
||||
$table->unsignedInteger('available_seats');
|
||||
$table->boolean('is_urgent')->default(false);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('course_schedules');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
<?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('announcements', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('slug')->unique();
|
||||
$table->string('title');
|
||||
$table->string('category');
|
||||
$table->text('excerpt');
|
||||
$table->longText('content');
|
||||
$table->string('image')->nullable();
|
||||
$table->boolean('is_featured')->default(false);
|
||||
$table->string('meta_title')->nullable();
|
||||
$table->text('meta_description')->nullable();
|
||||
$table->timestamp('published_at')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('announcements');
|
||||
}
|
||||
};
|
||||
@@ -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('hero_slides', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('label');
|
||||
$table->string('title');
|
||||
$table->text('description');
|
||||
$table->string('image')->nullable();
|
||||
$table->unsignedInteger('order')->default(0);
|
||||
$table->boolean('is_active')->default(true);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('hero_slides');
|
||||
}
|
||||
};
|
||||
41
database/migrations/2026_03_02_090007_create_leads_table.php
Normal file
41
database/migrations/2026_03_02_090007_create_leads_table.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?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('leads', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('phone');
|
||||
$table->string('target_course')->nullable();
|
||||
$table->string('education_level')->nullable();
|
||||
$table->string('subject')->nullable();
|
||||
$table->text('message')->nullable();
|
||||
$table->string('status')->default('new');
|
||||
$table->text('notes')->nullable();
|
||||
$table->boolean('is_read')->default(false);
|
||||
$table->string('source');
|
||||
$table->json('utm')->nullable();
|
||||
$table->boolean('consent_kvkk')->default(false);
|
||||
$table->string('consent_text_version')->nullable();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('leads');
|
||||
}
|
||||
};
|
||||
36
database/migrations/2026_03_02_090008_create_menus_table.php
Normal file
36
database/migrations/2026_03_02_090008_create_menus_table.php
Normal file
@@ -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::create('menus', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('location');
|
||||
$table->string('label');
|
||||
$table->string('url');
|
||||
$table->string('type')->default('link');
|
||||
$table->unsignedBigInteger('parent_id')->nullable();
|
||||
$table->unsignedInteger('order')->default(0);
|
||||
$table->boolean('is_active')->default(true);
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('parent_id')->references('id')->on('menus')->nullOnDelete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('menus');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
<?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('comments', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->morphs('commentable');
|
||||
$table->string('name_surname');
|
||||
$table->string('phone');
|
||||
$table->text('body');
|
||||
$table->text('admin_reply')->nullable();
|
||||
$table->boolean('is_approved')->default(false);
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('comments');
|
||||
}
|
||||
};
|
||||
32
database/migrations/2026_03_02_090010_create_faqs_table.php
Normal file
32
database/migrations/2026_03_02_090010_create_faqs_table.php
Normal 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
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('faqs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('category');
|
||||
$table->text('question');
|
||||
$table->text('answer');
|
||||
$table->unsignedInteger('order')->default(0);
|
||||
$table->boolean('is_active')->default(true);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('faqs');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
<?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('guide_cards', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('title');
|
||||
$table->text('description');
|
||||
$table->string('icon');
|
||||
$table->string('color');
|
||||
$table->string('link');
|
||||
$table->unsignedInteger('order')->default(0);
|
||||
$table->boolean('is_active')->default(true);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('guide_cards');
|
||||
}
|
||||
};
|
||||
@@ -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
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('settings', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('group');
|
||||
$table->string('key')->unique();
|
||||
$table->text('value')->nullable();
|
||||
$table->string('type')->default('text');
|
||||
$table->boolean('is_public')->default(true);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('settings');
|
||||
}
|
||||
};
|
||||
32
database/migrations/2026_03_02_090013_create_pages_table.php
Normal file
32
database/migrations/2026_03_02_090013_create_pages_table.php
Normal 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
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('pages', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('slug')->unique();
|
||||
$table->string('title');
|
||||
$table->string('meta_title')->nullable();
|
||||
$table->text('meta_description')->nullable();
|
||||
$table->boolean('is_active')->default(true);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('pages');
|
||||
}
|
||||
};
|
||||
@@ -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
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('page_blocks', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('page_id')->constrained()->cascadeOnDelete();
|
||||
$table->string('type');
|
||||
$table->json('content')->nullable();
|
||||
$table->unsignedInteger('order_index')->default(0);
|
||||
$table->boolean('is_active')->default(true);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('page_blocks');
|
||||
}
|
||||
};
|
||||
@@ -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
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('courses', function (Blueprint $table) {
|
||||
$table->json('scope')->nullable()->after('meta_description');
|
||||
$table->string('standard')->nullable()->after('scope');
|
||||
$table->string('language')->nullable()->default('Türkçe')->after('standard');
|
||||
$table->string('location')->nullable()->after('language');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('courses', function (Blueprint $table) {
|
||||
$table->dropColumn(['scope', 'standard', 'language', 'location']);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -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
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('courses', function (Blueprint $table) {
|
||||
// null = mega menu'de görünmez
|
||||
// 1, 2, 3 = kategori kartında gösterilecek kurs sırası
|
||||
$table->unsignedTinyInteger('menu_order')->nullable()->after('badge');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('courses', function (Blueprint $table) {
|
||||
$table->dropColumn('menu_order');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -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::table('settings', function (Blueprint $table) {
|
||||
$table->string('label', 150)->nullable()->after('type');
|
||||
$table->integer('order_index')->default(0)->after('label');
|
||||
|
||||
// Replace unique key constraint to (group, key) combo
|
||||
$table->dropUnique(['key']);
|
||||
$table->unique(['group', 'key']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->dropUnique(['group', 'key']);
|
||||
$table->unique('key');
|
||||
$table->dropColumn(['label', 'order_index']);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -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
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('course_blocks', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('course_id')->constrained()->cascadeOnDelete();
|
||||
$table->string('type', 50);
|
||||
$table->json('content')->nullable();
|
||||
$table->unsignedInteger('order_index')->default(0);
|
||||
$table->boolean('is_active')->default(true);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('course_blocks');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
<?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('leads', function (Blueprint $table) {
|
||||
$table->string('email')->nullable()->after('phone');
|
||||
$table->boolean('marketing_consent')->default(false)->after('consent_kvkk');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('leads', function (Blueprint $table) {
|
||||
$table->dropColumn(['email', 'marketing_consent']);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -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('faqs', function (Blueprint $table) {
|
||||
$table->renameColumn('order', 'order_index');
|
||||
});
|
||||
|
||||
Schema::table('hero_slides', function (Blueprint $table) {
|
||||
$table->renameColumn('order', 'order_index');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('faqs', function (Blueprint $table) {
|
||||
$table->renameColumn('order_index', 'order');
|
||||
});
|
||||
|
||||
Schema::table('hero_slides', function (Blueprint $table) {
|
||||
$table->renameColumn('order_index', 'order');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -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('stories', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('title');
|
||||
$table->string('badge')->nullable();
|
||||
$table->text('content');
|
||||
$table->string('image')->nullable();
|
||||
$table->string('cta_text')->nullable();
|
||||
$table->string('cta_url')->nullable();
|
||||
$table->unsignedSmallInteger('order_index')->default(0);
|
||||
$table->boolean('is_active')->default(true);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('stories');
|
||||
}
|
||||
};
|
||||
@@ -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
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('course_schedules', function (Blueprint $table) {
|
||||
$table->string('instructor')->nullable()->after('location');
|
||||
$table->unsignedInteger('enrolled_count')->default(0)->after('available_seats');
|
||||
$table->decimal('price_override', 10, 2)->nullable()->after('enrolled_count');
|
||||
$table->string('status')->default('planned')->after('price_override');
|
||||
$table->text('notes')->nullable()->after('is_urgent');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('course_schedules', function (Blueprint $table) {
|
||||
$table->dropColumn(['instructor', 'enrolled_count', 'price_override', 'status', 'notes']);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -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
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('hero_slides', function (Blueprint $table) {
|
||||
$table->string('media_type')->default('image')->after('description');
|
||||
$table->string('video_url')->nullable()->after('image');
|
||||
$table->string('mobile_image')->nullable()->after('video_url');
|
||||
$table->string('button_text')->nullable()->after('mobile_image');
|
||||
$table->string('button_url')->nullable()->after('button_text');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('hero_slides', function (Blueprint $table) {
|
||||
$table->dropColumn(['media_type', 'video_url', 'mobile_image', 'button_text', 'button_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('hero_slides', function (Blueprint $table) {
|
||||
$table->string('mobile_video_url')->nullable()->after('video_url');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('hero_slides', function (Blueprint $table) {
|
||||
$table->dropColumn('mobile_video_url');
|
||||
});
|
||||
}
|
||||
};
|
||||
27
database/seeders/AdminUserSeeder.php
Normal file
27
database/seeders/AdminUserSeeder.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class AdminUserSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$admin = User::query()->firstOrCreate(
|
||||
['email' => 'admin@bogazicidenizcilik.com.tr'],
|
||||
[
|
||||
'name' => 'Super Admin',
|
||||
'password' => Hash::make('password'),
|
||||
'email_verified_at' => now(),
|
||||
]
|
||||
);
|
||||
|
||||
$admin->assignRole('super-admin');
|
||||
}
|
||||
}
|
||||
94
database/seeders/AnnouncementSeeder.php
Normal file
94
database/seeders/AnnouncementSeeder.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class AnnouncementSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
DB::table('announcements')->truncate();
|
||||
|
||||
$announcements = [
|
||||
[
|
||||
'slug' => '2026-bahar-donemi-kayitlari-basladi',
|
||||
'title' => '2026 Bahar Dönemi Kayıtları Başladı',
|
||||
'category' => 'announcement',
|
||||
'excerpt' => 'Bahar dönemi eğitim programlarımıza kayıtlar başlamıştır. Kontenjanlarımız sınırlı olduğundan erken kayıt yaptırmanızı tavsiye ederiz.',
|
||||
'content' => "Bahar dönemi eğitim programlarımıza kayıtlar başlamıştır. Yeni dönemde hem yüz yüze hem de online eğitim seçeneklerimizle denizcilik kariyerinize hız kesmeden devam edebilir, eksik belgelerinizi tamamlayabilirsiniz.\n\n- Tüm eğitim başlıklarımızda %10 erken kayıt avantajı sunulmaktadır.\n- Kesin kayıt esnasında istenilen evrak listesini detay inceleyiniz.\n- Kontenjanlar dolmadan yerinizi ayırtmayı unutmayın.",
|
||||
'image' => null,
|
||||
'is_featured' => true,
|
||||
'meta_title' => '2026 Bahar Dönemi Kayıtları Başladı | Boğaziçi Denizcilik',
|
||||
'meta_description' => 'Bahar dönemi eğitim programlarımıza kayıtlar başlamıştır. %10 erken kayıt avantajı için hemen başvurun.',
|
||||
'published_at' => '2026-02-15 09:00:00',
|
||||
],
|
||||
[
|
||||
'slug' => 'imo-standartlari-guncellemesi',
|
||||
'title' => 'IMO Standartları Güncellemesi',
|
||||
'category' => 'news',
|
||||
'excerpt' => 'Uluslararası Denizcilik Örgütü\'nün (IMO) 2026 standart güncellemeleri eğitim programlarımıza yansıtıldı.',
|
||||
'content' => "Dünya çapında uygulanan denizcilik standartları, IMO (Uluslararası Denizcilik Örgütü) tarafından periyodik olarak güncellenmektedir. 2026 yılı için duyurulan yeni yönetmeliklere uygun olacak şekilde müfredatlarımız Ulaştırma ve Altyapı Bakanlığı onayıyla revize edilmiştir.\n\nYeni standartlarla birlikte güvenlik ve çevre alanındaki konularda eğitime ayrılan süre artırılmış olup, simülatör kullanımında gerçekçilik senaryoları çeşitlendirilmiştir.",
|
||||
'image' => null,
|
||||
'is_featured' => false,
|
||||
'meta_title' => 'IMO 2026 Standartları Güncellemesi | Boğaziçi Denizcilik',
|
||||
'meta_description' => 'IMO 2026 standart güncellemeleri eğitim programlarımıza yansıtıldı. Güncel müfredat hakkında bilgi alın.',
|
||||
'published_at' => '2026-02-12 09:00:00',
|
||||
],
|
||||
[
|
||||
'slug' => 'denizcilik-kariyer-fuari-2026',
|
||||
'title' => 'Denizcilik Kariyer Fuarı 2026',
|
||||
'category' => 'event',
|
||||
'excerpt' => 'İstanbul\'da düzenlenecek Kariyer Fuarı\'nda 40\'tan fazla firma stant açacak. Öğrencilerimize ücretsiz giriş.',
|
||||
'content' => "Kariyer yolculuğunuzda önemli bir kilometre taşı olan Denizcilik Kariyer Fuarı, bu yıl da sektörün öncü firmalarını öğrencilerimiz ve mezunlarımızla buluşturuyor.\n\nEtkinlik kapsamında uzman konuşmacılarla düzenlenecek panellere katılabilir, mülakat simülasyonlarıyla kendinizi sınayabilirsiniz. Boğaziçi Denizcilik kursiyerlerine özel ücretsiz giriş imkanından faydalanmak için öğrenci işleri birimimizle iletişime geçiniz.",
|
||||
'image' => null,
|
||||
'is_featured' => false,
|
||||
'meta_title' => 'Denizcilik Kariyer Fuarı 2026 | Boğaziçi Denizcilik',
|
||||
'meta_description' => 'Denizcilik Kariyer Fuarı 2026\'da 40\'tan fazla firma ile buluşun. Öğrencilerimize ücretsiz giriş.',
|
||||
'published_at' => '2026-02-05 09:00:00',
|
||||
],
|
||||
[
|
||||
'slug' => 'mezunlarimiz-uluslararasi-yarismada-birinci',
|
||||
'title' => 'Mezunlarımız Uluslararası Yarışmada 1. Oldu',
|
||||
'category' => 'news',
|
||||
'excerpt' => 'Öğrencilerimiz Avrupa Denizcilik Simülasyon Yarışması\'nda birinci olarak Türkiye\'yi temsil etti.',
|
||||
'content' => "Kurumumuz eğitimlerini başarıyla tamamlayan 3 mezunumuzdan oluşan Türkiye ekibi, Hollanda'da düzenlenen Avrupa Denizcilik Simülasyon Yarışması'nda (E-Sea Challenge 2026) kriz yönetimi ve yanaşma-kalkma operasyonlarındaki takım çalışmalarıyla 1. oldu.\n\nGeleceğin denizcilerini yetiştirmekten gurur duyuyor, başarılarının devamını diliyoruz.",
|
||||
'image' => null,
|
||||
'is_featured' => false,
|
||||
'meta_title' => 'Mezunlarımız Uluslararası Yarışmada 1. Oldu | Boğaziçi Denizcilik',
|
||||
'meta_description' => 'Boğaziçi Denizcilik mezunları Avrupa Denizcilik Simülasyon Yarışması\'nda Türkiye\'yi birinci sıraya taşıdı.',
|
||||
'published_at' => '2026-01-28 09:00:00',
|
||||
],
|
||||
[
|
||||
'slug' => 'yeni-simulasyon-sistemimiz-hizmete-girdi',
|
||||
'title' => 'Yeni Simülasyon Sistemimiz Hizmete Girdi',
|
||||
'category' => 'news',
|
||||
'excerpt' => 'En son teknoloji deniz simülatörlerimiz ile gerçek deniz koşullarında eğitim imkânı sunuyoruz.',
|
||||
'content' => 'Eğitim kalitemizi her geçen gün arttırmak amacıyla köprüüstü vizyon simülatör sistemimizi yeniledik. 4K panoramik görüntü sağlayan yeni cihazlarımız ile 30 farklı limana ve 20 farklı gemi modeline erişimimiz bulunmaktadır. Öğrencilerimiz, acil durum senaryolarını sıfır risk ile deneyimleme şansı bulmaktadır.',
|
||||
'image' => null,
|
||||
'is_featured' => false,
|
||||
'meta_title' => 'Yeni Simülasyon Sistemimiz Hizmete Girdi | Boğaziçi Denizcilik',
|
||||
'meta_description' => '4K panoramik köprüüstü simülatörümüz ile gerçek deniz koşullarında eğitim alın. 30 liman, 20 gemi modeli.',
|
||||
'published_at' => '2026-01-20 09:00:00',
|
||||
],
|
||||
[
|
||||
'slug' => 'online-egitim-platformumuz-yenilendi',
|
||||
'title' => 'Online Eğitim Platformumuz Yenilendi',
|
||||
'category' => 'announcement',
|
||||
'excerpt' => 'Kullanıcı deneyimini iyileştiren yeni online eğitim platformumuz aktif olmuştur.',
|
||||
'content' => 'Özellikle yenileme eğitimlerinde sıkça kullandığımız online uzaktan eğitim platformumuzu güncelledik. İnteraktif eğitim materyalleri, hızlı canlı yayın sistemi ve mobil uyumlu arayüzü ile dilediğiniz yerden eğitimlerinize daha rahat bir şekilde katılabileceksiniz. Kursiyerlerimiz şifrelerini güncelleyerek sisteme giriş yapabilir.',
|
||||
'image' => null,
|
||||
'is_featured' => false,
|
||||
'meta_title' => 'Online Eğitim Platformumuz Yenilendi | Boğaziçi Denizcilik',
|
||||
'meta_description' => 'Yenilenen online eğitim platformumuz ile uzaktan eğitimlerinize mobil ve masaüstünden kolayca katılın.',
|
||||
'published_at' => '2026-01-10 09:00:00',
|
||||
],
|
||||
];
|
||||
|
||||
DB::table('announcements')->insert(array_map(fn ($a) => array_merge($a, [
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]), $announcements));
|
||||
}
|
||||
}
|
||||
73
database/seeders/CategorySeeder.php
Normal file
73
database/seeders/CategorySeeder.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CategorySeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$categories = [
|
||||
[
|
||||
'slug' => 'guverte',
|
||||
'label' => 'Güverte Eğitimleri',
|
||||
'desc' => 'Seyir, köprüüstü operasyonu, ARPA/ECDIS simülatör eğitimleri',
|
||||
'image' => null,
|
||||
'meta_title' => 'Güverte Eğitimleri | Boğaziçi Denizcilik',
|
||||
'meta_description' => 'Seyir, köprüüstü operasyonu, ARPA/ECDIS simülatör eğitimleri. Boğaziçi Denizcilik Eğitim Kurumu.',
|
||||
],
|
||||
[
|
||||
'slug' => 'stcw',
|
||||
'label' => 'STCW Eğitimleri',
|
||||
'desc' => 'Zorunlu emniyet, yangın söndürme ve ilkyardım sertifikaları',
|
||||
'image' => null,
|
||||
'meta_title' => 'STCW Eğitimleri | Boğaziçi Denizcilik',
|
||||
'meta_description' => 'Zorunlu emniyet, yangın söndürme ve ilkyardım STCW sertifika programları. IMO onaylı eğitimler.',
|
||||
],
|
||||
[
|
||||
'slug' => 'makine',
|
||||
'label' => 'Makine Eğitimleri',
|
||||
'desc' => 'Dizel motor, elektrik sistemleri ve makine dairesi operasyonu',
|
||||
'image' => null,
|
||||
'meta_title' => 'Makine Eğitimleri | Boğaziçi Denizcilik',
|
||||
'meta_description' => 'Dizel motor, elektrik sistemleri ve makine dairesi operasyonu eğitimleri. STCW uyumlu programlar.',
|
||||
],
|
||||
[
|
||||
'slug' => 'yat-kaptanligi',
|
||||
'label' => 'Yat Kaptanlığı',
|
||||
'desc' => 'Tüm tonaj basamaklarında kaptan yeterlik',
|
||||
'image' => null,
|
||||
'meta_title' => 'Yat Kaptanlığı Eğitimleri | Boğaziçi Denizcilik',
|
||||
'meta_description' => '25 GT, 149 GT, 499 GT ve 3000 GT yat kaptanlığı yeterlik programları. Türkiye\'nin lider denizcilik okulu.',
|
||||
],
|
||||
[
|
||||
'slug' => 'yenileme',
|
||||
'label' => 'Yenileme Eğitimleri',
|
||||
'desc' => 'Süresi dolan sertifikalar için kısa güncelleme programları',
|
||||
'image' => null,
|
||||
'meta_title' => 'Yenileme Eğitimleri | Boğaziçi Denizcilik',
|
||||
'meta_description' => 'Süresi dolan denizcilik sertifikalarınız için kısa süreli güncelleme ve yenileme eğitimleri.',
|
||||
],
|
||||
[
|
||||
'slug' => 'guvenlik',
|
||||
'label' => 'Güvenlik (ISPS)',
|
||||
'desc' => 'Gemi ve liman güvenlik görevi sertifikaları',
|
||||
'image' => null,
|
||||
'meta_title' => 'Güvenlik (ISPS) Eğitimleri | Boğaziçi Denizcilik',
|
||||
'meta_description' => 'ISPS Kod kapsamında gemi ve liman güvenlik görevi sertifikaları. Uluslararası geçerliliğe sahip programlar.',
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($categories as $category) {
|
||||
DB::table('categories')->updateOrInsert(
|
||||
['slug' => $category['slug']],
|
||||
array_merge($category, [
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
250
database/seeders/CorporatePagesSeeder.php
Normal file
250
database/seeders/CorporatePagesSeeder.php
Normal file
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Page;
|
||||
use App\Models\PageBlock;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class CorporatePagesSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Seed corporate pages: Kalite Politikası, Hakkımızda, Vizyon ve Misyon.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$this->seedKalitePolitikasi();
|
||||
$this->seedHakkimizda();
|
||||
$this->seedVizyonMisyon();
|
||||
}
|
||||
|
||||
private function seedKalitePolitikasi(): void
|
||||
{
|
||||
$page = Page::firstOrCreate(
|
||||
['slug' => 'kalite-politikasi'],
|
||||
[
|
||||
'title' => 'Kalite Politikamız',
|
||||
'meta_title' => 'Kalite Politikamız | Boğaziçi Denizcilik – ISO 9001:2015 Sertifikalı Eğitim',
|
||||
'meta_description' => 'Boğaziçi Denizcilik Eğitim Kurumu kalite politikası. ISO 9001:2015 sertifikalı, STCW yetkili, MET akredite denizcilik eğitim kurumu.',
|
||||
'is_active' => true,
|
||||
],
|
||||
);
|
||||
|
||||
$blocks = [
|
||||
[
|
||||
'order_index' => 0,
|
||||
'type' => 'hero',
|
||||
'content' => [
|
||||
'breadcrumb' => 'Kurumsal|/kurumsal / Kalite Politikamız',
|
||||
'title' => "Kalite Bir Hedef Değil,\nBir Standart",
|
||||
'highlight' => 'Bir Standart',
|
||||
'description' => 'ISO 9001:2015 sertifikalı Kalite Yönetim Sistemimiz ile her süreçte mükemmelliği güvence altına alıyoruz.',
|
||||
],
|
||||
],
|
||||
[
|
||||
'order_index' => 1,
|
||||
'type' => 'cards',
|
||||
'content' => [
|
||||
'label' => 'AKREDİTASYONLAR',
|
||||
'title' => 'Sertifika & Belgelerimiz',
|
||||
'card_1_title' => 'ISO 9001:2015',
|
||||
'card_1_desc' => 'Kalite Yönetim Sistemi',
|
||||
'card_1_text' => "Türk Loydu · 2019'den beri",
|
||||
'card_1_icon' => 'award',
|
||||
'card_2_title' => 'STCW Yetki Belgesi',
|
||||
'card_2_desc' => 'Denizci Eğitim Kurumu Akreditasyonu',
|
||||
'card_2_text' => "UAB Denizcilik Genel Müdürlüğü · 2020'den beri",
|
||||
'card_2_icon' => 'shield',
|
||||
'card_3_title' => 'MET Akreditasyonu',
|
||||
'card_3_desc' => 'Uluslararası Denizcilik Eğitimi',
|
||||
'card_3_text' => "IMO Denizcilik Eğitim Standartları · 2021'den beri",
|
||||
'card_3_icon' => 'globe',
|
||||
],
|
||||
],
|
||||
[
|
||||
'order_index' => 2,
|
||||
'type' => 'text',
|
||||
'content' => [
|
||||
'_width' => 'half',
|
||||
'label' => 'KALİTE İLKELERİ',
|
||||
'title' => 'Taahhütlerimiz',
|
||||
'body' => '<ul><li>UAB ve IMO standartlarına tam uyumluluk</li><li>STCW Sözleşmesi müfredat gerekliliklerinin eksiksiz karşılanması</li><li>Eğitim kadrosunun denizcilik sektöründe aktif tecrübeye sahip olması</li><li>Simülatör ve laboratuvar ekipmanlarının güncel tutulması</li><li>Kursiyer memnuniyet oranının %95 üzerinde sürdürülmesi</li><li>Mezun istihdam takibi ve sektörel geri bildirim analizi</li><li>İç ve dış denetim bulgularına göre sürekli iyileştirme</li><li>Eğitim materyallerinin yıllık güncellenmesi</li></ul>',
|
||||
],
|
||||
],
|
||||
[
|
||||
'order_index' => 3,
|
||||
'type' => 'stats_grid',
|
||||
'content' => [
|
||||
'_width' => 'half',
|
||||
'label' => 'KALİTE DÖNGÜSÜ',
|
||||
'title' => 'PDCA Yaklaşımı',
|
||||
'stat_1_value' => '01',
|
||||
'stat_1_label' => 'Planlama — Yıllık kalite hedefleri ve iyileştirme planı oluşturulur.',
|
||||
'stat_2_value' => '02',
|
||||
'stat_2_label' => 'Uygulama — Planlar eğitim programlarına ve süreçlere entegre edilir.',
|
||||
'stat_3_value' => '03',
|
||||
'stat_3_label' => 'İzleme — Performans göstergeleri ve öğrenci memnuniyeti ölçülür.',
|
||||
'stat_4_value' => '04',
|
||||
'stat_4_label' => 'İyileştirme — Bulgular analiz edilerek sisteme geri besleme yapılır.',
|
||||
'note' => 'Bu döngü her yıl sistematik olarak tekrar edilir.',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$this->syncBlocks($page, $blocks);
|
||||
}
|
||||
|
||||
private function seedHakkimizda(): void
|
||||
{
|
||||
$page = Page::firstOrCreate(
|
||||
['slug' => 'hakkimizda'],
|
||||
[
|
||||
'title' => 'Hakkımızda',
|
||||
'meta_title' => 'Hakkımızda | Boğaziçi Denizcilik – 25 Yıllık Deneyim',
|
||||
'meta_description' => "1998'den bu yana 15.000+ denizci yetiştiren Boğaziçi Denizcilik Eğitim Kurumu hakkında bilgi alın.",
|
||||
'is_active' => true,
|
||||
],
|
||||
);
|
||||
|
||||
$blocks = [
|
||||
[
|
||||
'order_index' => 0,
|
||||
'type' => 'hero',
|
||||
'content' => [
|
||||
'breadcrumb' => 'Kurumsal|/kurumsal / Hakkımızda',
|
||||
'title' => "Türkiye'nin Köklü\nDenizcilik Okulu",
|
||||
'highlight' => 'Denizcilik Okulu',
|
||||
'description' => "1998'den bu yana 15.000'den fazla denizciyi uluslararası geçerli sertifikalarla donatıyoruz.",
|
||||
],
|
||||
],
|
||||
[
|
||||
'order_index' => 1,
|
||||
'type' => 'stats_grid',
|
||||
'content' => [
|
||||
'style' => 'dark',
|
||||
'stat_1_value' => '1998',
|
||||
'stat_1_label' => 'Kuruluş Yılı',
|
||||
'stat_2_value' => '25+',
|
||||
'stat_2_label' => 'Yıllık Tecrübe',
|
||||
'stat_3_value' => '15.000+',
|
||||
'stat_3_label' => 'Mezun Sayısı',
|
||||
'stat_4_value' => '%98',
|
||||
'stat_4_label' => 'Başarı Oranı',
|
||||
],
|
||||
],
|
||||
[
|
||||
'order_index' => 2,
|
||||
'type' => 'text_image',
|
||||
'content' => [
|
||||
'label' => 'HİKAYEMİZ',
|
||||
'title' => '25 Yılı Aşkın Deneyim ve Güven',
|
||||
'body' => "<p>Boğaziçi Denizcilik Eğitim Kurumu, 1998 yılında Kaptan Ahmet Yıldız tarafından İstanbul Kadıköy'de kurulmuştur. Ulaştırma ve Altyapı Bakanlığı (UAB) tarafından yetkilendirilmiş kurumumuz, STCW Sözleşmesi'nin gerektirdiği tüm zorunlu eğitimleri vermektedir.</p><p>Kuruluşumuzdan bu yana 15.000'i aşkın denizciyi sektöre kazandırdık. Mezunlarımız; Türk Deniz Kuvvetleri, MSC, CMA CGM, Maersk ve Türkiye'nin önde gelen denizcilik şirketlerinde aktif olarak görev yapmaktadır.</p><p>Eğitim merkezimiz; tam donanımlı köprüüstü simülatörü, ARPA/Radar eğitim istasyonları, ECDIS terminalleri, GMDSS telsiz laboratuvarı ve yangın tatbikat alanıyla donatılmıştır.</p>",
|
||||
'image' => 'h3.jpg',
|
||||
'image_alt' => 'Boğaziçi Denizcilik Eğitim Kurumu',
|
||||
'image_position' => 'right',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$this->syncBlocks($page, $blocks);
|
||||
}
|
||||
|
||||
private function seedVizyonMisyon(): void
|
||||
{
|
||||
$page = Page::firstOrCreate(
|
||||
['slug' => 'vizyon-misyon'],
|
||||
[
|
||||
'title' => 'Vizyon ve Misyon',
|
||||
'meta_title' => 'Vizyon ve Misyon | Boğaziçi Denizcilik',
|
||||
'meta_description' => "Boğaziçi Denizcilik Eğitim Kurumu'nun vizyonu, misyonu ve temel değerleri.",
|
||||
'is_active' => true,
|
||||
],
|
||||
);
|
||||
|
||||
$blocks = [
|
||||
[
|
||||
'order_index' => 0,
|
||||
'type' => 'hero',
|
||||
'content' => [
|
||||
'breadcrumb' => 'Kurumsal|/kurumsal / Vizyon ve Misyon',
|
||||
'title' => "Nereye Gidiyoruz,\nNeden Buradayız?",
|
||||
'highlight' => 'Neden Buradayız?',
|
||||
'description' => 'Denizcilik eğitiminde mükemmelliği bir hedef değil, bir standart olarak benimsiyoruz.',
|
||||
],
|
||||
],
|
||||
[
|
||||
'order_index' => 1,
|
||||
'type' => 'text',
|
||||
'content' => [
|
||||
'_width' => 'half',
|
||||
'label' => 'VİZYONUMUZ',
|
||||
'title' => 'Vizyonumuz',
|
||||
'body' => "<p>Türkiye'nin denizcilik eğitiminde referans noktası olarak, uluslararası standartları belirleyen, teknoloji odaklı ve sürekli gelişen bir eğitim kurumu olmak. Mezunlarımızın dünya denizlerinde tercih edilen profesyoneller olmasını sağlamak.</p>",
|
||||
],
|
||||
],
|
||||
[
|
||||
'order_index' => 2,
|
||||
'type' => 'text',
|
||||
'content' => [
|
||||
'_width' => 'half',
|
||||
'label' => 'MİSYONUMUZ',
|
||||
'title' => 'Misyonumuz',
|
||||
'body' => '<p>Ulaştırma ve Altyapı Bakanlığı ile IMO standartlarına uygun, STCW Sözleşmesi gerekliliklerini karşılayan eğitim programları sunmak. Denizcilik sektörünün ihtiyaç duyduğu nitelikli, güvenlik bilincine sahip personel yetiştirmek.</p>',
|
||||
],
|
||||
],
|
||||
[
|
||||
'order_index' => 3,
|
||||
'type' => 'cards',
|
||||
'content' => [
|
||||
'label' => 'TEMEL DEĞERLERİMİZ',
|
||||
'title' => 'Bizi Biz Yapan İlkeler',
|
||||
'card_1_title' => 'Denizde Güvenlik Önceliğimiz',
|
||||
'card_1_text' => 'Tüm eğitim programlarımızın temelinde denizde can ve mal güvenliği ilkesi yer alır.',
|
||||
'card_1_icon' => 'shield',
|
||||
'card_2_title' => 'Uluslararası Standartlar',
|
||||
'card_2_text' => 'IMO ve STCW standartlarına tam uyum, UAB denetim ve onayıyla kalitemizi garanti altına alırız.',
|
||||
'card_2_icon' => 'globe',
|
||||
'card_3_title' => 'Uygulamalı Eğitim',
|
||||
'card_3_text' => 'Simülatör, laboratuvar ve tatbikat alanlarında gerçek senaryolarla öğrenme deneyimi sunarız.',
|
||||
'card_3_icon' => 'heart',
|
||||
'card_4_title' => 'Sürekli Gelişim',
|
||||
'card_4_text' => 'Müfredatımızı sektörel gelişmeler doğrultusunda sürekli günceller, eğitim kadromuzun gelişimini destekleriz.',
|
||||
'card_4_icon' => 'zap',
|
||||
'card_5_title' => 'Kursiyer Odaklılık',
|
||||
'card_5_text' => 'Her kursiyerin bireysel ihtiyaçlarına yönelik danışmanlık ve destek hizmeti sunuruz.',
|
||||
'card_5_icon' => 'target',
|
||||
'card_6_title' => 'Şeffaflık',
|
||||
'card_6_text' => 'Eğitim süreçlerimizi, başarı oranlarımızı ve mezun istatistiklerimizi kamuoyuyla paylaşırız.',
|
||||
'card_6_icon' => 'eye',
|
||||
],
|
||||
],
|
||||
[
|
||||
'order_index' => 4,
|
||||
'type' => 'cta',
|
||||
'content' => [
|
||||
'title' => 'Bu Değerleri Birlikte Yaşayalım',
|
||||
'description' => 'Kalite Politikamız ve akreditasyonlarımız hakkında bilgi alın.',
|
||||
'button_text' => 'Kalite Politikamız',
|
||||
'button_url' => '/kurumsal/kalite-politikasi',
|
||||
'button_2_text' => 'Eğitimleri İncele',
|
||||
'button_2_url' => '/egitimler',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$this->syncBlocks($page, $blocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, array{order_index: int, type: string, content: array<string, mixed>}> $blocks
|
||||
*/
|
||||
private function syncBlocks(Page $page, array $blocks): void
|
||||
{
|
||||
foreach ($blocks as $block) {
|
||||
PageBlock::updateOrCreate(
|
||||
['page_id' => $page->id, 'order_index' => $block['order_index']],
|
||||
['type' => $block['type'], 'content' => $block['content']],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
143
database/seeders/CourseBlockExampleSeeder.php
Normal file
143
database/seeders/CourseBlockExampleSeeder.php
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Course;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class CourseBlockExampleSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Seed example blocks for "Gemici (Birleşik) Eğitimi" course.
|
||||
* Existing CourseSeeder remains untouched.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$course = Course::where('slug', 'gemici-birlesik-egitimi')->first();
|
||||
|
||||
if (! $course) {
|
||||
$this->command->warn('Gemici (Birleşik) Eğitimi bulunamadı, atlanıyor.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Mevcut blokları temizle
|
||||
$course->blocks()->delete();
|
||||
|
||||
$blocks = [
|
||||
// Blok 0 — Eğitim Hakkında (detaylı açıklama)
|
||||
[
|
||||
'order_index' => 0,
|
||||
'type' => 'text',
|
||||
'content' => [
|
||||
'label' => 'EĞİTİM HAKKINDA',
|
||||
'title' => 'Neden Bu Eğitim?',
|
||||
'body' => '<p>Gemici (Birleşik) Eğitimi, güverte bölümünde kariyer hedefleyen adayları <strong>tek bir program</strong> altında denizci olmaya hazırlar. Hem zorunlu güvenlik eğitimlerini hem de mesleki güverte operasyonlarını kapsayan bu birleşik format sayesinde iki ayrı eğitime katılma zorunluluğu ortadan kalkar.</p><p>32 günlük yoğun program boyunca kursiyerler; <strong>gerçek simülatör ortamlarında</strong> seyir gözetleme yapar, yangın tatbikat alanında bizzat müdahale eder ve can kurtarma botlarıyla açık deniz tatbikatı gerçekleştirir.</p><p>Eğitimi başarıyla tamamlayan adaylar <strong>UAB onaylı Gemici Yeterlik Belgesi</strong> almaya hak kazanır ve ticari gemilerde güverte tayfası olarak uluslararası sularda görev yapabilir.</p>',
|
||||
],
|
||||
],
|
||||
|
||||
// Blok 1 — Eğitim Kapsamı (sol yarım)
|
||||
[
|
||||
'order_index' => 1,
|
||||
'type' => 'text',
|
||||
'content' => [
|
||||
'_width' => 'half',
|
||||
'label' => 'EĞİTİM KAPSAMI',
|
||||
'title' => 'Ne Öğreneceksiniz?',
|
||||
'body' => '<ul><li><strong>Denizde Kişisel Güvenlik</strong> — Can kurtarma salı, şişme yelek, immersion suit kullanımı ve denizde hayatta kalma teknikleri</li><li><strong>Yangınla Mücadele</strong> — A, B, C sınıfı yangın söndürme, SCBA tüplü ortamda müdahale tatbikatları</li><li><strong>Gemi Manevrası</strong> — Yanaşma/kalkma operasyonları, halat atma, bağlama donanımı ve vinç kullanımı</li><li><strong>Seyir Gözetleme</strong> — Köprüüstü vardiya prosedürleri, dürbün ile gözetleme, COLREG kuralları</li><li><strong>Güverte Bakımı</strong> — Paslama, boyama, bakım-onarım prosedürleri ve iş güvenliği</li><li><strong>Çevre Koruma</strong> — MARPOL Sözleşmesi, deniz kirliliği önleme ve atık yönetimi</li></ul>',
|
||||
],
|
||||
],
|
||||
|
||||
// Blok 2 — Katılım Koşulları (sağ yarım)
|
||||
[
|
||||
'order_index' => 2,
|
||||
'type' => 'text',
|
||||
'content' => [
|
||||
'_width' => 'half',
|
||||
'label' => 'BAŞVURU ŞARTLARI',
|
||||
'title' => 'Kimler Katılabilir?',
|
||||
'body' => '<ul><li><strong>Yaş:</strong> 16 yaşını doldurmuş olmak</li><li><strong>Eğitim:</strong> En az ortaöğretim (lise) mezunu olmak</li><li><strong>Sağlık:</strong> Denizci sağlık raporu almaya engel durumu bulunmamak</li><li><strong>Adli Sicil:</strong> Denizcilik mesleğine engel sabıka kaydı bulunmamak</li></ul><p><strong>Önemli:</strong> Sağlık raporu eğitim başlangıcından önce temin edilmelidir. Kurumumuz, anlaşmalı sağlık kuruluşlarına yönlendirme yapmaktadır.</p>',
|
||||
],
|
||||
],
|
||||
|
||||
// Blok 3 — Eğitim Süreci (adım kartları)
|
||||
[
|
||||
'order_index' => 3,
|
||||
'type' => 'stats_grid',
|
||||
'content' => [
|
||||
'label' => 'EĞİTİM SÜRECİ',
|
||||
'title' => 'Başvurudan Belgeye 4 Adım',
|
||||
'stat_1_value' => '01',
|
||||
'stat_1_label' => 'Ön Kayıt — Online formu doldurun, danışmanlarımız sizi bilgilendirsin.',
|
||||
'stat_2_value' => '02',
|
||||
'stat_2_label' => 'Evrak & Sağlık — Gerekli belgeleri ve denizci sağlık raporunu hazırlayın.',
|
||||
'stat_3_value' => '03',
|
||||
'stat_3_label' => 'Eğitim — 32 gün boyunca teorik dersler ve uygulamalı tatbikatlar.',
|
||||
'stat_4_value' => '04',
|
||||
'stat_4_label' => 'Belgelendirme — Sınavı geçin, UAB onaylı Gemici Yeterlik Belgenizi alın.',
|
||||
],
|
||||
],
|
||||
|
||||
// Blok 4 — Kazanımlar (kartlar)
|
||||
[
|
||||
'order_index' => 4,
|
||||
'type' => 'cards',
|
||||
'content' => [
|
||||
'label' => 'KAZANIMLAR',
|
||||
'title' => 'Eğitim Sonunda Ne Kazanırsınız?',
|
||||
'card_1_title' => 'Gemici Yeterlik Belgesi',
|
||||
'card_1_text' => 'UAB tarafından düzenlenen, uluslararası geçerli yeterlik belgesi.',
|
||||
'card_1_icon' => 'award',
|
||||
'card_2_title' => 'Denizde Can Kurtarma Sertifikası',
|
||||
'card_2_text' => 'STCW A-VI/1 kapsamında kişisel güvenlik ve can kurtarma belgesi.',
|
||||
'card_2_icon' => 'life-buoy',
|
||||
'card_3_title' => 'Yangınla Mücadele Sertifikası',
|
||||
'card_3_text' => 'Temel yangın önleme ve söndürme yetkinlik belgesi.',
|
||||
'card_3_icon' => 'flame',
|
||||
'card_4_title' => 'Kariyer İmkanı',
|
||||
'card_4_text' => 'Ticari gemilerde güverte tayfası olarak uluslararası sularda çalışma hakkı.',
|
||||
'card_4_icon' => 'anchor',
|
||||
],
|
||||
],
|
||||
|
||||
// Blok 5 — SSS
|
||||
[
|
||||
'order_index' => 5,
|
||||
'type' => 'faq',
|
||||
'content' => [
|
||||
'title' => 'Sıkça Sorulan Sorular',
|
||||
'faq_1_question' => 'Bu eğitim ile Gemici (Temel) arasındaki fark nedir?',
|
||||
'faq_1_answer' => 'Birleşik eğitim, güvenlik eğitimleri (can kurtarma, yangın, kişisel emniyet) ile mesleki gemici eğitimini tek programda birleştirir. Temel eğitim ise sadece mesleki kısmı kapsar — güvenlik eğitimlerinizi daha önce almış olmanız gerekir.',
|
||||
'faq_2_question' => 'Devamsızlık sınırı nedir?',
|
||||
'faq_2_answer' => 'STCW düzenlemeleri gereği eğitim süresinin en az %90\'ına katılım zorunludur. Mazeretsiz devamsızlıkta eğitim tekrarı gerekebilir.',
|
||||
'faq_3_question' => 'Eğitim dili nedir?',
|
||||
'faq_3_answer' => 'Eğitim Türkçe olarak verilmektedir. Uluslararası denizcilik terminolojisi İngilizce olarak da öğretilmektedir.',
|
||||
'faq_4_question' => 'Sınav nasıl yapılıyor?',
|
||||
'faq_4_answer' => 'Eğitim sonunda UAB gözetiminde yazılı ve uygulamalı sınav yapılmaktadır. Başarılı olan adaylara yeterlik belgesi düzenlenir.',
|
||||
'faq_5_question' => 'Eğitim sonrası iş garantisi var mı?',
|
||||
'faq_5_answer' => 'İş garantisi verilmemekle birlikte, kurumumuz sektördeki denizcilik şirketleriyle iş birliği içindedir ve mezunlarımıza kariyer danışmanlığı sunmaktadır.',
|
||||
],
|
||||
],
|
||||
|
||||
// Blok 6 — CTA
|
||||
[
|
||||
'order_index' => 6,
|
||||
'type' => 'cta',
|
||||
'content' => [
|
||||
'title' => 'Denizcilik Kariyerinize İlk Adımı Atın',
|
||||
'description' => 'Ön kayıt formunu doldurun, eğitim danışmanlarımız sizinle en kısa sürede iletişime geçsin.',
|
||||
'button_text' => 'Ön Kayıt Yap',
|
||||
'button_url' => '/kayit?course=gemici-birlesik-egitimi',
|
||||
'button_2_text' => 'WhatsApp ile Bilgi Al',
|
||||
'button_2_url' => '/danismanlik',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($blocks as $block) {
|
||||
$course->blocks()->create($block);
|
||||
}
|
||||
|
||||
$this->command->info("Gemici (Birleşik) Eğitimi: {$course->blocks()->count()} blok oluşturuldu.");
|
||||
}
|
||||
}
|
||||
169
database/seeders/CourseContentSeeder.php
Normal file
169
database/seeders/CourseContentSeeder.php
Normal file
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Category;
|
||||
use App\Models\Course;
|
||||
use App\Models\CourseBlock;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class CourseContentSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Seed course blocks (rich content) from parsed docx articles.
|
||||
* Updates long_desc/requirements/scope on existing courses if empty.
|
||||
* Creates new courses from articles that don't match existing ones.
|
||||
*
|
||||
* Source: storage/app/course_blocks_data.json
|
||||
* Run AFTER CourseSeeder. Existing CourseSeeder is untouched.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$jsonPath = storage_path('app/course_blocks_data.json');
|
||||
|
||||
if (! file_exists($jsonPath)) {
|
||||
$this->command->error('course_blocks_data.json bulunamadı. Önce Python parse script çalıştırın.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var array<int, array<string, mixed>> $data */
|
||||
$data = json_decode(file_get_contents($jsonPath), true);
|
||||
$cats = Category::pluck('id', 'slug');
|
||||
$allCourses = Course::all();
|
||||
$matched = 0;
|
||||
$created = 0;
|
||||
$newCourses = 0;
|
||||
$blockCount = 0;
|
||||
|
||||
foreach ($data as $item) {
|
||||
$course = $this->findCourse($allCourses, $item);
|
||||
|
||||
if (! $course) {
|
||||
// Create new course from article data
|
||||
$categoryId = $cats[$item['category_slug']] ?? null;
|
||||
if (! $categoryId) {
|
||||
$this->command->warn("Kategori bulunamadı: {$item['category_slug']} -> {$item['title_short']}");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$course = Course::create([
|
||||
'category_id' => $categoryId,
|
||||
'slug' => Str::slug($item['title_short']),
|
||||
'title' => $item['title_short'],
|
||||
'desc' => Str::limit($item['long_desc'], 200),
|
||||
'long_desc' => $item['long_desc'],
|
||||
'duration' => '',
|
||||
'requirements' => $item['requirements'],
|
||||
'scope' => $item['scope'],
|
||||
'standard' => 'STCW / IMO Uyumlu',
|
||||
'language' => 'Türkçe',
|
||||
'location' => 'Kadıköy, İstanbul',
|
||||
'meta_title' => $item['title_short'].' | Boğaziçi Denizcilik',
|
||||
'meta_description' => Str::limit($item['long_desc'], 155),
|
||||
]);
|
||||
$newCourses++;
|
||||
$allCourses->push($course);
|
||||
} else {
|
||||
$matched++;
|
||||
$this->updateCourseFields($course, $item);
|
||||
}
|
||||
|
||||
// Sync blocks
|
||||
$count = $this->syncBlocks($course, $item['blocks']);
|
||||
$blockCount += $count;
|
||||
}
|
||||
|
||||
$total = count($data);
|
||||
$this->command->info("Toplam: {$total} makale, {$matched} eşleşme, {$newCourses} yeni kurs, {$blockCount} blok.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection<int, Course> $allCourses
|
||||
* @param array<string, mixed> $item
|
||||
*/
|
||||
private function findCourse($allCourses, array $item): ?Course
|
||||
{
|
||||
$articleSlug = Str::slug($item['title_short']);
|
||||
$titleNorm = $this->normalize($item['title_short']);
|
||||
|
||||
// 1. Exact slug match
|
||||
$found = $allCourses->first(fn (Course $c) => $c->slug === $articleSlug);
|
||||
if ($found) {
|
||||
return $found;
|
||||
}
|
||||
|
||||
// 2. Normalized title contains match
|
||||
$found = $allCourses->first(fn (Course $c) => $this->normalize($c->title) === $titleNorm);
|
||||
if ($found) {
|
||||
return $found;
|
||||
}
|
||||
|
||||
// 3. Fuzzy — first 25 chars of normalized title
|
||||
$prefix = mb_substr($titleNorm, 0, 25);
|
||||
|
||||
return $allCourses->first(fn (Course $c) => str_starts_with($this->normalize($c->title), $prefix));
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize text: lowercase, strip accents, collapse whitespace.
|
||||
*/
|
||||
private function normalize(string $text): string
|
||||
{
|
||||
$text = mb_strtolower($text);
|
||||
// Turkish specific replacements
|
||||
$text = str_replace(
|
||||
['ç', 'ğ', 'ı', 'ö', 'ş', 'ü', 'â', 'î', 'û'],
|
||||
['c', 'g', 'i', 'o', 's', 'u', 'a', 'i', 'u'],
|
||||
$text,
|
||||
);
|
||||
$text = preg_replace('/[^a-z0-9\s]/', '', $text);
|
||||
|
||||
return preg_replace('/\s+/', ' ', trim($text));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $item
|
||||
*/
|
||||
private function updateCourseFields(Course $course, array $item): void
|
||||
{
|
||||
$updates = [];
|
||||
|
||||
if (empty($course->long_desc) && ! empty($item['long_desc'])) {
|
||||
$updates['long_desc'] = $item['long_desc'];
|
||||
}
|
||||
|
||||
if ((empty($course->requirements) || $course->requirements === []) && ! empty($item['requirements'])) {
|
||||
$updates['requirements'] = $item['requirements'];
|
||||
}
|
||||
|
||||
if ((empty($course->scope) || $course->scope === []) && ! empty($item['scope'])) {
|
||||
$updates['scope'] = $item['scope'];
|
||||
}
|
||||
|
||||
if (! empty($updates)) {
|
||||
$course->update($updates);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, array<string, mixed>> $blocks
|
||||
*/
|
||||
private function syncBlocks(Course $course, array $blocks): int
|
||||
{
|
||||
$count = 0;
|
||||
|
||||
foreach ($blocks as $block) {
|
||||
CourseBlock::updateOrCreate(
|
||||
['course_id' => $course->id, 'order_index' => $block['order_index']],
|
||||
['type' => $block['type'], 'content' => $block['content']],
|
||||
);
|
||||
$count++;
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
}
|
||||
154
database/seeders/CourseScheduleSeeder.php
Normal file
154
database/seeders/CourseScheduleSeeder.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CourseScheduleSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
DB::table('course_schedules')->truncate();
|
||||
|
||||
// Kurs slug → id eşlemesi
|
||||
$courseIds = DB::table('courses')->pluck('id', 'slug');
|
||||
|
||||
$schedules = [
|
||||
// ── ŞUBAT 2026 ─────────────────────────────────────────────────
|
||||
[
|
||||
'course_id' => $courseIds['stcw-temel-guvenlik'] ?? null,
|
||||
'start_date' => '2026-02-24',
|
||||
'end_date' => '2026-02-28',
|
||||
'location' => 'Kadıköy',
|
||||
'quota' => 20,
|
||||
'available_seats' => 8,
|
||||
'is_urgent' => false,
|
||||
],
|
||||
[
|
||||
'course_id' => $courseIds['yat-kaptani-25-gt'] ?? null,
|
||||
'start_date' => '2026-02-26',
|
||||
'end_date' => '2026-02-28',
|
||||
'location' => 'Kadıköy',
|
||||
'quota' => 12,
|
||||
'available_seats' => 4,
|
||||
'is_urgent' => true,
|
||||
],
|
||||
|
||||
// ── MART 2026 ───────────────────────────────────────────────────
|
||||
[
|
||||
'course_id' => $courseIds['arpa-radar-simulator'] ?? null,
|
||||
'start_date' => '2026-03-03',
|
||||
'end_date' => '2026-03-05',
|
||||
'location' => 'Online',
|
||||
'quota' => 20,
|
||||
'available_seats' => 12,
|
||||
'is_urgent' => false,
|
||||
],
|
||||
[
|
||||
'course_id' => $courseIds['gmdss-genel-telsiz-operatoru-goc'] ?? null,
|
||||
'start_date' => '2026-03-10',
|
||||
'end_date' => '2026-03-17',
|
||||
'location' => 'Kadıköy',
|
||||
'quota' => 15,
|
||||
'available_seats' => 6,
|
||||
'is_urgent' => true,
|
||||
],
|
||||
[
|
||||
'course_id' => $courseIds['aff-yangin-sondurme'] ?? null,
|
||||
'start_date' => '2026-03-17',
|
||||
'end_date' => '2026-03-19',
|
||||
'location' => 'Kadıköy',
|
||||
'quota' => 20,
|
||||
'available_seats' => 10,
|
||||
'is_urgent' => false,
|
||||
],
|
||||
[
|
||||
'course_id' => $courseIds['dizel-motor-teknigi'] ?? null,
|
||||
'start_date' => '2026-03-24',
|
||||
'end_date' => '2026-03-28',
|
||||
'location' => 'Kadıköy',
|
||||
'quota' => 15,
|
||||
'available_seats' => 9,
|
||||
'is_urgent' => false,
|
||||
],
|
||||
|
||||
// ── NİSAN 2026 ──────────────────────────────────────────────────
|
||||
[
|
||||
'course_id' => $courseIds['stcw-temel-guvenlik'] ?? null,
|
||||
'start_date' => '2026-04-07',
|
||||
'end_date' => '2026-04-11',
|
||||
'location' => 'Kadıköy',
|
||||
'quota' => 20,
|
||||
'available_seats' => 14,
|
||||
'is_urgent' => false,
|
||||
],
|
||||
[
|
||||
'course_id' => $courseIds['yat-kaptani-149-gt-egitimi-temel'] ?? null,
|
||||
'start_date' => '2026-04-14',
|
||||
'end_date' => '2026-04-19',
|
||||
'location' => 'Kadıköy',
|
||||
'quota' => 12,
|
||||
'available_seats' => 3,
|
||||
'is_urgent' => true,
|
||||
],
|
||||
[
|
||||
'course_id' => $courseIds['bst-yenileme'] ?? null,
|
||||
'start_date' => '2026-04-21',
|
||||
'end_date' => '2026-04-22',
|
||||
'location' => 'Online',
|
||||
'quota' => 30,
|
||||
'available_seats' => 20,
|
||||
'is_urgent' => false,
|
||||
],
|
||||
[
|
||||
'course_id' => $courseIds['ecdis-tip-bazli-egitim'] ?? null,
|
||||
'start_date' => '2026-04-28',
|
||||
'end_date' => '2026-04-30',
|
||||
'location' => 'Kadıköy',
|
||||
'quota' => 15,
|
||||
'available_seats' => 7,
|
||||
'is_urgent' => false,
|
||||
],
|
||||
|
||||
// ── MAYIS 2026 ──────────────────────────────────────────────────
|
||||
[
|
||||
'course_id' => $courseIds['stcw-temel-guvenlik'] ?? null,
|
||||
'start_date' => '2026-05-05',
|
||||
'end_date' => '2026-05-09',
|
||||
'location' => 'Kadıköy',
|
||||
'quota' => 20,
|
||||
'available_seats' => 15,
|
||||
'is_urgent' => false,
|
||||
],
|
||||
[
|
||||
'course_id' => $courseIds['yat-kaptani-3000-gt'] ?? null,
|
||||
'start_date' => '2026-05-12',
|
||||
'end_date' => '2026-05-23',
|
||||
'location' => 'Kadıköy',
|
||||
'quota' => 10,
|
||||
'available_seats' => 5,
|
||||
'is_urgent' => false,
|
||||
],
|
||||
[
|
||||
'course_id' => $courseIds['makine-dairesi-operasyonu'] ?? null,
|
||||
'start_date' => '2026-05-19',
|
||||
'end_date' => '2026-05-21',
|
||||
'location' => 'Kadıköy',
|
||||
'quota' => 15,
|
||||
'available_seats' => 8,
|
||||
'is_urgent' => false,
|
||||
],
|
||||
];
|
||||
|
||||
// Null olan course_id'leri filtrele (kurs bulunamadıysa atla)
|
||||
$validSchedules = array_filter($schedules, fn ($s) => $s['course_id'] !== null);
|
||||
|
||||
foreach ($validSchedules as $schedule) {
|
||||
DB::table('course_schedules')->insert(array_merge($schedule, [
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]));
|
||||
}
|
||||
}
|
||||
}
|
||||
1248
database/seeders/CourseSeeder.php
Normal file
1248
database/seeders/CourseSeeder.php
Normal file
File diff suppressed because it is too large
Load Diff
31
database/seeders/DatabaseSeeder.php
Normal file
31
database/seeders/DatabaseSeeder.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
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
|
||||
{
|
||||
$this->call([
|
||||
RolePermissionSeeder::class,
|
||||
AdminUserSeeder::class,
|
||||
SettingSeeder::class,
|
||||
CategorySeeder::class,
|
||||
CourseSeeder::class,
|
||||
CourseScheduleSeeder::class,
|
||||
AnnouncementSeeder::class,
|
||||
HeroSlideSeeder::class,
|
||||
FaqSeeder::class,
|
||||
// MenuSeeder kaldırıldı - navbar categories + courses tablosundan dinamik olarak besleniyor
|
||||
CorporatePagesSeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
68
database/seeders/FaqContentSeeder.php
Normal file
68
database/seeders/FaqContentSeeder.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Faq;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class FaqContentSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Seed FAQs from parsed docx articles.
|
||||
* Source: storage/app/parsed_faqs.json
|
||||
* Uses firstOrCreate (question-based) — safe to re-run.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$jsonPath = storage_path('app/parsed_faqs.json');
|
||||
|
||||
if (! file_exists($jsonPath)) {
|
||||
$this->command->error('parsed_faqs.json bulunamadı. Önce Python parse script çalıştırın.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var array<int, array{question: string, answer: string, source: string}> $faqs */
|
||||
$faqs = json_decode(file_get_contents($jsonPath), true);
|
||||
|
||||
$categoryMap = [
|
||||
'Guverte_Egitimleri' => 'egitimler',
|
||||
'STCW_Egitimleri' => 'stcw',
|
||||
'Makine_Egitimleri' => 'makine',
|
||||
'Yat_Kaptanligi_Egitimleri' => 'yat-kaptanligi',
|
||||
'Yenileme_Egitimleri' => 'yenileme',
|
||||
'Seminer_Sertifikalari' => 'guvenlik',
|
||||
];
|
||||
|
||||
$created = 0;
|
||||
$skipped = 0;
|
||||
$orderCounters = [];
|
||||
|
||||
foreach ($faqs as $faq) {
|
||||
// Determine category from source folder
|
||||
$sourceFolder = explode('/', $faq['source'])[0] ?? '';
|
||||
$category = $categoryMap[$sourceFolder] ?? 'egitimler';
|
||||
|
||||
// Track order per category
|
||||
$orderCounters[$category] = ($orderCounters[$category] ?? -1) + 1;
|
||||
|
||||
$result = Faq::firstOrCreate(
|
||||
['question' => $faq['question']],
|
||||
[
|
||||
'category' => $category,
|
||||
'answer' => $faq['answer'],
|
||||
'order_index' => $orderCounters[$category],
|
||||
'is_active' => true,
|
||||
],
|
||||
);
|
||||
|
||||
if ($result->wasRecentlyCreated) {
|
||||
$created++;
|
||||
} else {
|
||||
$skipped++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->command->info("FAQ: {$created} oluşturuldu, {$skipped} zaten mevcuttu.");
|
||||
}
|
||||
}
|
||||
83
database/seeders/FaqSeeder.php
Normal file
83
database/seeders/FaqSeeder.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class FaqSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
DB::table('faqs')->truncate();
|
||||
|
||||
$faqs = [
|
||||
// EĞİTİMLER
|
||||
[
|
||||
'category' => 'egitimler',
|
||||
'question' => 'Eğitimleriniz hangi kurumlar tarafından onaylıdır?',
|
||||
'answer' => 'Tüm eğitimlerimiz Ulaştırma ve Altyapı Bakanlığı Denizcilik Genel Müdürlüğü onaylı olmakla birlikte, uluslararası IMO ve STCW sözleşmelerine %100 uyumludur.',
|
||||
'order_index' => 1,
|
||||
'is_active' => true,
|
||||
],
|
||||
[
|
||||
'category' => 'egitimler',
|
||||
'question' => 'Simülatör eğitimleriniz nasıl gerçekleştiriliyor?',
|
||||
'answer' => 'Köprüüstü ARPA/Radar ve ECDIS eğitimlerimiz ile Makine Dairesi operasyonlarımız son teknoloji Kongsberg simülatör sistemleri ile uygulamalı olarak gerçekleştirilmektedir.',
|
||||
'order_index' => 2,
|
||||
'is_active' => true,
|
||||
],
|
||||
[
|
||||
'category' => 'egitimler',
|
||||
'question' => 'Eğitim süreleri ne kadar devam ediyor?',
|
||||
'answer' => 'Temel sertifika programları 2-5 gün, yeterlik hazırlık kursları (Yat Kaptanlığı vb.) ise 10-15 gün arasında değişmektedir.',
|
||||
'order_index' => 3,
|
||||
'is_active' => true,
|
||||
],
|
||||
|
||||
// KAYIT SÜREÇLERİ
|
||||
[
|
||||
'category' => 'kayit',
|
||||
'question' => 'Kayıt olmak için hangi belgelere ihtiyacım var?',
|
||||
'answer' => 'Kayıt olmak istediğiniz eğitim kategorisine göre değişiklik göstermekle beraber genel olarak; Gemiadamı Cüzdanı fotokopisi, Nüfus Cüzdanı, Fotoğraf ve Sağlık Raporu istenmektedir.',
|
||||
'order_index' => 4,
|
||||
'is_active' => true,
|
||||
],
|
||||
[
|
||||
'category' => 'kayit',
|
||||
'question' => 'Ön kayıt sonrası ödeme süreci nasıl ilerliyor?',
|
||||
'answer' => 'Web sitemiz üzerinden ön kayıt oluşturduğunuzda eğitim danışmanlarımız sizi arayarak belgeleriniz ve kontenjan durumu hakkında bilgi verir. Kesin kayıt sırasında havale, EFT veya kredi kartı ile ödeme yapabilirsiniz.',
|
||||
'order_index' => 5,
|
||||
'is_active' => true,
|
||||
],
|
||||
[
|
||||
'category' => 'kayit',
|
||||
'question' => 'Eğitimlere uzaktan (online) katılmak mümkün mü?',
|
||||
'answer' => 'Ulaştırma Bakanlığı mevzuatı gereği STCW kapsamındaki güvenlik eğitimleri ve harita uygulamaları örgün (yüz yüze) olmak zorundadır. Ancak bazı seminer ve yenileme teorik dersleri uzaktan eğitim modeliyle sunulabilmektedir.',
|
||||
'order_index' => 6,
|
||||
'is_active' => true,
|
||||
],
|
||||
|
||||
// İLETİŞİM & ULAŞIM
|
||||
[
|
||||
'category' => 'iletisim',
|
||||
'question' => 'Eğitim merkezinize nasıl ulaşabilirim?',
|
||||
'answer' => 'Eğitim merkezimiz Kadıköy Rıhtım\'a 5 dakika yürüme mesafesinde, merkezi bir konumdadır. Şehir içinden metro, vapur veya otobüs ile kolayca ulaşım sağlayabilirsiniz.',
|
||||
'order_index' => 7,
|
||||
'is_active' => true,
|
||||
],
|
||||
[
|
||||
'category' => 'iletisim',
|
||||
'question' => 'Şehir dışından gelenler için konaklama desteği var mı?',
|
||||
'answer' => 'Kurumumuza ait bir misafirhane bulunmamakla birlikte, anlaşmalı olduğumuz yakın otel ve yurtlarda öğrencilerimize özel indirimli fiyat avantajlarından yararlanmanızı sağlıyoruz.',
|
||||
'order_index' => 8,
|
||||
'is_active' => true,
|
||||
],
|
||||
];
|
||||
|
||||
DB::table('faqs')->insert(array_map(fn ($f) => array_merge($f, [
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]), $faqs));
|
||||
}
|
||||
}
|
||||
46
database/seeders/HeroSlideSeeder.php
Normal file
46
database/seeders/HeroSlideSeeder.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class HeroSlideSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
DB::table('hero_slides')->truncate();
|
||||
|
||||
$slides = [
|
||||
[
|
||||
'label' => 'Güvenlik Eğitimleri',
|
||||
'title' => 'Profesyonel Eğitimle Güvenli Seferler İçin',
|
||||
'description' => 'IMO standartlarında yangın, cankurtarma ve tehlikeli madde eğitimleriyle kariyerinizi güvene alın.',
|
||||
'image' => null,
|
||||
'order_index' => 1,
|
||||
'is_active' => true,
|
||||
],
|
||||
[
|
||||
'label' => 'Yat Kaptanlığı',
|
||||
'title' => 'Denizde Kendi Rotanızı Çizin',
|
||||
'description' => '149 GT ve 499 GT yat kaptanlığı eğitimleriyle Türkiye\'nin en gözde kıyılarında profesyonel kaptan olarak görev yapın.',
|
||||
'image' => null,
|
||||
'order_index' => 2,
|
||||
'is_active' => true,
|
||||
],
|
||||
[
|
||||
'label' => 'Belge Yenileme',
|
||||
'title' => 'Belgelerinizi Zamanında Yenileyin',
|
||||
'description' => 'STCW yenileme, GOC/ROC tazeleme ve yat kaptanlığı tazeleme eğitimleriyle yeterliliklerinizi güncel tutun.',
|
||||
'image' => null,
|
||||
'order_index' => 3,
|
||||
'is_active' => true,
|
||||
],
|
||||
];
|
||||
|
||||
DB::table('hero_slides')->insert(array_map(fn ($s) => array_merge($s, [
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]), $slides));
|
||||
}
|
||||
}
|
||||
100
database/seeders/MenuSeeder.php
Normal file
100
database/seeders/MenuSeeder.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class MenuSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
DB::table('menus')->truncate();
|
||||
|
||||
$now = now();
|
||||
|
||||
// ── HEADER menüsü ─────────────────────────────────────────────────
|
||||
$headerItems = [
|
||||
['location' => 'header', 'label' => 'Anasayfa', 'url' => '/', 'type' => 'link', 'parent_id' => null, 'order' => 1, 'is_active' => true],
|
||||
['location' => 'header', 'label' => 'Kurumsal', 'url' => '/kurumsal', 'type' => 'link', 'parent_id' => null, 'order' => 2, 'is_active' => true],
|
||||
['location' => 'header', 'label' => 'Eğitimler', 'url' => '/egitimler', 'type' => 'link', 'parent_id' => null, 'order' => 3, 'is_active' => true],
|
||||
['location' => 'header', 'label' => 'Eğitim Takvimi', 'url' => '/egitim-takvimi', 'type' => 'link', 'parent_id' => null, 'order' => 4, 'is_active' => true],
|
||||
['location' => 'header', 'label' => 'Duyurular', 'url' => '/duyurular', 'type' => 'link', 'parent_id' => null, 'order' => 5, 'is_active' => true],
|
||||
['location' => 'header', 'label' => 'S.S.S.', 'url' => '/sss', 'type' => 'link', 'parent_id' => null, 'order' => 6, 'is_active' => true],
|
||||
['location' => 'header', 'label' => 'İletişim', 'url' => '/iletisim', 'type' => 'link', 'parent_id' => null, 'order' => 7, 'is_active' => true],
|
||||
];
|
||||
|
||||
foreach ($headerItems as $item) {
|
||||
DB::table('menus')->insert(array_merge($item, ['created_at' => $now, 'updated_at' => $now]));
|
||||
}
|
||||
|
||||
// Kurumsal dropdown parent id
|
||||
$kurumsalId = DB::table('menus')->where('label', 'Kurumsal')->where('location', 'header')->value('id');
|
||||
|
||||
$kurumsalChildren = [
|
||||
['location' => 'header', 'label' => 'Hakkımızda', 'url' => '/kurumsal/hakkimizda', 'type' => 'link', 'parent_id' => $kurumsalId, 'order' => 1, 'is_active' => true],
|
||||
['location' => 'header', 'label' => 'Vizyon ve Misyon', 'url' => '/kurumsal/vizyon-ve-misyon', 'type' => 'link', 'parent_id' => $kurumsalId, 'order' => 2, 'is_active' => true],
|
||||
['location' => 'header', 'label' => 'Kalite Politikamız', 'url' => '/kurumsal/kalite-politikamiz', 'type' => 'link', 'parent_id' => $kurumsalId, 'order' => 3, 'is_active' => true],
|
||||
];
|
||||
|
||||
foreach ($kurumsalChildren as $item) {
|
||||
DB::table('menus')->insert(array_merge($item, ['created_at' => $now, 'updated_at' => $now]));
|
||||
}
|
||||
|
||||
// Eğitimler dropdown parent id
|
||||
$egitimlerParentId = DB::table('menus')->where('label', 'Eğitimler')->where('location', 'header')->value('id');
|
||||
|
||||
$egitimlerChildren = [
|
||||
['location' => 'header', 'label' => 'Güverte Eğitimleri', 'url' => '/egitimler/guverte', 'type' => 'category', 'parent_id' => $egitimlerParentId, 'order' => 1, 'is_active' => true],
|
||||
['location' => 'header', 'label' => 'STCW Eğitimleri', 'url' => '/egitimler/stcw', 'type' => 'category', 'parent_id' => $egitimlerParentId, 'order' => 2, 'is_active' => true],
|
||||
['location' => 'header', 'label' => 'Makine Eğitimleri', 'url' => '/egitimler/makine', 'type' => 'category', 'parent_id' => $egitimlerParentId, 'order' => 3, 'is_active' => true],
|
||||
['location' => 'header', 'label' => 'Yat Kaptanlığı', 'url' => '/egitimler/yat-kaptanligi', 'type' => 'category', 'parent_id' => $egitimlerParentId, 'order' => 4, 'is_active' => true],
|
||||
['location' => 'header', 'label' => 'Yenileme Eğitimleri', 'url' => '/egitimler/yenileme', 'type' => 'category', 'parent_id' => $egitimlerParentId, 'order' => 5, 'is_active' => true],
|
||||
['location' => 'header', 'label' => 'Güvenlik (ISPS)', 'url' => '/egitimler/guvenlik', 'type' => 'category', 'parent_id' => $egitimlerParentId, 'order' => 6, 'is_active' => true],
|
||||
];
|
||||
|
||||
foreach ($egitimlerChildren as $item) {
|
||||
DB::table('menus')->insert(array_merge($item, ['created_at' => $now, 'updated_at' => $now]));
|
||||
}
|
||||
|
||||
// ── FOOTER menüsü ─────────────────────────────────────────────────
|
||||
$footerItems = [
|
||||
// Kurumsal grubu
|
||||
['location' => 'footer', 'label' => 'Kurumsal', 'url' => '/kurumsal', 'type' => 'link', 'parent_id' => null, 'order' => 1, 'is_active' => true],
|
||||
['location' => 'footer', 'label' => 'Eğitimler', 'url' => '/egitimler', 'type' => 'link', 'parent_id' => null, 'order' => 2, 'is_active' => true],
|
||||
['location' => 'footer', 'label' => 'Hızlı Linkler', 'url' => '#', 'type' => 'link', 'parent_id' => null, 'order' => 3, 'is_active' => true],
|
||||
];
|
||||
|
||||
foreach ($footerItems as $item) {
|
||||
DB::table('menus')->insert(array_merge($item, ['created_at' => $now, 'updated_at' => $now]));
|
||||
}
|
||||
|
||||
$footerKurumsalId = DB::table('menus')->where('label', 'Kurumsal')->where('location', 'footer')->value('id');
|
||||
$footerEgitimId = DB::table('menus')->where('label', 'Eğitimler')->where('location', 'footer')->value('id');
|
||||
$footerHizliId = DB::table('menus')->where('label', 'Hızlı Linkler')->where('location', 'footer')->value('id');
|
||||
|
||||
$footerChildren = [
|
||||
// Kurumsal alt menü
|
||||
['location' => 'footer', 'label' => 'Hakkımızda', 'url' => '/kurumsal/hakkimizda', 'type' => 'link', 'parent_id' => $footerKurumsalId, 'order' => 1, 'is_active' => true],
|
||||
['location' => 'footer', 'label' => 'Misyon & Vizyon', 'url' => '/kurumsal/vizyon-ve-misyon', 'type' => 'link', 'parent_id' => $footerKurumsalId, 'order' => 2, 'is_active' => true],
|
||||
['location' => 'footer', 'label' => 'Kalite Politikamız', 'url' => '/kurumsal/kalite-politikamiz', 'type' => 'link', 'parent_id' => $footerKurumsalId, 'order' => 3, 'is_active' => true],
|
||||
['location' => 'footer', 'label' => 'İletişim', 'url' => '/iletisim', 'type' => 'link', 'parent_id' => $footerKurumsalId, 'order' => 4, 'is_active' => true],
|
||||
|
||||
// Eğitimler alt menü
|
||||
['location' => 'footer', 'label' => 'Tüm Eğitimler', 'url' => '/egitimler', 'type' => 'link', 'parent_id' => $footerEgitimId, 'order' => 1, 'is_active' => true],
|
||||
['location' => 'footer', 'label' => 'Güverte Eğitimleri', 'url' => '/egitimler/guverte', 'type' => 'link', 'parent_id' => $footerEgitimId, 'order' => 2, 'is_active' => true],
|
||||
['location' => 'footer', 'label' => 'STCW Eğitimleri', 'url' => '/egitimler/stcw', 'type' => 'link', 'parent_id' => $footerEgitimId, 'order' => 3, 'is_active' => true],
|
||||
['location' => 'footer', 'label' => 'Yat Kaptanlığı', 'url' => '/egitimler/yat-kaptanligi', 'type' => 'link', 'parent_id' => $footerEgitimId, 'order' => 4, 'is_active' => true],
|
||||
|
||||
// Hızlı Linkler alt menü
|
||||
['location' => 'footer', 'label' => 'Eğitim Takvimi', 'url' => '/egitim-takvimi', 'type' => 'link', 'parent_id' => $footerHizliId, 'order' => 1, 'is_active' => true],
|
||||
['location' => 'footer', 'label' => 'Duyurular & Haberler', 'url' => '/duyurular', 'type' => 'link', 'parent_id' => $footerHizliId, 'order' => 2, 'is_active' => true],
|
||||
['location' => 'footer', 'label' => 'Ön Kayıt Ekranı', 'url' => '/kayit', 'type' => 'link', 'parent_id' => $footerHizliId, 'order' => 3, 'is_active' => true],
|
||||
['location' => 'footer', 'label' => 'S.S.S.', 'url' => '/sss', 'type' => 'link', 'parent_id' => $footerHizliId, 'order' => 4, 'is_active' => true],
|
||||
];
|
||||
|
||||
foreach ($footerChildren as $item) {
|
||||
DB::table('menus')->insert(array_merge($item, ['created_at' => $now, 'updated_at' => $now]));
|
||||
}
|
||||
}
|
||||
}
|
||||
78
database/seeders/RolePermissionSeeder.php
Normal file
78
database/seeders/RolePermissionSeeder.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Spatie\Permission\Models\Permission;
|
||||
use Spatie\Permission\Models\Role;
|
||||
use Spatie\Permission\PermissionRegistrar;
|
||||
|
||||
class RolePermissionSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Modellere göre tanımlanacak permission grupları.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
private const MODULES = [
|
||||
'category',
|
||||
'course',
|
||||
'schedule',
|
||||
'announcement',
|
||||
'hero-slide',
|
||||
'lead',
|
||||
'menu',
|
||||
'comment',
|
||||
'faq',
|
||||
'guide-card',
|
||||
'setting',
|
||||
'page',
|
||||
'user',
|
||||
'role',
|
||||
];
|
||||
|
||||
/**
|
||||
* Her modül için oluşturulacak CRUD aksiyonlar.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
private const ACTIONS = ['view', 'create', 'update', 'delete'];
|
||||
|
||||
/**
|
||||
* Editor rolüne verilmeyecek aksiyonlar.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
private const EDITOR_EXCLUDED_ACTIONS = ['delete'];
|
||||
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
app()[PermissionRegistrar::class]->forgetCachedPermissions();
|
||||
|
||||
$allPermissions = [];
|
||||
$editorPermissions = [];
|
||||
|
||||
foreach (self::MODULES as $module) {
|
||||
foreach (self::ACTIONS as $action) {
|
||||
$permissionName = "{$action}-{$module}";
|
||||
Permission::firstOrCreate(['name' => $permissionName, 'guard_name' => 'web']);
|
||||
$allPermissions[] = $permissionName;
|
||||
|
||||
if (! in_array($action, self::EDITOR_EXCLUDED_ACTIONS)) {
|
||||
$editorPermissions[] = $permissionName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// super-admin: tüm yetkiler
|
||||
$superAdmin = Role::firstOrCreate(['name' => 'super-admin', 'guard_name' => 'web']);
|
||||
$superAdmin->syncPermissions($allPermissions);
|
||||
|
||||
// editor: silme hariç tüm yetkiler
|
||||
$editor = Role::firstOrCreate(['name' => 'editor', 'guard_name' => 'web']);
|
||||
$editor->syncPermissions($editorPermissions);
|
||||
}
|
||||
}
|
||||
18
database/seeders/RoleSeeder.php
Normal file
18
database/seeders/RoleSeeder.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Spatie\Permission\Models\Role;
|
||||
|
||||
class RoleSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
Role::findOrCreate('super-admin', 'web');
|
||||
Role::findOrCreate('editor', 'web');
|
||||
}
|
||||
}
|
||||
274
database/seeders/SettingSeeder.php
Normal file
274
database/seeders/SettingSeeder.php
Normal file
@@ -0,0 +1,274 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class SettingSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Seed site settings across all groups.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$settings = [
|
||||
...$this->general(),
|
||||
...$this->contact(),
|
||||
...$this->maps(),
|
||||
...$this->social(),
|
||||
...$this->seo(),
|
||||
...$this->analytics(),
|
||||
...$this->header(),
|
||||
...$this->footer(),
|
||||
...$this->integrations(),
|
||||
...$this->infoSections(),
|
||||
];
|
||||
|
||||
foreach ($settings as $setting) {
|
||||
$value = $setting['value'];
|
||||
unset($setting['value']);
|
||||
|
||||
Setting::query()->updateOrCreate(
|
||||
['group' => $setting['group'], 'key' => $setting['key']],
|
||||
array_merge($setting, [
|
||||
'value' => Setting::query()
|
||||
->where('group', $setting['group'])
|
||||
->where('key', $setting['key'])
|
||||
->value('value') ?? $value,
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private function general(): array
|
||||
{
|
||||
$g = 'general';
|
||||
|
||||
return [
|
||||
['group' => $g, 'key' => 'site_name', 'value' => 'Boğaziçi Denizcilik Eğitim Kurumu', 'type' => 'text', 'label' => 'Site Adı', 'order_index' => 0, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'site_tagline', 'value' => null, 'type' => 'text', 'label' => 'Slogan', 'order_index' => 1, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'site_description', 'value' => null, 'type' => 'textarea', 'label' => 'Kısa Site Açıklaması', 'order_index' => 2, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'logo_light', 'value' => null, 'type' => 'image', 'label' => 'Logo — Açık Tema (beyaz navbar)', 'order_index' => 3, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'logo_dark', 'value' => null, 'type' => 'image', 'label' => 'Logo — Koyu Tema (dark bg)', 'order_index' => 4, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'favicon', 'value' => null, 'type' => 'image', 'label' => 'Favicon (32x32 PNG)', 'order_index' => 5, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'apple_touch_icon', 'value' => null, 'type' => 'image', 'label' => 'Apple Touch Icon (180x180)', 'order_index' => 6, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'announcement_bar_active', 'value' => 'false', 'type' => 'boolean', 'label' => 'Üst Bar Aktif mi', 'order_index' => 7, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'announcement_bar_text', 'value' => null, 'type' => 'text', 'label' => 'Üst Bar Metni', 'order_index' => 8, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'announcement_bar_url', 'value' => null, 'type' => 'url', 'label' => 'Üst Bar Linki', 'order_index' => 9, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'announcement_bar_bg_color', 'value' => '#1a3e74', 'type' => 'color', 'label' => 'Üst Bar Arka Plan Rengi', 'order_index' => 10, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'maintenance_mode', 'value' => 'false', 'type' => 'boolean', 'label' => 'Bakım Modu', 'order_index' => 11, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'maintenance_message', 'value' => null, 'type' => 'textarea', 'label' => 'Bakım Modu Mesajı', 'order_index' => 12, 'is_public' => true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private function contact(): array
|
||||
{
|
||||
$g = 'contact';
|
||||
|
||||
return [
|
||||
['group' => $g, 'key' => 'phone_primary', 'value' => null, 'type' => 'text', 'label' => 'Ana Telefon', 'order_index' => 0, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'phone_secondary', 'value' => null, 'type' => 'text', 'label' => 'İkinci Telefon', 'order_index' => 1, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'email_info', 'value' => null, 'type' => 'text', 'label' => 'Bilgi E-postası', 'order_index' => 2, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'email_support', 'value' => null, 'type' => 'text', 'label' => 'Destek E-postası', 'order_index' => 3, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'email_kayit', 'value' => null, 'type' => 'text', 'label' => 'Kayıt E-postası', 'order_index' => 4, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'address_full', 'value' => null, 'type' => 'textarea', 'label' => 'Tam Adres', 'order_index' => 5, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'address_short', 'value' => null, 'type' => 'text', 'label' => 'Kısa Adres (navbar için)', 'order_index' => 6, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'district', 'value' => null, 'type' => 'text', 'label' => 'İlçe', 'order_index' => 7, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'city', 'value' => null, 'type' => 'text', 'label' => 'Şehir', 'order_index' => 8, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'postal_code', 'value' => null, 'type' => 'text', 'label' => 'Posta Kodu', 'order_index' => 9, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'working_hours_weekday', 'value' => null, 'type' => 'text', 'label' => 'Hafta İçi Saatleri', 'order_index' => 10, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'working_hours_saturday', 'value' => null, 'type' => 'text', 'label' => 'Cumartesi Saatleri', 'order_index' => 11, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'working_hours_sunday', 'value' => null, 'type' => 'text', 'label' => 'Pazar Saatleri', 'order_index' => 12, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'whatsapp_number', 'value' => null, 'type' => 'text', 'label' => 'WhatsApp (+90 ile başlayan)', 'order_index' => 13, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'whatsapp_message', 'value' => null, 'type' => 'text', 'label' => 'WhatsApp Varsayılan Mesaj', 'order_index' => 14, 'is_public' => true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private function maps(): array
|
||||
{
|
||||
$g = 'maps';
|
||||
|
||||
return [
|
||||
['group' => $g, 'key' => 'google_maps_embed_url', 'value' => null, 'type' => 'textarea', 'label' => 'Google Maps Embed URL (iframe src)', 'order_index' => 0, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'google_maps_place_url', 'value' => null, 'type' => 'url', 'label' => 'Google Maps Profil Linki', 'order_index' => 1, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'google_maps_api_key', 'value' => null, 'type' => 'text', 'label' => 'Google Maps API Key', 'order_index' => 2, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'latitude', 'value' => null, 'type' => 'text', 'label' => 'Enlem', 'order_index' => 3, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'longitude', 'value' => null, 'type' => 'text', 'label' => 'Boylam', 'order_index' => 4, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'map_zoom_level', 'value' => '15', 'type' => 'text', 'label' => 'Harita Zoom (1-20)', 'order_index' => 5, 'is_public' => true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private function social(): array
|
||||
{
|
||||
$g = 'social';
|
||||
|
||||
return [
|
||||
['group' => $g, 'key' => 'instagram_url', 'value' => null, 'type' => 'url', 'label' => 'Instagram Profil URL', 'order_index' => 0, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'instagram_handle', 'value' => null, 'type' => 'text', 'label' => 'Instagram Kullanıcı Adı (@siz)', 'order_index' => 1, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'facebook_url', 'value' => null, 'type' => 'url', 'label' => 'Facebook Sayfası URL', 'order_index' => 2, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'facebook_page_id', 'value' => null, 'type' => 'text', 'label' => 'Facebook Page ID', 'order_index' => 3, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'twitter_url', 'value' => null, 'type' => 'url', 'label' => 'X (Twitter) Profil URL', 'order_index' => 4, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'twitter_handle', 'value' => null, 'type' => 'text', 'label' => 'X Kullanıcı Adı (@siz)', 'order_index' => 5, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'youtube_url', 'value' => null, 'type' => 'url', 'label' => 'YouTube Kanal URL', 'order_index' => 6, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'youtube_channel_id', 'value' => null, 'type' => 'text', 'label' => 'YouTube Channel ID', 'order_index' => 7, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'linkedin_url', 'value' => null, 'type' => 'url', 'label' => 'LinkedIn Sayfa URL', 'order_index' => 8, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'tiktok_url', 'value' => null, 'type' => 'url', 'label' => 'TikTok Profil URL', 'order_index' => 9, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'pinterest_url', 'value' => null, 'type' => 'url', 'label' => 'Pinterest URL', 'order_index' => 10, 'is_public' => true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private function seo(): array
|
||||
{
|
||||
$g = 'seo';
|
||||
|
||||
return [
|
||||
// Temel SEO
|
||||
['group' => $g, 'key' => 'meta_title_suffix', 'value' => 'Boğaziçi Denizcilik', 'type' => 'text', 'label' => 'Title Eki', 'order_index' => 0, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'meta_title_separator', 'value' => '|', 'type' => 'text', 'label' => 'Ayraç Karakteri', 'order_index' => 1, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'default_meta_description', 'value' => null, 'type' => 'textarea', 'label' => 'Varsayılan Meta Açıklama', 'order_index' => 2, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'default_meta_keywords', 'value' => null, 'type' => 'textarea', 'label' => 'Varsayılan Keywords (virgülle)', 'order_index' => 3, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'robots', 'value' => 'index, follow', 'type' => 'text', 'label' => 'Robots', 'order_index' => 4, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'canonical_domain', 'value' => null, 'type' => 'url', 'label' => 'Canonical Domain', 'order_index' => 5, 'is_public' => true],
|
||||
// Open Graph
|
||||
['group' => $g, 'key' => 'og_title', 'value' => null, 'type' => 'text', 'label' => 'OG Default Title', 'order_index' => 6, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'og_description', 'value' => null, 'type' => 'textarea', 'label' => 'OG Default Description', 'order_index' => 7, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'og_image', 'value' => null, 'type' => 'image', 'label' => 'OG Default Görsel (1200x630 px)', 'order_index' => 8, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'og_type', 'value' => 'website', 'type' => 'text', 'label' => 'OG Type', 'order_index' => 9, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'og_locale', 'value' => 'tr_TR', 'type' => 'text', 'label' => 'OG Locale', 'order_index' => 10, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'og_site_name', 'value' => null, 'type' => 'text', 'label' => 'OG Site Name', 'order_index' => 11, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'facebook_app_id', 'value' => null, 'type' => 'text', 'label' => 'Facebook App ID', 'order_index' => 12, 'is_public' => false],
|
||||
// Twitter / X Card
|
||||
['group' => $g, 'key' => 'twitter_card_type', 'value' => 'summary_large_image', 'type' => 'text', 'label' => 'Card Tipi', 'order_index' => 13, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'twitter_site', 'value' => null, 'type' => 'text', 'label' => 'Site @handle', 'order_index' => 14, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'twitter_creator', 'value' => null, 'type' => 'text', 'label' => 'İçerik Sahibi @handle', 'order_index' => 15, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'twitter_title', 'value' => null, 'type' => 'text', 'label' => 'Twitter Default Title', 'order_index' => 16, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'twitter_description', 'value' => null, 'type' => 'textarea', 'label' => 'Twitter Default Description', 'order_index' => 17, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'twitter_image', 'value' => null, 'type' => 'image', 'label' => 'Twitter Card Görseli (1200x600 px)', 'order_index' => 18, 'is_public' => true],
|
||||
// Doğrulama Kodları
|
||||
['group' => $g, 'key' => 'google_site_verification', 'value' => null, 'type' => 'text', 'label' => 'Google Search Console Kodu', 'order_index' => 19, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'bing_site_verification', 'value' => null, 'type' => 'text', 'label' => 'Bing Webmaster Kodu', 'order_index' => 20, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'yandex_verification', 'value' => null, 'type' => 'text', 'label' => 'Yandex Webmaster Kodu', 'order_index' => 21, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'pinterest_verification', 'value' => null, 'type' => 'text', 'label' => 'Pinterest Doğrulama Kodu', 'order_index' => 22, 'is_public' => true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private function analytics(): array
|
||||
{
|
||||
$g = 'analytics';
|
||||
|
||||
return [
|
||||
['group' => $g, 'key' => 'google_analytics_id', 'value' => null, 'type' => 'text', 'label' => 'Google Analytics 4 ID (G-XXXXXXXX)', 'order_index' => 0, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'google_tag_manager_id', 'value' => null, 'type' => 'text', 'label' => 'Google Tag Manager ID (GTM-XXXXXXX)', 'order_index' => 1, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'google_ads_id', 'value' => null, 'type' => 'text', 'label' => 'Google Ads Conversion ID', 'order_index' => 2, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'facebook_pixel_id', 'value' => null, 'type' => 'text', 'label' => 'Meta (Facebook) Pixel ID', 'order_index' => 3, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'hotjar_id', 'value' => null, 'type' => 'text', 'label' => 'Hotjar Site ID', 'order_index' => 4, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'clarity_id', 'value' => null, 'type' => 'text', 'label' => 'Microsoft Clarity ID', 'order_index' => 5, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'tiktok_pixel_id', 'value' => null, 'type' => 'text', 'label' => 'TikTok Pixel ID', 'order_index' => 6, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'crisp_website_id', 'value' => null, 'type' => 'text', 'label' => 'Crisp Chat Website ID', 'order_index' => 7, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'custom_head_scripts', 'value' => null, 'type' => 'textarea', 'label' => '<head> içine özel script', 'order_index' => 8, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'custom_body_scripts', 'value' => null, 'type' => 'textarea', 'label' => '<body> sonuna özel script', 'order_index' => 9, 'is_public' => false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private function header(): array
|
||||
{
|
||||
$g = 'header';
|
||||
|
||||
return [
|
||||
['group' => $g, 'key' => 'navbar_style_default', 'value' => 'transparent', 'type' => 'text', 'label' => 'Varsayılan Navbar Stili (transparent/white)', 'order_index' => 0, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'cta_button_text', 'value' => 'Başvuru Yap', 'type' => 'text', 'label' => 'Sağ Üst Buton Metni', 'order_index' => 1, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'cta_button_url', 'value' => '/kayit', 'type' => 'url', 'label' => 'Sağ Üst Buton Linki', 'order_index' => 2, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'cta_button_color', 'value' => '#1a3e74', 'type' => 'color', 'label' => 'Sağ Üst Buton Rengi', 'order_index' => 3, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'show_phone_topbar', 'value' => 'true', 'type' => 'boolean', 'label' => "Üst Bar'da Telefon Göster", 'order_index' => 4, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'show_email_topbar', 'value' => 'true', 'type' => 'boolean', 'label' => "Üst Bar'da E-posta Göster", 'order_index' => 5, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'show_address_topbar', 'value' => 'true', 'type' => 'boolean', 'label' => "Üst Bar'da Adres Göster", 'order_index' => 6, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'show_hours_topbar', 'value' => 'true', 'type' => 'boolean', 'label' => "Üst Bar'da Saat Göster", 'order_index' => 7, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'show_social_navbar', 'value' => 'true', 'type' => 'boolean', 'label' => "Navbar'da Sosyal Medya İkonları Göster", 'order_index' => 8, 'is_public' => true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private function footer(): array
|
||||
{
|
||||
$g = 'footer';
|
||||
|
||||
return [
|
||||
['group' => $g, 'key' => 'footer_description', 'value' => null, 'type' => 'textarea', 'label' => 'Footer Açıklaması', 'order_index' => 0, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'footer_logo', 'value' => null, 'type' => 'image', 'label' => 'Footer Logo (varsa ayrı)', 'order_index' => 1, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'copyright_text', 'value' => '© 2026 Boğaziçi Denizcilik', 'type' => 'text', 'label' => 'Copyright Metni', 'order_index' => 2, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'footer_address', 'value' => null, 'type' => 'textarea', 'label' => 'Footer Adres', 'order_index' => 3, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'footer_phone', 'value' => null, 'type' => 'text', 'label' => 'Footer Telefon', 'order_index' => 4, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'footer_email', 'value' => null, 'type' => 'text', 'label' => 'Footer E-posta', 'order_index' => 5, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'footer_bg_color', 'value' => '#0f2847', 'type' => 'color', 'label' => 'Footer Arka Plan Rengi', 'order_index' => 6, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'show_social_footer', 'value' => 'true', 'type' => 'boolean', 'label' => "Footer'da Sosyal Medya Göster", 'order_index' => 7, 'is_public' => true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private function integrations(): array
|
||||
{
|
||||
$g = 'integrations';
|
||||
|
||||
return [
|
||||
['group' => $g, 'key' => 'recaptcha_site_key', 'value' => null, 'type' => 'text', 'label' => 'reCAPTCHA v3 Site Key', 'order_index' => 0, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'recaptcha_secret_key', 'value' => null, 'type' => 'text', 'label' => 'reCAPTCHA v3 Secret Key', 'order_index' => 1, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'smtp_host', 'value' => null, 'type' => 'text', 'label' => 'SMTP Host', 'order_index' => 2, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'smtp_port', 'value' => '587', 'type' => 'text', 'label' => 'SMTP Port', 'order_index' => 3, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'smtp_username', 'value' => null, 'type' => 'text', 'label' => 'SMTP Kullanıcı Adı', 'order_index' => 4, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'smtp_password', 'value' => null, 'type' => 'text', 'label' => 'SMTP Şifre', 'order_index' => 5, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'smtp_encryption', 'value' => 'tls', 'type' => 'text', 'label' => 'SMTP Şifreleme (tls/ssl)', 'order_index' => 6, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'smtp_from_name', 'value' => 'Boğaziçi Denizcilik', 'type' => 'text', 'label' => 'Mail Gönderen Adı', 'order_index' => 7, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'smtp_from_email', 'value' => null, 'type' => 'text', 'label' => 'Mail Gönderen Adresi', 'order_index' => 8, 'is_public' => false],
|
||||
['group' => $g, 'key' => 'notification_emails', 'value' => null, 'type' => 'textarea', 'label' => 'Bildirim E-postaları (virgülle)', 'order_index' => 9, 'is_public' => false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private function infoSections(): array
|
||||
{
|
||||
$g = 'info_sections';
|
||||
|
||||
return [
|
||||
// Info Section 1
|
||||
['group' => $g, 'key' => 'info_section_1_badge', 'value' => 'Neden Boğaziçi Denizcilik?', 'type' => 'text', 'label' => 'Bölüm 1 — Etiket', 'order_index' => 0, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'info_section_1_title', 'value' => 'Uluslararası Standartlarda Denizcilik Eğitimi', 'type' => 'text', 'label' => 'Bölüm 1 — Başlık', 'order_index' => 1, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'info_section_1_body', 'value' => 'Boğaziçi Denizcilik Eğitim Kurumu, Ulaştırma ve Altyapı Bakanlığı onaylı eğitim programlarıyla denizcilik sektörüne nitelikli personel yetiştirmektedir. STCW Sözleşmesi gerekliliklerini karşılayan müfredatımız; köprüüstü simülatörleri, GMDSS telsiz laboratuvarı ve yangın tatbikat alanında uygulamalı olarak verilmektedir.', 'type' => 'textarea', 'label' => 'Bölüm 1 — İçerik', 'order_index' => 2, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'info_section_1_quote', 'value' => "Boğaziçi Denizcilik'ten aldığım STCW eğitimleri ve simülatör deneyimi sayesinde uluslararası bir denizcilik şirketinde güverte zabiti olarak göreve başladım.", 'type' => 'text', 'label' => 'Bölüm 1 — Alıntı', 'order_index' => 3, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'info_section_1_quote_author', 'value' => 'Kpt. Murat Aydın — Vardiya Zabiti, MSC Denizcilik', 'type' => 'text', 'label' => 'Bölüm 1 — Alıntı Yazarı', 'order_index' => 4, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'info_section_1_image', 'value' => null, 'type' => 'image', 'label' => 'Bölüm 1 — Görsel', 'order_index' => 5, 'is_public' => true],
|
||||
// Info Section 2
|
||||
['group' => $g, 'key' => 'info_section_2_badge', 'value' => 'Simülatör Destekli Eğitim', 'type' => 'text', 'label' => 'Bölüm 2 — Etiket', 'order_index' => 6, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'info_section_2_title', 'value' => 'Teoriden Pratiğe, Sınıftan Köprüüstüne', 'type' => 'text', 'label' => 'Bölüm 2 — Başlık', 'order_index' => 7, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'info_section_2_body', 'value' => 'Eğitim merkezimizde bulunan tam donanımlı köprüüstü simülatörü, ARPA/radar eğitim istasyonları ve ECDIS terminalleri ile kursiyerlerimiz gerçek seyir senaryolarında deneyim kazanmaktadır. GMDSS laboratuvarımızda DSC, NAVTEX, Inmarsat-C ve VHF/MF/HF cihazları üzerinde birebir uygulama yapılmaktadır.', 'type' => 'textarea', 'label' => 'Bölüm 2 — İçerik', 'order_index' => 8, 'is_public' => true],
|
||||
['group' => $g, 'key' => 'info_section_2_image', 'value' => null, 'type' => 'image', 'label' => 'Bölüm 2 — Görsel', 'order_index' => 9, 'is_public' => true],
|
||||
];
|
||||
}
|
||||
}
|
||||
79
database/seeders/StorySeeder.php
Normal file
79
database/seeders/StorySeeder.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Story;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class StorySeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Seed stories for homepage.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$stories = [
|
||||
[
|
||||
'title' => 'Boğaziçi Denizcilik',
|
||||
'badge' => 'Tanıtım',
|
||||
'content' => "1998'den bu yana Türk denizciliğine nitelikli personel yetiştiriyoruz. IMO standartlarında, STCW uyumlu eğitimlerimizle 15.000+ mezun.",
|
||||
'image' => null,
|
||||
'cta_text' => 'Hakkımızda',
|
||||
'cta_url' => '/kurumsal/hakkimizda',
|
||||
'order_index' => 0,
|
||||
],
|
||||
[
|
||||
'title' => 'Eğitimler Başlıyor',
|
||||
'badge' => 'Yeni Dönem',
|
||||
'content' => 'Güverte, makine ve STCW eğitim gruplarımız açılıyor. Teori ve simülatör destekli uygulamalı müfredat.',
|
||||
'image' => null,
|
||||
'cta_text' => 'Eğitim Takvimi',
|
||||
'cta_url' => '/egitimler/takvim',
|
||||
'order_index' => 1,
|
||||
],
|
||||
[
|
||||
'title' => 'Eğitim Kategorileri',
|
||||
'badge' => 'Katalog',
|
||||
'content' => 'Güverte, makine, STCW güvenlik, yat kaptanlığı, telsiz ve belge yenileme — 6 ana kategoride 45+ eğitim programı.',
|
||||
'image' => null,
|
||||
'cta_text' => 'Tüm Eğitimler',
|
||||
'cta_url' => '/egitimler',
|
||||
'order_index' => 2,
|
||||
],
|
||||
[
|
||||
'title' => 'Belge Yenileme',
|
||||
'badge' => 'Yenileme',
|
||||
'content' => 'BST, AFF, ilk yardım ve güverte/makine yeterlik belgelerinizin süresi mi doluyor? Hafta sonu tazeleme programlarımız açık.',
|
||||
'image' => null,
|
||||
'cta_text' => 'Yenileme Eğitimleri',
|
||||
'cta_url' => '/egitimler/yenileme',
|
||||
'order_index' => 3,
|
||||
],
|
||||
[
|
||||
'title' => 'Yat Kaptanlığı',
|
||||
'badge' => 'Yat',
|
||||
'content' => '25 GT, 149 GT ve 3000 GT tonaj sınıflarında yat kaptanlığı eğitimleri. Kıyı seyri, manevra, deniz hukuku ve güvenlik.',
|
||||
'image' => null,
|
||||
'cta_text' => 'Detaylı Bilgi',
|
||||
'cta_url' => '/egitimler/yat-kaptanligi',
|
||||
'order_index' => 4,
|
||||
],
|
||||
[
|
||||
'title' => 'STCW Güvenlik',
|
||||
'badge' => 'STCW',
|
||||
'content' => 'Temel Güvenlik (BST), ileri yangın söndürme (AFF), denizde kişisel can kurtarma ve ilk yardım — zorunlu STCW sertifikaları.',
|
||||
'image' => null,
|
||||
'cta_text' => 'STCW Eğitimleri',
|
||||
'cta_url' => '/egitimler/stcw',
|
||||
'order_index' => 5,
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($stories as $story) {
|
||||
Story::firstOrCreate(
|
||||
['title' => $story['title']],
|
||||
$story,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user