# Personalized Meeting Links Implementation ## Overview All meeting links are now personalized with the user's name and role-specific settings. This ensures users join meetings with their actual names instead of generic identifiers, and admins get appropriate moderator privileges. ## Changes Made ### 1. API Endpoints with Personalized Links #### GET /api/bookings Returns the authenticated user's bookings with personalized meeting links. **Response Example:** ```json { "bookings": [ { "id": 123, "user_id": 45, "scheduled_at": "2024-01-15T10:00:00Z", "duration": 60, "status": "scheduled", "jitsi_room_id": "booking-123-1234567890-abc123", "jitsi_room_url": "https://meet.jit.si/booking-123-1234567890-abc123", "personalized_meeting_url": "https://meet.jit.si/booking-123-1234567890-abc123#userInfo.displayName=\"John Doe\"", "amount": 100.00, "payment_status": "succeeded" } ] } ``` **Key Fields:** - `jitsi_room_url`: Original Jitsi room URL (kept for backward compatibility) - `personalized_meeting_url`: User-specific URL with their name pre-filled #### GET /api/admin/bookings Returns all bookings with admin's personalized meeting links. **Response Example:** ```json { "bookings": [ { "id": 123, "user_id": 45, "scheduled_at": "2024-01-15T10:00:00Z", "duration": 60, "status": "scheduled", "jitsi_room_id": "booking-123-1234567890-abc123", "jitsi_room_url": "https://meet.jit.si/booking-123-1234567890-abc123", "admin_meeting_url": "https://meet.jit.si/booking-123-1234567890-abc123#userInfo.displayName=\"Dr. Smith\"&config.startWithAudioMuted=false&config.startWithVideoMuted=false", "amount": 100.00, "payment_status": "succeeded" } ], "total": 1, "limit": 50, "offset": 0 } ``` **Key Fields:** - `admin_meeting_url`: Admin-specific URL with moderator privileges #### GET /api/meetings/:id/link Returns a personalized meeting link for a specific booking. **Response Example:** ```json { "booking_id": 123, "meeting_url": "https://meet.jit.si/booking-123-1234567890-abc123#userInfo.displayName=\"John Doe\"", "display_name": "John Doe", "is_admin": false, "scheduled_at": "2024-01-15T10:00:00Z", "duration": 60, "status": "scheduled" } ``` ### 2. Email Notifications All email notifications now include personalized meeting links: #### Meeting Info Email (After Booking) - Sent to: **User** - Link includes: User's name - Example: `https://meet.jit.si/room-id#userInfo.displayName="John Doe"` #### Reminder Email (Before Meeting) - Sent to: **User** - Link includes: User's name - Example: `https://meet.jit.si/room-id#userInfo.displayName="John Doe"` **Note:** Admin users receive emails with admin privileges in the link if they book for themselves. ### 3. Display Name Logic The system determines display names in this order: 1. **First Name + Last Name**: `"John Doe"` 2. **Email**: If name fields are empty, uses email address 3. **Fallback**: Email as last resort ### 4. Admin vs Regular User Differences #### Regular User Link ``` https://meet.jit.si/room-id#userInfo.displayName="John Doe" ``` **Features:** - Name pre-filled - Standard participant permissions - Default audio/video settings #### Admin User Link ``` https://meet.jit.si/room-id#userInfo.displayName="Dr. Smith"&config.startWithAudioMuted=false&config.startWithVideoMuted=false ``` **Features:** - Name pre-filled - Moderator privileges - Audio and video enabled by default - Can manage participants - Can start/stop recording (if configured) ## Frontend Implementation Guide ### Using Personalized Links from /api/bookings ```javascript // Fetch user's bookings async function fetchMyBookings() { const response = await fetch('/api/bookings', { headers: { 'Authorization': `Bearer ${userToken}` } }); const data = await response.json(); // Use personalized_meeting_url instead of jitsi_room_url data.bookings.forEach(booking => { if (booking.personalized_meeting_url) { console.log(`Join link: ${booking.personalized_meeting_url}`); } }); } ``` ### Using Admin Links from /api/admin/bookings ```javascript // Fetch all bookings as admin async function fetchAllBookings() { const response = await fetch('/api/admin/bookings', { headers: { 'Authorization': `Bearer ${adminToken}` } }); const data = await response.json(); // Use admin_meeting_url for admin access data.bookings.forEach(booking => { if (booking.admin_meeting_url) { console.log(`Admin join link: ${booking.admin_meeting_url}`); } }); } ``` ### React Component Example ```jsx function BookingCard({ booking, isAdmin }) { const getMeetingLink = () => { if (isAdmin && booking.admin_meeting_url) { return booking.admin_meeting_url; } return booking.personalized_meeting_url || booking.jitsi_room_url; }; const handleJoinMeeting = () => { const meetingLink = getMeetingLink(); window.open(meetingLink, '_blank'); }; return (
Scheduled: {new Date(booking.scheduled_at).toLocaleString()}
{booking.status === 'scheduled' && ( )}