feat: implement customer registration flow and business hours system

Major changes:
- Add customer registration with email/phone lookup (app/booking/registro)
- Add customers API endpoint (app/api/customers/route)
- Implement business hours for locations (mon-fri 10-7, sat 10-6, sun closed)
- Fix availability function type casting issues
- Add business hours utilities (lib/utils/business-hours.ts)
- Update Location type to include business_hours JSONB
- Add mock payment component for testing
- Remove Supabase auth from booking flow
- Fix /cita redirect path in booking flow

Database migrations:
- Add category column to services table
- Add business_hours JSONB column to locations table
- Fix availability functions with proper type casting
- Update get_detailed_availability to use business_hours

Features:
- Customer lookup by email or phone
- Auto-redirect to registration if customer not found
- Pre-fill customer data if exists
- Business hours per day of week
- Location-specific opening/closing times
This commit is contained in:
Marco Gallegos
2026-01-17 00:29:49 -06:00
parent fb60178c86
commit 583a25a6f6
56 changed files with 2676 additions and 491 deletions

View File

@@ -0,0 +1,81 @@
-- Seed data for testing booking flow
-- Execute in Supabase Dashboard: Database > SQL Editor
-- Get active locations
DO $$
DECLARE
v_location_id UUID;
v_staff_id UUID;
v_resource_id UUID;
v_service_id UUID;
BEGIN
-- Get first active location
SELECT id INTO v_location_id FROM locations WHERE is_active = true LIMIT 1;
IF v_location_id IS NULL THEN
RAISE NOTICE 'No active locations found';
RETURN;
END IF;
RAISE NOTICE 'Using location: %', v_location_id;
-- Insert sample staff if none exists
INSERT INTO staff (user_id, location_id, role, display_name, phone, is_active, is_available_for_booking, work_hours_start, work_hours_end, work_days)
SELECT
gen_random_uuid(),
v_location_id,
'artist',
'Artista Demo',
'+52 844 123 4567',
true,
true,
'10:00'::TIME,
'19:00'::TIME,
'MON,TUE,WED,THU,FRI,SAT'
WHERE NOT EXISTS (SELECT 1 FROM staff WHERE display_name = 'Artista Demo' AND location_id = v_location_id)
RETURNING id INTO v_staff_id;
IF v_staff_id IS NOT NULL THEN
RAISE NOTICE 'Created staff: %', v_staff_id;
ELSE
SELECT id INTO v_staff_id FROM staff WHERE display_name = 'Artista Demo' AND location_id = v_location_id;
RAISE NOTICE 'Using existing staff: %', v_staff_id;
END IF;
-- Insert sample resources if none exists
INSERT INTO resources (location_id, name, type, capacity, is_active)
SELECT
v_location_id,
'Estación Demo',
'station',
1,
true
WHERE NOT EXISTS (SELECT 1 FROM resources WHERE name = 'Estación Demo' AND location_id = v_location_id)
RETURNING id INTO v_resource_id;
IF v_resource_id IS NOT NULL THEN
RAISE NOTICE 'Created resource: %', v_resource_id;
ELSE
SELECT id INTO v_resource_id FROM resources WHERE name = 'Estación Demo' AND location_id = v_location_id;
RAISE NOTICE 'Using existing resource: %', v_resource_id;
END IF;
-- Check if we have services
SELECT id INTO v_service_id FROM services WHERE is_active = true LIMIT 1;
IF v_service_id IS NOT NULL THEN
RAISE NOTICE 'Using service: %', v_service_id;
END IF;
RAISE NOTICE 'Seed data completed';
END $$;
-- Verify results
SELECT
'Locations' as type, COUNT(*)::text as count FROM locations WHERE is_active = true
UNION ALL
SELECT 'Staff', COUNT(*)::text FROM staff WHERE is_active = true
UNION ALL
SELECT 'Resources', COUNT(*)::text FROM resources WHERE is_active = true
UNION ALL
SELECT 'Services', COUNT(*)::text FROM services WHERE is_active = true;