Files
fotospiel-app/app/Http/Controllers/Api/Tenant/EventController.php

351 lines
11 KiB
PHP

<?php
namespace App\Http\Controllers\Api\Tenant;
use App\Http\Controllers\Controller;
use App\Http\Requests\Tenant\EventStoreRequest;
use App\Http\Resources\Tenant\EventResource;
use App\Models\Event;
use App\Models\Tenant;
use App\Models\Photo;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
class EventController extends Controller
{
public function index(Request $request): AnonymousResourceCollection
{
$tenantId = $request->attributes->get('tenant_id');
if (! $tenantId) {
throw ValidationException::withMessages([
'tenant_id' => 'Tenant ID not found in request context.',
]);
}
$query = Event::where('tenant_id', $tenantId)
->with(['eventType', 'photos'])
->orderBy('created_at', 'desc');
if ($request->has('status')) {
$query->where('status', $request->status);
}
if ($request->has('type_id')) {
$query->where('event_type_id', $request->type_id);
}
$events = $query->paginate($request->get('per_page', 15));
return EventResource::collection($events);
}
public function store(EventStoreRequest $request): JsonResponse
{
$tenant = $request->attributes->get('tenant');
if (! $tenant instanceof Tenant) {
$tenantId = $request->attributes->get('tenant_id');
$tenant = Tenant::findOrFail($tenantId);
}
// Package check is now handled by middleware
$validated = $request->validated();
$tenantId = $tenant->id;
$packageId = $validated['package_id'] ?? 1; // Default to Free package ID 1
unset($validated['package_id']);
$eventData = array_merge($validated, [
'tenant_id' => $tenantId,
'status' => $validated['status'] ?? 'draft',
'slug' => $this->generateUniqueSlug($validated['name'], $tenantId),
]);
if (isset($eventData['event_date'])) {
$eventData['date'] = $eventData['event_date'];
unset($eventData['event_date']);
}
$settings = $eventData['settings'] ?? [];
foreach (['public_url', 'custom_domain', 'theme_color'] as $key) {
if (array_key_exists($key, $eventData)) {
$settings[$key] = $eventData[$key];
unset($eventData[$key]);
}
}
if (isset($eventData['features'])) {
$settings['features'] = $eventData['features'];
unset($eventData['features']);
}
if ($settings === [] || $settings === null) {
unset($eventData['settings']);
} else {
$eventData['settings'] = $settings;
}
foreach (['password', 'password_confirmation', 'password_protected', 'logo_image', 'cover_image'] as $unused) {
unset($eventData[$unused]);
}
$allowed = [
'tenant_id',
'name',
'description',
'date',
'slug',
'location',
'max_participants',
'settings',
'event_type_id',
'is_active',
'join_link_enabled',
'photo_upload_enabled',
'task_checklist_enabled',
'default_locale',
'status',
];
$eventData = Arr::only($eventData, $allowed);
$event = DB::transaction(function () use ($tenant, $eventData, $packageId) {
$event = Event::create($eventData);
// Create EventPackage and PackagePurchase for Free package
$package = \App\Models\Package::findOrFail($packageId);
$eventPackage = \App\Models\EventPackage::create([
'event_id' => $event->id,
'package_id' => $packageId,
'purchased_price' => $package->price,
'purchased_at' => now(),
]);
\App\Models\PackagePurchase::create([
'tenant_id' => $tenant->id,
'event_id' => $event->id,
'package_id' => $packageId,
'provider_id' => 'free',
'price' => $package->price,
'type' => 'endcustomer_event',
'metadata' => json_encode(['note' => 'Free package assigned on event creation']),
]);
if ($tenant->activeResellerPackage) {
$tenant->incrementUsedEvents();
}
return $event;
});
$tenant->refresh();
$event->load(['eventType', 'tenant', 'eventPackage.package']);
return response()->json([
'message' => 'Event created successfully',
'data' => new EventResource($event),
'package' => $event->eventPackage ? $event->eventPackage->package->name : 'None',
'remaining_events' => $tenant->activeResellerPackage ? $tenant->activeResellerPackage->remaining_events : 0,
], 201);
}
public function show(Request $request, Event $event): JsonResponse
{
$tenantId = $request->attributes->get('tenant_id');
if ($event->tenant_id !== $tenantId) {
return response()->json(['error' => 'Event not found'], 404);
}
$event->load([
'eventType',
'photos' => fn ($query) => $query->with('likes')->latest(),
'tasks',
'tenant' => fn ($query) => $query->select('id', 'name', 'event_credits_balance'),
]);
return response()->json([
'data' => new EventResource($event),
]);
}
public function update(EventStoreRequest $request, Event $event): JsonResponse
{
$tenantId = $request->attributes->get('tenant_id');
if ($event->tenant_id !== $tenantId) {
return response()->json(['error' => 'Event not found'], 404);
}
$validated = $request->validated();
if (isset($validated['event_date'])) {
$validated['date'] = $validated['event_date'];
unset($validated['event_date']);
}
if ($validated['name'] !== $event->name) {
$validated['slug'] = $this->generateUniqueSlug($validated['name'], $tenantId, $event->id);
}
foreach (['password', 'password_confirmation', 'password_protected'] as $unused) {
unset($validated[$unused]);
}
$event->update($validated);
$event->load(['eventType', 'tenant']);
return response()->json([
'message' => 'Event updated successfully',
'data' => new EventResource($event),
]);
}
public function destroy(Request $request, Event $event): JsonResponse
{
$tenantId = $request->attributes->get('tenant_id');
if ($event->tenant_id !== $tenantId) {
return response()->json(['error' => 'Event not found'], 404);
}
$event->delete();
return response()->json([
'message' => 'Event deleted successfully',
]);
}
public function stats(Request $request, Event $event): JsonResponse
{
$tenantId = $request->attributes->get('tenant_id');
if ($event->tenant_id !== $tenantId) {
return response()->json(['error' => 'Event not found'], 404);
}
$totalPhotos = Photo::where('event_id', $event->id)->count();
$featuredPhotos = Photo::where('event_id', $event->id)->where('is_featured', true)->count();
$likes = Photo::where('event_id', $event->id)->sum('likes_count');
$recentUploads = Photo::where('event_id', $event->id)
->where('created_at', '>=', now()->subDays(7))
->count();
return response()->json([
'total' => $totalPhotos,
'featured' => $featuredPhotos,
'likes' => (int) $likes,
'recent_uploads' => $recentUploads,
'status' => $event->status,
'is_active' => (bool) $event->is_active,
]);
}
public function toggle(Request $request, Event $event): JsonResponse
{
$tenantId = $request->attributes->get('tenant_id');
if ($event->tenant_id !== $tenantId) {
return response()->json(['error' => 'Event not found'], 404);
}
$activate = ! (bool) $event->is_active;
$event->is_active = $activate;
if ($activate) {
$event->status = 'published';
} elseif ($event->status === 'published') {
$event->status = 'draft';
}
$event->save();
$event->refresh()->load(['eventType', 'tenant']);
return response()->json([
'message' => $activate ? 'Event activated' : 'Event deactivated',
'data' => new EventResource($event),
'is_active' => (bool) $event->is_active,
]);
}
public function createInvite(Request $request, Event $event): JsonResponse
{
$tenantId = $request->attributes->get('tenant_id');
if ($event->tenant_id !== $tenantId) {
return response()->json(['error' => 'Event not found'], 404);
}
$token = (string) Str::uuid();
$link = url("/e/{$event->slug}?invite={$token}");
return response()->json([
'link' => $link,
'token' => $token,
]);
}
public function bulkUpdateStatus(Request $request): JsonResponse
{
$tenantId = $request->attributes->get('tenant_id');
$validated = $request->validate([
'event_ids' => 'required|array',
'event_ids.*' => 'exists:events,id',
'status' => 'required|in:draft,published,archived',
]);
$updatedCount = Event::whereIn('id', $validated['event_ids'])
->where('tenant_id', $tenantId)
->update(['status' => $validated['status']]);
return response()->json([
'message' => "{$updatedCount} events updated successfully",
'updated_count' => $updatedCount,
]);
}
private function generateUniqueSlug(string $name, int $tenantId, ?int $excludeId = null): string
{
$slug = Str::slug($name);
$originalSlug = $slug;
$counter = 1;
while (Event::where('slug', $slug)
->where('tenant_id', $tenantId)
->when($excludeId, fn ($query) => $query->where('id', '!=', $excludeId))
->exists()) {
$slug = $originalSlug . '-' . $counter;
$counter++;
}
return $slug;
}
public function search(Request $request): AnonymousResourceCollection
{
$tenantId = $request->attributes->get('tenant_id');
$query = $request->get('q', '');
if (strlen($query) < 2) {
return EventResource::collection(collect([]));
}
$events = Event::where('tenant_id', $tenantId)
->where(function ($q) use ($query) {
$q->where('name', 'like', "%{$query}%")
->orWhere('description', 'like', "%{$query}%");
})
->with('eventType')
->limit(10)
->get();
return EventResource::collection($events);
}
}