Files
ladill-frontdesk/config/frontdesk.php
T
isaaccladandCursor 6bc52d9ef3
Deploy Ladill Frontdesk / deploy (push) Successful in 1m13s
Add dashboard upgrade banner for free Frontdesk plans.
Show the Pro upsell CTA on the reception dashboard so free orgs can discover plans without opening the sidebar.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-30 18:13:18 +00:00

345 lines
13 KiB
PHP

<?php
return [
/*
|--------------------------------------------------------------------------
| Inbound service API keys (sibling Ladill apps calling Frontdesk)
|--------------------------------------------------------------------------
*/
'service_api_keys' => array_filter([
'pos' => env('FRONTDESK_API_KEY_POS'),
'crm' => env('FRONTDESK_API_KEY_CRM'),
'care' => env('FRONTDESK_API_KEY_CARE'),
'lab' => env('FRONTDESK_API_KEY_LAB'),
]),
'visitor_types' => [
'visitor' => 'Visitor',
'contractor' => 'Contractor',
'vendor' => 'Vendor',
'interview_candidate' => 'Interview Candidate',
'delivery' => 'Delivery Personnel',
],
'visit_purposes' => [
'meeting' => 'Business meeting',
'interview' => 'Job interview',
'delivery' => 'Delivery or pickup',
'maintenance' => 'Maintenance or repairs',
'sales' => 'Sales or vendor visit',
'training' => 'Training or workshop',
'personal' => 'Personal visit',
'other' => 'Other',
],
'visit_statuses' => [
'scheduled' => 'Scheduled',
'expected' => 'Expected',
'waiting' => 'Waiting',
'checked_in' => 'Checked In',
'checked_out' => 'Checked Out',
'cancelled' => 'Cancelled',
'overdue' => 'Overdue',
],
'watchlist_statuses' => [
'allowed' => 'Allowed',
'requires_approval' => 'Requires Approval',
'blacklisted' => 'Blacklisted',
],
'audit_actions' => [
'visit.checked_in' => 'Visit checked in',
'visit.checked_out' => 'Visit checked out',
'visit.awaiting_approval' => 'Visit awaiting approval',
'visit.scheduled' => 'Visit scheduled',
'visit.waiting' => 'Visitor waiting',
'visit.cancelled' => 'Visit cancelled',
'visit.deleted' => 'Visit archived',
'visit.restored' => 'Visit restored',
'visitor.deleted' => 'Visitor archived',
'visitor.restored' => 'Visitor restored',
'watchlist.blocked_attempt' => 'Blocked check-in attempt',
'watchlist.flagged_checkin' => 'Flagged visitor check-in',
'watchlist.entry_created' => 'Watchlist entry added',
'watchlist.entry_removed' => 'Watchlist entry removed',
'badge.expired' => 'Badge expired',
'employee.signed_in' => 'Employee signed in',
'employee.signed_out' => 'Employee signed out',
'employee.stepped_out' => 'Employee stepped out',
'employee.stepped_in' => 'Employee returned',
],
'roles' => [
'super_admin' => 'Super Administrator',
'org_admin' => 'Organization Administrator',
'branch_admin' => 'Branch Administrator',
'receptionist' => 'Receptionist',
'security_officer' => 'Security Officer',
'host' => 'Host',
'auditor' => 'Auditor',
],
'device_types' => [
'reception_computer' => 'Reception Computer',
'kiosk' => 'Visitor Kiosk',
'tablet' => 'Tablet',
'badge_printer' => 'Badge Printer',
'qr_scanner' => 'QR Scanner',
'camera' => 'Camera',
'signature_pad' => 'Signature Pad',
],
/*
| Device types that receive a server-generated token for unattended API/kiosk access.
*/
'device_token_types' => ['kiosk', 'badge_printer', 'qr_scanner'],
/*
| Contextual copy for the register / edit device forms (keyed by device type).
*/
'device_registration_hints' => [
'reception_computer' => 'Tracked for your team only. Staff sign in on this machine — no device token or automatic connection is created.',
'kiosk' => 'A device token is created after registration. Open the kiosk URL on your tablet to run self-service check-in without staff login.',
'tablet' => 'Tracked for inventory. Use Visitor Kiosk if this tablet should run unattended check-in.',
'badge_printer' => 'A device token is created for unattended printing. The printer connects when your print agent sends requests with that token.',
'qr_scanner' => 'A device token is created for unattended scanning. The scanner connects when it calls Frontdesk with that token.',
'camera' => 'Tracked for inventory at this reception desk or branch — no device token is issued.',
'signature_pad' => 'Tracked for inventory at this reception desk or branch — no device token is issued.',
],
'notification_channels' => [
'email' => 'Email (platform SMTP)',
'sms' => 'SMS',
],
'billing' => [
'email_cost_ghs' => (float) env('FRONTDESK_EMAIL_COST_GHS', 0.0135),
'sms_cost_per_segment_ghs' => (float) env('FRONTDESK_SMS_COST_PER_SEGMENT_GHS', 0.05),
'sms_segment_length' => (int) env('FRONTDESK_SMS_SEGMENT_LENGTH', 160),
],
'pro' => [
'grace_days' => (int) env('FRONTDESK_PRO_GRACE_DAYS', 3),
'period_days' => (int) env('FRONTDESK_PRO_PERIOD_DAYS', 30),
],
'plans' => [
'free' => [
'label' => 'Free',
'price_minor' => 0,
'max_branches' => 1,
'max_kiosk_devices' => 1,
'free_emails_per_month' => (int) env('FRONTDESK_FREE_EMAILS_PER_MONTH', 100),
'features' => [
'check_in',
'hosts',
'badges',
'watchlist',
],
],
'pro' => [
'label' => 'Pro',
'price_minor' => (int) env('FRONTDESK_PRO_PRICE_MINOR', 7900),
'max_branches' => null,
'max_kiosk_devices' => null,
'free_emails_per_month' => env('FRONTDESK_PRO_FREE_EMAILS_PER_MONTH') !== null
? (int) env('FRONTDESK_PRO_FREE_EMAILS_PER_MONTH')
: null,
'features' => [
'check_in',
'hosts',
'badges',
'watchlist',
'integrations',
'webhooks',
'scheduled_reports',
'custom_badge_templates',
],
],
'enterprise' => [
'label' => 'Enterprise',
'max_branches' => null,
'max_kiosk_devices' => null,
'free_emails_per_month' => null,
'features' => [
'check_in',
'hosts',
'badges',
'watchlist',
'integrations',
'webhooks',
'scheduled_reports',
'custom_badge_templates',
],
],
],
'prepaid_months' => [6, 12, 24],
'notification_events' => [
'visitor_arrived' => 'Visitor arrived (checked in)',
'visitor_checked_out' => 'Visitor checked out',
'visitor_expected' => 'Visitor expected today',
'visitor_waiting' => 'Visitor waiting in reception',
'visit_cancelled' => 'Visit cancelled',
'approval_needed' => 'Approval required',
'watchlist_alert' => 'Watchlist / security alerts',
'badge_expired' => 'Expired badge while checked in',
'employee_overdue_return' => 'Employee overdue to return from step-out',
],
'default_notification_events' => [
'visitor_arrived' => true,
'visitor_checked_out' => true,
'visitor_expected' => true,
'visitor_waiting' => true,
'visit_cancelled' => true,
'approval_needed' => true,
'watchlist_alert' => true,
'badge_expired' => true,
'employee_overdue_return' => true,
],
'kiosk' => [
'inactivity_reset_seconds' => (int) env('FRONTDESK_KIOSK_RESET_SECONDS', 120),
'default_visit_duration_minutes' => 60,
],
'employee_presence_statuses' => [
'off_site' => 'Off site',
'on_site' => 'On site',
'stepped_out' => 'Stepped out',
],
'employee_step_out_reasons' => [
'lunch' => 'Lunch',
'client_visit' => 'Client / external meeting',
'errand' => 'Bank / errands',
'personal' => 'Personal',
'other' => 'Other',
],
'employee_presence_events' => [
'sign_in' => 'Sign in',
'sign_out' => 'Sign out',
'step_out' => 'Step out',
'step_in' => 'Return',
],
'badge' => [
'default_expiry_hours' => 8,
'qr_url_path' => '/q',
'employee_qr_url_path' => '/eq',
],
'default_badge_template' => [
'show_photo' => true,
'show_qr' => true,
'show_host' => true,
'show_company' => true,
'show_type' => true,
'primary_color' => '#0d9488',
'footer_text' => '',
],
'webhook_events' => [
'visit.checked_in',
'visit.checked_out',
'visit.awaiting_approval',
'employee.signed_in',
'employee.signed_out',
'employee.stepped_out',
'employee.stepped_in',
],
'integrations' => [
'care' => 'Ladill Care',
'lab' => 'Ladill Lab',
'pos' => 'Ladill POS',
'crm' => 'Ladill CRM',
'queue' => 'Ladill Queue',
],
'queue' => [
'api_url' => env('QUEUE_API_URL', 'https://queue.ladill.com/api/v1'),
'api_key' => env('QUEUE_API_KEY_FRONTDESK'),
],
'printers' => [
'default_driver' => env('FRONTDESK_PRINTER_DRIVER', 'pdf'),
'drivers' => ['pdf', 'zebra', 'brother', 'dymo'],
],
/*
|--------------------------------------------------------------------------
| Visitor type workflows (Phase 4)
|--------------------------------------------------------------------------
| Config-driven fields, badge expiry overrides, and approval requirements.
*/
'visitor_type_config' => [
'visitor' => [
'requires_approval' => false,
'badge_expiry_hours' => null,
'details_key' => null,
'fields' => [],
],
'contractor' => [
'requires_approval' => false,
'badge_expiry_hours' => 12,
'details_key' => 'contractor_details',
'fields' => [
['name' => 'contract_company', 'label' => 'Contract company', 'type' => 'text', 'required' => true],
['name' => 'supervisor', 'label' => 'Site supervisor', 'type' => 'text', 'required' => true],
['name' => 'contract_start', 'label' => 'Contract start', 'type' => 'date', 'required' => false],
['name' => 'contract_end', 'label' => 'Contract end', 'type' => 'date', 'required' => false],
['name' => 'safety_induction_completed', 'label' => 'Safety induction completed', 'type' => 'checkbox', 'required' => true],
['name' => 'insurance_reference', 'label' => 'Insurance reference', 'type' => 'text', 'required' => false],
['name' => 'permit_number', 'label' => 'Permit number', 'type' => 'text', 'required' => false],
['name' => 'equipment_carried', 'label' => 'Equipment carried', 'type' => 'textarea', 'required' => false],
],
],
'delivery' => [
'requires_approval' => false,
'badge_expiry_hours' => 2,
'details_key' => 'delivery_details',
'fields' => [
['name' => 'courier_company', 'label' => 'Courier company', 'type' => 'text', 'required' => true],
['name' => 'recipient', 'label' => 'Recipient', 'type' => 'text', 'required' => true],
['name' => 'tracking_number', 'label' => 'Tracking number', 'type' => 'text', 'required' => false],
['name' => 'package_description', 'label' => 'Package description', 'type' => 'text', 'required' => false],
['name' => 'delivery_photo', 'label' => 'Delivery photo', 'type' => 'photo', 'required' => false],
['name' => 'delivery_signature', 'label' => 'Signature', 'type' => 'signature', 'required' => false],
],
],
'vendor' => [
'requires_approval' => true,
'badge_expiry_hours' => null,
'details_key' => 'contractor_details',
'fields' => [
['name' => 'vendor_company', 'label' => 'Vendor company', 'type' => 'text', 'required' => true],
['name' => 'service_type', 'label' => 'Service / product', 'type' => 'text', 'required' => true],
['name' => 'purchase_order', 'label' => 'PO number', 'type' => 'text', 'required' => false],
],
],
'interview_candidate' => [
'requires_approval' => true,
'badge_expiry_hours' => null,
'details_key' => 'contractor_details',
'fields' => [
['name' => 'position_applied', 'label' => 'Position applied for', 'type' => 'text', 'required' => true],
['name' => 'interviewer', 'label' => 'Interviewer', 'type' => 'text', 'required' => false],
['name' => 'scheduled_interview_at', 'label' => 'Interview time', 'type' => 'datetime-local', 'required' => false],
],
],
],
'upgrade_banner' => [
'title' => 'Unlock Frontdesk Pro or Enterprise',
'description' => 'Unlimited kiosks, webhooks, iCal sync & scheduled reports — from GHS 79/mo.',
'route' => 'frontdesk.pro.index',
],
];