'use client' import { useState, useEffect, Suspense } from 'react' import { useRouter, useSearchParams } from 'next/navigation' function JoinContent() { const [shareCode, setShareCode] = useState('') const [loading, setLoading] = useState(false) const [error, setError] = useState('') const [tripData, setTripData] = useState(null) const [selectedParticipant, setSelectedParticipant] = useState('') const [needsPassword, setNeedsPassword] = useState(false) const [password, setPassword] = useState('') const [tripIdForAuth, setTripIdForAuth] = useState(null) const router = useRouter() const searchParams = useSearchParams() // Auto-fill share code from URL parameter useEffect(() => { const codeFromUrl = searchParams.get('code') if (codeFromUrl) { const uppercaseCode = codeFromUrl.toUpperCase() setShareCode(uppercaseCode) // Clear any existing errors when URL parameter is detected setError('') } }, [searchParams]) // Separate effect to handle auto-trigger after shareCode is updated useEffect(() => { if (shareCode.length === 6 && searchParams.get('code')) { // Small delay to ensure state is fully updated const timer = setTimeout(() => { handleFindTrip() }, 200) return () => clearTimeout(timer) } }, [shareCode, searchParams]) const handleFindTrip = async () => { // Convert to uppercase for validation and API call const uppercaseCode = shareCode.toUpperCase() if (!shareCode || uppercaseCode.length !== 6) { setError('Please enter a valid 6-character code') return } setLoading(true) setError('') try { // Use the API instance with configured baseURL const { tripApi } = await import('@/lib/api') const data = await tripApi.getByShareCode(uppercaseCode) setTripData(data) setError('') return } catch (error: any) { // Check if it's a 401 error (password protected) if (error.response?.status === 401) { // Trip is password protected setNeedsPassword(true) setError('This trip is password protected. Please enter the password.') return } else if (error.response?.status === 404) { setError('Trip not found. Please check the code and try again.') } else { setError('Network error. Please check your connection and try again.') } console.error('Error finding trip:', error) } finally { setLoading(false) } } const handleIdentify = async () => { if (!selectedParticipant) { setError('Please select your name from the list') return } setLoading(true) setError('') try { // Get or create device ID let deviceId = localStorage.getItem('juntete_device_id') if (!deviceId) { deviceId = `device_${Date.now()}_${Math.random().toString(36).substr(2, 9)}` localStorage.setItem('juntete_device_id', deviceId) } // Find selected participant ID const participant = tripData.participants.find((p: any) => p.name === selectedParticipant) if (!participant) { setError('Participant not found') return } // Call API to identify user (use relative URL for mobile compatibility) const response = await fetch('/api/auth/identify', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ trip_id: tripData.id.toString(), participant_id: participant.id.toString(), device_id: deviceId, }), }) if (!response.ok) { throw new Error('Failed to identify user') } const result = await response.json() // Store identity locally localStorage.setItem('juntete_identity', JSON.stringify({ participantName: selectedParticipant, tripId: tripData.id, deviceId: deviceId, createdAt: Date.now(), lastAccessed: Date.now(), })) // Navigate to trip dashboard router.push(`/trip/${tripData.id}`) } catch (error) { setError('Failed to join trip. Please try again.') console.error('Error joining trip:', error) } finally { setLoading(false) } } const handlePasswordSubmit = async (e: React.FormEvent) => { e.preventDefault() if (!password.trim() || !tripIdForAuth) { setError('Please enter a password') return } setLoading(true) setError('') try { const { authenticateTrip } = await import('@/lib/trip-auth') await authenticateTrip(tripIdForAuth, password.trim()) // Now use API instance to get trip data const { tripApi } = await import('@/lib/api') const data = await tripApi.getById(tripIdForAuth) setTripData(data) setNeedsPassword(false) setPassword('') setError('') } catch (err: any) { setError(err.message || 'Incorrect password. Please try again.') setPassword('') } finally { setLoading(false) } } const handleBack = () => { setTripData(null) setSelectedParticipant('') setError('') setShareCode('') setNeedsPassword(false) setPassword('') setTripIdForAuth(null) } if (needsPassword && tripIdForAuth) { return (

Password Required

This trip is password protected

{error && (
{error}
)}
setPassword(e.target.value)} placeholder="Enter trip password" className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100" required autoFocus />
) } if (tripData) { return (

Welcome to {tripData.name || 'this trip'}!

Select your name to join this trip

Who are you?

{tripData.participants && tripData.participants.map((participant: any) => ( ))}
{error && (
{error}
)}
) } return (

Join Trip

Enter the 6-character code to join your group

setShareCode(e.target.value.toUpperCase())} placeholder="ABC123" maxLength={6} className="w-full px-3 py-3 text-center text-lg font-mono border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent uppercase bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100" disabled={loading} />
{error && (
{error}
)}
← Back to Home
) } export default function JoinPage() { return (

Join Trip

Loading...

}>
) }