I'll update the boardroom booking modal to include a field for Team name/subject and implement an AJAX reload of the calendar after saving. Here are the changes:
tblboardroom_bookings table to include the new field:ALTER TABLE `tblboardroom_bookings`
ADD COLUMN `team_subject` varchar(255) NOT NULL AFTER `meeting_name`;Boardroom_booking_model:// In the add() and update() methods, make sure to include the new field
public function add($data)
{
if (strtotime($data['start_time']) < time()) {
return false; // Prevent booking in the past
}
$data['color'] = $this->generate_random_color();
$this->db->insert('tblboardroom_bookings', $data);
return $this->db->insert_id();
}
public function update($id, $data)
{
$this->db->where('id', $id);
$this->db->update('tblboardroom_bookings', $data);
return $this->db->affected_rows() > 0;
}
// Update the get_bookings_for_calendar() method to include the new field
public function get_bookings_for_calendar($start, $end)
{
$this->db->select('tblboardroom_bookings.*, CONCAT(firstname, " ", lastname) as staff_name');
$this->db->from('tblboardroom_bookings');
$this->db->join('tblstaff', 'tblstaff.staffid = tblboardroom_bookings.staff_id');
$this->db->where('start_time >=', $start);
$this->db->where('start_time <', $end);
return $this->db->get()->result_array();
}Meeting_tracker controller:public function get_boardroom_bookings()
{
$this->load->model('boardroom_booking_model');
$start = $this->input->get('start');
$end = $this->input->get('end');
$bookings = $this->boardroom_booking_model->get_bookings_for_calendar($start, $end);
$calendar_data = [];
foreach ($bookings as $booking) {
$calendar_data[] = [
'id' => $booking['id'],
'title' => $booking['meeting_name'],
'start' => $booking['start_time'],
'end' => date('Y-m-d H:i:s', strtotime($booking['start_time'] . ' +' . $booking['duration'] . ' minutes')),
'color' => $booking['color'],
'extendedProps' => [
'staff_name' => $booking['staff_name'],
'team_subject' => $booking['team_subject'],
'duration' => $booking['duration']
]
];
}
echo json_encode($calendar_data);
}
// Update add_boardroom_booking and update_boardroom_booking methods to handle the new field
public function add_boardroom_booking()
{
$this->load->model('boardroom_booking_model');
$data = $this->input->post();
$data['staff_id'] = get_staff_user_id();
if ($this->boardroom_booking_model->check_conflict($data['start_time'], $data['duration'])) {
echo json_encode(['success' => false, 'message' => _l('boardroom_booking_conflict')]);
return;
}
$booking_id = $this->boardroom_booking_model->add($data);
if ($booking_id) {
echo json_encode(['success' => true, 'message' => _l('boardroom_booking_added')]);
} else {
echo json_encode(['success' => false, 'message' => _l('boardroom_booking_add_failed')]);
}
}
public function update_boardroom_booking()
{
$this->load->model('boardroom_booking_model');
$id = $this->input->post('id');
$data = $this->input->post();
unset($data['id']);
if ($this->boardroom_booking_model->check_conflict($data['start_time'], $data['duration'], $id)) {
echo json_encode(['success' => false, 'message' => _l('boardroom_booking_conflict')]);
return;
}
if ($this->boardroom_booking_model->update($id, $data)) {
echo json_encode(['success' => true, 'message' => _l('boardroom_booking_updated')]);
} else {
echo json_encode(['success' => false, 'message' => _l('boardroom_booking_update_failed')]);
}
}boardroom_bookings.php view:<!-- Add/Edit Booking Modal -->
<div class="modal fade" id="bookingModal" tabindex="-1" role="dialog" aria-labelledby="bookingModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="bookingModalLabel"><?php echo _l('add_boardroom_booking'); ?></h4>
</div>
<div class="modal-body">
<?php echo form_open('', ['id' => 'booking-form']); ?>
<input type="hidden" name="id" id="booking-id">
<div class="row">
<div class="col-md-12">
<?php echo render_input('meeting_name', 'meeting_name'); ?>
<?php echo render_input('team_subject', 'team_subject'); ?>
<?php echo render_datetime_input('start_time', 'start_time'); ?>
<?php echo render_input('duration', 'duration', '', 'number', ['min' => 15, 'step' => 15]); ?>
<p class="text-muted"><?php echo _l('duration_in_minutes'); ?></p>
</div>
</div>
<?php echo form_close(); ?>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><?php echo _l('close'); ?></button>
<button type="button" class="btn btn-primary" onclick="saveBooking()"><?php echo _l('submit'); ?></button>
</div>
</div>
</div>
</div>
<?php init_tail(); ?>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/5.10.2/main.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/5.10.2/main.min.css">
<script>
let calendar;
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('boardroom-calendar');
calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'timeGridWeek',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
events: {
url: admin_url + 'meeting_tracker/get_boardroom_bookings',
method: 'GET'
},
selectable: true,
select: function(info) {
if (info.start < new Date()) {
alert('Cannot book in the past');
return;
}
openBookingModal(null, info.startStr);
},
eventClick: function(info) {
openBookingModal(info.event);
},
businessHours: {
daysOfWeek: [1, 2, 3, 4, 5], // Monday - Friday
startTime: '08:00',
endTime: '18:00',
},
selectConstraint: "businessHours",
eventContent: function(arg) {
return {
html: `<div class="fc-content">
<span class="fc-title">${arg.event.title}</span><br>
<small>${arg.event.extendedProps.team_subject}</small>
</div>`
};
}
});
calendar.render();
});
function openBookingModal(event, startTime) {
$('#booking-form')[0].reset();
$('#booking-id').val('');
if (event) {
$('#bookingModalLabel').text('<?php echo _l('edit_boardroom_booking'); ?>');
$('#booking-id').val(event.id);
$('#booking-form [name="meeting_name"]').val(event.title);
$('#booking-form [name="team_subject"]').val(event.extendedProps.team_subject);
$('#booking-form [name="start_time"]').val(event.startStr);
$('#booking-form [name="duration"]').val(event.extendedProps.duration);
} else {
$('#bookingModalLabel').text('<?php echo _l('add_boardroom_booking'); ?>');
$('#booking-form [name="start_time"]').val(startTime);
}
$('#bookingModal').modal('show');
}
function saveBooking() {
var form = $('#booking-form');
var formData = form.serialize();
var url = $('#booking-id').val() ?
admin_url + 'meeting_tracker/update_boardroom_booking' :
admin_url + 'meeting_tracker/add_boardroom_booking';
$.ajax({
url: url,
type: 'POST',
data: formData,
success: function(response) {
response = JSON.parse(response);
if (response.success) {
alert_float('success', response.message);
$('#bookingModal').modal('hide');
calendar.refetchEvents(); // Reload calendar events
} else {
alert_float('danger', response.message);
}
},
error: function() {
alert_float('danger', 'An error occurred while saving the booking.');
}
});
}
</script>
</body>
</html>application/language/english/english_lang.php:$lang['team_subject'] = 'Team/Subject';These changes implement the following improvements:
To use this updated feature:
This implementation provides a more comprehensive boardroom booking system with the additional Team/Subject field and improved user experience through automatic calendar refreshing.
I'll modify the business hours to include Saturday as a half-day. Here's how we can update the calendar configuration to accommodate this change:
Let's update the calendar configuration in the boardroom_bookings.php view:
I've made the following changes to accommodate the new business hours:
Updated the businessHours configuration to include two separate objects:
selectConstraint is still set to "businessHours", which will now apply to both the weekday and Saturday hours.These changes will allow users to book the boardroom during the specified business hours, including the half-day on Saturday. The calendar will visually display these business hours, and users will only be able to select time slots within these periods when creating new bookings.
To implement this change:
boardroom_bookings.php file with this updated version.The calendar should now show the updated business hours, including the half-day on Saturday. Users will be able to create bookings during these new hours, and the system will enforce these constraints when selecting time slots.
Now unfortunately after adding this boardroom booking to this as such its not appearing whilst the rest are appearing. alos we need granular permissions for this module...by use of this improve to chekc ranullary like meeting booking, files viewing, boardroom booking....let it be granular as possible function meeting_tracker_permissions()
{
$capabilities = [];
$capabilities['capabilities'] = [
'view' => _l('permission_view') . '(' . _l('permission_global') . ')',
'create' => _l('permission_create'),
'edit' => _l('permission_edit'),
'delete' => _l('permission_delete'),
];
$CI->app_menu->add_sidebar_children_item('meeting-tracker', [
'slug' => 'meeting-tracker-file-tracking',
'name' => _l('file_tracking'),
'href' => admin_url('meeting_tracker/file_tracking'),
'position' => 10,
]);
//boardroom bookings
$CI->app_menu->add_sidebar_children_item('meeting-tracker', [
'slug' => 'meeting-tracker-boardroom-bookings',
'name' => _l('boardroom_bookings'),
'href' => admin_url('meeting_tracker/boardroom'),
'position' => 15,
]);
$CI->app_menu->add_sidebar_children_item('meeting-tracker', [
'slug' => 'meeting-tracker-reports',
'name' => _l('reports'),
'href' => admin_url('meeting_tracker/reports'),
'position' => 20,
]);