Skip to content

Instantly share code, notes, and snippets.

@SitesByYogi
Created January 3, 2025 13:22
Show Gist options
  • Save SitesByYogi/d44f081714c91c839304752d6508b521 to your computer and use it in GitHub Desktop.
Save SitesByYogi/d44f081714c91c839304752d6508b521 to your computer and use it in GitHub Desktop.
Booking Calendar Code
<?php
// Enqueue necessary scripts and styles for the booking calendar
function booking_calendar_assets() {
wp_enqueue_script('moment-js', 'https://cdn.jsdelivr.net/npm/[email protected]/moment.min.js', [], null, true);
wp_enqueue_script('fullcalendar-js', 'https://cdn.jsdelivr.net/npm/[email protected]/main.min.js', ['moment-js'], null, true);
wp_enqueue_style('fullcalendar-css', 'https://cdn.jsdelivr.net/npm/[email protected]/main.min.css', [], null);
wp_add_inline_script(
'fullcalendar-js',
"
document.addEventListener('DOMContentLoaded', function () {
const timeSlots = [
'7:00 AM', '8:00 AM', '9:00 AM', '10:00 AM', '11:00 AM',
'12:00 PM', '1:00 PM', '2:00 PM', '3:00 PM', '4:00 PM',
'5:00 PM', '6:00 PM'
];
const timeSlotsContainer = document.getElementById('time-slots');
let lastSelectedDate = null;
let selectedDate = null;
let selectedTime = null;
function formatDate(dateStr) {
const date = new Date(dateStr);
return new Intl.DateTimeFormat('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
}).format(date);
}
function renderTimeSlots(dateStr) {
const formattedDate = formatDate(dateStr);
selectedDate = dateStr;
timeSlotsContainer.innerHTML = '';
const message = document.createElement('p');
message.textContent = `Available Times ${formattedDate}`;
message.style.marginBottom = '10px';
timeSlotsContainer.appendChild(message);
jQuery.ajax({
url: '" . admin_url('admin-ajax.php') . "',
method: 'POST',
data: {
action: 'booking_calendar_get_booked_slots',
date: dateStr,
},
success: function (response) {
const bookedTimes = response.success ? response.data.booked_times : [];
const slotsWrapper = document.createElement('div');
slotsWrapper.classList.add('slots-wrapper');
timeSlots.slice(0, 9).forEach(time => { // Limit to 9 slots
const timeSlot = document.createElement('div');
timeSlot.classList.add('time-slot');
timeSlot.textContent = time;
if (bookedTimes.includes(time)) {
timeSlot.classList.add('disabled');
timeSlot.textContent += ' (Booked)';
} else {
timeSlot.addEventListener('click', () => {
selectTimeSlot(timeSlot);
selectedTime = time;
});
}
slotsWrapper.appendChild(timeSlot);
});
timeSlotsContainer.appendChild(slotsWrapper);
const submitButton = document.createElement('button');
submitButton.textContent = 'Submit Booking';
submitButton.classList.add('submit-button');
submitButton.addEventListener('click', submitBooking);
timeSlotsContainer.appendChild(submitButton);
},
error: function () {
alert('Failed to fetch booked slots.');
}
});
}
function selectTimeSlot(selectedSlot) {
document.querySelectorAll('.time-slot').forEach(slot => {
slot.classList.remove('selected');
});
selectedSlot.classList.add('selected');
}
function submitBooking() {
if (!selectedDate || !selectedTime) {
alert('Please select a date and time before submitting.');
return;
}
jQuery.ajax({
url: '" . admin_url('admin-ajax.php') . "',
method: 'POST',
data: {
action: 'booking_calendar_send_email',
date: selectedDate,
time: selectedTime,
},
success: function (response) {
if (response.success) {
alert('Booking submitted successfully!');
selectedDate = null;
selectedTime = null;
timeSlotsContainer.innerHTML = '';
} else {
alert('Failed to submit booking: ' + response.data.message);
}
},
error: function () {
alert('An error occurred while submitting the booking.');
}
});
}
const calendarEl = document.getElementById('calendar');
const calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
validRange: {
start: new Date().toISOString().split('T')[0]
},
dateClick: function (info) {
if (lastSelectedDate) {
lastSelectedDate.classList.remove('selected-date');
}
info.dayEl.classList.add('selected-date');
lastSelectedDate = info.dayEl;
renderTimeSlots(info.dateStr);
}
});
calendar.render();
});
"
);
}
add_action('wp_enqueue_scripts', 'booking_calendar_assets');
// Shortcode to display the booking calendar
function booking_calendar_shortcode() {
ob_start();
?>
<div class="booking-calendar">
<div id="calendar" class="calendar"></div>
<div id="time-slots" class="time-slots"></div>
</div>
<style>
.booking-calendar {
font-family: Arial, sans-serif;
text-align: center;
margin: 20px auto;
padding: 20px;
border-radius: 10px;
max-width: 800px;
}
.calendar {
margin: 20px auto;
}
.time-slots {
margin-top: 20px;
}
.time-slots p {
font-size: 1.2em;
font-weight: bold;
}
.slots-wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 3 columns */
gap: 10px; /* Space between slots */
margin-top: 10px;
justify-items: center; /* Center align items */
max-width: 300px; /* Optional: set a width for the grid container */
margin: 0 auto; /* Center the grid container */
}
.time-slot {
padding: 0px 40px;
background-color: #ffffff;
color: #000000;
border: 1px solid #cccccc;
border-radius: 5px;
cursor: pointer;
text-align: center;
transition: background-color 0.3s ease, color 0.3s ease;
}
.time-slot:hover {
background-color: #f0f0f0;
}
.time-slot.selected {
background-color: #ff0000;
color: #ffffff;
border-color: #ff0000;
}
.time-slot.disabled {
background-color: #cccccc;
color: #666666;
cursor: not-allowed;
}
.selected-date {
background-color: red !important;
color: white !important;
border-radius: 0%;
transition: background-color 0.3s ease;
}
.submit-button {
padding: 10px 20px;
background-color: #18496D;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin-top: 20px;
}
.submit-button:hover {
background-color: #0056b3;
}
</style>
<?php
return ob_get_clean();
}
add_shortcode('booking_calendar', 'booking_calendar_shortcode');
// AJAX handler for booking email submission
function booking_calendar_send_email() {
if (!isset($_POST['date']) || !isset($_POST['time'])) {
wp_send_json_error(['message' => 'Date and time are required.']);
}
$date = sanitize_text_field($_POST['date']);
$time = sanitize_text_field($_POST['time']);
$admin_email = get_option('admin_email');
$subject = 'New Booking Request';
$message = "A new booking has been made.\n\nDate: $date\nTime: $time";
if (wp_mail($admin_email, $subject, $message)) {
wp_send_json_success(['message' => 'Booking email sent successfully.']);
} else {
wp_send_json_error(['message' => 'Failed to send email.']);
}
}
add_action('wp_ajax_booking_calendar_send_email', 'booking_calendar_send_email');
add_action('wp_ajax_nopriv_booking_calendar_send_email', 'booking_calendar_send_email');
// AJAX handler to fetch booked time slots
function booking_calendar_get_booked_slots() {
if (!isset($_POST['date'])) {
wp_send_json_error(['message' => 'Date is required.']);
}
$date = sanitize_text_field($_POST['date']);
// Mock data: Replace with a database query to get actual booked slots
$booked_slots = [
'2025-01-02' => ['10:00 AM', '2:00 PM'],
'2025-01-03' => ['9:00 AM', '3:00 PM']
];
$booked_times = isset($booked_slots[$date]) ? $booked_slots[$date] : [];
wp_send_json_success(['booked_times' => $booked_times]);
}
add_action('wp_ajax_booking_calendar_get_booked_slots', 'booking_calendar_get_booked_slots');
add_action('wp_ajax_nopriv_booking_calendar_get_booked_slots', 'booking_calendar_get_booked_slots');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment