247 lines
7.9 KiB
PHP
247 lines
7.9 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Event;
|
|
use App\Models\Location;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Http\Request;
|
|
use OpenApi\Attributes as OA;
|
|
|
|
#[OA\Info(
|
|
title: "Veranstaltungen API",
|
|
version: "1.0.0",
|
|
description: "API für Event Management mit Location und Occurrence Management",
|
|
)]
|
|
class EventController extends Controller
|
|
{
|
|
#[OA\Get(
|
|
path: "/api/events",
|
|
summary: "Alle Events auflisten",
|
|
description: "Listet alle veröffentlichten Events mit optionalen Filtern auf",
|
|
tags: ["Events"],
|
|
parameters: [
|
|
new OA\Parameter(
|
|
name: "from",
|
|
in: "query",
|
|
description: "Startdatum (Format: YYYY-MM-DD)",
|
|
schema: new OA\Schema(type: "string", format: "date")
|
|
),
|
|
new OA\Parameter(
|
|
name: "to",
|
|
in: "query",
|
|
description: "Enddatum (Format: YYYY-MM-DD)",
|
|
schema: new OA\Schema(type: "string", format: "date")
|
|
),
|
|
new OA\Parameter(
|
|
name: "category",
|
|
in: "query",
|
|
description: "Filter nach Kategorie",
|
|
schema: new OA\Schema(type: "string")
|
|
),
|
|
new OA\Parameter(
|
|
name: "location",
|
|
in: "query",
|
|
description: "Filter nach Ort oder Stadt",
|
|
schema: new OA\Schema(type: "string")
|
|
),
|
|
new OA\Parameter(
|
|
name: "limit",
|
|
in: "query",
|
|
description: "Anzahl der Events pro Seite (1-100, Standard: 20)",
|
|
schema: new OA\Schema(type: "integer", default: 20)
|
|
),
|
|
],
|
|
responses: [
|
|
new OA\Response(
|
|
response: 200,
|
|
description: "Liste der Events",
|
|
content: new OA\JsonContent(type: "object")
|
|
),
|
|
]
|
|
)]
|
|
public function index(Request $request)
|
|
{
|
|
$validated = $request->validate([
|
|
'from' => 'nullable|date',
|
|
'to' => 'nullable|date',
|
|
'category' => 'nullable|string',
|
|
'location' => 'nullable|string',
|
|
'limit' => 'nullable|integer|min:1|max:100',
|
|
]);
|
|
|
|
$from = ($validated['from'] ?? null)
|
|
? Carbon::parse($validated['from'])->startOfDay()
|
|
: now()->startOfDay();
|
|
|
|
$to = ($validated['to'] ?? null)
|
|
? Carbon::parse($validated['to'])->endOfDay()
|
|
: now()->addMonths(3)->endOfDay();
|
|
|
|
$limit = $validated['limit'] ?? 20;
|
|
|
|
$query = Event::published()
|
|
->with(['source', 'location', 'occurrences' => function ($q) use ($from, $to) {
|
|
$q->whereBetween('start_datetime', [$from, $to])
|
|
->where('status', 'scheduled')
|
|
->orderBy('start_datetime');
|
|
}])
|
|
->whereHas('occurrences', function ($q) use ($from, $to) {
|
|
$q->whereBetween('start_datetime', [$from, $to])
|
|
->where('status', 'scheduled');
|
|
})
|
|
->orderBy('title');
|
|
|
|
// Filter nach Kategorie
|
|
if (!empty($validated['category'])) {
|
|
$query->byCategory($validated['category']);
|
|
}
|
|
|
|
// Filter nach Ort
|
|
if (!empty($validated['location'])) {
|
|
$query->byLocation($validated['location']);
|
|
}
|
|
|
|
$events = $query->paginate($limit);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => $events->items(),
|
|
'pagination' => [
|
|
'total' => $events->total(),
|
|
'per_page' => $events->perPage(),
|
|
'current_page' => $events->currentPage(),
|
|
'last_page' => $events->lastPage(),
|
|
]
|
|
]);
|
|
}
|
|
|
|
#[OA\Get(
|
|
path: "/api/events/{event}",
|
|
summary: "Einzelnes Event anzeigen",
|
|
description: "Zeigt ein einzelnes veröffentlichtes Event mit allen seinen Terminen",
|
|
tags: ["Events"],
|
|
parameters: [
|
|
new OA\Parameter(
|
|
name: "event",
|
|
in: "path",
|
|
required: true,
|
|
description: "Event ID",
|
|
schema: new OA\Schema(type: "integer")
|
|
),
|
|
],
|
|
responses: [
|
|
new OA\Response(
|
|
response: 200,
|
|
description: "Event Details",
|
|
content: new OA\JsonContent(type: "object")
|
|
),
|
|
new OA\Response(
|
|
response: 404,
|
|
description: "Event nicht gefunden"
|
|
),
|
|
]
|
|
)]
|
|
public function show(Event $event)
|
|
{
|
|
// Nur veröffentlichte Events anzeigen
|
|
if ($event->status !== 'published') {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Event nicht gefunden.',
|
|
], 404);
|
|
}
|
|
|
|
$event->load(['source', 'occurrences' => function ($query) {
|
|
$query->where('status', 'scheduled')
|
|
->orderBy('start_datetime');
|
|
}]);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => $event,
|
|
]);
|
|
}
|
|
|
|
#[OA\Get(
|
|
path: "/api/events/categories/list",
|
|
summary: "Verfügbare Kategorien",
|
|
description: "Listet alle verfügbaren Event-Kategorien auf",
|
|
tags: ["Utilities"],
|
|
responses: [
|
|
new OA\Response(
|
|
response: 200,
|
|
description: "Liste der Kategorien",
|
|
content: new OA\JsonContent(
|
|
type: "object",
|
|
properties: [
|
|
"success" => new OA\Property(type: "boolean"),
|
|
"data" => new OA\Property(type: "array", items: new OA\Items(type: "string"))
|
|
]
|
|
)
|
|
),
|
|
]
|
|
)]
|
|
public function categories()
|
|
{
|
|
$categories = Event::published()
|
|
->distinct()
|
|
->pluck('category')
|
|
->filter()
|
|
->sort()
|
|
->values();
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => $categories,
|
|
]);
|
|
}
|
|
|
|
#[OA\Get(
|
|
path: "/api/events/locations/list",
|
|
summary: "Verfügbare Veranstaltungsorte",
|
|
description: "Listet alle verfügbaren Veranstaltungsorte mit vollständigen Adressinformationen auf",
|
|
tags: ["Utilities"],
|
|
responses: [
|
|
new OA\Response(
|
|
response: 200,
|
|
description: "Liste der Veranstaltungsorte",
|
|
content: new OA\JsonContent(type: "object")
|
|
),
|
|
]
|
|
)]
|
|
public function locations()
|
|
{
|
|
$locations = Location::orderBy('city')
|
|
->orderBy('name')
|
|
->get()
|
|
->map(function ($location) {
|
|
return [
|
|
'id' => $location->id,
|
|
'name' => $location->name,
|
|
'address' => [
|
|
'street' => $location->street,
|
|
'house_number' => $location->house_number,
|
|
'postal_code' => $location->postal_code,
|
|
'city' => $location->city,
|
|
'state' => $location->state,
|
|
'country' => $location->country,
|
|
'full_address' => $location->full_address,
|
|
'short_address' => $location->short_address,
|
|
],
|
|
'contact' => [
|
|
'phone' => $location->phone,
|
|
'email' => $location->email,
|
|
'website' => $location->website,
|
|
],
|
|
'event_count' => $location->events()->published()->count(),
|
|
];
|
|
});
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => $locations,
|
|
]);
|
|
}
|
|
}
|