From 3bcab953f963946979fbbd25ba92c534cfde9625 Mon Sep 17 00:00:00 2001
From: isaacclad
Date: Sun, 7 Jun 2026 21:10:47 +0000
Subject: [PATCH] Replace native confirm() dialogs with styled confirm modals.
Add shared confirm-dialog component, Alpine ladillConfirm store, and
swap browser confirms for consistent bottom-sheet modals across user,
admin, and hosting flows.
Co-authored-by: Cursor
---
resources/js/app.js | 7 ++
resources/js/ladill-modals.js | 75 +++++++++++++++++++
.../views/components/confirm-dialog.blade.php | 69 +++++++++++++++++
.../views/email/account/developers.blade.php | 16 +++-
.../views/email/account/settings.blade.php | 23 ++++--
resources/views/email/account/team.blade.php | 16 +++-
resources/views/email/domains/show.blade.php | 17 ++++-
.../views/email/mailboxes/show.blade.php | 17 ++++-
resources/views/layouts/hosting.blade.php | 1 +
resources/views/layouts/user.blade.php | 1 +
.../views/partials/confirm-prompt.blade.php | 65 ++++++++++++++++
resources/views/qr-codes/attendees.blade.php | 11 ++-
.../views/qr/account/developers.blade.php | 16 +++-
resources/views/qr/account/team.blade.php | 16 +++-
14 files changed, 318 insertions(+), 32 deletions(-)
create mode 100644 resources/js/ladill-modals.js
create mode 100644 resources/views/components/confirm-dialog.blade.php
create mode 100644 resources/views/partials/confirm-prompt.blade.php
diff --git a/resources/js/app.js b/resources/js/app.js
index 61cc8be..ad8634c 100644
--- a/resources/js/app.js
+++ b/resources/js/app.js
@@ -1,5 +1,10 @@
import './bootstrap';
+import { registerLadillConfirmStore, registerLadillModalHelpers } from './ladill-modals';
+
+registerLadillModalHelpers();
+
+
import Alpine from 'alpinejs';
import collapse from '@alpinejs/collapse';
import QRCodeStyling from 'qr-code-styling';
@@ -191,4 +196,6 @@ Alpine.data('topbarSearch', (config = {}) => ({
}));
window.Alpine = Alpine;
+registerLadillConfirmStore(Alpine);
+
Alpine.start();
diff --git a/resources/js/ladill-modals.js b/resources/js/ladill-modals.js
new file mode 100644
index 0000000..eb2bf74
--- /dev/null
+++ b/resources/js/ladill-modals.js
@@ -0,0 +1,75 @@
+/**
+ * Lightweight modal dispatch helpers (optional — balanceGate in layout is primary).
+ */
+
+export function openLadillModal(name) {
+ if (!name) {
+ return false;
+ }
+
+ window.dispatchEvent(new CustomEvent('open-modal', { detail: name, bubbles: true }));
+
+ return true;
+}
+
+export function closeLadillModal(name) {
+ if (!name) {
+ return false;
+ }
+
+ window.dispatchEvent(new CustomEvent('close-modal', { detail: name, bubbles: true }));
+
+ return true;
+}
+
+export function ladillNeedsTopup(balance, price) {
+ const normalizedBalance = Number.parseFloat(balance);
+ const normalizedPrice = Number.parseFloat(price);
+
+ if (!Number.isFinite(normalizedBalance) || !Number.isFinite(normalizedPrice)) {
+ return false;
+ }
+
+ return normalizedBalance <= 0 || normalizedBalance < normalizedPrice;
+}
+
+export function registerLadillConfirmStore(Alpine) {
+ Alpine.store('ladillConfirm', {
+ open: false,
+ title: '',
+ message: '',
+ confirmLabel: 'Confirm',
+ cancelLabel: 'Cancel',
+ variant: 'danger',
+ _resolve: null,
+
+ ask(options = {}) {
+ return new Promise((resolve) => {
+ this.title = options.title || 'Are you sure?';
+ this.message = options.message || '';
+ this.confirmLabel = options.confirmLabel || 'Confirm';
+ this.cancelLabel = options.cancelLabel || 'Cancel';
+ this.variant = options.variant || 'danger';
+ this._resolve = resolve;
+ this.open = true;
+ });
+ },
+
+ answer(confirmed) {
+ if (this._resolve) {
+ this._resolve(confirmed);
+ }
+
+ this.open = false;
+ this._resolve = null;
+ },
+ });
+
+ window.ladillConfirm = (options = {}) => Alpine.store('ladillConfirm').ask(options);
+}
+
+export function registerLadillModalHelpers() {
+ window.openLadillModal = openLadillModal;
+ window.closeLadillModal = closeLadillModal;
+ window.ladillNeedsTopup = ladillNeedsTopup;
+}
diff --git a/resources/views/components/confirm-dialog.blade.php b/resources/views/components/confirm-dialog.blade.php
new file mode 100644
index 0000000..1d0ee69
--- /dev/null
+++ b/resources/views/components/confirm-dialog.blade.php
@@ -0,0 +1,69 @@
+@props([
+ 'name',
+ 'title',
+ 'message' => null,
+ 'action',
+ 'method' => 'POST',
+ 'confirmLabel' => 'Confirm',
+ 'cancelLabel' => 'Cancel',
+ 'variant' => 'danger',
+])
+
+@php
+ $confirmBtnClass = $variant === 'danger'
+ ? 'bg-red-600 hover:bg-red-700'
+ : 'bg-violet-600 hover:bg-violet-700';
+ $iconWrapClass = $variant === 'danger'
+ ? 'bg-red-100 text-red-600'
+ : 'bg-violet-100 text-violet-600';
+@endphp
+
+@if(isset($trigger))
+
+ {{ $trigger }}
+
+@endif
+
+
+
+
+
+ @if($variant === 'danger')
+
+ @else
+
+ @endif
+
+
{{ $title }}
+ @if($message)
+
{{ $message }}
+ @endif
+ @isset($details)
+
{{ $details }}
+ @endisset
+
+
+
+
+
diff --git a/resources/views/email/account/developers.blade.php b/resources/views/email/account/developers.blade.php
index 28d1b4a..ea2649a 100644
--- a/resources/views/email/account/developers.blade.php
+++ b/resources/views/email/account/developers.blade.php
@@ -46,10 +46,18 @@
{{ $token->last_used_at ? 'last used '.$token->last_used_at->diffForHumans() : 'never used' }}
-
+
+
+
+
+
@empty
No tokens yet.
diff --git a/resources/views/email/account/settings.blade.php b/resources/views/email/account/settings.blade.php
index 7ec7bfc..54b854a 100644
--- a/resources/views/email/account/settings.blade.php
+++ b/resources/views/email/account/settings.blade.php
@@ -22,13 +22,22 @@
Linked mailbox: {{ $linkStatus['linked_mailbox'] }}
-
+
+
+
+
+
@elseif(($linkStatus['stage'] ?? '') === 'needs_domain')
Add and verify an email domain first.
diff --git a/resources/views/email/account/team.blade.php b/resources/views/email/account/team.blade.php
index 48793ae..70c9fef 100644
--- a/resources/views/email/account/team.blade.php
+++ b/resources/views/email/account/team.blade.php
@@ -64,10 +64,18 @@
-
+
+
+
+
+
@else
{{ $member->role }}
@endif
diff --git a/resources/views/email/domains/show.blade.php b/resources/views/email/domains/show.blade.php
index 7805fb8..0d4c453 100644
--- a/resources/views/email/domains/show.blade.php
+++ b/resources/views/email/domains/show.blade.php
@@ -54,9 +54,18 @@
@endunless
-
+
+
+
+
+
@endsection
diff --git a/resources/views/email/mailboxes/show.blade.php b/resources/views/email/mailboxes/show.blade.php
index 79c78f8..e5ee875 100644
--- a/resources/views/email/mailboxes/show.blade.php
+++ b/resources/views/email/mailboxes/show.blade.php
@@ -74,10 +74,19 @@
Delete mailbox
This permanently removes the mailbox and its email.
-
+
+
+
+
+
@endsection
diff --git a/resources/views/layouts/hosting.blade.php b/resources/views/layouts/hosting.blade.php
index 3de0095..d8b409e 100644
--- a/resources/views/layouts/hosting.blade.php
+++ b/resources/views/layouts/hosting.blade.php
@@ -55,5 +55,6 @@
])
@include('partials.afia')
@endauth
+@include('partials.confirm-prompt')