diff --git a/src/lib/components/NewTripPopup.svelte b/src/lib/components/NewTripPopup.svelte index 39a1777..fb57061 100644 --- a/src/lib/components/NewTripPopup.svelte +++ b/src/lib/components/NewTripPopup.svelte @@ -9,13 +9,18 @@ export let fromPage = 'home'; let destination = ""; + let lastSelectedPlaceName = ""; let startDate = ""; let endDate = ""; - let friends = ""; + let friends: string[] = []; + let currentEmail = ""; let destinationError = false; let startDateError = false; let endDateError = false; + let dateOrderError = false; let destinationInput: HTMLDivElement; + let autocomplete: google.maps.places.Autocomplete | null = null; + let isGoogleLoaded = false; const GOOGLE_PLACES_API_KEY = import.meta.env.VITE_GOOGLE_PLACES_API_KEY; @@ -34,59 +39,91 @@ try { await loader.importLibrary("places"); - - const waitForElement = () => new Promise((resolve) => { - const check = () => { - if (destinationInput) return resolve(); - requestAnimationFrame(check); - }; - check(); - }); - - await waitForElement(); - - const input = document.createElement('input'); - input.type = 'text'; - input.id = 'destination-input'; - input.placeholder = 'Where do you want to go?'; - - destinationInput.appendChild(input); - - const autocomplete = new google.maps.places.Autocomplete(input, { - types: ['(regions)'] - }); - autocomplete.setFields(['name', 'formatted_address']); - - autocomplete.addListener('place_changed', () => { - const place = autocomplete.getPlace(); - destination = place.name || ""; - }); - - - // ------ The Implementation below is the new one, but can't style it -------- - // const placeAutocomplete = new google.maps.places.PlaceAutocompleteElement({ - // types: ['(cities)'], // Restrict to cities only - // }); - - // destinationInput.appendChild(placeAutocomplete); - - // //@ts-ignore - // placeAutocomplete.addEventListener('gmp-select', async ({ placePrediction }) => { - // const place = placePrediction.toPlace(); - // await place.fetchFields({ fields: ['displayName', 'formattedAddress', 'location'] }); - // destination = place.displayName; - // }); + isGoogleLoaded = true; } catch (error) { console.error('Error loading Places Autocomplete:', error); } }); + async function initializeAutocomplete() { + if (!isGoogleLoaded || !destinationInput) return; + + const input = document.createElement('input'); + input.type = 'text'; + input.id = 'destination-input'; + input.placeholder = 'Where do you want to go?'; + + destinationInput.appendChild(input); + + autocomplete = new google.maps.places.Autocomplete(input, { + types: ['(regions)'] + }); + autocomplete.setFields(['name', 'formatted_address']); + + autocomplete.addListener('place_changed', () => { + if (!autocomplete) return; + const place = autocomplete.getPlace(); + if (place.name) { + destination = place.name; + lastSelectedPlaceName = input.value.trim(); + destinationError = false; + } + }); + + let placeChangeTimeout; + + input.addEventListener('blur', () => { + // Use a small delay to allow place_changed event to fire first + placeChangeTimeout = setTimeout(() => { + const trimmed = input.value.trim(); + if (trimmed && trimmed !== lastSelectedPlaceName) { + destinationError = true; + } + else if (!trimmed) { + // Don't show error for empty field + destinationError = false; + destination = ""; + } + }, 200); + }); + } + + function isValidEmail(email: string) { + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailRegex.test(email); + } + + function handleEmailInput(event: KeyboardEvent) { + if (event.key === 'Enter') { + event.preventDefault(); + const email = currentEmail.trim(); + + if (email && isValidEmail(email) && !friends.includes(email)) { + friends = [...friends, email]; + currentEmail = ""; + } + } + } + + function removeEmail(emailToRemove: string) { + friends = friends.filter(email => email !== emailToRemove); + } + function handleCancel() { showPopup = false; destination = ""; startDate = ""; endDate = ""; - friends = ""; + friends = []; + currentEmail = ""; + destinationError = false; + startDateError = false; + endDateError = false; + + if (autocomplete) { + google.maps.event.clearInstanceListeners(autocomplete); + autocomplete = null; + } } function handleStart() { @@ -94,13 +131,32 @@ startDateError = !startDate; endDateError = !endDate; - if (destinationError || startDateError || endDateError) { - alert('Please fill in all required fields: Destination, Start Date, End Date'); - return; + // Check if both dates are filled before comparing them + if (startDate && endDate) { + const startDateTime = new Date(startDate).getTime(); + const endDateTime = new Date(endDate).getTime(); + + if (endDateTime < startDateTime) { + startDateError = true; + endDateError = true; + dateOrderError = true; + return; + } + dateOrderError = false; } - goto(`/itinerary?from=${fromPage}`); - handleCancel(); + if (destinationError || startDateError || endDateError) { + // alert('Please fill in all required fields: Destination, Start Date, End Date'); + return; + } + else { + goto(`/itinerary?from=${fromPage}`); + handleCancel(); + } + } + + $: if (showPopup && isGoogleLoaded && destinationInput) { + initializeAutocomplete(); } @@ -110,45 +166,67 @@

Start a New Plan

- +
+ {#if destinationError} +

Please enter your destination

+ {/if}
- + + {#if startDateError} +

+ {dateOrderError ? 'Start date must be before end date' : 'Please enter the starting date'} +

+ {/if}
- + + {#if endDateError} +

+ {dateOrderError ? 'End date must be after start date' : 'Please enter the ending date'} +

+ {/if}
- +
@@ -199,8 +277,10 @@ color: var(--gray-800); } - .input-form label.error { - color: var(--memory-600) !important; + .error-message { + color: var(--memory-600); + margin: 0.5rem 0 0 0; + font-size: 0.8rem; } .input-form input { @@ -253,4 +333,58 @@ gap: 1rem; margin-top: 2rem; } + + .email-input-container { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + padding: 0.25rem 0.5rem; + border: 1px solid var(--gray-200); + border-radius: 8px; + min-height: 2.5rem; + align-items: center; + } + + .email-input-container input { + border: none; + outline: none; + flex: 1; + min-width: 50px; + padding: 0; + padding-left: 0.25rem; + } + + .email-input-container input:focus { + outline: none; + } + + .email-tag { + display: flex; + align-items: center; + background-color: var(--gray-100); + padding: 0.25rem 1rem; + border-radius: 20px; + font-size: 0.9rem; + gap: 0.5rem; + } + .email-tag:hover { + background-color: var(--gray-200); + opacity: 0.8; + } + + .remove-email { + background: none; + border: none; + color: var(--gray-600); + cursor: pointer; + padding: 0; + font-size: 1.2rem; + line-height: 1; + display: flex; + align-items: center; + } + + .remove-email:hover { + color: var(--memory-600); + } \ No newline at end of file