diff --git a/admin/index.php b/admin/index.php
index bfcea6d..3092780 100644
--- a/admin/index.php
+++ b/admin/index.php
@@ -198,7 +198,7 @@ if ($isAjax) {
if (!$pid) { echo json_encode(['error'=>'No payment on file']); exit; }
$resp = squareApi('POST', "/payments/{$pid}/cancel");
if (($resp['payment']['status'] ?? '') === 'CANCELED') {
- db()->prepare("UPDATE bookings SET square_payment_status='CANCELED' WHERE id=?")->execute([$id]);
+ db()->prepare("UPDATE bookings SET square_payment_status='CANCELED', status='cancelled' WHERE id=?")->execute([$id]);
echo json_encode(['ok'=>true,'status'=>'CANCELED']);
} else {
echo json_encode(['error' => $resp['errors'][0]['detail'] ?? 'Void failed']);
@@ -221,7 +221,7 @@ if ($isAjax) {
'reason' => 'Security deposit refund — booking returned in good condition',
]);
if (!empty($resp['refund']['id'])) {
- db()->prepare("UPDATE bookings SET square_payment_status='REFUNDED', square_refund_id=?, deposit_paid=0 WHERE id=?")
+ db()->prepare("UPDATE bookings SET square_payment_status='REFUNDED', square_refund_id=?, deposit_paid=0, status='cancelled' WHERE id=?")
->execute([$resp['refund']['id'], $id]);
echo json_encode(['ok'=>true,'status'=>'REFUNDED']);
} else {
@@ -686,12 +686,12 @@ textarea.notes-ta:focus{border-color:#f97316}
-
+
-
+
@@ -812,7 +812,29 @@ textarea.notes-ta:focus{border-color:#f97316}
-
+
+
+
+ = $stepLicense?'✓':($cancelled?'—':'5') ?>
+
+
+ Driver's License Verified
+
+ = $stepLicense?'License verified':($cancelled?'N/A':'Verify at pickup') ?>
+
+
+
+
+
+
+
+
+
+
@@ -853,14 +876,18 @@ textarea.notes-ta:focus{border-color:#f97316}
-
-
+
+
+
+
-
-
+
+
+
+
-
-
-
- = $stepLicense?'✓':($cancelled?'—':'6') ?>
-
-
- Driver's License Verified
-
- = $stepLicense?'License verified':($cancelled?'N/A':'Verify at pickup') ?>
-
-
-
-
-
-
-
-
-
@@ -1010,14 +1015,14 @@ textarea.notes-ta:focus{border-color:#f97316}
>
Bring proof of insurance
-
+
+
+
+ = $stepLicense?'✓':($cancelled?'—':'5') ?>
+
+
+ Driver's License Verified
+
+ = $stepLicense?'Verified — on file':($cancelled?'N/A':'Verify at pickup') ?>
+
+
+
+
+
+
+
+
+
@@ -1316,9 +1341,9 @@ textarea.notes-ta:focus{border-color:#f97316}
-
+
-
+
-
-
- = $stepLicense?'✓':($cancelled?'—':'6') ?>
-
-
- Driver's License Verified
-
- = $stepLicense?'Verified — on file':($cancelled?'N/A':'Verify at pickup') ?>
-
-
-
-
-
-
-
-
-
Pre-Departure
@@ -1532,7 +1537,7 @@ function toggleReq(id, field, btn) {
const icon = document.getElementById('icon-'+id+'-'+field);
if (icon) {
icon.className = 'flow-icon ' + (on ? 'done' : 'pending');
- const stepNums = {insurance_verified:'4', deposit_received:'5', license_verified:'6', helmet_provided:'7', safety_course:'8', operational_course:'9'};
+ const stepNums = {insurance_verified:'4', license_verified:'5', deposit_received:'6', helmet_provided:'7', safety_course:'8', operational_course:'9'};
icon.textContent = on ? '✓' : (stepNums[field] || '?');
}
// Update meta text
@@ -1624,8 +1629,8 @@ function squareAction(id, action, btn) {
const [orig, working, done] = labels[action];
const confirmMsg = {
square_capture: 'Charge the $= number_format(DEPOSIT_AMOUNT,2) ?> deposit hold to this card?',
- square_void: 'Void the $= number_format(DEPOSIT_AMOUNT,2) ?> deposit hold? The customer will NOT be charged.',
- square_refund: 'Refund the deposit to this card?',
+ square_void: 'Void the $= number_format(DEPOSIT_AMOUNT,2) ?> deposit hold and CANCEL this booking? The customer will NOT be charged.',
+ square_refund: 'Refund the $= number_format(DEPOSIT_AMOUNT,2) ?> deposit and CANCEL this booking? This cannot be undone.',
}[action];
if (!confirm(confirmMsg)) return;
btn.disabled = true;
@@ -1650,19 +1655,31 @@ function squareAction(id, action, btn) {
if (dot) dot.className='dot dot-done';
// Replace action area with refund button
const area = document.getElementById('deposit-actions-'+id);
- if (area) area.innerHTML = ' ';
- } else if (d.status === 'CANCELED') {
- if (meta) meta.textContent = 'Hold voided — no charge';
+ if (area) area.innerHTML = ' ';
+ } else if (d.status === 'CANCELED' || d.status === 'REFUNDED') {
+ const t = d.status === 'CANCELED' ? 'Hold voided — booking cancelled' : 'Refunded — booking cancelled';
+ if (meta) meta.textContent = t;
if (icon) { icon.className='flow-icon skip'; icon.textContent='—'; }
if (dot) dot.className='dot dot-skip';
const area = document.getElementById('deposit-actions-'+id);
if (area) area.innerHTML = '';
- } else if (d.status === 'REFUNDED') {
- if (meta) meta.textContent = 'Refunded — deposit returned';
- if (icon) { icon.className='flow-icon pending'; icon.textContent='↩'; }
- if (dot) dot.className='dot dot-skip';
- const area = document.getElementById('deposit-actions-'+id);
- if (area) area.innerHTML = '';
+ // Update booking status selects and row data-status
+ document.querySelectorAll('select.status-sel[data-id="'+id+'"]').forEach(sel => {
+ sel.value = 'cancelled';
+ });
+ document.querySelectorAll('tr.booking-row, tr.detail-row').forEach(row => {
+ const s = row.querySelector('select[data-id="'+id+'"]');
+ if (s) row.dataset.status = 'cancelled';
+ });
+ // Update confirmed step icon
+ ['icon','cv-icon'].forEach(p => {
+ const el = document.getElementById(p+'-'+id+'-confirmed');
+ if (el) { el.className='flow-icon skip'; el.textContent='—'; }
+ });
+ ['meta','cv-meta'].forEach(p => {
+ const el = document.getElementById(p+'-'+id+'-confirmed');
+ if (el) el.textContent = 'Cancelled';
+ });
}
} else {
btn.textContent = orig;
@@ -1830,8 +1847,8 @@ function cvSquareAction(bid, action, btn) {
const [orig, working] = labels[action];
const confirmMsg = {
square_capture: 'Charge the $= number_format(DEPOSIT_AMOUNT,2) ?> deposit hold to this card?',
- square_void: 'Void the $= number_format(DEPOSIT_AMOUNT,2) ?> deposit hold? The customer will NOT be charged.',
- square_refund: 'Refund the deposit to this card?',
+ square_void: 'Void the $= number_format(DEPOSIT_AMOUNT,2) ?> deposit hold and CANCEL this booking? The customer will NOT be charged.',
+ square_refund: 'Refund the $= number_format(DEPOSIT_AMOUNT,2) ?> deposit and CANCEL this booking? This cannot be undone.',
}[action];
if (!confirm(confirmMsg)) return;
btn.disabled = true;
@@ -1853,13 +1870,13 @@ function cvSquareAction(bid, action, btn) {
const t = 'Captured — deposit charged';
if (cvMeta) cvMeta.textContent = t;
if (cvIcon) { cvIcon.className='flow-icon done'; cvIcon.textContent='✓'; }
- if (cvArea) cvArea.innerHTML = ' ';
+ if (cvArea) cvArea.innerHTML = ' ';
if (meta) meta.textContent = t;
if (icon) { icon.className='flow-icon done'; icon.textContent='✓'; }
if (dot) dot.className='dot dot-done';
- if (area) area.innerHTML = ' ';
- } else if (d.status === 'CANCELED') {
- const t = 'Hold voided — no charge';
+ if (area) area.innerHTML = ' ';
+ } else if (d.status === 'CANCELED' || d.status === 'REFUNDED') {
+ const t = d.status === 'CANCELED' ? 'Hold voided — booking cancelled' : 'Refunded — booking cancelled';
if (cvMeta) cvMeta.textContent = t;
if (cvIcon) { cvIcon.className='flow-icon skip'; cvIcon.textContent='—'; }
if (cvArea) cvArea.innerHTML = '';
@@ -1867,15 +1884,23 @@ function cvSquareAction(bid, action, btn) {
if (icon) { icon.className='flow-icon skip'; icon.textContent='—'; }
if (dot) dot.className='dot dot-skip';
if (area) area.innerHTML = '';
- } else if (d.status === 'REFUNDED') {
- const t = 'Refunded — deposit returned';
- if (cvMeta) cvMeta.textContent = t;
- if (cvIcon) { cvIcon.className='flow-icon pending'; cvIcon.textContent='↩'; }
- if (cvArea) cvArea.innerHTML = '';
- if (meta) meta.textContent = t;
- if (icon) { icon.className='flow-icon pending'; icon.textContent='↩'; }
- if (dot) dot.className='dot dot-skip';
- if (area) area.innerHTML = '';
+ // Update booking status selects and row data-status
+ document.querySelectorAll('select.status-sel[data-id="'+bid+'"]').forEach(sel => {
+ sel.value = 'cancelled';
+ });
+ document.querySelectorAll('tr.booking-row, tr.detail-row').forEach(row => {
+ const s = row.querySelector('select[data-id="'+bid+'"]');
+ if (s) row.dataset.status = 'cancelled';
+ });
+ // Update confirmed step icon
+ ['icon','cv-icon'].forEach(p => {
+ const el = document.getElementById(p+'-'+bid+'-confirmed');
+ if (el) { el.className='flow-icon skip'; el.textContent='—'; }
+ });
+ ['meta','cv-meta'].forEach(p => {
+ const el = document.getElementById(p+'-'+bid+'-confirmed');
+ if (el) el.textContent = 'Cancelled';
+ });
}
} else {
btn.textContent = orig;
|