fix: replace all native confirm() dialogs with styled modal macros
Some checks failed
CI / ruff (push) Successful in 9s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled

Migrated ~68 native browser confirm() calls across 74 files to use the
project's confirm_modal/confirm_modal_dynamic Jinja2 macros, providing
consistent styled confirmation dialogs instead of plain browser popups.

Modules updated: core, tenancy, cms, marketplace, messaging, billing,
customers, orders, cart. Uses danger/warning/info variants and
double-confirm pattern for destructive delete operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 16:56:25 +01:00
parent 182610283d
commit 167bb50f4f
74 changed files with 939 additions and 436 deletions

View File

@@ -48,6 +48,9 @@ function adminLetzshop() {
pendingOrders: 0
},
// Confirm modals
showDeleteStoreConfigModal: false,
// Configuration modal
showConfigModal: false,
selectedStore: null,
@@ -191,10 +194,6 @@ function adminLetzshop() {
* Delete store configuration
*/
async deleteStoreConfig() {
if (!confirm(I18n.t('marketplace.confirmations.remove_letzshop_config_store'))) {
return;
}
try {
await apiClient.delete(`/admin/letzshop/stores/${this.selectedStore.store_id}/credentials`);
this.showConfigModal = false;

View File

@@ -124,6 +124,15 @@ function adminMarketplaceLetzshop() {
productStats: { total: 0, active: 0, inactive: 0, last_sync: null },
showImportModal: false,
// Confirm modals
showDeclineOrderModal: false,
orderToDecline: null,
showConfirmAllItemsModal: false,
showDeclineAllItemsModal: false,
showDeleteCredentialsModal: false,
showIgnoreExceptionModal: false,
exceptionToIgnore: null,
// Modals
showTrackingModal: false,
showOrderModal: false,
@@ -1010,8 +1019,6 @@ function adminMarketplaceLetzshop() {
async declineOrder(order) {
if (!this.selectedStore) return;
if (!confirm(I18n.t('marketplace.confirmations.decline_order'))) return;
try {
await apiClient.post(`/admin/letzshop/stores/${this.selectedStore.id}/orders/${order.id}/reject`);
this.successMessage = 'Order declined';
@@ -1128,8 +1135,6 @@ function adminMarketplaceLetzshop() {
async confirmAllItems(order) {
if (!this.selectedStore) return;
if (!confirm(I18n.t('marketplace.confirmations.confirm_all_items'))) return;
try {
await apiClient.post(
`/admin/letzshop/stores/${this.selectedStore.id}/orders/${order.id}/confirm`
@@ -1149,8 +1154,6 @@ function adminMarketplaceLetzshop() {
async declineAllItems(order) {
if (!this.selectedStore) return;
if (!confirm(I18n.t('marketplace.confirmations.decline_all_items'))) return;
try {
await apiClient.post(
`/admin/letzshop/stores/${this.selectedStore.id}/orders/${order.id}/reject`
@@ -1241,10 +1244,6 @@ function adminMarketplaceLetzshop() {
async deleteCredentials() {
if (!this.selectedStore) return;
if (!confirm(I18n.t('marketplace.confirmations.remove_letzshop_config'))) {
return;
}
try {
await apiClient.delete(`/admin/letzshop/stores/${this.selectedStore.id}/credentials`);
this.successMessage = 'Credentials removed';
@@ -1459,10 +1458,6 @@ function adminMarketplaceLetzshop() {
* Ignore an exception
*/
async ignoreException(exception) {
if (!confirm(I18n.t('marketplace.confirmations.ignore_exception'))) {
return;
}
try {
await apiClient.post(`/admin/order-exceptions/${exception.id}/ignore`, {
notes: 'Ignored via admin interface'

View File

@@ -66,6 +66,13 @@ function storeLetzshop() {
shipped: 0
},
// Confirm modals
showDeleteCredentialsModal: false,
showConfirmOrderModal: false,
orderToConfirm: null,
showRejectOrderModal: false,
orderToReject: null,
// Modals
showTrackingModal: false,
showOrderModal: false,
@@ -291,10 +298,6 @@ function storeLetzshop() {
* Delete credentials
*/
async deleteCredentials() {
if (!confirm(I18n.t('marketplace.confirmations.remove_letzshop_credentials'))) {
return;
}
try {
await apiClient.delete('/store/letzshop/credentials');
this.credentials = null;
@@ -316,10 +319,6 @@ function storeLetzshop() {
* Confirm order
*/
async confirmOrder(order) {
if (!confirm(I18n.t('marketplace.confirmations.confirm_order'))) {
return;
}
try {
const response = await apiClient.post(`/store/letzshop/orders/${order.id}/confirm`);
@@ -340,10 +339,6 @@ function storeLetzshop() {
* Reject order
*/
async rejectOrder(order) {
if (!confirm(I18n.t('marketplace.confirmations.reject_order'))) {
return;
}
try {
const response = await apiClient.post(`/store/letzshop/orders/${order.id}/reject`);

View File

@@ -4,7 +4,7 @@
{% from 'shared/macros/headers.html' import page_header_flex, refresh_button %}
{% from 'shared/macros/alerts.html' import error_state, alert_dynamic %}
{% from 'shared/macros/tables.html' import table_wrapper, table_header %}
{% from 'shared/macros/modals.html' import modal %}
{% from 'shared/macros/modals.html' import modal, confirm_modal %}
{% block title %}Letzshop Management{% endblock %}
@@ -283,7 +283,7 @@
<button
type="button"
x-show="storeCredentials"
@click="deleteStoreConfig()"
@click="showDeleteStoreConfigModal = true"
class="px-4 py-2 text-sm font-medium text-red-600 border border-red-300 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/20"
>
Remove
@@ -310,6 +310,9 @@
{% endcall %}
<!-- Orders Modal -->
<!-- Delete Store Config Confirm Modal -->
{{ confirm_modal('deleteStoreConfigModal', 'Remove Configuration', 'Are you sure you want to remove the Letzshop configuration for this store? This will delete the API key and disable syncing.', 'deleteStoreConfig()', 'showDeleteStoreConfigModal', 'Remove', 'Cancel', 'danger') }}
{% call modal('ordersModal', 'Store Orders', 'showOrdersModal', size='xl') %}
<p class="text-sm text-gray-500 dark:text-gray-400 mb-4">
Orders for: <span class="font-semibold" x-text="selectedStore?.store_name"></span>

View File

@@ -4,7 +4,7 @@
{% from 'shared/macros/alerts.html' import alert_dynamic, error_state %}
{% from 'shared/macros/headers.html' import page_header_flex, refresh_button %}
{# Import modals macro - custom modals below use inline definition for specialized forms #}
{% from 'shared/macros/modals.html' import modal_simple %}
{% from 'shared/macros/modals.html' import modal_simple, confirm_modal %}
{% block title %}Letzshop Management{% endblock %}
{% block alpine_data %}adminMarketplaceLetzshop(){% endblock %}
@@ -426,13 +426,13 @@
<!-- Bulk Actions -->
<div x-show="selectedOrder?.status === 'pending'" class="mt-4 flex gap-2 justify-end">
<button
@click="confirmAllItems(selectedOrder)"
@click="showConfirmAllItemsModal = true"
class="px-3 py-1.5 text-sm text-white bg-green-600 hover:bg-green-700 rounded-lg"
>
Confirm All Items
</button>
<button
@click="declineAllItems(selectedOrder)"
@click="showDeclineAllItemsModal = true"
class="px-3 py-1.5 text-sm text-white bg-red-600 hover:bg-red-700 rounded-lg"
>
Decline All Items
@@ -582,6 +582,21 @@
</form>
</div>
</div>
<!-- Decline Order Confirm Modal -->
{{ confirm_modal('declineOrderModal', 'Decline Order', 'Are you sure you want to decline this order? This action cannot be undone.', 'declineOrder(orderToDecline)', 'showDeclineOrderModal', 'Decline', 'Cancel', 'danger') }}
<!-- Confirm All Items Modal -->
{{ confirm_modal('confirmAllItemsModal', 'Confirm All Items', 'Are you sure you want to confirm all items in this order?', 'confirmAllItems(selectedOrder)', 'showConfirmAllItemsModal', 'Confirm All', 'Cancel', 'info') }}
<!-- Decline All Items Modal -->
{{ confirm_modal('declineAllItemsModal', 'Decline All Items', 'Are you sure you want to decline all items in this order? This action cannot be undone.', 'declineAllItems(selectedOrder)', 'showDeclineAllItemsModal', 'Decline All', 'Cancel', 'danger') }}
<!-- Delete Credentials Confirm Modal -->
{{ confirm_modal('deleteCredentialsModal', 'Remove Credentials', 'Are you sure you want to remove the Letzshop API credentials? This will disable order syncing for this store.', 'deleteCredentials()', 'showDeleteCredentialsModal', 'Remove', 'Cancel', 'danger') }}
<!-- Ignore Exception Confirm Modal -->
{{ confirm_modal('ignoreExceptionModal', 'Ignore Exception', 'Are you sure you want to ignore this exception? The unmatched product will not be resolved.', 'ignoreException(exceptionToIgnore)', 'showIgnoreExceptionModal', 'Ignore', 'Cancel', 'warning') }}
{% endblock %}
{% block extra_scripts %}

View File

@@ -186,7 +186,7 @@
</template>
<template x-if="exc.status === 'pending'">
<button
@click="ignoreException(exc)"
@click="exceptionToIgnore = exc; showIgnoreExceptionModal = true"
class="flex items-center justify-center px-2 py-1 text-sm text-gray-600 transition-colors duration-150 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700"
title="Ignore Exception"
>

View File

@@ -275,7 +275,7 @@
</button>
<button
x-show="order.status === 'pending'"
@click="declineOrder(order)"
@click="orderToDecline = order; showDeclineOrderModal = true"
class="flex items-center justify-center px-2 py-1 text-sm text-red-600 transition-colors duration-150 rounded-md hover:bg-red-100 dark:hover:bg-red-900"
title="Decline Order"
>

View File

@@ -148,7 +148,7 @@
<button
type="button"
x-show="credentials"
@click="deleteCredentials()"
@click="showDeleteCredentialsModal = true"
class="flex items-center px-4 py-2 text-sm font-medium leading-5 text-red-600 transition-colors duration-150 bg-white dark:bg-gray-800 border border-red-300 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/20 focus:outline-none"
>
<span x-html="$icon('trash', 'w-4 h-4 mr-2')"></span>

View File

@@ -2,7 +2,7 @@
{% extends "store/base.html" %}
{% from 'shared/macros/headers.html' import page_header_flex %}
{% from 'shared/macros/tables.html' import table_wrapper, table_header %}
{% from 'shared/macros/modals.html' import form_modal %}
{% from 'shared/macros/modals.html' import form_modal, confirm_modal %}
{% block title %}Letzshop Orders{% endblock %}
@@ -217,7 +217,7 @@
<div class="flex items-center space-x-2 text-sm">
<button
x-show="order.sync_status === 'pending'"
@click="confirmOrder(order)"
@click="orderToConfirm = order; showConfirmOrderModal = true"
class="flex items-center justify-center px-2 py-1 text-sm text-green-600 transition-colors duration-150 rounded-md hover:bg-green-100 dark:hover:bg-green-900"
title="Confirm Order"
>
@@ -225,7 +225,7 @@
</button>
<button
x-show="order.sync_status === 'pending'"
@click="rejectOrder(order)"
@click="orderToReject = order; showRejectOrderModal = true"
class="flex items-center justify-center px-2 py-1 text-sm text-red-600 transition-colors duration-150 rounded-md hover:bg-red-100 dark:hover:bg-red-900"
title="Reject Order"
>
@@ -551,7 +551,7 @@
<button
type="button"
x-show="credentials"
@click="deleteCredentials()"
@click="showDeleteCredentialsModal = true"
class="flex items-center px-4 py-2 text-sm font-medium leading-5 text-red-600 transition-colors duration-150 bg-white dark:bg-gray-800 border border-red-300 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/20 focus:outline-none"
>
<span x-html="$icon('trash', 'w-4 h-4 mr-2')"></span>
@@ -683,4 +683,13 @@
</div>
</div>
</div>
<!-- Delete Credentials Confirm Modal -->
{{ confirm_modal('deleteCredentialsModal', 'Remove Credentials', 'Are you sure you want to remove your Letzshop API credentials? This will disable order syncing.', 'deleteCredentials()', 'showDeleteCredentialsModal', 'Remove', 'Cancel', 'danger') }}
<!-- Confirm Order Modal -->
{{ confirm_modal('confirmOrderModal', 'Confirm Order', 'Are you sure you want to confirm this order? The order will be marked as accepted.', 'confirmOrder(orderToConfirm)', 'showConfirmOrderModal', 'Confirm', 'Cancel', 'info') }}
<!-- Reject Order Modal -->
{{ confirm_modal('rejectOrderModal', 'Reject Order', 'Are you sure you want to reject this order? This action cannot be undone.', 'rejectOrder(orderToReject)', 'showRejectOrderModal', 'Reject', 'Cancel', 'danger') }}
{% endblock %}