mirror of
https://github.com/myronblair/parkerslingshot
synced 2026-06-30 17:50:22 -05:00
Fix multi-day full-day pricing: add days selector, multiply amount by rental days
This commit is contained in:
+12
-6
@@ -35,9 +35,13 @@ if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date) || strtotime($date) < strtotime(
|
|||||||
echo json_encode(['success'=>false,'error'=>'Invalid or past date.']); exit;
|
echo json_encode(['success'=>false,'error'=>'Invalid or past date.']); exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$pkg = PACKAGES[$package];
|
$pkg = PACKAGES[$package];
|
||||||
|
$rentalDays = ($package === 'full-day') ? max(1, min(3, (int)($input['rental_days'] ?? 1))) : 1;
|
||||||
$rentalDate = $date;
|
$rentalDate = $date;
|
||||||
$endDate = date('Y-m-d', strtotime($date . ' +' . $pkg['days'] . ' days'));
|
$endDate = ($package === 'full-day')
|
||||||
|
? date('Y-m-d', strtotime($date . ' +' . ($rentalDays - 1) . ' days'))
|
||||||
|
: date('Y-m-d', strtotime($date . ' +' . $pkg['days'] . ' days'));
|
||||||
|
$totalAmount = ($package === 'full-day') ? $pkg['amount'] * $rentalDays : $pkg['amount'];
|
||||||
|
|
||||||
// Check availability
|
// Check availability
|
||||||
$conflict = db()->prepare(
|
$conflict = db()->prepare(
|
||||||
@@ -57,10 +61,12 @@ if ($blockedCheck->fetch()) {
|
|||||||
|
|
||||||
$ref = generateRef();
|
$ref = generateRef();
|
||||||
$dateLabel = date('F j, Y', strtotime($rentalDate));
|
$dateLabel = date('F j, Y', strtotime($rentalDate));
|
||||||
$pkgLabel = $pkg['label'];
|
$pkgLabel = ($package === 'full-day' && $rentalDays > 1)
|
||||||
$amountLabel = '$' . number_format($pkg['amount'], 2);
|
? $pkg['label'] . ' × ' . $rentalDays . ' days'
|
||||||
|
: $pkg['label'];
|
||||||
|
$amountLabel = '$' . number_format($totalAmount, 2);
|
||||||
$depositLabel = '$' . number_format(DEPOSIT_AMOUNT, 2);
|
$depositLabel = '$' . number_format(DEPOSIT_AMOUNT, 2);
|
||||||
$balance = $pkg['amount'] - DEPOSIT_AMOUNT;
|
$balance = $totalAmount - DEPOSIT_AMOUNT;
|
||||||
$balanceLabel = '$' . number_format($balance, 2);
|
$balanceLabel = '$' . number_format($balance, 2);
|
||||||
|
|
||||||
// ── Square: create customer + card on file + deposit hold ─────────────────────
|
// ── Square: create customer + card on file + deposit hold ─────────────────────
|
||||||
@@ -143,7 +149,7 @@ $stmt = db()->prepare(
|
|||||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
|
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
|
||||||
);
|
);
|
||||||
$stmt->execute([
|
$stmt->execute([
|
||||||
$ref, $name, $email, $phone, $package, $rentalDate, $endDate, $pkg['amount'], $message,
|
$ref, $name, $email, $phone, $package, $rentalDate, $endDate, $totalAmount, $message,
|
||||||
$sqCustomerId, $sqCardId, $sqCardLast4, $sqCardBrand,
|
$sqCustomerId, $sqCardId, $sqCardLast4, $sqCardBrand,
|
||||||
$sqPaymentId, $sqPaymentStatus,
|
$sqPaymentId, $sqPaymentStatus,
|
||||||
]);
|
]);
|
||||||
|
|||||||
+40
-12
@@ -35,7 +35,7 @@
|
|||||||
"name": "Parker County Slingshot Rentals",
|
"name": "Parker County Slingshot Rentals",
|
||||||
"description": "Polaris Slingshot rentals in Parker County, Texas. Daily and weekend rentals available for thrill-seekers near Weatherford and the DFW metroplex.",
|
"description": "Polaris Slingshot rentals in Parker County, Texas. Daily and weekend rentals available for thrill-seekers near Weatherford and the DFW metroplex.",
|
||||||
"url": "https://parkerslingshotrentals.com",
|
"url": "https://parkerslingshotrentals.com",
|
||||||
"telephone": "+1-817-555-0199",
|
"telephone": "+1-817-266-2022",
|
||||||
"email": "info@parkerslingshotrentals.com",
|
"email": "info@parkerslingshotrentals.com",
|
||||||
"priceRange": "$$",
|
"priceRange": "$$",
|
||||||
"currenciesAccepted": "USD",
|
"currenciesAccepted": "USD",
|
||||||
@@ -768,7 +768,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="contact-detail">
|
<div class="contact-detail">
|
||||||
<span>📞</span>
|
<span>📞</span>
|
||||||
<a href="tel:+18175550199" style="color:inherit;text-decoration:none;">(817) 555-0199</a>
|
<a href="tel:+18172662022" style="color:inherit;text-decoration:none;">(817) 266-2022</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="contact-detail">
|
<div class="contact-detail">
|
||||||
<span>✉️</span>
|
<span>✉️</span>
|
||||||
@@ -808,9 +808,16 @@
|
|||||||
<select name="package" required>
|
<select name="package" required>
|
||||||
<option value="">Select Rental Package</option>
|
<option value="">Select Rental Package</option>
|
||||||
<option value="half-day">Half Day — $80</option>
|
<option value="half-day">Half Day — $80</option>
|
||||||
<option value="full-day">Full Day — $150</option>
|
<option value="full-day">Full Day — $150/day</option>
|
||||||
<option value="weekend">3 Day Adventure — $449</option>
|
<option value="weekend">3 Day Adventure — $449</option>
|
||||||
</select>
|
</select>
|
||||||
|
<div id="rental-days-row" style="display:none">
|
||||||
|
<select name="rental_days" id="rentalDaysSelect">
|
||||||
|
<option value="1">1 Day — $150</option>
|
||||||
|
<option value="2">2 Days — $300</option>
|
||||||
|
<option value="3">3 Days — $450</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<input type="date" name="date" required />
|
<input type="date" name="date" required />
|
||||||
<div id="date-unavail-msg" style="display:none;color:#f87171;font-size:.82rem;margin-top:.25rem">That date is already booked or unavailable. Please choose another.</div>
|
<div id="date-unavail-msg" style="display:none;color:#f87171;font-size:.82rem;margin-top:.25rem">That date is already booked or unavailable. Please choose another.</div>
|
||||||
<textarea name="message" placeholder="Anything else we should know? (optional)"></textarea>
|
<textarea name="message" placeholder="Anything else we should know? (optional)"></textarea>
|
||||||
@@ -1069,14 +1076,35 @@
|
|||||||
// ── Balance-due display ───────────────────────────────────────────────────────
|
// ── Balance-due display ───────────────────────────────────────────────────────
|
||||||
const PACKAGE_PRICES = { 'half-day': 80, 'full-day': 150, 'weekend': 449 };
|
const PACKAGE_PRICES = { 'half-day': 80, 'full-day': 150, 'weekend': 449 };
|
||||||
const DEPOSIT = 45;
|
const DEPOSIT = 45;
|
||||||
const pkgSelect = document.querySelector('select[name="package"]');
|
const pkgSelect = document.querySelector('select[name="package"]');
|
||||||
|
const rentalDaysSelect = document.getElementById('rentalDaysSelect');
|
||||||
|
const rentalDaysRow = document.getElementById('rental-days-row');
|
||||||
const balLabel = document.getElementById('balance-due-label');
|
const balLabel = document.getElementById('balance-due-label');
|
||||||
const balAmt = document.getElementById('balance-due-amount');
|
const balAmt = document.getElementById('balance-due-amount');
|
||||||
|
|
||||||
|
function calcTotal(pkg, days) {
|
||||||
|
const base = PACKAGE_PRICES[pkg];
|
||||||
|
if (!base) return null;
|
||||||
|
return pkg === 'full-day' ? base * days : base;
|
||||||
|
}
|
||||||
|
function updateBalance() {
|
||||||
|
const pkg = pkgSelect ? pkgSelect.value : '';
|
||||||
|
const days = rentalDaysSelect ? parseInt(rentalDaysSelect.value) || 1 : 1;
|
||||||
|
const total = calcTotal(pkg, days);
|
||||||
|
if (total && balLabel && balAmt) {
|
||||||
|
balAmt.textContent = '$' + (total - DEPOSIT).toFixed(2).replace(/\.00$/, '');
|
||||||
|
balLabel.style.display = '';
|
||||||
|
} else if (balLabel) {
|
||||||
|
balLabel.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pkgSelect) { selectedPackage = pkgSelect.value || 'half-day'; }
|
if (pkgSelect) { selectedPackage = pkgSelect.value || 'half-day'; }
|
||||||
if (pkgSelect) {
|
if (pkgSelect) {
|
||||||
pkgSelect.addEventListener('change', function() {
|
pkgSelect.addEventListener('change', function() {
|
||||||
selectedPackage = this.value;
|
selectedPackage = this.value;
|
||||||
updateLegend();
|
updateLegend();
|
||||||
|
if (rentalDaysRow) rentalDaysRow.style.display = this.value === 'full-day' ? '' : 'none';
|
||||||
if (selectedDates.size > 0) {
|
if (selectedDates.size > 0) {
|
||||||
Promise.all([...selectedDates].map(d => hasRangeConflict(d, selectedPackage).then(c => c ? d : null)))
|
Promise.all([...selectedDates].map(d => hasRangeConflict(d, selectedPackage).then(c => c ? d : null)))
|
||||||
.then(conflicts => {
|
.then(conflicts => {
|
||||||
@@ -1087,15 +1115,12 @@
|
|||||||
renderCalendar(calMonth, calYear);
|
renderCalendar(calMonth, calYear);
|
||||||
});
|
});
|
||||||
} else { renderCalendar(calMonth, calYear); }
|
} else { renderCalendar(calMonth, calYear); }
|
||||||
const price = PACKAGE_PRICES[this.value];
|
updateBalance();
|
||||||
if (price && balLabel && balAmt) {
|
|
||||||
balAmt.textContent = '$' + (price - DEPOSIT).toFixed(2).replace(/\.00$/, '');
|
|
||||||
balLabel.style.display = '';
|
|
||||||
} else if (balLabel) {
|
|
||||||
balLabel.style.display = 'none';
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (rentalDaysSelect) {
|
||||||
|
rentalDaysSelect.addEventListener('change', updateBalance);
|
||||||
|
}
|
||||||
|
|
||||||
// ── Square Web Payments ───────────────────────────────────────────────────────
|
// ── Square Web Payments ───────────────────────────────────────────────────────
|
||||||
let squareCard = null;
|
let squareCard = null;
|
||||||
@@ -1166,11 +1191,14 @@
|
|||||||
setDepStatus('Card verified — authorizing $45 deposit hold…', 'processing');
|
setDepStatus('Card verified — authorizing $45 deposit hold…', 'processing');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const pkgVal = form.querySelector('[name="package"]').value;
|
||||||
|
const daysVal = pkgVal === 'full-day' ? (parseInt(form.querySelector('[name="rental_days"]')?.value) || 1) : 1;
|
||||||
const data = {
|
const data = {
|
||||||
name: form.querySelector('[name="name"]').value,
|
name: form.querySelector('[name="name"]').value,
|
||||||
email: form.querySelector('[name="email"]').value,
|
email: form.querySelector('[name="email"]').value,
|
||||||
phone: form.querySelector('[name="phone"]').value,
|
phone: form.querySelector('[name="phone"]').value,
|
||||||
package: form.querySelector('[name="package"]').value,
|
package: pkgVal,
|
||||||
|
rental_days: daysVal,
|
||||||
date: form.querySelector('[name="date"]').value,
|
date: form.querySelector('[name="date"]').value,
|
||||||
message: form.querySelector('[name="message"]').value,
|
message: form.querySelector('[name="message"]').value,
|
||||||
square_token: squareToken,
|
square_token: squareToken,
|
||||||
|
|||||||
Reference in New Issue
Block a user