when not zoomed and double‑tap/double‑click to toggle zoom. I also added a guest haptics toggle in settings (sheet
+ /settings) backed by localStorage.
and a reduced‑motion guard. Haptics now honor the toggle and still fall back gracefully on iOS (switch disabled when
navigator.vibrate isn’t available).
What changed
- Haptics preference storage + gating: resources/js/guest/lib/haptics.ts
- Preference hook: resources/js/guest/hooks/useHapticsPreference.ts
- Settings UI toggle in sheet + page: resources/js/guest/components/settings-sheet.tsx, resources/js/guest/pages/
SettingsPage.tsx
- i18n labels: resources/js/guest/i18n/messages.ts
- Tests: resources/js/guest/lib/__tests__/haptics.test.ts
injectManifest, a new typed SW source, runtime caching, and a non‑blocking update toast with an action button. The
guest shell now links a dedicated manifest and theme color, and background upload sync is managed in a single
PwaManager component.
Key changes (where/why)
- vite.config.ts: added VitePWA injectManifest config, guest manifest, and output to /public so the SW can control /
scope.
- resources/js/guest/guest-sw.ts: new Workbox SW (precache + runtime caching for guest navigation, GET /api/v1/*,
images, fonts) and preserves push/sync/notification logic.
- resources/js/guest/components/PwaManager.tsx: registers SW, shows update/offline toasts, and processes the upload
queue on sync/online.
- resources/js/guest/components/ToastHost.tsx: action-capable toasts so update prompts can include a CTA.
- resources/js/guest/i18n/messages.ts: added common.updateAvailable, common.updateAction, common.offlineReady.
- resources/views/guest.blade.php: manifest + theme color + apple touch icon.
- .gitignore: ignore generated public/guest-sw.js and public/guest.webmanifest; public/guest-sw.js removed since it’s
now build output.
screen where users pick an eligible end‑customer purchase and confirm. Eligibility is enforced server‑side
(endcustomer_event, within 14 days, no event package created after purchase), refund is issued via Paddle, the
purchase is marked refunded, the tenant package is deactivated, and a new confirmation email is sent using resources/
views/emails/partials/layout.blade.php.
Details
- New controller + form request for the confirm flow: app/Http/Controllers/WithdrawalController.php, app/Http/
Requests/Marketing/WithdrawalConfirmRequest.php
- New confirmation page + CTA: resources/js/pages/marketing/WithdrawalConfirm.tsx, resources/js/pages/legal/Show.tsx
- Routes + locale rewrites: routes/web.php, resources/js/lib/localizedPath.ts
- New email notification + template: app/Notifications/Customer/WithdrawalConfirmed.php, resources/views/emails/
withdrawal-confirmation.blade.php
- Translations added for marketing UI + backend flash + email copy: public/lang/de/marketing.json, public/lang/en/
marketing.json, resources/lang/de/marketing.php, resources/lang/en/marketing.php, resources/lang/de/emails.php,
resources/lang/en/emails.php
- Tests: tests/Feature/Marketing/WithdrawalConfirmationTest.php
the MailMessage builders to use view(). This keeps the existing copy/labels but aligns the look with resources/views/
emails/partials/layout.blade.php. I also switched the customer add‑on receipt notification to reuse the existing
branded view and added missing translations for the upload pipeline alert.
checkout_id direkt an das Backend, damit der Server die Session via Paddle‑API finalisiert (auch wenn der Webhook
nicht greift). Dadurch sollte “Zahlung wird verarbeitet” nicht mehr hängen bleiben.
Services/Helpers sind entfernt, API/Frontend angepasst, Tests auf Paddle umgestellt. Außerdem wurde die CSP gestrafft
und Stripe‑Texte in den Abandoned‑Checkout‑Mails ersetzt.
tab flows.
- Added a dynamic MobileShell with sticky header (notification bell with badge, quick QR when an event is
active, event switcher for multi-event users) and stabilized bottom tabs (home, tasks, uploads, profile)
driven by useMobileNav (resources/js/admin/mobile/components/MobileShell.tsx, components/BottomNav.tsx, hooks/
useMobileNav.ts).
- Centralized event handling now supports 0/1/many-event states without auto-selecting in multi-tenant mode and
exposes helper flags/activeSlug for consumers (resources/js/admin/context/EventContext.tsx).
- Rebuilt the mobile dashboard into explicit states: onboarding/no-event, single-event focus, and multi-event picker
with featured/secondary actions, KPI strip, and alerts (resources/js/admin/mobile/DashboardPage.tsx).
- Introduced tab entry points that respect event context and prompt selection when needed (resources/js/admin/
mobile/TasksTabPage.tsx, UploadsTabPage.tsx). Refreshed tasks/uploads detail screens to use the new shell and sync
event selection (resources/js/admin/mobile/EventTasksPage.tsx, EventPhotosPage.tsx).
- Updated mobile routes and existing screens to the new tab keys and header/footer behavior (resources/js/admin/
router.tsx, mobile/* pages, i18n nav/header strings).