234 lines
9.7 KiB
HTML
234 lines
9.7 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Order Confirmation</title>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f7; padding: 20px; }
|
|
|
|
.order-card { background: #fff; border-radius: 16px; border: 1px solid #e5e5ea; overflow: hidden; max-width: 480px; margin: 0 auto; }
|
|
.order-header { padding: 20px 24px 16px; border-bottom: 1px solid #f0f0f0; }
|
|
.order-title { font-size: 20px; font-weight: 700; color: #1d1d1f; }
|
|
.order-id { font-size: 13px; color: #86868b; margin-top: 4px; }
|
|
|
|
.order-items { padding: 16px 24px; }
|
|
.order-item { display: flex; align-items: center; padding: 12px 0; border-bottom: 1px solid #f5f5f7; }
|
|
.order-item:last-child { border-bottom: none; }
|
|
.item-img { width: 48px; height: 48px; border-radius: 10px; object-fit: cover; background: #f0f0f0; margin-right: 12px; flex-shrink: 0; }
|
|
.item-img-placeholder { width: 48px; height: 48px; border-radius: 10px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
display: flex; align-items: center; justify-content: center; color: #fff; font-size: 18px; font-weight: 600; margin-right: 12px; flex-shrink: 0; }
|
|
.item-info { flex: 1; min-width: 0; }
|
|
.item-name { font-size: 15px; font-weight: 500; color: #1d1d1f; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
.item-qty { font-size: 13px; color: #86868b; margin-top: 2px; }
|
|
.item-price { font-size: 15px; font-weight: 600; color: #1d1d1f; flex-shrink: 0; margin-left: 12px; }
|
|
|
|
.order-summary { padding: 16px 24px; border-top: 1px solid #e5e5ea; background: #fafafa; }
|
|
.summary-row { display: flex; justify-content: space-between; padding: 4px 0; font-size: 14px; color: #6e6e73; }
|
|
.summary-row.discount { color: #34c759; }
|
|
.summary-row.total { padding-top: 12px; margin-top: 8px; border-top: 1px solid #e5e5ea;
|
|
font-size: 18px; font-weight: 700; color: #1d1d1f; }
|
|
|
|
.payment-section { padding: 20px 24px; }
|
|
.payment-qr { display: flex; flex-direction: column; align-items: center; padding: 16px 0; }
|
|
.payment-qr img { width: 160px; height: 160px; border-radius: 8px; border: 1px solid #e5e5ea; }
|
|
.payment-qr-hint { font-size: 13px; color: #86868b; margin-top: 8px; }
|
|
|
|
.btn-row { display: flex; gap: 10px; }
|
|
.btn { flex: 1; padding: 14px; border: none; border-radius: 12px; font-size: 15px; font-weight: 600; cursor: pointer; transition: all 0.15s; }
|
|
.btn-primary { background: #0071e3; color: #fff; }
|
|
.btn-primary:hover { background: #0077ed; }
|
|
.btn-primary:active { background: #005bb5; }
|
|
.btn-secondary { background: #f5f5f7; color: #1d1d1f; border: 1px solid #d1d1d6; }
|
|
.btn-secondary:hover { background: #e8e8ed; }
|
|
.btn-link { background: #34c759; color: #fff; text-decoration: none; text-align: center; display: block; }
|
|
.btn-link:hover { background: #2db84d; }
|
|
|
|
.success-overlay { display: none; position: absolute; top: 0; left: 0; right: 0; bottom: 0;
|
|
background: rgba(255,255,255,0.95); border-radius: 16px;
|
|
flex-direction: column; align-items: center; justify-content: center; }
|
|
.success-overlay.show { display: flex; }
|
|
.success-icon { font-size: 48px; margin-bottom: 12px; }
|
|
.success-text { font-size: 18px; font-weight: 600; color: #1d1d1f; }
|
|
.success-sub { font-size: 14px; color: #86868b; margin-top: 4px; }
|
|
|
|
.order-card-wrapper { position: relative; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="order-card-wrapper">
|
|
<div class="order-card" id="order-card"></div>
|
|
<div class="success-overlay" id="success-overlay">
|
|
<div class="success-icon" id="success-icon"></div>
|
|
<div class="success-text" id="success-text"></div>
|
|
<div class="success-sub" id="success-sub"></div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
(function () {
|
|
function esc(t) { var d = document.createElement('div'); d.textContent = t; return d.innerHTML; }
|
|
|
|
function render(payload) {
|
|
var card = document.getElementById('order-card');
|
|
card.innerHTML = '';
|
|
var order = payload.order || {};
|
|
var payment = payload.payment || {};
|
|
var currency = order.currency || '$';
|
|
|
|
// Header
|
|
var header = document.createElement('div');
|
|
header.className = 'order-header';
|
|
header.innerHTML = '<div class="order-title">' + esc(payload.title || 'Order Confirmation') + '</div>'
|
|
+ (order.order_id ? '<div class="order-id">Order #' + esc(order.order_id) + '</div>' : '');
|
|
card.appendChild(header);
|
|
|
|
// Items
|
|
var itemsDiv = document.createElement('div');
|
|
itemsDiv.className = 'order-items';
|
|
(order.items || []).forEach(function (item) {
|
|
var row = document.createElement('div');
|
|
row.className = 'order-item';
|
|
|
|
if (item.image) {
|
|
var img = document.createElement('img');
|
|
img.className = 'item-img';
|
|
img.src = item.image;
|
|
img.onerror = function () {
|
|
var ph = document.createElement('div');
|
|
ph.className = 'item-img-placeholder';
|
|
ph.textContent = (item.name || 'I').charAt(0).toUpperCase();
|
|
row.replaceChild(ph, img);
|
|
};
|
|
row.appendChild(img);
|
|
} else {
|
|
var ph = document.createElement('div');
|
|
ph.className = 'item-img-placeholder';
|
|
ph.textContent = (item.name || 'I').charAt(0).toUpperCase();
|
|
row.appendChild(ph);
|
|
}
|
|
|
|
var info = document.createElement('div');
|
|
info.className = 'item-info';
|
|
info.innerHTML = '<div class="item-name">' + esc(item.name || '') + '</div>'
|
|
+ '<div class="item-qty">x' + (item.quantity || 1) + '</div>';
|
|
row.appendChild(info);
|
|
|
|
var price = document.createElement('div');
|
|
price.className = 'item-price';
|
|
price.textContent = currency + ((item.price || 0) * (item.quantity || 1)).toFixed(2);
|
|
row.appendChild(price);
|
|
|
|
itemsDiv.appendChild(row);
|
|
});
|
|
card.appendChild(itemsDiv);
|
|
|
|
// Summary
|
|
var summary = document.createElement('div');
|
|
summary.className = 'order-summary';
|
|
if (order.subtotal !== undefined) {
|
|
summary.innerHTML += '<div class="summary-row"><span>Subtotal</span><span>' + currency + (order.subtotal || 0).toFixed(2) + '</span></div>';
|
|
}
|
|
if (order.tax) {
|
|
summary.innerHTML += '<div class="summary-row"><span>Tax</span><span>' + currency + order.tax.toFixed(2) + '</span></div>';
|
|
}
|
|
if (order.discount) {
|
|
summary.innerHTML += '<div class="summary-row discount"><span>Discount</span><span>-' + currency + order.discount.toFixed(2) + '</span></div>';
|
|
}
|
|
summary.innerHTML += '<div class="summary-row total"><span>Total</span><span>' + currency + (order.total || 0).toFixed(2) + '</span></div>';
|
|
card.appendChild(summary);
|
|
|
|
// Payment
|
|
var payDiv = document.createElement('div');
|
|
payDiv.className = 'payment-section';
|
|
|
|
if (payment.method === 'qrcode' && payment.qrcode_url) {
|
|
var qrDiv = document.createElement('div');
|
|
qrDiv.className = 'payment-qr';
|
|
qrDiv.innerHTML = '<img src="' + esc(payment.qrcode_url) + '" alt="Payment QR Code">'
|
|
+ '<div class="payment-qr-hint">Scan to pay</div>';
|
|
payDiv.appendChild(qrDiv);
|
|
}
|
|
|
|
var btnRow = document.createElement('div');
|
|
btnRow.className = 'btn-row';
|
|
|
|
// Cancel button
|
|
var cancelBtn = document.createElement('button');
|
|
cancelBtn.className = 'btn btn-secondary';
|
|
cancelBtn.textContent = 'Cancel';
|
|
cancelBtn.addEventListener('click', function () {
|
|
showOverlay('cancelled');
|
|
window.parent.postMessage({
|
|
type: 'mcp-app-response',
|
|
payload: { action: 'cancel', order_id: order.order_id || '' }
|
|
}, '*');
|
|
});
|
|
btnRow.appendChild(cancelBtn);
|
|
|
|
if (payment.method === 'link' && payment.payment_url) {
|
|
var linkBtn = document.createElement('a');
|
|
linkBtn.className = 'btn btn-link';
|
|
linkBtn.href = payment.payment_url;
|
|
linkBtn.target = '_blank';
|
|
linkBtn.rel = 'noopener';
|
|
linkBtn.textContent = payment.button_text || 'Pay Now';
|
|
linkBtn.addEventListener('click', function () {
|
|
setTimeout(function () {
|
|
showOverlay('confirmed');
|
|
window.parent.postMessage({
|
|
type: 'mcp-app-response',
|
|
payload: { action: 'confirm', order_id: order.order_id || '' }
|
|
}, '*');
|
|
}, 500);
|
|
});
|
|
btnRow.appendChild(linkBtn);
|
|
} else {
|
|
var confirmBtn = document.createElement('button');
|
|
confirmBtn.className = 'btn btn-primary';
|
|
confirmBtn.textContent = payment.button_text || 'Confirm Payment';
|
|
confirmBtn.addEventListener('click', function () {
|
|
showOverlay('confirmed');
|
|
window.parent.postMessage({
|
|
type: 'mcp-app-response',
|
|
payload: { action: 'confirm', order_id: order.order_id || '' }
|
|
}, '*');
|
|
});
|
|
btnRow.appendChild(confirmBtn);
|
|
}
|
|
|
|
payDiv.appendChild(btnRow);
|
|
card.appendChild(payDiv);
|
|
}
|
|
|
|
function showOverlay(type) {
|
|
var overlay = document.getElementById('success-overlay');
|
|
var icon = document.getElementById('success-icon');
|
|
var text = document.getElementById('success-text');
|
|
var sub = document.getElementById('success-sub');
|
|
if (type === 'confirmed') {
|
|
icon.textContent = '\u2705';
|
|
text.textContent = 'Payment Confirmed';
|
|
sub.textContent = 'Your order has been placed successfully!';
|
|
} else {
|
|
icon.textContent = '\u274C';
|
|
text.textContent = 'Order Cancelled';
|
|
sub.textContent = 'Your order has been cancelled.';
|
|
}
|
|
overlay.classList.add('show');
|
|
}
|
|
|
|
window.addEventListener('message', function (event) {
|
|
var msg = event.data;
|
|
if (msg && msg.type === 'mcp-app-data') {
|
|
document.getElementById('success-overlay').classList.remove('show');
|
|
render(msg.payload);
|
|
}
|
|
});
|
|
|
|
window.parent.postMessage({ type: 'mcp-app-ready' }, '*');
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|