Add visual booking calendar (weekly Teams-style view)

- New weekly calendar at /bookings/calendar with time blocks per booking
- Color-coded by worker, overlapping bookings shown side-by-side
- Click booking to see details, edit or delete
- Worker filter dropdown, week navigation (prev/next/today)
- AJAX week loading for smooth navigation
- Link between list view and calendar view

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ubuntu
2026-05-07 14:03:41 +00:00
co-authored by Claude Opus 4.6
parent a100acddec
commit 6abb90329d
6 changed files with 584 additions and 0 deletions
+50
View File
@@ -795,6 +795,56 @@ class Service_model extends CI_Model {
return $query->num_rows() > 0;
}
public function getBookingsByDateRange($startDate, $endDate, $workerId = null) {
$this->load->database();
$sql = 'SELECT b.*, w.worker_name, w.worker_profile_img
FROM bookings b
JOIN workers w ON b.worker_id = w.worker_id
WHERE b.booking_date BETWEEN ? AND ?';
$params = array($startDate, $endDate);
if ($workerId) {
$sql .= ' AND b.worker_id = ?';
$params[] = $workerId;
}
$sql .= ' ORDER BY b.booking_date, b.booking_start_time';
$query = $this->db->query($sql, $params);
if ($query->num_rows() == 0) return array();
$resultsArray = array();
foreach ($query->result() as $row) {
$resultTmp = (array)$row;
$resultTmp['services'] = array();
$resultTmp['service_names_joined'] = '';
if (!empty($resultTmp['service_ids'])) {
$servicesArr = unserialize($resultTmp['service_ids']);
if (is_array($servicesArr)) {
$names = array();
foreach ($servicesArr as $sid) {
$svc = $this->getServiceById($sid);
if (is_object($svc)) {
$resultTmp['services'][] = (object)array(
'service_name' => $svc->service_name_hu,
'service_price' => $svc->service_price,
'service_time' => $svc->service_time
);
$names[] = $svc->service_name_hu;
}
}
$resultTmp['service_names_joined'] = implode(', ', $names);
}
}
$resultsArray[] = (object)$resultTmp;
}
return $resultsArray;
}