415 lines
18 KiB
PHP
415 lines
18 KiB
PHP
<?php
|
|
|
|
use App\Http\Controllers\Auth\AuthenticatedSessionController;
|
|
use App\Http\Controllers\Auth\RegisteredUserController;
|
|
use App\Http\Controllers\CheckoutController;
|
|
use App\Http\Controllers\CheckoutFacebookController;
|
|
use App\Http\Controllers\CheckoutGoogleController;
|
|
use App\Http\Controllers\DashboardController;
|
|
use App\Http\Controllers\LegalPageController;
|
|
use App\Http\Controllers\LocaleController;
|
|
use App\Http\Controllers\Marketing\GiftVoucherPrintController;
|
|
use App\Http\Controllers\MarketingController;
|
|
use App\Http\Controllers\PaddleCheckoutController;
|
|
use App\Http\Controllers\PaddleWebhookController;
|
|
use App\Http\Controllers\ProfileAccountController;
|
|
use App\Http\Controllers\ProfileController;
|
|
use App\Http\Controllers\ProfileDataExportController;
|
|
use App\Http\Controllers\SuperAdmin\DataExportController as SuperAdminDataExportController;
|
|
use App\Http\Controllers\Tenant\EventPhotoArchiveController;
|
|
use App\Http\Controllers\TenantAdminAuthController;
|
|
use App\Http\Controllers\TenantAdminFacebookController;
|
|
use App\Http\Controllers\TenantAdminGoogleController;
|
|
use App\Http\Controllers\WithdrawalController;
|
|
use App\Models\Package;
|
|
use App\Support\CheckoutRoutes;
|
|
use App\Support\LocaleConfig;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Route;
|
|
use Inertia\Inertia;
|
|
use Spatie\Honeypot\ProtectAgainstSpam;
|
|
|
|
require __DIR__.'/auth.php';
|
|
require __DIR__.'/settings.php';
|
|
|
|
$supportedLocales = LocaleConfig::normalized();
|
|
$localePattern = LocaleConfig::routePattern();
|
|
|
|
$rewritePath = static function (string $path, string $locale): string {
|
|
$normalized = '/'.ltrim($path, '/');
|
|
if ($normalized === '//') {
|
|
$normalized = '/';
|
|
}
|
|
|
|
$map = [
|
|
'/kontakt' => ['en' => '/contact'],
|
|
'/contact' => ['de' => '/kontakt'],
|
|
'/so-funktionierts' => ['en' => '/how-it-works'],
|
|
'/how-it-works' => ['de' => '/so-funktionierts'],
|
|
'/anlaesse' => ['en' => '/occasions'],
|
|
'/anlaesse/hochzeit' => ['en' => '/occasions/wedding'],
|
|
'/anlaesse/geburtstag' => ['en' => '/occasions/birthday'],
|
|
'/anlaesse/firmenevent' => ['en' => '/occasions/corporate-event'],
|
|
'/anlaesse/konfirmation' => ['en' => '/occasions/confirmation'],
|
|
'/occasions/wedding' => ['de' => '/anlaesse/hochzeit'],
|
|
'/occasions/birthday' => ['de' => '/anlaesse/geburtstag'],
|
|
'/occasions/corporate-event' => ['de' => '/anlaesse/firmenevent'],
|
|
'/occasions/confirmation' => ['de' => '/anlaesse/konfirmation'],
|
|
];
|
|
|
|
$rewrites = $map[$normalized] ?? [];
|
|
|
|
return $rewrites[$locale] ?? $normalized;
|
|
};
|
|
|
|
$determinePreferredLocale = static function (Request $request) use ($supportedLocales): string {
|
|
$sessionLocale = $request->session()->get('preferred_locale');
|
|
if ($sessionLocale && in_array($sessionLocale, $supportedLocales, true)) {
|
|
return $sessionLocale;
|
|
}
|
|
|
|
$headerLocale = $request->getPreferredLanguage($supportedLocales);
|
|
if ($headerLocale && in_array($headerLocale, $supportedLocales, true)) {
|
|
return $headerLocale;
|
|
}
|
|
|
|
return $supportedLocales[0] ?? 'de';
|
|
};
|
|
|
|
Route::prefix('{locale}')
|
|
->where(['locale' => $localePattern])
|
|
->group(function () {
|
|
Route::get('/', [MarketingController::class, 'index'])->name('marketing.home');
|
|
|
|
Route::middleware('guest')->group(function () {
|
|
Route::get('/login', [AuthenticatedSessionController::class, 'create']);
|
|
Route::post('/login', [AuthenticatedSessionController::class, 'store']);
|
|
Route::get('/register', [RegisteredUserController::class, 'create']);
|
|
Route::post('/register', [RegisteredUserController::class, 'store']);
|
|
});
|
|
|
|
Route::get('/contact', [MarketingController::class, 'contactView'])
|
|
->name('marketing.contact');
|
|
Route::post('/contact', [MarketingController::class, 'contact'])
|
|
->middleware(['throttle:contact-form', ProtectAgainstSpam::class])
|
|
->name('marketing.contact.submit');
|
|
|
|
Route::get('/kontakt', [MarketingController::class, 'contactView'])
|
|
->name('kontakt');
|
|
Route::post('/kontakt', [MarketingController::class, 'contact'])
|
|
->middleware(['throttle:contact-form', ProtectAgainstSpam::class])
|
|
->name('kontakt.submit');
|
|
|
|
Route::get('/blog', [MarketingController::class, 'blogIndex'])->name('blog');
|
|
Route::get('/blog/{slug}', [MarketingController::class, 'blogShow'])->name('blog.show');
|
|
|
|
Route::get('/packages', [MarketingController::class, 'packagesIndex'])->name('packages');
|
|
|
|
Route::get('/anlaesse/{type}', [MarketingController::class, 'occasionsType'])->name('anlaesse.type');
|
|
Route::get('/occasions/{type}', [MarketingController::class, 'occasionsType'])
|
|
->name('occasions.type');
|
|
|
|
Route::get('/so-funktionierts', [MarketingController::class, 'howItWorks'])
|
|
->where('locale', 'de');
|
|
Route::get('/how-it-works', [MarketingController::class, 'howItWorks'])
|
|
->where('locale', 'en')
|
|
->name('marketing.how-it-works');
|
|
|
|
Route::get('/demo', [MarketingController::class, 'demo'])->name('demo');
|
|
Route::get('/success/{packageId?}', [MarketingController::class, 'success'])->name('marketing.success');
|
|
Route::get('/gutschein', [MarketingController::class, 'giftVouchers'])->name('marketing.gift-voucher.de');
|
|
Route::get('/gift-card', [MarketingController::class, 'giftVouchers'])->name('marketing.gift-voucher.en');
|
|
Route::get('/gift-vouchers/{voucher}/print', GiftVoucherPrintController::class)
|
|
->middleware('signed')
|
|
->name('marketing.gift-vouchers.print');
|
|
Route::middleware('auth')->group(function () {
|
|
Route::get('/voucher-status', fn () => Inertia::render('marketing/GiftVoucherStatus'))
|
|
->name('marketing.gift-voucher.status');
|
|
});
|
|
|
|
Route::get('/impressum', [LegalPageController::class, 'show'])
|
|
->defaults('slug', 'impressum')
|
|
->name('impressum');
|
|
Route::get('/imprint', [LegalPageController::class, 'show'])
|
|
->where('locale', 'en')
|
|
->defaults('slug', 'impressum')
|
|
->name('imprint');
|
|
Route::get('/datenschutz', [LegalPageController::class, 'show'])
|
|
->defaults('slug', 'datenschutz')
|
|
->name('datenschutz');
|
|
Route::get('/privacy', [LegalPageController::class, 'show'])
|
|
->where('locale', 'en')
|
|
->defaults('slug', 'datenschutz')
|
|
->name('privacy');
|
|
Route::get('/agb', [LegalPageController::class, 'show'])
|
|
->defaults('slug', 'agb')
|
|
->name('agb');
|
|
Route::get('/terms', [LegalPageController::class, 'show'])
|
|
->where('locale', 'en')
|
|
->defaults('slug', 'agb')
|
|
->name('terms');
|
|
Route::get('/widerrufsbelehrung', [LegalPageController::class, 'show'])
|
|
->defaults('slug', 'widerrufsbelehrung')
|
|
->name('widerrufsbelehrung');
|
|
Route::get('/withdrawal', [LegalPageController::class, 'show'])
|
|
->where('locale', 'en')
|
|
->defaults('slug', 'widerrufsbelehrung')
|
|
->name('withdrawal');
|
|
|
|
Route::get('/buy/{packageId}', [MarketingController::class, 'buyPackages'])
|
|
->name('buy.packages')
|
|
->defaults('locale', config('app.locale', 'de'));
|
|
|
|
if (config('checkout.enabled')) {
|
|
Route::get('/{checkoutSlug}/{package}', [CheckoutController::class, 'show'])
|
|
->where('checkoutSlug', 'bestellen|checkout')
|
|
->name('checkout.show');
|
|
} else {
|
|
Route::get('/{checkoutSlug}/{package}', function (string $locale, string $checkoutSlug, string $package) {
|
|
$resolvedPackage = Package::query()->find($package);
|
|
|
|
if (! $resolvedPackage) {
|
|
return redirect()
|
|
->route('packages', ['locale' => $locale])
|
|
->with('error', __('marketing.packages.package_not_found'));
|
|
}
|
|
|
|
return redirect()->route('packages', [
|
|
'locale' => $locale,
|
|
'highlight' => $resolvedPackage->slug,
|
|
]);
|
|
})
|
|
->where('checkoutSlug', 'bestellen|checkout')
|
|
->name('checkout.show');
|
|
}
|
|
|
|
Route::middleware('auth')->group(function () {
|
|
Route::get('/profile', [ProfileController::class, 'index'])
|
|
->name('marketing.profile.index');
|
|
|
|
Route::get('/widerruf', [WithdrawalController::class, 'show'])
|
|
->where('locale', 'de')
|
|
->name('marketing.withdrawal.confirm.de');
|
|
Route::post('/widerruf', [WithdrawalController::class, 'confirm'])
|
|
->where('locale', 'de')
|
|
->name('marketing.withdrawal.confirm.submit.de');
|
|
Route::get('/withdrawal/confirm', [WithdrawalController::class, 'show'])
|
|
->where('locale', 'en')
|
|
->name('marketing.withdrawal.confirm.en');
|
|
Route::post('/withdrawal/confirm', [WithdrawalController::class, 'confirm'])
|
|
->where('locale', 'en')
|
|
->name('marketing.withdrawal.confirm.submit.en');
|
|
});
|
|
|
|
Route::fallback(function () {
|
|
return Inertia::render('marketing/NotFound', [
|
|
'requestedPath' => request()->path(),
|
|
])->toResponse(request())->setStatusCode(404);
|
|
});
|
|
});
|
|
|
|
Route::get('/', function (Request $request) use ($determinePreferredLocale) {
|
|
$locale = $determinePreferredLocale($request);
|
|
|
|
return redirect("/{$locale}", 302);
|
|
})->name('home');
|
|
|
|
Route::get('/contact', function (Request $request) use ($determinePreferredLocale, $rewritePath) {
|
|
$locale = $determinePreferredLocale($request);
|
|
$path = $rewritePath('/contact', $locale);
|
|
|
|
return redirect("/{$locale}".($path === '/' ? '' : $path), 301);
|
|
});
|
|
|
|
Route::get('/kontakt', function (Request $request) use ($determinePreferredLocale, $rewritePath) {
|
|
$locale = $determinePreferredLocale($request);
|
|
$path = $rewritePath('/kontakt', $locale);
|
|
|
|
return redirect("/{$locale}".($path === '/' ? '' : $path), 301);
|
|
});
|
|
|
|
Route::get('/so-funktionierts', function (Request $request) use ($determinePreferredLocale, $rewritePath) {
|
|
$locale = $determinePreferredLocale($request);
|
|
$path = $rewritePath('/so-funktionierts', $locale);
|
|
|
|
return redirect("/{$locale}{$path}", 301);
|
|
});
|
|
|
|
Route::get('/how-it-works', function (Request $request) use ($determinePreferredLocale, $rewritePath) {
|
|
$locale = $determinePreferredLocale($request);
|
|
$path = $rewritePath('/how-it-works', $locale);
|
|
|
|
return redirect("/{$locale}{$path}", 301);
|
|
});
|
|
|
|
Route::get('/blog', function (Request $request) use ($determinePreferredLocale) {
|
|
$locale = $determinePreferredLocale($request);
|
|
|
|
return redirect("/{$locale}/blog", 301);
|
|
});
|
|
|
|
Route::get('/blog/{slug}', function (Request $request, string $slug) use ($determinePreferredLocale) {
|
|
$locale = $determinePreferredLocale($request);
|
|
|
|
return redirect("/{$locale}/blog/{$slug}", 301);
|
|
});
|
|
|
|
Route::get('/packages', function (Request $request) use ($determinePreferredLocale) {
|
|
$locale = $determinePreferredLocale($request);
|
|
|
|
return redirect("/{$locale}/packages", 301);
|
|
});
|
|
|
|
Route::get('/anlaesse/{type}', function (Request $request, string $type) use ($determinePreferredLocale, $rewritePath) {
|
|
$locale = $determinePreferredLocale($request);
|
|
$path = $rewritePath("/anlaesse/{$type}", $locale);
|
|
|
|
return redirect("/{$locale}{$path}", 301);
|
|
});
|
|
|
|
Route::get('/occasions/{type}', function (Request $request, string $type) use ($determinePreferredLocale, $rewritePath) {
|
|
$locale = $determinePreferredLocale($request);
|
|
$path = $rewritePath("/occasions/{$type}", $locale);
|
|
|
|
return redirect("/{$locale}{$path}", 301);
|
|
});
|
|
|
|
Route::get('/demo', function (Request $request) use ($determinePreferredLocale) {
|
|
$locale = $determinePreferredLocale($request);
|
|
|
|
return redirect("/{$locale}/demo", 301);
|
|
});
|
|
|
|
Route::get('/marketing/login', function (Request $request) use ($determinePreferredLocale) {
|
|
$locale = $determinePreferredLocale($request);
|
|
$destination = "/{$locale}/login";
|
|
$query = $request->getQueryString();
|
|
|
|
return redirect($query ? "{$destination}?{$query}" : $destination, 302);
|
|
})->name('marketing.login');
|
|
|
|
Route::get('/success/{packageId?}', function (Request $request, ?int $packageId = null) use ($determinePreferredLocale) {
|
|
$locale = $determinePreferredLocale($request);
|
|
$path = "/{$locale}/success";
|
|
|
|
if ($packageId !== null) {
|
|
$path .= "/{$packageId}";
|
|
}
|
|
|
|
return redirect($path, 301);
|
|
});
|
|
|
|
Route::get('/buy/{packageId}', function (Request $request, int $packageId) use ($determinePreferredLocale) {
|
|
$locale = $determinePreferredLocale($request);
|
|
|
|
return redirect("/{$locale}/buy/{$packageId}", 301);
|
|
});
|
|
|
|
Route::get('/dashboard', DashboardController::class)
|
|
->middleware(['auth'])
|
|
->name('dashboard');
|
|
Route::middleware('auth')->group(function () {
|
|
Route::get('/profile', [ProfileController::class, 'index'])
|
|
->name('profile.index');
|
|
Route::post('/profile/data-exports', [ProfileDataExportController::class, 'store'])
|
|
->name('profile.data-exports.store');
|
|
Route::get('/profile/data-exports/{export}', [ProfileDataExportController::class, 'download'])
|
|
->name('profile.data-exports.download');
|
|
Route::delete('/profile/account', [ProfileAccountController::class, 'destroy'])
|
|
->name('profile.account.destroy');
|
|
});
|
|
Route::middleware('auth:super_admin')->group(function () {
|
|
Route::get('/super-admin/data-exports/{export}/download', [SuperAdminDataExportController::class, 'download'])
|
|
->name('superadmin.data-exports.download');
|
|
});
|
|
Route::prefix('event-admin')->group(function () {
|
|
$renderAdmin = fn () => view('admin');
|
|
$authAdmin = TenantAdminAuthController::class;
|
|
|
|
// Public routes (auth check inside controller)
|
|
Route::get('/auth/callback', $renderAdmin)->name('tenant.admin.auth.callback');
|
|
Route::get('/login', $renderAdmin)->name('tenant.admin.login');
|
|
Route::get('/auth/google', [TenantAdminGoogleController::class, 'redirect'])
|
|
->name('tenant.admin.google.redirect');
|
|
Route::get('/auth/google/callback', [TenantAdminGoogleController::class, 'callback'])
|
|
->name('tenant.admin.google.callback');
|
|
Route::get('/auth/facebook', [TenantAdminFacebookController::class, 'redirect'])
|
|
->name('tenant.admin.facebook.redirect');
|
|
Route::get('/auth/facebook/callback', [TenantAdminFacebookController::class, 'callback'])
|
|
->name('tenant.admin.facebook.callback');
|
|
|
|
// Protected routes (auth check inside controller)
|
|
Route::get('/logout', $authAdmin)->name('tenant.admin.logout');
|
|
Route::get('/dashboard', $authAdmin)->name('tenant.admin.dashboard');
|
|
Route::get('/{view?}', $renderAdmin)
|
|
->where('view', '.*')
|
|
->name('tenant.admin.app');
|
|
});
|
|
Route::view('/event', 'guest')->name('guest.pwa.landing');
|
|
Route::view('/g/{token}', 'guest')->where('token', '.*')->name('guest.gallery');
|
|
Route::view('/show/{token}', 'guest')->where('token', '.*')->name('guest.live-show');
|
|
Route::view('/e/{token}/{path?}', 'guest')
|
|
->where('token', '.*')
|
|
->where('path', '.*')
|
|
->name('guest.event');
|
|
Route::view('/share/{slug}', 'guest')
|
|
->where('slug', '[A-Za-z0-9]+')
|
|
->name('guest.share');
|
|
Route::middleware('auth')->group(function () {
|
|
Route::get('/tenant/events/{event}/photos/archive', EventPhotoArchiveController::class)
|
|
->name('tenant.events.photos.archive');
|
|
});
|
|
|
|
Route::get('/purchase-wizard/{package}', function (Request $request, string $package) use ($determinePreferredLocale) {
|
|
$locale = $determinePreferredLocale($request);
|
|
$resolvedPackage = Package::query()->find($package);
|
|
|
|
if (! $resolvedPackage) {
|
|
return redirect()
|
|
->route('packages', ['locale' => $locale])
|
|
->with('error', __('marketing.packages.package_not_found'));
|
|
}
|
|
|
|
return redirect()->to(CheckoutRoutes::wizardUrl($resolvedPackage, $locale), 301);
|
|
});
|
|
|
|
Route::get('/checkout/{package}', function (Request $request, string $package) use ($determinePreferredLocale) {
|
|
$locale = $determinePreferredLocale($request);
|
|
$resolvedPackage = Package::query()->find($package);
|
|
|
|
if (! $resolvedPackage) {
|
|
return redirect()
|
|
->route('packages', ['locale' => $locale])
|
|
->with('error', __('marketing.packages.package_not_found'));
|
|
}
|
|
|
|
return redirect()->to(CheckoutRoutes::wizardUrl($resolvedPackage, $locale), 301);
|
|
});
|
|
Route::post('/checkout/login', [CheckoutController::class, 'login'])->name('checkout.login');
|
|
Route::post('/checkout/register', [CheckoutController::class, 'register'])->name('checkout.register');
|
|
Route::get('/checkout/auth/google', [CheckoutGoogleController::class, 'redirect'])->name('checkout.google.redirect');
|
|
Route::get('/checkout/auth/google/callback', [CheckoutGoogleController::class, 'callback'])->name('checkout.google.callback');
|
|
Route::get('/checkout/auth/facebook', [CheckoutFacebookController::class, 'redirect'])->name('checkout.facebook.redirect');
|
|
Route::get('/checkout/auth/facebook/callback', [CheckoutFacebookController::class, 'callback'])->name('checkout.facebook.callback');
|
|
Route::post('/checkout/track-abandoned', [CheckoutController::class, 'trackAbandonedCheckout'])->name('checkout.track-abandoned');
|
|
Route::post('/set-locale', [LocaleController::class, 'set'])->name('set-locale');
|
|
|
|
Route::middleware('auth')->group(function () {
|
|
Route::post('/checkout/free-activate', [CheckoutController::class, 'activateFree'])->name('checkout.free-activate');
|
|
Route::get('/checkout/session/{session}/status', [CheckoutController::class, 'sessionStatus'])
|
|
->whereUuid('session')
|
|
->name('checkout.session.status');
|
|
Route::post('/checkout/session/{session}/confirm', [CheckoutController::class, 'confirmSession'])
|
|
->whereUuid('session')
|
|
->name('checkout.session.confirm');
|
|
Route::post('/paddle/create-checkout', [PaddleCheckoutController::class, 'create'])->name('paddle.checkout.create');
|
|
});
|
|
|
|
Route::get('/paddle/return', \App\Http\Controllers\PaddleReturnController::class)
|
|
->name('paddle.return');
|
|
|
|
Route::post('/paddle/webhook', [PaddleWebhookController::class, 'handle'])
|
|
->withoutMiddleware([\Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class])
|
|
->middleware('throttle:paddle-webhook')
|
|
->name('paddle.webhook');
|