update deploy
This commit is contained in:
62
app/Http/Controllers/Api/V1/AnnouncementController.php
Normal file
62
app/Http/Controllers/Api/V1/AnnouncementController.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\AnnouncementResource;
|
||||
use App\Repositories\Contracts\AnnouncementRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class AnnouncementController extends Controller
|
||||
{
|
||||
public function __construct(private AnnouncementRepositoryInterface $repository) {}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/announcements',
|
||||
summary: 'Duyuruları listele',
|
||||
tags: ['Announcements'],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'category', in: 'query', required: false, schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'featured', in: 'query', required: false, schema: new OA\Schema(type: 'boolean')),
|
||||
new OA\Parameter(name: 'search', in: 'query', required: false, schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'sort', in: 'query', required: false, schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'per_page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 15)),
|
||||
],
|
||||
responses: [new OA\Response(response: 200, description: 'Duyuru listesi')],
|
||||
)]
|
||||
public function index(Request $request): AnonymousResourceCollection
|
||||
{
|
||||
$announcements = $this->repository->paginate(
|
||||
$request->only(['category', 'featured', 'search', 'sort']),
|
||||
$request->integer('per_page', 15),
|
||||
);
|
||||
|
||||
return AnnouncementResource::collection($announcements);
|
||||
}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/announcements/{slug}',
|
||||
summary: 'Duyuru detayı',
|
||||
tags: ['Announcements'],
|
||||
parameters: [new OA\Parameter(name: 'slug', in: 'path', required: true, schema: new OA\Schema(type: 'string'))],
|
||||
responses: [
|
||||
new OA\Response(response: 200, description: 'Duyuru detayı'),
|
||||
new OA\Response(response: 404, description: 'Duyuru bulunamadı'),
|
||||
],
|
||||
)]
|
||||
public function show(string $slug): JsonResponse
|
||||
{
|
||||
$announcement = $this->repository->findBySlug($slug);
|
||||
|
||||
if (! $announcement) {
|
||||
return response()->json(['message' => 'Duyuru bulunamadı.'], 404);
|
||||
}
|
||||
|
||||
$announcement->load(['comments' => fn ($q) => $q->where('is_approved', true)->latest()]);
|
||||
|
||||
return response()->json(new AnnouncementResource($announcement));
|
||||
}
|
||||
}
|
||||
60
app/Http/Controllers/Api/V1/CategoryController.php
Normal file
60
app/Http/Controllers/Api/V1/CategoryController.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\CategoryResource;
|
||||
use App\Repositories\Contracts\CategoryRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
public function __construct(private CategoryRepositoryInterface $repository) {}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/categories',
|
||||
summary: 'Kategorileri listele',
|
||||
description: 'Tüm aktif kategorileri sayfalanmış olarak döndürür.',
|
||||
tags: ['Categories'],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'search', in: 'query', required: false, schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'per_page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 15)),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(response: 200, description: 'Kategori listesi'),
|
||||
],
|
||||
)]
|
||||
public function index(Request $request): AnonymousResourceCollection
|
||||
{
|
||||
$categories = $this->repository->paginate(
|
||||
filters: $request->only('search'),
|
||||
perPage: $request->integer('per_page', 15),
|
||||
);
|
||||
|
||||
return CategoryResource::collection($categories);
|
||||
}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/categories/{slug}',
|
||||
summary: 'Kategori detayı',
|
||||
description: 'Slug ile kategori detayını döndürür.',
|
||||
tags: ['Categories'],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'slug', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(response: 200, description: 'Kategori detayı'),
|
||||
new OA\Response(response: 404, description: 'Kategori bulunamadı'),
|
||||
],
|
||||
)]
|
||||
public function show(string $slug): CategoryResource
|
||||
{
|
||||
$category = $this->repository->findBySlug($slug);
|
||||
|
||||
abort_if(! $category, 404, 'Kategori bulunamadı.');
|
||||
|
||||
return new CategoryResource($category);
|
||||
}
|
||||
}
|
||||
92
app/Http/Controllers/Api/V1/CommentController.php
Normal file
92
app/Http/Controllers/Api/V1/CommentController.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Actions\Comment\CreateCommentAction;
|
||||
use App\DTOs\CommentData;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Comment\StoreCommentRequest;
|
||||
use App\Http\Resources\CommentResource;
|
||||
use App\Models\Announcement;
|
||||
use App\Models\Category;
|
||||
use App\Models\Course;
|
||||
use App\Repositories\Contracts\CommentRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class CommentController extends Controller
|
||||
{
|
||||
/**
|
||||
* Morph map for commentable types from the request.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private const COMMENTABLE_MAP = [
|
||||
'course' => Course::class,
|
||||
'category' => Category::class,
|
||||
'announcement' => Announcement::class,
|
||||
];
|
||||
|
||||
public function __construct(private CommentRepositoryInterface $repository) {}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/comments/{type}/{id}',
|
||||
summary: 'Onaylı yorumları getir',
|
||||
tags: ['Comments'],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'type', in: 'path', required: true, schema: new OA\Schema(type: 'string', enum: ['course', 'category', 'announcement'])),
|
||||
new OA\Parameter(name: 'id', in: 'path', required: true, schema: new OA\Schema(type: 'integer')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(response: 200, description: 'Onaylı yorum listesi'),
|
||||
new OA\Response(response: 404, description: 'Geçersiz yorum tipi'),
|
||||
],
|
||||
)]
|
||||
public function index(string $type, int $id): AnonymousResourceCollection|JsonResponse
|
||||
{
|
||||
$commentableType = self::COMMENTABLE_MAP[$type] ?? null;
|
||||
|
||||
if ($commentableType === null) {
|
||||
return response()->json(['message' => 'Geçersiz yorum tipi.'], 404);
|
||||
}
|
||||
|
||||
$comments = $this->repository->getApprovedByCommentable($commentableType, $id);
|
||||
|
||||
return CommentResource::collection($comments);
|
||||
}
|
||||
|
||||
#[OA\Post(
|
||||
path: '/api/v1/comments',
|
||||
summary: 'Yorum gönder',
|
||||
tags: ['Comments'],
|
||||
requestBody: new OA\RequestBody(
|
||||
required: true,
|
||||
content: new OA\JsonContent(
|
||||
required: ['body', 'author_name', 'author_email', 'commentable_type', 'commentable_id'],
|
||||
properties: [
|
||||
new OA\Property(property: 'body', type: 'string'),
|
||||
new OA\Property(property: 'author_name', type: 'string'),
|
||||
new OA\Property(property: 'author_email', type: 'string', format: 'email'),
|
||||
new OA\Property(property: 'commentable_type', type: 'string', enum: ['course', 'category', 'announcement']),
|
||||
new OA\Property(property: 'commentable_id', type: 'integer'),
|
||||
new OA\Property(property: 'rating', type: 'integer', minimum: 1, maximum: 5),
|
||||
],
|
||||
),
|
||||
),
|
||||
responses: [
|
||||
new OA\Response(response: 201, description: 'Yorum gönderildi'),
|
||||
new OA\Response(response: 422, description: 'Validasyon hatası'),
|
||||
],
|
||||
)]
|
||||
public function store(StoreCommentRequest $request, CreateCommentAction $action): JsonResponse
|
||||
{
|
||||
$validated = $request->validated();
|
||||
$validated['commentable_type'] = self::COMMENTABLE_MAP[$validated['commentable_type']] ?? $validated['commentable_type'];
|
||||
|
||||
$dto = CommentData::fromArray($validated);
|
||||
$action->execute($dto);
|
||||
|
||||
return response()->json(['message' => 'Yorumunuz incelenmek üzere gönderildi.'], 201);
|
||||
}
|
||||
}
|
||||
62
app/Http/Controllers/Api/V1/CourseController.php
Normal file
62
app/Http/Controllers/Api/V1/CourseController.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\CourseResource;
|
||||
use App\Repositories\Contracts\CourseRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class CourseController extends Controller
|
||||
{
|
||||
public function __construct(private CourseRepositoryInterface $repository) {}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/courses',
|
||||
summary: 'Eğitimleri listele',
|
||||
description: 'Tüm eğitimleri sayfalanmış olarak döndürür. Kategori, arama ve sıralama filtresi destekler.',
|
||||
tags: ['Courses'],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'category', in: 'query', required: false, schema: new OA\Schema(type: 'string'), description: 'Kategori slug filtresi'),
|
||||
new OA\Parameter(name: 'search', in: 'query', required: false, schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'sort', in: 'query', required: false, schema: new OA\Schema(type: 'string'), description: 'Örn: -created_at, title'),
|
||||
new OA\Parameter(name: 'per_page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 15)),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(response: 200, description: 'Eğitim listesi'),
|
||||
],
|
||||
)]
|
||||
public function index(Request $request): AnonymousResourceCollection
|
||||
{
|
||||
$courses = $this->repository->paginate(
|
||||
filters: $request->only('category', 'search', 'sort'),
|
||||
perPage: $request->integer('per_page', 15),
|
||||
);
|
||||
|
||||
return CourseResource::collection($courses);
|
||||
}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/courses/{slug}',
|
||||
summary: 'Eğitim detayı',
|
||||
description: 'Slug ile eğitim detayını döndürür.',
|
||||
tags: ['Courses'],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'slug', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(response: 200, description: 'Eğitim detayı'),
|
||||
new OA\Response(response: 404, description: 'Eğitim bulunamadı'),
|
||||
],
|
||||
)]
|
||||
public function show(string $slug): CourseResource
|
||||
{
|
||||
$course = $this->repository->findBySlug($slug);
|
||||
|
||||
abort_if(! $course, 404, 'Eğitim bulunamadı.');
|
||||
|
||||
return new CourseResource($course);
|
||||
}
|
||||
}
|
||||
55
app/Http/Controllers/Api/V1/FaqController.php
Normal file
55
app/Http/Controllers/Api/V1/FaqController.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Enums\FaqCategory;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\FaqResource;
|
||||
use App\Repositories\Contracts\FaqRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class FaqController extends Controller
|
||||
{
|
||||
public function __construct(private FaqRepositoryInterface $repository) {}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/faqs/{category?}',
|
||||
summary: 'SSS listesi',
|
||||
description: 'Tüm veya kategoriye göre filtrelenmiş SSS listesi döndürür. ?limit=6 ile anasayfa için sınırlanabilir.',
|
||||
tags: ['FAQs'],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'category', in: 'path', required: false, schema: new OA\Schema(type: 'string'), description: 'FAQ kategori filtresi'),
|
||||
new OA\Parameter(name: 'limit', in: 'query', required: false, schema: new OA\Schema(type: 'integer'), description: 'Dönen SSS sayısını sınırla (anasayfa için)'),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(response: 200, description: 'SSS listesi'),
|
||||
new OA\Response(response: 404, description: 'Kategori bulunamadı'),
|
||||
],
|
||||
)]
|
||||
public function index(Request $request, ?string $category = null): AnonymousResourceCollection
|
||||
{
|
||||
$limit = $request->integer('limit', 0);
|
||||
|
||||
if ($category) {
|
||||
$faqCategory = FaqCategory::tryFrom($category);
|
||||
|
||||
if (! $faqCategory) {
|
||||
abort(404, 'FAQ kategorisi bulunamadı.');
|
||||
}
|
||||
|
||||
$faqs = $this->repository->getByCategory($faqCategory);
|
||||
|
||||
if ($limit > 0) {
|
||||
$faqs = $faqs->take($limit);
|
||||
}
|
||||
|
||||
return FaqResource::collection($faqs);
|
||||
}
|
||||
|
||||
$perPage = $limit > 0 ? $limit : 100;
|
||||
|
||||
return FaqResource::collection($this->repository->paginate([], $perPage));
|
||||
}
|
||||
}
|
||||
25
app/Http/Controllers/Api/V1/GuideCardController.php
Normal file
25
app/Http/Controllers/Api/V1/GuideCardController.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\GuideCardResource;
|
||||
use App\Repositories\Contracts\GuideCardRepositoryInterface;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class GuideCardController extends Controller
|
||||
{
|
||||
public function __construct(private GuideCardRepositoryInterface $repository) {}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/guide-cards',
|
||||
summary: 'Rehber kartlarını listele',
|
||||
tags: ['Guide Cards'],
|
||||
responses: [new OA\Response(response: 200, description: 'Rehber kart listesi')],
|
||||
)]
|
||||
public function index(): AnonymousResourceCollection
|
||||
{
|
||||
return GuideCardResource::collection($this->repository->active());
|
||||
}
|
||||
}
|
||||
25
app/Http/Controllers/Api/V1/HeroSlideController.php
Normal file
25
app/Http/Controllers/Api/V1/HeroSlideController.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\HeroSlideResource;
|
||||
use App\Repositories\Contracts\HeroSlideRepositoryInterface;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class HeroSlideController extends Controller
|
||||
{
|
||||
public function __construct(private HeroSlideRepositoryInterface $repository) {}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/hero-slides',
|
||||
summary: 'Aktif hero slide listesi',
|
||||
tags: ['Hero Slides'],
|
||||
responses: [new OA\Response(response: 200, description: 'Aktif hero slide listesi')],
|
||||
)]
|
||||
public function index(): AnonymousResourceCollection
|
||||
{
|
||||
return HeroSlideResource::collection($this->repository->active());
|
||||
}
|
||||
}
|
||||
54
app/Http/Controllers/Api/V1/LeadController.php
Normal file
54
app/Http/Controllers/Api/V1/LeadController.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Actions\Lead\CreateLeadAction;
|
||||
use App\DTOs\LeadData;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Lead\StoreLeadRequest;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class LeadController extends Controller
|
||||
{
|
||||
#[OA\Post(
|
||||
path: '/api/v1/leads',
|
||||
summary: 'Yeni başvuru/talep oluştur',
|
||||
tags: ['Leads'],
|
||||
requestBody: new OA\RequestBody(
|
||||
required: true,
|
||||
content: new OA\JsonContent(
|
||||
required: ['name', 'phone', 'source', 'kvkk_consent'],
|
||||
properties: [
|
||||
new OA\Property(property: 'name', type: 'string', description: 'Ad Soyad'),
|
||||
new OA\Property(property: 'phone', type: 'string', description: 'Telefon'),
|
||||
new OA\Property(property: 'email', type: 'string', format: 'email', nullable: true),
|
||||
new OA\Property(property: 'source', type: 'string', description: 'kurs_kayit, danismanlik, duyuru, iletisim'),
|
||||
new OA\Property(property: 'target_course', type: 'string', nullable: true, description: 'Kurs slug'),
|
||||
new OA\Property(property: 'education_level', type: 'string', nullable: true),
|
||||
new OA\Property(property: 'subject', type: 'string', nullable: true),
|
||||
new OA\Property(property: 'message', type: 'string', nullable: true),
|
||||
new OA\Property(property: 'kvkk_consent', type: 'boolean', description: 'KVKK onayı (zorunlu, true olmalı)'),
|
||||
new OA\Property(property: 'marketing_consent', type: 'boolean', nullable: true),
|
||||
new OA\Property(property: 'utm_source', type: 'string', nullable: true),
|
||||
new OA\Property(property: 'utm_medium', type: 'string', nullable: true),
|
||||
new OA\Property(property: 'utm_campaign', type: 'string', nullable: true),
|
||||
],
|
||||
),
|
||||
),
|
||||
responses: [
|
||||
new OA\Response(response: 201, description: 'Başvuru alındı'),
|
||||
new OA\Response(response: 422, description: 'Validasyon hatası'),
|
||||
],
|
||||
)]
|
||||
public function store(StoreLeadRequest $request, CreateLeadAction $action): JsonResponse
|
||||
{
|
||||
$dto = LeadData::fromArray($request->validated());
|
||||
$action->execute($dto);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Talebiniz alınmıştır. En kısa sürede sizinle iletişime geçeceğiz.',
|
||||
], 201);
|
||||
}
|
||||
}
|
||||
36
app/Http/Controllers/Api/V1/MenuController.php
Normal file
36
app/Http/Controllers/Api/V1/MenuController.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Enums\MenuLocation;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\MenuResource;
|
||||
use App\Repositories\Contracts\MenuRepositoryInterface;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class MenuController extends Controller
|
||||
{
|
||||
public function __construct(private MenuRepositoryInterface $repository) {}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/menus/{location}',
|
||||
summary: 'Konuma göre menü öğelerini getir',
|
||||
tags: ['Menus'],
|
||||
parameters: [new OA\Parameter(name: 'location', in: 'path', required: true, schema: new OA\Schema(type: 'string'), description: 'header, footer, mobile')],
|
||||
responses: [
|
||||
new OA\Response(response: 200, description: 'Menü listesi'),
|
||||
new OA\Response(response: 404, description: 'Menü konumu bulunamadı'),
|
||||
],
|
||||
)]
|
||||
public function index(string $location): AnonymousResourceCollection
|
||||
{
|
||||
$menuLocation = MenuLocation::tryFrom($location);
|
||||
|
||||
if (! $menuLocation) {
|
||||
abort(404, 'Menü konumu bulunamadı.');
|
||||
}
|
||||
|
||||
return MenuResource::collection($this->repository->getByLocation($menuLocation));
|
||||
}
|
||||
}
|
||||
35
app/Http/Controllers/Api/V1/PageController.php
Normal file
35
app/Http/Controllers/Api/V1/PageController.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\PageResource;
|
||||
use App\Repositories\Contracts\PageRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class PageController extends Controller
|
||||
{
|
||||
public function __construct(private PageRepositoryInterface $repository) {}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/pages/{slug}',
|
||||
summary: 'Sayfa detayı',
|
||||
tags: ['Pages'],
|
||||
parameters: [new OA\Parameter(name: 'slug', in: 'path', required: true, schema: new OA\Schema(type: 'string'))],
|
||||
responses: [
|
||||
new OA\Response(response: 200, description: 'Sayfa detayı'),
|
||||
new OA\Response(response: 404, description: 'Sayfa bulunamadı'),
|
||||
],
|
||||
)]
|
||||
public function show(string $slug): JsonResponse
|
||||
{
|
||||
$page = $this->repository->findBySlug($slug);
|
||||
|
||||
if (! $page || ! $page->is_active) {
|
||||
return response()->json(['message' => 'Sayfa bulunamadı.'], 404);
|
||||
}
|
||||
|
||||
return response()->json(new PageResource($page));
|
||||
}
|
||||
}
|
||||
32
app/Http/Controllers/Api/V1/PreviewController.php
Normal file
32
app/Http/Controllers/Api/V1/PreviewController.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class PreviewController extends Controller
|
||||
{
|
||||
#[OA\Get(
|
||||
path: '/api/v1/preview/{token}',
|
||||
summary: 'Önizleme verisini getir (public)',
|
||||
tags: ['Preview'],
|
||||
parameters: [new OA\Parameter(name: 'token', in: 'path', required: true, schema: new OA\Schema(type: 'string'))],
|
||||
responses: [
|
||||
new OA\Response(response: 200, description: 'Önizleme verisi'),
|
||||
new OA\Response(response: 404, description: 'Önizleme bulunamadı veya süresi dolmuş'),
|
||||
],
|
||||
)]
|
||||
public function show(string $token): JsonResponse
|
||||
{
|
||||
$data = Cache::get("preview_{$token}");
|
||||
|
||||
if (! $data) {
|
||||
return response()->json(['message' => 'Önizleme bulunamadı veya süresi dolmuş.'], 404);
|
||||
}
|
||||
|
||||
return response()->json(['data' => $data]);
|
||||
}
|
||||
}
|
||||
72
app/Http/Controllers/Api/V1/ScheduleController.php
Normal file
72
app/Http/Controllers/Api/V1/ScheduleController.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\CourseScheduleResource;
|
||||
use App\Repositories\Contracts\ScheduleRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class ScheduleController extends Controller
|
||||
{
|
||||
public function __construct(private ScheduleRepositoryInterface $repository) {}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/schedules',
|
||||
summary: 'Eğitim takvimini listele',
|
||||
tags: ['Schedules'],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'course_id', in: 'query', required: false, schema: new OA\Schema(type: 'integer')),
|
||||
new OA\Parameter(name: 'per_page', in: 'query', required: false, schema: new OA\Schema(type: 'integer', default: 15)),
|
||||
],
|
||||
responses: [new OA\Response(response: 200, description: 'Takvim listesi')],
|
||||
)]
|
||||
public function index(Request $request): AnonymousResourceCollection
|
||||
{
|
||||
$schedules = $this->repository->paginate(
|
||||
$request->only(['course_id']),
|
||||
$request->integer('per_page', 15),
|
||||
);
|
||||
|
||||
return CourseScheduleResource::collection($schedules);
|
||||
}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/schedules/upcoming',
|
||||
summary: 'Yaklaşan eğitimleri listele',
|
||||
tags: ['Schedules'],
|
||||
responses: [new OA\Response(response: 200, description: 'Yaklaşan eğitimler')],
|
||||
)]
|
||||
public function upcoming(): AnonymousResourceCollection
|
||||
{
|
||||
$schedules = $this->repository->upcoming(20);
|
||||
|
||||
return CourseScheduleResource::collection($schedules);
|
||||
}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/schedules/{id}',
|
||||
summary: 'Takvim detayı',
|
||||
tags: ['Schedules'],
|
||||
parameters: [new OA\Parameter(name: 'id', in: 'path', required: true, schema: new OA\Schema(type: 'integer'))],
|
||||
responses: [
|
||||
new OA\Response(response: 200, description: 'Takvim detayı'),
|
||||
new OA\Response(response: 404, description: 'Takvim bulunamadı'),
|
||||
],
|
||||
)]
|
||||
public function show(int $id): JsonResponse
|
||||
{
|
||||
$schedule = $this->repository->findById($id);
|
||||
|
||||
if (! $schedule) {
|
||||
return response()->json(['message' => 'Takvim bulunamadı.'], 404);
|
||||
}
|
||||
|
||||
$schedule->load('course.category');
|
||||
|
||||
return response()->json(new CourseScheduleResource($schedule));
|
||||
}
|
||||
}
|
||||
52
app/Http/Controllers/Api/V1/SettingController.php
Normal file
52
app/Http/Controllers/Api/V1/SettingController.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Enums\SettingGroup;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Repositories\Contracts\SettingRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class SettingController extends Controller
|
||||
{
|
||||
public function __construct(private SettingRepositoryInterface $repository) {}
|
||||
|
||||
/**
|
||||
* Return all public settings grouped by group name.
|
||||
*/
|
||||
#[OA\Get(
|
||||
path: '/api/v1/settings',
|
||||
summary: 'Tüm site ayarlarını getir (group bazlı nested)',
|
||||
tags: ['Settings'],
|
||||
responses: [new OA\Response(response: 200, description: 'Ayarlar listesi')],
|
||||
)]
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
return response()->json($this->repository->publicGrouped());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return public settings for a single group.
|
||||
*/
|
||||
#[OA\Get(
|
||||
path: '/api/v1/settings/{group}',
|
||||
summary: 'Tek grup ayarlarını getir',
|
||||
tags: ['Settings'],
|
||||
parameters: [new OA\Parameter(name: 'group', in: 'path', required: true, schema: new OA\Schema(type: 'string'))],
|
||||
responses: [
|
||||
new OA\Response(response: 200, description: 'Grup ayarları'),
|
||||
new OA\Response(response: 404, description: 'Grup bulunamadı'),
|
||||
],
|
||||
)]
|
||||
public function show(string $group): JsonResponse
|
||||
{
|
||||
$settingGroup = SettingGroup::tryFrom($group);
|
||||
|
||||
if (! $settingGroup) {
|
||||
abort(404, 'Ayar grubu bulunamadı.');
|
||||
}
|
||||
|
||||
return response()->json($this->repository->publicByGroup($settingGroup));
|
||||
}
|
||||
}
|
||||
54
app/Http/Controllers/Api/V1/SitemapController.php
Normal file
54
app/Http/Controllers/Api/V1/SitemapController.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Announcement;
|
||||
use App\Models\Course;
|
||||
use App\Models\Page;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class SitemapController extends Controller
|
||||
{
|
||||
#[OA\Get(
|
||||
path: '/api/v1/sitemap-data',
|
||||
summary: 'SEO sitemap verisi',
|
||||
description: 'Yayındaki tüm kurs, duyuru ve sayfa slug+updated_at bilgilerini döner.',
|
||||
tags: ['Sitemap'],
|
||||
responses: [new OA\Response(response: 200, description: 'Sitemap verisi')],
|
||||
)]
|
||||
public function index(): JsonResponse
|
||||
{
|
||||
$courses = Course::query()
|
||||
->select('slug', 'updated_at')
|
||||
->get()
|
||||
->map(fn (Course $c) => [
|
||||
'loc' => '/courses/'.$c->slug,
|
||||
'lastmod' => $c->updated_at?->toISOString(),
|
||||
]);
|
||||
|
||||
$announcements = Announcement::query()
|
||||
->select('slug', 'updated_at')
|
||||
->get()
|
||||
->map(fn (Announcement $a) => [
|
||||
'loc' => '/announcements/'.$a->slug,
|
||||
'lastmod' => $a->updated_at?->toISOString(),
|
||||
]);
|
||||
|
||||
$pages = Page::query()
|
||||
->where('is_active', true)
|
||||
->select('slug', 'updated_at')
|
||||
->get()
|
||||
->map(fn (Page $p) => [
|
||||
'loc' => '/'.$p->slug,
|
||||
'lastmod' => $p->updated_at?->toISOString(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'courses' => $courses,
|
||||
'announcements' => $announcements,
|
||||
'pages' => $pages,
|
||||
]);
|
||||
}
|
||||
}
|
||||
28
app/Http/Controllers/Api/V1/StoryController.php
Normal file
28
app/Http/Controllers/Api/V1/StoryController.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\StoryResource;
|
||||
use App\Models\Story;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class StoryController extends Controller
|
||||
{
|
||||
#[OA\Get(
|
||||
path: '/api/v1/stories',
|
||||
summary: 'Aktif hikayeleri listele',
|
||||
tags: ['Stories'],
|
||||
responses: [new OA\Response(response: 200, description: 'Hikaye listesi')],
|
||||
)]
|
||||
public function index(): AnonymousResourceCollection
|
||||
{
|
||||
$stories = Story::query()
|
||||
->where('is_active', true)
|
||||
->orderBy('order_index')
|
||||
->get();
|
||||
|
||||
return StoryResource::collection($stories);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user