| 1 |
import SweetAlert from 'sweetalert2'; |
| 2 |
import * as lpToastify from 'lpAssetsJsPath/lpToastify'; |
| 3 |
import * as lpUtils from 'lpAssetsJsPath/utils.js'; |
| 4 |
|
| 5 |
/** |
| 6 |
* Handle admin approve/deny refund actions. |
| 7 |
* |
| 8 |
* @since 4.3.9 |
| 9 |
* @version 1.0.0 |
| 10 |
*/ |
| 11 |
export class RefundOrder { |
| 12 |
constructor() { |
| 13 |
this.isRequesting = false; |
| 14 |
this.isReloading = false; |
| 15 |
} |
| 16 |
|
| 17 |
static selectors = { |
| 18 |
panel: '.order-data-refund-request', |
| 19 |
action: '.lp-admin-refund-order-action', |
| 20 |
}; |
| 21 |
|
| 22 |
init() { |
| 23 |
this.events(); |
| 24 |
} |
| 25 |
|
| 26 |
events() { |
| 27 |
if ( RefundOrder._loadedEvents ) { |
| 28 |
return; |
| 29 |
} |
| 30 |
|
| 31 |
RefundOrder._loadedEvents = this; |
| 32 |
|
| 33 |
lpUtils.eventHandlers( 'click', [ |
| 34 |
{ |
| 35 |
selector: RefundOrder.selectors.action, |
| 36 |
class: this, |
| 37 |
callBack: this.handleAction.name, |
| 38 |
}, |
| 39 |
] ); |
| 40 |
} |
| 41 |
|
| 42 |
getPanelData( panel ) { |
| 43 |
const orderTotal = parseFloat( panel.dataset.orderTotal || '0' ); |
| 44 |
|
| 45 |
return { |
| 46 |
orderId: parseInt( panel.dataset.orderId || '0', 10 ), |
| 47 |
orderTotal: Number.isNaN( orderTotal ) ? 0 : orderTotal, |
| 48 |
orderTotalFormatted: panel.dataset.orderTotalFormatted || '', |
| 49 |
confirmTitle: panel.dataset.confirmTitle || 'Approve refund?', |
| 50 |
confirmText: panel.dataset.confirmText || '', |
| 51 |
messageLabel: panel.dataset.messageLabel || 'Message to payer', |
| 52 |
messagePlaceholder: panel.dataset.messagePlaceholder || '', |
| 53 |
amountLabel: panel.dataset.amountLabel || 'Refund amount', |
| 54 |
amountInvalid: panel.dataset.amountInvalid || 'Invalid refund amount.', |
| 55 |
confirmButton: panel.dataset.confirmButton || 'Approve Refund', |
| 56 |
cancelButton: panel.dataset.cancelButton || 'Cancel', |
| 57 |
}; |
| 58 |
} |
| 59 |
|
| 60 |
setLoadingState( panel, isLoading ) { |
| 61 |
panel.querySelectorAll( RefundOrder.selectors.action ).forEach( ( button ) => { |
| 62 |
button.disabled = isLoading; |
| 63 |
} ); |
| 64 |
} |
| 65 |
|
| 66 |
openApproveModal( data ) { |
| 67 |
const content = document.createElement( 'div' ); |
| 68 |
const messageLabel = document.createElement( 'label' ); |
| 69 |
const message = document.createElement( 'textarea' ); |
| 70 |
const amountLabel = document.createElement( 'label' ); |
| 71 |
const amount = document.createElement( 'input' ); |
| 72 |
|
| 73 |
content.className = 'lp-admin-refund-modal__form'; |
| 74 |
|
| 75 |
if ( data.confirmText ) { |
| 76 |
const confirmText = document.createElement( 'p' ); |
| 77 |
confirmText.className = 'lp-admin-refund-modal__description'; |
| 78 |
confirmText.textContent = data.confirmText; |
| 79 |
content.append( confirmText ); |
| 80 |
} |
| 81 |
|
| 82 |
messageLabel.textContent = data.messageLabel; |
| 83 |
messageLabel.htmlFor = 'lp-admin-refund-message'; |
| 84 |
messageLabel.className = 'swal2-input-label'; |
| 85 |
message.id = 'lp-admin-refund-message'; |
| 86 |
message.className = 'swal2-textarea'; |
| 87 |
message.placeholder = data.messagePlaceholder; |
| 88 |
|
| 89 |
amountLabel.textContent = `${ data.amountLabel } (${ data.orderTotalFormatted })`; |
| 90 |
amountLabel.htmlFor = 'lp-admin-refund-amount'; |
| 91 |
amountLabel.className = 'swal2-input-label'; |
| 92 |
amount.id = 'lp-admin-refund-amount'; |
| 93 |
amount.className = 'swal2-input'; |
| 94 |
amount.type = 'number'; |
| 95 |
amount.min = '0.01'; |
| 96 |
amount.max = data.orderTotal.toString(); |
| 97 |
amount.step = '0.01'; |
| 98 |
amount.value = data.orderTotal.toFixed( 2 ); |
| 99 |
|
| 100 |
content.append( messageLabel, message, amountLabel, amount ); |
| 101 |
|
| 102 |
return SweetAlert.fire( { |
| 103 |
icon: 'warning', |
| 104 |
title: data.confirmTitle, |
| 105 |
html: content, |
| 106 |
showCancelButton: true, |
| 107 |
confirmButtonText: data.confirmButton, |
| 108 |
cancelButtonText: data.cancelButton, |
| 109 |
focusConfirm: false, |
| 110 |
customClass: { |
| 111 |
popup: 'lp-admin-refund-modal', |
| 112 |
htmlContainer: 'lp-admin-refund-modal__content', |
| 113 |
actions: 'lp-admin-refund-modal__actions', |
| 114 |
}, |
| 115 |
preConfirm: () => { |
| 116 |
const refundAmount = parseFloat( amount.value ); |
| 117 |
if ( |
| 118 |
Number.isNaN( refundAmount ) || |
| 119 |
refundAmount <= 0 || |
| 120 |
refundAmount > data.orderTotal |
| 121 |
) { |
| 122 |
SweetAlert.showValidationMessage( data.amountInvalid ); |
| 123 |
return false; |
| 124 |
} |
| 125 |
|
| 126 |
return { |
| 127 |
note: message.value.trim(), |
| 128 |
refundAmount, |
| 129 |
}; |
| 130 |
}, |
| 131 |
} ); |
| 132 |
} |
| 133 |
|
| 134 |
sendAction( actionButton, panel, refundAction, refundAmount = 0, note = '' ) { |
| 135 |
const data = this.getPanelData( panel ); |
| 136 |
|
| 137 |
if ( ! data.orderId ) { |
| 138 |
lpToastify.show( 'Invalid order.', 'error' ); |
| 139 |
return; |
| 140 |
} |
| 141 |
|
| 142 |
this.isRequesting = true; |
| 143 |
this.setLoadingState( panel, true ); |
| 144 |
lpUtils.lpSetLoadingEl( actionButton, 1 ); |
| 145 |
|
| 146 |
window.lpAJAXG.fetchAJAX( |
| 147 |
{ |
| 148 |
action: 'admin_handle_request_refund', |
| 149 |
order_id: data.orderId, |
| 150 |
refund_action: refundAction, |
| 151 |
refund_amount: refundAmount, |
| 152 |
note, |
| 153 |
}, |
| 154 |
{ |
| 155 |
success: ( response ) => { |
| 156 |
const { status, message, data } = response; |
| 157 |
|
| 158 |
if ( status !== 'success' ) { |
| 159 |
throw new Error( message ); |
| 160 |
} |
| 161 |
|
| 162 |
lpToastify.show( message, 'success' ); |
| 163 |
this.isReloading = true; |
| 164 |
window.setTimeout( () => window.location.reload(), 1200 ); |
| 165 |
}, |
| 166 |
error: ( error ) => { |
| 167 |
const messageResponse = |
| 168 |
error?.message || error || 'Refund action failed.'; |
| 169 |
lpToastify.show( messageResponse, 'error' ); |
| 170 |
}, |
| 171 |
completed: () => { |
| 172 |
if ( this.isReloading ) { |
| 173 |
return; |
| 174 |
} |
| 175 |
|
| 176 |
this.isRequesting = false; |
| 177 |
this.setLoadingState( panel, false ); |
| 178 |
lpUtils.lpSetLoadingEl( actionButton, 0 ); |
| 179 |
}, |
| 180 |
}, |
| 181 |
); |
| 182 |
} |
| 183 |
|
| 184 |
async handleAction( args ) { |
| 185 |
const { e, target } = args; |
| 186 |
e.preventDefault(); |
| 187 |
|
| 188 |
const actionButton = target.closest( RefundOrder.selectors.action ); |
| 189 |
const panel = actionButton?.closest( RefundOrder.selectors.panel ); |
| 190 |
if ( ! actionButton || ! panel || this.isRequesting ) { |
| 191 |
return; |
| 192 |
} |
| 193 |
|
| 194 |
const refundAction = actionButton.dataset.refundAction || ''; |
| 195 |
let amount = ''; |
| 196 |
let note = ''; |
| 197 |
|
| 198 |
if ( 'reject' === refundAction ) { |
| 199 |
return this.sendAction( actionButton, panel, refundAction ); |
| 200 |
} |
| 201 |
|
| 202 |
const result = await this.openApproveModal( this.getPanelData( panel ) ); |
| 203 |
if ( result.isConfirmed && result.value ) { |
| 204 |
amount = result.value.refundAmount; |
| 205 |
note = result.value.note; |
| 206 |
this.sendAction( actionButton, panel, refundAction, amount, note ); |
| 207 |
} |
| 208 |
} |
| 209 |
} |
| 210 |
|
| 211 |
const refundOrder = () => { |
| 212 |
const refundOrderHandle = new RefundOrder(); |
| 213 |
|
| 214 |
lpUtils.lpOnElementReady( RefundOrder.selectors.action, () => { |
| 215 |
refundOrderHandle.init(); |
| 216 |
} ); |
| 217 |
}; |
| 218 |
|
| 219 |
export default refundOrder; |
| 220 |
|