From 6abb90329d26f6264b0a71c89e897dd68d91a394 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 7 May 2026 14:03:41 +0000 Subject: [PATCH] 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 --- application/config/routes.php | 2 + application/controllers/Admin.php | 90 ++++ application/models/Service_model.php | 50 ++ application/views/admin/booking-calendar.php | 5 + .../admin/includes/booking-calendar-form.php | 436 ++++++++++++++++++ .../views/admin/includes/bookings-form.php | 1 + 6 files changed, 584 insertions(+) create mode 100644 application/views/admin/booking-calendar.php create mode 100644 application/views/admin/includes/booking-calendar-form.php diff --git a/application/config/routes.php b/application/config/routes.php index 0203361..118875b 100755 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -95,6 +95,8 @@ $route['workers/store-calendar-override'] = 'admin/store_calendar_override'; $route['workers/delete-calendar-override'] = 'admin/delete_calendar_override'; $route['bookings'] = 'admin/bookings'; +$route['bookings/calendar'] = 'admin/booking_calendar'; +$route['bookings/calendar-data'] = 'admin/booking_calendar_data'; $route['bookings/add-booking'] = 'admin/add_booking'; $route['bookings/update-booking/(:any)'] = 'admin/update_booking/$1'; $route['bookings/booking-process'] = 'admin/booking_process'; diff --git a/application/controllers/Admin.php b/application/controllers/Admin.php index 4c011d1..6345c83 100755 --- a/application/controllers/Admin.php +++ b/application/controllers/Admin.php @@ -695,6 +695,96 @@ class Admin extends CI_Controller { } } + public function booking_calendar(){ + $this->load->helper('url'); + $this->load->model('User_model'); + $this->load->model('Service_model'); + $this->load->model('Module_model'); + + if(isset($_SESSION['username'])){ + $data['currentUser'] = $this->User_model->getUserByUsername($_SESSION['username']); + $data['pageTitle'] = 'Foglalási naptár'; + $data['message'] = ''; + $data['message_class'] = ''; + if($this->User_model->is_user_admin($_SESSION['username'])){ + $data['activeModules'] = $this->Module_model->getAllModule(); + } else { + $data['activeModules'] = $this->Module_model->getUserModules($data['currentUser']->user_id); + } + + // Compute week bounds + $weekParam = isset($_GET['week']) ? $_GET['week'] : date('Y-m-d'); + $monday = new DateTime($weekParam); + $dow = (int)$monday->format('N'); // 1=Mon..7=Sun + if ($dow > 1) $monday->modify('-'.($dow - 1).' days'); + $sunday = clone $monday; + $sunday->modify('+6 days'); + + $data['weekStart'] = $monday->format('Y-m-d'); + $data['weekEnd'] = $sunday->format('Y-m-d'); + $data['workers'] = $this->Service_model->getActiveWorkers(); + + $workerId = isset($_GET['worker_id']) ? $_GET['worker_id'] : null; + $data['bookings'] = $this->Service_model->getBookingsByDateRange($data['weekStart'], $data['weekEnd'], $workerId); + + $this->load->view('admin/booking-calendar', $data); + } else { + header("Location:".SITEURL."login"); + } + } + + public function booking_calendar_data(){ + $this->load->helper('url'); + $this->load->model('User_model'); + $this->load->model('Service_model'); + + if(!isset($_SESSION['username'])){ + header('Content-Type: application/json'); + echo json_encode(array('error' => 'unauthorized')); + return; + } + + $weekParam = isset($_GET['week']) ? $_GET['week'] : date('Y-m-d'); + $monday = new DateTime($weekParam); + $dow = (int)$monday->format('N'); + if ($dow > 1) $monday->modify('-'.($dow - 1).' days'); + $sunday = clone $monday; + $sunday->modify('+6 days'); + + $workerId = isset($_GET['worker_id']) && $_GET['worker_id'] !== '' ? $_GET['worker_id'] : null; + $bookings = $this->Service_model->getBookingsByDateRange($monday->format('Y-m-d'), $sunday->format('Y-m-d'), $workerId); + + $result = array(); + foreach ($bookings as $b) { + $services = array(); + if (is_array($b->services)) { + foreach ($b->services as $s) { + $services[] = array( + 'service_name' => $s->service_name, + 'service_price' => $s->service_price, + 'service_time' => $s->service_time + ); + } + } + $result[] = array( + 'booking_id' => $b->booking_id, + 'guest_name' => $b->guest_name, + 'guest_email' => $b->guest_email, + 'guest_phone' => $b->guest_phone, + 'worker_id' => $b->worker_id, + 'worker_name' => $b->worker_name, + 'booking_date' => $b->booking_date, + 'booking_start_time' => $b->booking_start_time, + 'booking_finish_time' => $b->booking_finish_time, + 'services' => $services, + 'service_names_joined' => $b->service_names_joined + ); + } + + header('Content-Type: application/json'); + echo json_encode($result); + } + public function add_booking(){ $this->load->helper('url'); $this->load->model('User_model'); diff --git a/application/models/Service_model.php b/application/models/Service_model.php index 34dc00c..d568b04 100755 --- a/application/models/Service_model.php +++ b/application/models/Service_model.php @@ -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; + } + diff --git a/application/views/admin/booking-calendar.php b/application/views/admin/booking-calendar.php new file mode 100644 index 0000000..5ce15b5 --- /dev/null +++ b/application/views/admin/booking-calendar.php @@ -0,0 +1,5 @@ + diff --git a/application/views/admin/includes/booking-calendar-form.php b/application/views/admin/includes/booking-calendar-form.php new file mode 100644 index 0000000..bdc4be3 --- /dev/null +++ b/application/views/admin/includes/booking-calendar-form.php @@ -0,0 +1,436 @@ +worker_id] = $colorPalette[$i % count($colorPalette)]; + $i++; +} + +// Build initial bookings JSON +$bookingsJson = array(); +foreach ($bookings as $b) { + $services = array(); + if (is_array($b->services)) { + foreach ($b->services as $s) { + $services[] = array( + 'service_name' => $s->service_name, + 'service_price' => $s->service_price, + 'service_time' => $s->service_time + ); + } + } + $bookingsJson[] = array( + 'booking_id' => $b->booking_id, + 'guest_name' => $b->guest_name, + 'guest_email' => $b->guest_email, + 'guest_phone' => $b->guest_phone, + 'worker_id' => $b->worker_id, + 'worker_name' => $b->worker_name, + 'booking_date' => $b->booking_date, + 'booking_start_time' => $b->booking_start_time, + 'booking_finish_time' => $b->booking_finish_time, + 'services' => $services, + 'service_names_joined' => $b->service_names_joined + ); +} +?> + + + +
+
+ +
+ + + Listanézet + Naptárnézet +
+ + + +
+ +
+
+ + +
+
+

Foglalás részletei

+
+ +
+
+ + diff --git a/application/views/admin/includes/bookings-form.php b/application/views/admin/includes/bookings-form.php index 53dd10c..2cbeb17 100755 --- a/application/views/admin/includes/bookings-form.php +++ b/application/views/admin/includes/bookings-form.php @@ -2,6 +2,7 @@