Introduces /massage alongside barber and beauty: landing page, booking flow, admin support, home tile and SEO entries, in all three languages. Architecture - application/config/verticals.php + vertical_helper.php: one registry entry per vertical (branding, assets, views, behaviour flags). A fourth vertical is a config entry plus content files. - Strangler: barber and beauty keep pointing at their existing view files, so their rendered HTML is unchanged. Only massage uses the new generic pages/vertical-*.php and includes/vertical-*.php views, which collapse the four duplicated per-language nav/footer branches into one. - Pages::vertical() + one route; booking(), booking_finished(), _booking_error() and manage_booking() are now registry-driven. Worker/vertical coupling - getActiveWorkers() derives the vertical from services.service_category_id instead of the workers.is_barber / is_beauty flags, which were a hand-maintained cache of exactly that fact. Verified against production data: the derived set reproduced the stored flags for every worker, in both verticals. No schema change was needed for massage. - The legacy flags are now written through from the category so a rollback cannot strand a new worker, and the admin worker UI shows the derived verticals read-only instead of two dropdowns that controlled nothing. Bug fixes found along the way (all pre-existing) - booking_process() had no server-side category guard; cross-vertical mixing was prevented only by client-side JS. - add-service-form / add-worker-form emitted `selected` on every category option, so the newest category silently became the default. - update-service-form offered only barber/beauty, so editing a service of any other type silently rewrote it. - getWorkerScheduleByDay ignored schedule overrides while getAvailableTimes honoured them, so slots could be shown and then rejected. Added an override-aware getWorkerScheduleForDate() and used it in both guards. - Booking lists dereferenced a null service if one had been hard-deleted. - main.css: .tiles was tuned for exactly two tiles, including an absolutely-positioned .style1 at the 1280px breakpoint. Massage-specific behaviour, opt-in per vertical - strip_category_prefix: grouped service lists show "50 min" under the treatment heading rather than repeating the full name. The full name is carried in data-service-name so the totals panel stays unambiguous, and services.service_name is untouched for emails and admin. - single_service_booking: one treatment per booking, enforced in the UI and in booking_process(). Re-clicking the selection releases it. - Displayed treatment time (50/80/110 min) is in the service name; the booked slot (60/90/120 min) is service_time and covers changing and payment. service_time is never shown to the guest. DB migrations for dev/prod are in documents/ - additive only, no ALTER. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
111 lines
4.8 KiB
PHP
Executable File
111 lines
4.8 KiB
PHP
Executable File
<?php
|
|
defined('BASEPATH') OR exit('No direct script access allowed');
|
|
|
|
/*
|
|
| -------------------------------------------------------------------------
|
|
| URI ROUTING
|
|
| -------------------------------------------------------------------------
|
|
| This file lets you re-map URI requests to specific controller functions.
|
|
|
|
|
| Typically there is a one-to-one relationship between a URL string
|
|
| and its corresponding controller class/method. The segments in a
|
|
| URL normally follow this pattern:
|
|
|
|
|
| example.com/class/method/id/
|
|
|
|
|
| In some instances, however, you may want to remap this relationship
|
|
| so that a different class/function is called than the one
|
|
| corresponding to the URL.
|
|
|
|
|
| Please see the user guide for complete details:
|
|
|
|
|
| https://codeigniter.com/userguide3/general/routing.html
|
|
|
|
|
| -------------------------------------------------------------------------
|
|
| RESERVED ROUTES
|
|
| -------------------------------------------------------------------------
|
|
|
|
|
| There are three reserved routes:
|
|
|
|
|
| $route['default_controller'] = 'welcome';
|
|
|
|
|
| This route indicates which controller class should be loaded if the
|
|
| URI contains no data. In the above example, the "welcome" class
|
|
| would be loaded.
|
|
|
|
|
| $route['404_override'] = 'errors/page_missing';
|
|
|
|
|
| This route will tell the Router which controller/method to use if those
|
|
| provided in the URL cannot be matched to a valid route.
|
|
|
|
|
| $route['translate_uri_dashes'] = FALSE;
|
|
|
|
|
| This is not exactly a route, but allows you to automatically route
|
|
| controller and method names that contain dashes. '-' isn't a valid
|
|
| class or method name character, so it requires translation.
|
|
| When you set this option to TRUE, it will replace ALL dashes in the
|
|
| controller and method URI segments.
|
|
|
|
|
| Examples: my-controller/index -> my_controller/index
|
|
| my-controller/my-method -> my_controller/my_method
|
|
*/
|
|
//public pages
|
|
$route['default_controller'] = 'pages/index';
|
|
$route['404_override'] = '';
|
|
$route['translate_uri_dashes'] = FALSE;
|
|
|
|
$route['home'] = 'pages/index';
|
|
$route['dashboard'] = 'admin/dashboard';
|
|
$route['profile'] = 'pages/profile';
|
|
$route['log-monitor'] = 'Pages/log_monitor';
|
|
$route['(:any)/barber'] = 'pages/barber/$1';
|
|
$route['(:any)/beauty'] = 'pages/beauty/$1';
|
|
// Verticals added after the registry was introduced dispatch through
|
|
// Pages::vertical(), which resolves branding and views from
|
|
// application/config/verticals.php. barber and beauty keep their original
|
|
// dedicated routes so their output stays byte-identical.
|
|
$route['(:any)/massage'] = 'pages/vertical/$1/massage';
|
|
$route['(:any)/booking/(:any)'] = 'pages/booking/$1/$2';
|
|
$route['(:any)/booking-finished/(:any)'] = 'pages/booking_finished/$1/$2';
|
|
$route['email-verification'] = 'pages/email_verification';
|
|
$route['ajax'] = 'pages/ajax';
|
|
$route['module-management'] = 'ModuleManagement/index';
|
|
$route['booking-process'] = 'pages/booking_process';
|
|
|
|
//admin portal
|
|
$route['login'] = 'Login/index';
|
|
$route['users'] = 'admin/users';
|
|
$route['user-management'] = 'UserManagement/index';
|
|
$route['add-new-user'] = 'UserManagement/add_new_user';
|
|
$route['modify-user/(:any)'] = 'UserManagement/modify_user/$1';
|
|
$route['user-process'] = 'UserManagement/user_process';
|
|
|
|
$route['services'] = 'admin/services';
|
|
$route['services/add-service'] = 'admin/add_service';
|
|
$route['services/update-service/(:any)'] = 'admin/update_service/$1';
|
|
$route['services/service-process'] = 'admin/service_process';
|
|
|
|
$route['service-categories'] = 'admin/service_categories';
|
|
$route['services/add-service-category'] = 'admin/add_service_category';
|
|
$route['services/update-service-category/(:any)'] = 'admin/update_service_category/$1';
|
|
$route['services/service-category-process'] = 'admin/service_category_process';
|
|
|
|
$route['workers'] = 'admin/workers';
|
|
$route['workers/add-worker'] = 'admin/add_worker';
|
|
$route['workers/update-worker/(:any)'] = 'admin/update_worker/$1';
|
|
$route['workers/worker-process'] = 'admin/worker_process';
|
|
$route['workers/worker-calendar'] = 'admin/worker_calendar';
|
|
$route['workers/worker-calendar/(:any)'] = 'admin/worker_calendar/$1';
|
|
$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';
|
|
$route['(:any)/manage-booking/(:any)'] = 'pages/manage_booking/$1/$2';
|
|
$route['manage-booking-process'] = 'pages/manage_booking_process';
|
|
$route['manage-booking-cancel'] = 'pages/manage_booking_cancel';
|