# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project overview Online booking platform for Studio Beve (barber + beauty salon, Norway). Guests browse services, book appointments, and receive email confirmations. Admins manage services, workers, bookings, and schedules via an admin portal. Multilingual: Norwegian (`no`), English (`en`), Hungarian (`hu`). ## Stack - **Framework**: CodeIgniter 3 (PHP MVC), entry point `index.php` - **Database**: MySQL — credentials in `application/config/database.php` - **Email**: PHPMailer 6 via `vendor/autoload.php` - **Google Calendar**: `google/apiclient:^2.0`, service account key at `application/config/service-account-key.json` - **Frontend**: jQuery, jQuery UI datepicker, moment.js, Font Awesome, Google reCAPTCHA - **Dependencies**: managed via Composer (`composer.json`) ## Development commands ```bash # Install/update PHP dependencies composer install composer update # No build step — PHP files are served directly by the web server # No test runner is configured (composer.json has a test:coverage script but no tests exist) ``` Deployment is file-based: copy changed files to the live server. Database migrations must be run separately on the live MySQL instance. ## Architecture ### MVC layout | Layer | Location | Key files | |-------|----------|-----------| | Controllers | `application/controllers/` | `Pages.php` (public + booking), `Admin.php` (admin portal), `Login.php`, `UserManagement.php` | | Models | `application/models/` | `Service_model.php` (services, workers, bookings, schedules), `User_model.php` (users, `sendEmail()`), `Log_model.php` | | Views | `application/views/` | `pages/` (public), `admin/` (admin portal), `includes/` (shared skeletons) | | Libraries | `application/libraries/` | `GoogleCalendar.php` (createEvent, updateEvent, deleteEvent — failures never break booking flow) | | Config | `application/config/` | `routes.php`, `database.php`, `google_calendar.php` | ### Public booking flow 1. Guest selects services → worker → date/time → contact info (multi-step form) 2. POST to `booking-process` → validates → saves to DB → sends email → redirects to `booking-finished` 3. Confirmation email contains a unique manage link: `SITEURL + lang + /manage-booking/ + manage_token` ### Guest self-management - Token in `bookings.manage_token` (VARCHAR 64, UNIQUE), generated via `bin2hex(random_bytes(16))` - Routes: `(:any)/manage-booking/(:any)`, `manage-booking-process`, `manage-booking-cancel` - 24h cutoff: modifications/cancellations blocked if appointment is less than 24h away - Emails sent to guest + CC evelin@studiobeve.no on modify/cancel ### AJAX endpoint `Pages::ajax()` handles all async requests: `getAvailableTimes`, `getAvailableWorkers`, etc. `getAvailableTimes($worker_id, $date, $servicelength)` excludes already-booked slots, enforces closing time (18:00), max 3-month booking window, and floating lunch breaks. ### Worker scheduling - Regular hours in `worker_schedule` table - Day-off/absence overrides in `worker_schedule_overrides` (`absence_type`: `vacation`, `sick`, `custom`, `other`; NULL = plain day-off) - Floating lunch: `workers.lunch_window_start` / `lunch_window_end` — first free 30-min slot in window ### Google Calendar Workers and Evelin get calendar events on new/modify/cancel bookings. Worker calendar IDs stored in `workers.google_calendar_id`. Booking event IDs stored in `bookings.gcal_event_id_worker` and `bookings.gcal_event_id_owner`. ### Admin portal `Admin.php` handles all CRUD for services, workers, bookings, users, and the visual worker calendar (`workers/worker-calendar`). ## View conventions - Pages use skeleton includes: `barber-skeleton-top/bottom.php` or `beauty-skeleton-top/bottom.php` - Shared CSS: `assets/css/style.css` (booking UI), `assets/css/barber.css` / `beauty.css` (page-specific + responsive) - Responsive breakpoint at **736px**: booking layout switches to stacked - `.bookingButtonContainer` is `position: absolute; bottom: 10px` — must be inside a `position: relative` parent (`.BookingStepContainer`) - `.workerTable` has `height: 85px` — override with `height: auto` when pre-rendering multiple workers statically - `.bookingCalendar` and `.bookingResultsWrapper` use `float: left` — contain them with `overflow: auto` on the parent and `
` before following elements ## File encoding Source files use **CRLF (`\r\n`)** line endings. When editing large blocks, prefer Python (`open(..., newline='')`) or `sed` over the Edit tool to avoid line-ending corruption. ## Passwords & sessions - Passwords hashed with SHA-256 - Admin session key: `$_SESSION['username']` ## Git remote ```bash git push http://Zoli:Belepes06@gl-fraudshield.com/Zoli/studiobeve.no.git ``` ## Database migrations (reference) These have already been applied to test; must be run on live when deploying the relevant features: ```sql -- Guest manage-booking token (2026-02-28) ALTER TABLE bookings ADD COLUMN manage_token VARCHAR(64) UNIQUE DEFAULT NULL; -- Google Calendar event IDs (2026-03-01) ALTER TABLE workers ADD COLUMN google_calendar_id VARCHAR(255) NULL DEFAULT NULL; ALTER TABLE bookings ADD COLUMN gcal_event_id_worker VARCHAR(255) NULL DEFAULT NULL; ALTER TABLE bookings ADD COLUMN gcal_event_id_owner VARCHAR(255) NULL DEFAULT NULL; -- Floating lunch break (2026-03-04) ALTER TABLE workers ADD COLUMN lunch_window_start TIME NULL DEFAULT NULL, ADD COLUMN lunch_window_end TIME NULL DEFAULT NULL; -- Visual worker calendar absence types (2026-03-04) ALTER TABLE worker_schedule_overrides ADD COLUMN absence_type VARCHAR(20) NULL DEFAULT NULL, ADD COLUMN note TEXT NULL DEFAULT NULL; ```