Hintergründe zum EventInvitePage Layout Customizer hinzugefügt. Badge und CTA entfernt, Textfelder zu Textareas gemacht. Geschenkgutscheine verbessert, E-Mail-Versand ergänzt + Resend + Confirmationseite mit Code-Copy und Link zur Package-Seite, die den Code als URL-Parameter enthält.

This commit is contained in:
Codex Agent
2025-12-08 16:20:04 +01:00
parent 046e2fe3ec
commit 4784c23e70
35 changed files with 1503 additions and 136 deletions

View File

@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Api\Marketing;
use App\Http\Controllers\Controller;
use App\Models\GiftVoucher;
use App\Services\GiftVouchers\GiftVoucherCheckoutService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -41,4 +42,44 @@ class GiftVoucherCheckoutController extends Controller
return response()->json($checkout);
}
public function show(Request $request): JsonResponse
{
$data = $request->validate([
'checkout_id' => ['nullable', 'string', 'required_without_all:transaction_id,code'],
'transaction_id' => ['nullable', 'string', 'required_without_all:checkout_id,code'],
'code' => ['nullable', 'string', 'required_without_all:checkout_id,transaction_id'],
]);
$voucherQuery = GiftVoucher::query();
if (! empty($data['checkout_id'])) {
$voucherQuery->where('paddle_checkout_id', $data['checkout_id']);
}
if (! empty($data['transaction_id'])) {
$voucherQuery->orWhere('paddle_transaction_id', $data['transaction_id']);
}
if (! empty($data['code'])) {
$voucherQuery->orWhere('code', strtoupper($data['code']));
}
$voucher = $voucherQuery->latest()->firstOrFail();
return response()->json([
'data' => [
'code' => $voucher->code,
'amount' => (float) $voucher->amount,
'currency' => $voucher->currency,
'expires_at' => optional($voucher->expires_at)->toIso8601String(),
'recipient_name' => $voucher->recipient_name,
'recipient_email' => $voucher->recipient_email,
'purchaser_email' => $voucher->purchaser_email,
'status' => $voucher->status,
'redeemed_at' => optional($voucher->redeemed_at)->toIso8601String(),
'refunded_at' => optional($voucher->refunded_at)->toIso8601String(),
],
]);
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace App\Http\Controllers\Api\Marketing;
use App\Http\Controllers\Controller;
use App\Models\GiftVoucher;
use App\Services\GiftVouchers\GiftVoucherService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
class GiftVoucherResendController extends Controller
{
public function __construct(private readonly GiftVoucherService $vouchers) {}
public function __invoke(Request $request): JsonResponse
{
$data = $request->validate([
'code' => ['required', 'string'],
'recipient_only' => ['sometimes', 'boolean'],
'locale' => ['nullable', 'string'],
'schedule_at' => ['nullable', 'date'],
]);
$voucher = GiftVoucher::query()
->where('code', strtoupper($data['code']))
->first();
if (! $voucher) {
throw ValidationException::withMessages([
'code' => __('Voucher not found.'),
]);
}
if (! empty($data['schedule_at'])) {
$this->vouchers->scheduleRecipientDelivery($voucher, now()->parse($data['schedule_at']), $data['locale'] ?? app()->getLocale());
} else {
$this->vouchers->resend($voucher, $data['locale'] ?? app()->getLocale(), $data['recipient_only'] ?? null);
}
return response()->json([
'status' => 'ok',
]);
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\Marketing;
use App\Http\Controllers\Controller;
use App\Models\GiftVoucher;
use Illuminate\Http\Request;
class GiftVoucherPrintController extends Controller
{
public function __invoke(Request $request, GiftVoucher $voucher)
{
if ($voucher->code !== strtoupper($request->query('code'))) {
abort(404);
}
return view('marketing.gift-voucher-print', [
'voucher' => $voucher,
]);
}
}