- Update beauty booking forms (en, hu, no) - Update manage-booking view, worker calendar view - Update config.php, google_calendar.php, GoogleCalendar library - Add CLAUDE.md project instructions - Add service-account-key.json to .gitignore - Update ledigestilling page Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
5.8 KiB
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 atapplication/config/service-account-key.json - Frontend: jQuery, jQuery UI datepicker, moment.js, Font Awesome, Google reCAPTCHA
- Dependencies: managed via Composer (
composer.json)
Development commands
# 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
- Guest selects services → worker → date/time → contact info (multi-step form)
- POST to
booking-process→ validates → saves to DB → sends email → redirects tobooking-finished - 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 viabin2hex(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_scheduletable - 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.phporbeauty-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
.bookingButtonContainerisposition: absolute; bottom: 10px— must be inside aposition: relativeparent (.BookingStepContainer).workerTablehasheight: 85px— override withheight: autowhen pre-rendering multiple workers statically.bookingCalendarand.bookingResultsWrapperusefloat: left— contain them withoverflow: autoon the parent and<div style="clear:both;">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
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:
-- 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;