From 89931b817d7509bd8e47de4187d774424f95b363 Mon Sep 17 00:00:00 2001
From: "bert.hausmans"
Date: Sun, 5 Apr 2026 11:12:10 +0200
Subject: [PATCH] feat(admin): Weeztix setup wizard, integration status badges
- Summary view when Weeztix is configured; edits only via 3-step wizard
- Step 1: reuse or replace OAuth client ID/secret; callback URL shown
- Step 2: OAuth connect (resume wizard after callback when started from wizard)
- Step 3: coupon, prefix, usage; finishing exits wizard
- PreregistrationPage: mailwizz/weeztix integration status helpers
- Pages index: Integrations column with MW/WZ badges; edit page: status cards
Made-with: Cursor
---
app/Http/Controllers/Admin/PageController.php | 8 +-
.../Controllers/Admin/WeeztixController.php | 40 +-
.../Admin/WeeztixOAuthController.php | 39 +-
app/Models/PreregistrationPage.php | 52 ++
.../admin/pages/_integration_badges.blade.php | 55 ++
resources/views/admin/pages/edit.blade.php | 28 +-
resources/views/admin/pages/index.blade.php | 9 +-
resources/views/admin/weeztix/edit.blade.php | 483 +++++++++++-------
8 files changed, 504 insertions(+), 210 deletions(-)
create mode 100644 resources/views/admin/pages/_integration_badges.blade.php
diff --git a/app/Http/Controllers/Admin/PageController.php b/app/Http/Controllers/Admin/PageController.php
index 6835d33..986b30e 100644
--- a/app/Http/Controllers/Admin/PageController.php
+++ b/app/Http/Controllers/Admin/PageController.php
@@ -28,7 +28,7 @@ class PageController extends Controller
{
$query = PreregistrationPage::query()
->withCount('subscribers')
- ->with('weeztixConfig')
+ ->with(['weeztixConfig', 'mailwizzConfig'])
->orderByDesc('start_date');
if (! $request->user()?->isSuperadmin()) {
@@ -86,7 +86,11 @@ class PageController extends Controller
public function edit(PreregistrationPage $page): View
{
- $page->load(['blocks' => fn ($q) => $q->orderBy('sort_order')]);
+ $page->load([
+ 'blocks' => fn ($q) => $q->orderBy('sort_order'),
+ 'mailwizzConfig',
+ 'weeztixConfig',
+ ]);
return view('admin.pages.edit', compact('page'));
}
diff --git a/app/Http/Controllers/Admin/WeeztixController.php b/app/Http/Controllers/Admin/WeeztixController.php
index c85a2f8..444041d 100644
--- a/app/Http/Controllers/Admin/WeeztixController.php
+++ b/app/Http/Controllers/Admin/WeeztixController.php
@@ -8,18 +8,34 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\UpdateWeeztixConfigRequest;
use App\Models\PreregistrationPage;
use Illuminate\Http\RedirectResponse;
+use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
class WeeztixController extends Controller
{
- public function edit(PreregistrationPage $page): View
+ public function edit(Request $request, PreregistrationPage $page): View
{
$this->authorize('update', $page);
$page->load('weeztixConfig');
- return view('admin.weeztix.edit', compact('page'));
+ $showWizard = $page->weeztixConfig === null || $request->boolean('wizard');
+ $wizardStep = $showWizard ? min(3, max(1, (int) $request->query('step', 1))) : 1;
+ if ($showWizard && $page->weeztixConfig === null && $wizardStep !== 1) {
+ return redirect()
+ ->route('admin.pages.weeztix.edit', ['page' => $page, 'wizard' => 1, 'step' => 1]);
+ }
+ $hasStoredCredentials = $page->weeztixConfig !== null
+ && is_string($page->weeztixConfig->client_id)
+ && $page->weeztixConfig->client_id !== '';
+
+ return view('admin.weeztix.edit', compact(
+ 'page',
+ 'showWizard',
+ 'wizardStep',
+ 'hasStoredCredentials'
+ ));
}
public function update(UpdateWeeztixConfigRequest $request, PreregistrationPage $page): RedirectResponse
@@ -41,8 +57,26 @@ class WeeztixController extends Controller
);
});
+ $page->load('weeztixConfig');
+
+ if ($request->boolean('wizard')) {
+ if ($request->boolean('wizard_coupon_save')) {
+ return redirect()
+ ->route('admin.pages.weeztix.edit', ['page' => $page])
+ ->with('status', __('Weeztix-configuratie opgeslagen.'));
+ }
+
+ return redirect()
+ ->route('admin.pages.weeztix.edit', [
+ 'page' => $page,
+ 'wizard' => 1,
+ 'step' => 2,
+ ])
+ ->with('status', __('Weeztix-configuratie opgeslagen.'));
+ }
+
return redirect()
- ->route('admin.pages.weeztix.edit', $page)
+ ->route('admin.pages.weeztix.edit', ['page' => $page])
->with('status', __('Weeztix-configuratie opgeslagen.'));
}
diff --git a/app/Http/Controllers/Admin/WeeztixOAuthController.php b/app/Http/Controllers/Admin/WeeztixOAuthController.php
index bd19ad5..8466723 100644
--- a/app/Http/Controllers/Admin/WeeztixOAuthController.php
+++ b/app/Http/Controllers/Admin/WeeztixOAuthController.php
@@ -15,7 +15,7 @@ use RuntimeException;
class WeeztixOAuthController extends Controller
{
- public function redirect(PreregistrationPage $page): RedirectResponse
+ public function redirect(Request $request, PreregistrationPage $page): RedirectResponse
{
$this->authorize('update', $page);
@@ -38,6 +38,7 @@ class WeeztixOAuthController extends Controller
session([
'weeztix_oauth_state' => $state,
'weeztix_page_id' => $page->id,
+ 'weeztix_oauth_resume_wizard' => $request->boolean('wizard'),
]);
$redirectUri = $config->redirect_uri;
@@ -90,7 +91,7 @@ class WeeztixOAuthController extends Controller
$config = $page->weeztixConfig;
if ($config === null) {
- session()->forget(['weeztix_oauth_state', 'weeztix_page_id']);
+ $this->forgetOauthSession();
return redirect()
->route('admin.pages.weeztix.edit', $page)
@@ -110,30 +111,52 @@ class WeeztixOAuthController extends Controller
'message' => $e->getMessage(),
]);
- session()->forget(['weeztix_oauth_state', 'weeztix_page_id']);
+ $resumeWizard = $this->forgetOauthSession();
return redirect()
- ->route('admin.pages.weeztix.edit', $page)
+ ->route('admin.pages.weeztix.edit', $this->weeztixEditParams($page, $resumeWizard, 2))
->with('error', __('Verbinden met Weeztix is mislukt. Controleer je gegevens en probeer opnieuw.'));
}
- session()->forget(['weeztix_oauth_state', 'weeztix_page_id']);
+ $resumeWizard = $this->forgetOauthSession();
return redirect()
- ->route('admin.pages.weeztix.edit', $page)
+ ->route('admin.pages.weeztix.edit', $this->weeztixEditParams($page, $resumeWizard, 3))
->with('status', __('Succesvol verbonden met Weeztix.'));
}
+ /**
+ * @return array{page: PreregistrationPage, wizard?: int, step?: int}
+ */
+ private function weeztixEditParams(PreregistrationPage $page, bool $resumeWizard, int $step): array
+ {
+ $params = ['page' => $page];
+ if ($resumeWizard) {
+ $params['wizard'] = 1;
+ $params['step'] = $step;
+ }
+
+ return $params;
+ }
+
+ private function forgetOauthSession(): bool
+ {
+ $resumeWizard = (bool) session()->pull('weeztix_oauth_resume_wizard', false);
+ session()->forget(['weeztix_oauth_state', 'weeztix_page_id']);
+
+ return $resumeWizard;
+ }
+
private function redirectToWeeztixEditWithSessionPage(string $message): RedirectResponse
{
$pageId = session('weeztix_page_id');
- session()->forget(['weeztix_oauth_state', 'weeztix_page_id']);
+ $resumeWizard = $this->forgetOauthSession();
if (is_int($pageId) || is_numeric($pageId)) {
$page = PreregistrationPage::query()->find((int) $pageId);
if ($page !== null) {
return redirect()
- ->route('admin.pages.weeztix.edit', $page)
+ ->route('admin.pages.weeztix.edit', $this->weeztixEditParams($page, $resumeWizard, 2))
->with('error', $message);
}
}
diff --git a/app/Models/PreregistrationPage.php b/app/Models/PreregistrationPage.php
index 73ca190..98884f7 100644
--- a/app/Models/PreregistrationPage.php
+++ b/app/Models/PreregistrationPage.php
@@ -204,4 +204,56 @@ class PreregistrationPage extends Model
return 'active';
}
+
+ /**
+ * Mailwizz setup depth for admin UI (API key + list + email field = ready to sync).
+ *
+ * @return 'none'|'partial'|'ready'
+ */
+ public function mailwizzIntegrationStatus(): string
+ {
+ $c = $this->mailwizzConfig;
+ if ($c === null) {
+ return 'none';
+ }
+
+ $key = $c->api_key;
+ if (! is_string($key) || $key === '') {
+ return 'partial';
+ }
+
+ if (! is_string($c->list_uid) || $c->list_uid === '' || ! is_string($c->field_email) || $c->field_email === '') {
+ return 'partial';
+ }
+
+ return 'ready';
+ }
+
+ /**
+ * Weeztix setup depth for admin UI.
+ *
+ * @return 'none'|'credentials'|'connected'|'ready'
+ */
+ public function weeztixIntegrationStatus(): string
+ {
+ $c = $this->weeztixConfig;
+ if ($c === null) {
+ return 'none';
+ }
+
+ $hasClient = is_string($c->client_id) && $c->client_id !== '';
+ if (! $hasClient) {
+ return 'none';
+ }
+
+ if (! $c->is_connected) {
+ return 'credentials';
+ }
+
+ if (! is_string($c->coupon_guid) || $c->coupon_guid === '') {
+ return 'connected';
+ }
+
+ return 'ready';
+ }
}
diff --git a/resources/views/admin/pages/_integration_badges.blade.php b/resources/views/admin/pages/_integration_badges.blade.php
new file mode 100644
index 0000000..faaad8f
--- /dev/null
+++ b/resources/views/admin/pages/_integration_badges.blade.php
@@ -0,0 +1,55 @@
+@php
+ $only = $only ?? null;
+ $integrationBadgeClass = $integrationBadgeClass ?? '';
+ if (! in_array($only, [null, 'mailwizz', 'weeztix'], true)) {
+ $only = null;
+ }
+
+ $mailwizz = $page->mailwizzIntegrationStatus();
+ $weeztix = $page->weeztixIntegrationStatus();
+
+ $mailwizzClasses = match ($mailwizz) {
+ 'ready' => 'border-emerald-200 bg-emerald-50 text-emerald-900',
+ 'partial' => 'border-amber-200 bg-amber-50 text-amber-950',
+ default => 'border-slate-200 bg-slate-50 text-slate-600',
+ };
+ $mailwizzLabel = match ($mailwizz) {
+ 'ready' => __('Ready'),
+ 'partial' => __('Incomplete'),
+ default => __('Off'),
+ };
+
+ $weeztixClasses = match ($weeztix) {
+ 'ready' => 'border-emerald-200 bg-emerald-50 text-emerald-900',
+ 'connected' => 'border-sky-200 bg-sky-50 text-sky-950',
+ 'credentials' => 'border-amber-200 bg-amber-50 text-amber-950',
+ default => 'border-slate-200 bg-slate-50 text-slate-600',
+ };
+ $weeztixLabel = match ($weeztix) {
+ 'ready' => __('Ready'),
+ 'connected' => __('Connected'),
+ 'credentials' => __('OAuth only'),
+ default => __('Off'),
+ };
+
+ $showMailwizz = $only === null || $only === 'mailwizz';
+ $showWeeztix = $only === null || $only === 'weeztix';
+@endphp
+
+ @if ($showMailwizz)
+
+ {{ __('MW') }} · {{ $mailwizzLabel }}
+
+ @endif
+ @if ($showWeeztix)
+
+ {{ __('WZ') }} · {{ $weeztixLabel }}
+
+ @endif
+
diff --git a/resources/views/admin/pages/edit.blade.php b/resources/views/admin/pages/edit.blade.php
index 6cdeb97..697ce75 100644
--- a/resources/views/admin/pages/edit.blade.php
+++ b/resources/views/admin/pages/edit.blade.php
@@ -13,10 +13,30 @@
{{ __('Public URL') }}: {{ url('/r/'.$page->slug) }}
@can('update', $page)
-
- {{ __('Mailwizz integration') }} →
- {{ __('Weeztix integration') }} →
-
+
@endcan
diff --git a/resources/views/admin/pages/index.blade.php b/resources/views/admin/pages/index.blade.php
index 394f515..51b8e65 100644
--- a/resources/views/admin/pages/index.blade.php
+++ b/resources/views/admin/pages/index.blade.php
@@ -32,6 +32,7 @@
{{ __('Start') }} |
{{ __('End') }} |
{{ __('Subscribers') }} |
+ {{ __('Integrations') }} |
{{ __('Actions') }} |
@@ -64,6 +65,9 @@
{{ $page->start_date->timezone(config('app.timezone'))->format('Y-m-d H:i') }} |
{{ $page->end_date->timezone(config('app.timezone'))->format('Y-m-d H:i') }} |
{{ number_format($page->subscribers_count) }} |
+
+ @include('admin.pages._integration_badges', ['page' => $page])
+ |
@can('update', $page)
@@ -77,9 +81,6 @@
@endcan
@can('update', $page)
{{ __('Weeztix') }}
- @if ($page->weeztixConfig?->is_connected)
- ●
- @endif
@endcan
|