Scheduler & Calendar Microservice
The Scheduler Microservice (scheduler/) delivers an embeddable, customizable appointment booking engine for cooperative consultations, energy audits, and technical inspections.
1. Directory Structure
scheduler/├── assets/│ └── script_v2.js # Client-side booking logic, slots & timezones├── backend/│ ├── api.php # Core REST API: slots check & booking execution│ ├── api_debug.log # Debug log trace for development│ ├── auth_callback.php # Google OAuth2 authorization code callback│ ├── auth_start.php # Google OAuth2 handshake initiator│ ├── config_google.php # Google API client & credentials setup│ ├── delete_json.php # Calendar configuration purge endpoint│ └── save_scheduler.php # Calendar settings persistence├── cookie-banner.php # GDPR / RODO compliance banner├── data/ # Calendar configuration files ({id}.json)├── default.php # Default fallback booking template├── index.php # Interactive booking application entrypoint├── composer.json # PHP dependencies (google/apiclient, monolog)└── .htaccess # Apache rewrite rules (if deployed on Apache)2. Interactive Booking Flow
sequenceDiagram
autonumber
actor Customer as Prospect / Member
participant UI as "Scheduler Frontend (index.php)"
participant JS as "Client Script (script_v2.js)"
participant API as "Scheduler API (backend/api.php)"
participant Google as Google Calendar API
participant Supabase as Supabase Database
Customer->>UI: Opens https://scheduler.planovi.app/?id=default
UI->>JS: Injects calendar configuration & branding
JS->>Customer: Renders interactive month view with active days
Customer->>JS: Selects Date (e.g., 2026-09-25)
JS->>API: GET /backend/api.php?id=default&date=2026-09-25
API->>Google: Query existing events to prevent double-booking
Google-->>API: Busy periods
API->>Supabase: Query booked appointments in Supabase
Supabase-->>API: Confirmed platform bookings
API-->>JS: Returns open slots: ["09:00", "09:30", "11:00", ...]
JS->>Customer: Displays available time buttons
Customer->>JS: Selects Slot "11:00" & Enters Name, Email, Notes
Customer->>JS: Clicks "Confirm Appointment"
JS->>API: POST /backend/api.php (name, email, time, date)
API->>Google: Insert Event into Primary Calendar (with Google Meet link)
API->>Supabase: Insert appointment record for cooperative CRM
API-->>JS: Success response { "status": "confirmed", "event_id": "..." }
JS->>Customer: Displays Confirmation Screen with ICS download & Meet link
3. Dynamic Branding & Contrast Luminance Engine
In scheduler/index.php, the booking interface dynamically adopts the tenant’s brand identity while guaranteeing WCAG contrast compliance:
// Contrast detection algorithm in index.phpfunction isDarkColor($hexColor) { $clean = str_replace('#', '', $hexColor); if (strlen($clean) !== 6) return true; $r = hexdec(substr($clean, 0, 2)); $g = hexdec(substr($clean, 2, 2)); $b = hexdec(substr($clean, 4, 2)); $luminance = (0.2126 * $r + 0.7152 * $g + 0.0722 * $b) / 255; return $luminance < 0.5;}
$primary_color = $config['brand_color_primary'] ?? '#14B8A6';$secondary_color = $config['brand_color_secondary'] ?? '#0D9488';$bg_color = $config['brand_color_bg'] ?? '#0F172A';- If a cooperative selects a light brand background, foreground elements, typography, and borders automatically switch to high-contrast dark tones.
- If a dark background is selected, sleek dark-mode glassmorphism tokens are applied.
4. Timezone & Localization Engine (script_v2.js)
Scheduling across different time zones is handled reliably in scheduler/assets/script_v2.js:
- Automatically reads the client browser’s local timezone via
Intl.DateTimeFormat().resolvedOptions().timeZone. - Converts host slots (default
Europe/Warsaw) to the client’s local viewing time. - Supports bilingual interface strings (Polish
pland Englishen) for date pickers, day labels, and booking confirmations.
5. Google Calendar OAuth2 Synchronization
- An administrator clicks Connect Google Calendar in their Planovi CRM dashboard, directing to
backend/auth_start.php. - The user authenticates with Google and grants Calendar permissions.
- Google redirects to
backend/auth_callback.phpwith an authorization code. - The callback exchanges the code for a permanent
refresh_tokenand updatesscheduler/data/{id}.json. - When subsequent bookings are made,
backend/api.phpcallsgetGoogleClient()->fetchAccessTokenWithRefreshToken()to create the event in real-time.