Learn how to build a travel itinerary app with Lovable. Follow our step-by-step guide to create a seamless and enjoyable travel planning experience.
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Project File Structure and Setup
index.html
, style.css
, and app.js
.
Adding Dependencies Without a Terminal
index.html
file using CDN links.index.html
file and insert the following code inside the <head>
tag to load the dependencies:
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Travel Itinerary App</title>
<link rel="stylesheet" href="style.css">
<!-- Dependency: Moment.js for date handling -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/min/moment.min.js"></script>
</head>
Building the HTML Structure
index.html
file to create the basic HTML structure of your travel itinerary app.body
section of your index.html
file:
<body>
<header>
<h1>Travel Itinerary App</h1>
</header>
<main>
<form id="itinerary-form">
<input type="text" id="destination" placeholder="Destination" required>
<input type="date" id="date" required>
<input type="text" id="activity" placeholder="Activity" required>
<button type="submit">Add Itinerary</button>
</form>
<section id="itinerary-list">
<h2>Your Itinerary</h2>
<!-- Itinerary items will appear here -->
</section>
</main>
<script src="app.js"></script>
</body>
Styling the App with CSS
style.css
file and add the following CSS to style the app layout and elements:
/_ Basic styling for the Travel Itinerary App _/
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f4f4f4;
}
header {
text-align: center;
margin-bottom: 20px;
}
form {
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: center;
margin-bottom: 20px;
}
form input, form button {
padding: 10px;
font-size: 1rem;
}
#itinerary-list {
max-width: 600px;
margin: 0 auto;
background-color: #fff;
border-radius: 5px;
padding: 20px;
box-shadow: 0px 0px 10px rgba(0,0,0,0.1);
}
#itinerary-list h2 {
text-align: center;
}
.itinerary-item {
border-bottom: 1px solid #ddd;
padding: 10px 0;
}
.itinerary-item:last-child {
border-bottom: none;
}
Implementing JavaScript Functionality
app.js
file.app.js
file:
// Wait until the document is fully loaded
document.addEventListener('DOMContentLoaded', function () {
// Reference to the itinerary form and list
var form = document.getElementById('itinerary-form');
var itineraryList = document.getElementById('itinerary-list');
// Listen for form submission
form.addEventListener('submit', function(event) {
event.preventDefault(); // Prevent page refresh
// Get values from the form inputs
var destination = document.getElementById('destination').value;
var date = document.getElementById('date').value;
var activity = document.getElementById('activity').value;
// Format the date using Moment.js (if date is valid)
var formattedDate = moment(date).format('MMMM Do, YYYY');
// Create a new itinerary item element
var item = document.createElement('div');
item.className = 'itinerary-item';
item.innerHTML = '<strong>Destination:</strong> ' + destination + '<br>' +
'<strong>Date:</strong> ' + formattedDate + '<br>' +
'<strong>Activity:</strong> ' + activity;
// Append the item to the itinerary list
itineraryList.appendChild(item);
// Clear the form inputs
form.reset();
});
});
Testing Your Travel Itinerary App
Final Notes and Deployment
index.html
, style.css
, app.js
), save them and use the “Run” feature to view your updates.index.html
file as done for Moment.js.
const express = require('express');
const mongoose = require('mongoose');
const app = express();
app.use(express.json());
const ItinerarySchema = new mongoose.Schema({
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
title: { type: String, required: true },
dates: {
start: { type: Date, required: true },
end: { type: Date, required: true }
},
stops: [{
location: { type: String, required: true },
arrival: { type: Date, required: true },
departure: { type: Date, required: true },
activities: [{ type: String }],
isLoved: { type: Boolean, default: false }
}]
});
const Itinerary = mongoose.model('Itinerary', ItinerarySchema);
app.post('/api/itineraries', async (req, res) => {
try {
const itinerary = new Itinerary(req.body);
await itinerary.save();
res.status(201).json(itinerary);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
app.post('/api/itineraries/:id/stops', async (req, res) => {
try {
const itinerary = await Itinerary.findById(req.params.id);
if (!itinerary) return res.status(404).json({ error: 'Itinerary not found' });
itinerary.stops.push(req.body);
await itinerary.save();
res.status(200).json(itinerary);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
mongoose.connect('mongodb://localhost/travelitinerary', { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => app.listen(3000))
.catch(err => console.error(err));
const express = require('express');
const axios = require('axios');
const router = express.Router();
router.get('/api/external/recommendations', async (req, res) => {
const { latitude, longitude, category } = req.query;
if (!latitude || !longitude) {
return res.status(400).json({ error: 'latitude and longitude query parameters are required.' });
}
try {
const externalResponse = await axios.get('https://api.externaltravel.com/v1/places', {
params: {
lat: latitude,
lng: longitude,
term: category || 'landmark',
sort: 'popular'
},
headers: {
'Authorization': 'Bearer YOUR_EXTERNAL_API\_KEY'
}
});
// Example: Filter and transform data to include only highly rated places marked as "loved"
const recommendations = externalResponse.data.places
.filter(place => place.rating >= 4.5)
.map(place => ({
id: place.id,
name: place.name,
address: place.location.address,
rating: place.rating,
isLoved: true // mark as loved based on high rating
}));
res.status(200).json({ recommendations });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
module.exports = router;
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const ItinerarySchema = new mongoose.Schema({
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
title: { type: String, required: true },
dates: {
start: { type: Date, required: true },
end: { type: Date, required: true }
},
stops: [{
stopId: { type: mongoose.Schema.Types.ObjectId, auto: true },
location: { type: String, required: true },
arrival: { type: Date, required: true },
departure: { type: Date, required: true },
activities: [{ type: String }],
isLoved: { type: Boolean, default: false }
}]
});
const Itinerary = mongoose.model('Itinerary', ItinerarySchema);
router.put('/api/itineraries/:itineraryId/stops/:stopId/delay', async (req, res) => {
try {
const { itineraryId, stopId } = req.params;
const { delay } = req.body; // delay in minutes
if (!delay || isNaN(delay)) {
return res.status(400).json({ error: 'A valid delay (in minutes) is required.' });
}
const itinerary = await Itinerary.findById(itineraryId);
if (!itinerary) {
return res.status(404).json({ error: 'Itinerary not found.' });
}
const stops = itinerary.stops;
const index = stops.findIndex(stop => stop.stopId.toString() === stopId);
if (index === -1) {
return res.status(404).json({ error: 'Stop not found in itinerary.' });
}
const delayMs = delay \* 60000;
// Adjust the departure time for the affected stop
stops[index].departure = new Date(new Date(stops[index].departure).getTime() + delayMs);
// Propagate delay to subsequent stops
for (let i = index + 1; i < stops.length; i++) {
stops[i].arrival = new Date(new Date(stops[i].arrival).getTime() + delayMs);
stops[i].departure = new Date(new Date(stops[i].departure).getTime() + delayMs);
}
// If the delay is significant, mark the stop as "loved"
if (delay >= 30) {
stops[index].isLoved = true;
}
await itinerary.save();
res.json({ itinerary });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
module.exports = router;
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Overview of the Travel Itinerary App with AI Code Generators
Project Planning and Setting Requirements
Selecting Tools and AI Code Generators
Designing the User Interface (UI)
Integrating AI Code Generators into Your App
# Example Python code snippet for AI integration
import requests
def get_itinerary_suggestions(user_input):
api_url = "https://api.example-ai.com/generate"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
payload = {"input": user_input}
response = requests.post(api_url, json=payload, headers=headers)
if response.status_code == 200:
return response.json().get("suggestions")
else:
return "An error occurred while generating suggestions."
Example usage
user_input = "3-day trip in Paris with a focus on art and cuisine"
suggestions = get_itinerary_suggestions(user_input)
print(suggestions)
Building and Customizing Key Features
Testing and Debugging Your Itinerary App
Deployment and Hosting
Post-Launch Best Practices
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.