Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# [Project Name] 🎯
# DestINo 🎯


## Basic Details
Expand Down
47 changes: 47 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Travel Itinerary Planner</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.4.0/jspdf.umd.min.js"></script>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<h1>AI Travel Itinerary Planner</h1>
</header>

<div class="form-container">
<h2>Select Your Destination</h2>
<select id="destination">
<option value="" disabled selected>Select a destination</option>
<option value="Paris">Paris</option>
<option value="New York">New York</option>
<option value="Tokyo">Tokyo</option>
<option value="London">London</option>
<option value="Rome">Rome</option>
<option value="Sydney">Sydney</option>
<option value="Dubai">Dubai</option>
</select>

<h2>Enter Your Budget</h2>
<input type="number" id="budget" placeholder="Enter Budget">

Comment on lines +17 to +30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance form accessibility and validation.

The form inputs need accessibility improvements and better validation:

  1. Missing ARIA labels
  2. Missing form validation attributes
  3. Missing currency indicator

Apply these improvements:

-        <select id="destination">
+        <select id="destination" aria-label="Select your travel destination" required>
             <option value="" disabled selected>Select a destination</option>
             <option value="Paris">Paris</option>
             <!-- ... other options ... -->
         </select>
 
         <h2>Enter Your Budget</h2>
-        <input type="number" id="budget" placeholder="Enter Budget">
+        <div class="input-group">
+            <span class="currency">$</span>
+            <input 
+                type="number" 
+                id="budget" 
+                placeholder="Enter Budget" 
+                aria-label="Enter your budget in USD"
+                min="0" 
+                step="0.01" 
+                required
+            >
+        </div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<select id="destination">
<option value="" disabled selected>Select a destination</option>
<option value="Paris">Paris</option>
<option value="New York">New York</option>
<option value="Tokyo">Tokyo</option>
<option value="London">London</option>
<option value="Rome">Rome</option>
<option value="Sydney">Sydney</option>
<option value="Dubai">Dubai</option>
</select>
<h2>Enter Your Budget</h2>
<input type="number" id="budget" placeholder="Enter Budget">
<select id="destination" aria-label="Select your travel destination" required>
<option value="" disabled selected>Select a destination</option>
<option value="Paris">Paris</option>
<option value="New York">New York</option>
<option value="Tokyo">Tokyo</option>
<option value="London">London</option>
<option value="Rome">Rome</option>
<option value="Sydney">Sydney</option>
<option value="Dubai">Dubai</option>
</select>
<h2>Enter Your Budget</h2>
<div class="input-group">
<span class="currency">$</span>
<input
type="number"
id="budget"
placeholder="Enter Budget"
aria-label="Enter your budget in USD"
min="0"
step="0.01"
required
>
</div>

<h2>Select Your Trip Dates</h2>
<input type="date" id="start-date">
<input type="date" id="end-date">

<button onclick="generateItinerary()">Generate Itinerary</button>
</div>

<div id="itinerary-view">
<h2>Your AI-Generated Itinerary</h2>
<div id="itinerary-summary"></div>
</div>

<button onclick="exportItinerary()">Export as PDF</button>

<script src="script.js"></script>
</body>
</html>
108 changes: 108 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
const destinationData = {
"Paris": {
activities: [
{ name: "Eiffel Tower Visit", cost: 30 },
{ name: "Louvre Museum", cost: 20 },
{ name: "Seine River Cruise", cost: 50 },
{ name: "Notre-Dame Cathedral", cost: 0 }
],
accommodations: [
{ name: "Budget Hotel", costPerNight: 100 },
{ name: "Mid-range Hotel", costPerNight: 200 },
{ name: "Luxury Hotel", costPerNight: 400 }
]
},
"New York": {
activities: [
{ name: "Statue of Liberty", cost: 25 },
{ name: "Central Park", cost: 0 },
{ name: "Broadway Show", cost: 100 },
{ name: "Times Square", cost: 0 }
],
accommodations: [
{ name: "Budget Hostel", costPerNight: 50 },
{ name: "Mid-range Hotel", costPerNight: 150 },
{ name: "Luxury Hotel", costPerNight: 350 }
]
},
"Tokyo": {
activities: [
{ name: "Shibuya Crossing", cost: 0 },
{ name: "Tokyo Tower", cost: 15 },
{ name: "Senso-ji Temple", cost: 0 },
{ name: "Odaiba Shopping Mall", cost: 30 }
],
accommodations: [
{ name: "Capsule Hotel", costPerNight: 40 },
{ name: "Business Hotel", costPerNight: 100 },
{ name: "Luxury Hotel", costPerNight: 300 }
]
},
"London": {
activities: [
{ name: "London Eye", cost: 30 },
{ name: "British Museum", cost: 0 },
{ name: "Westminster Abbey", cost: 20 }
],
accommodations: [
{ name: "Budget Hostel", costPerNight: 60 },
{ name: "Mid-range Hotel", costPerNight: 180 },
{ name: "Luxury Hotel", costPerNight: 400 }
]
}
};

function generateItinerary() {
const destinationSelect = document.getElementById('destination');
const selectedDestination = destinationSelect.value;
const budget = parseFloat(document.getElementById('budget').value);
const startDate = document.getElementById('start-date').value;
const endDate = document.getElementById('end-date').value;

if (!selectedDestination || isNaN(budget) || budget <= 0 || !startDate || !endDate) {
alert("Please select a valid destination, enter a valid budget, and select trip dates.");
return;
}

const data = destinationData[selectedDestination];
if (!data) {
alert("Sorry, we don't have data for this destination.");
return;
}

const start = new Date(startDate);
const end = new Date(endDate);
const days = Math.floor((end - start) / (1000 * 60 * 60 * 24));

let activities = data.activities.filter(activity => activity.cost <= budget);
let accommodations = data.accommodations.filter(acc => acc.costPerNight <= budget / 3);

let itinerarySummary = `
<h3>Destination: ${selectedDestination}</h3>
<h4>Dates: ${startDate} to ${endDate} (Total Days: ${days})</h4>
<h4>Activities:</h4>
<ul>
${activities.map(activity => `<li>${activity.name} - $${activity.cost}</li>`).join('')}
</ul>
<h4>Accommodation Options:</h4>
<ul>
${accommodations.map(acc => `<li>${acc.name} - $${acc.costPerNight} per night</li>`).join('')}
</ul>
<h4>Suggested Itinerary:</h4>
<ul>
<li>Day 1: Arrive and check into your accommodation</li>
${activities.slice(0, days - 1).map((activity, index) => `<li>Day ${index + 2}: ${activity.name}</li>`).join('')}
</ul>
`;

document.getElementById('itinerary-summary').innerHTML = itinerarySummary;
}
Comment on lines +55 to +99
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve input validation and error handling.

The function needs additional validation and error handling:

  1. Validate that end date is after start date
  2. Improve budget filtering logic
  3. Handle edge cases (e.g., no activities/accommodations within budget)

Apply these improvements:

 function generateItinerary() {
     const destinationSelect = document.getElementById('destination');
     const selectedDestination = destinationSelect.value;
     const budget = parseFloat(document.getElementById('budget').value);
     const startDate = document.getElementById('start-date').value;
     const endDate = document.getElementById('end-date').value;
 
     if (!selectedDestination || isNaN(budget) || budget <= 0 || !startDate || !endDate) {
         alert("Please select a valid destination, enter a valid budget, and select trip dates.");
         return;
     }
 
+    const start = new Date(startDate);
+    const end = new Date(endDate);
+    if (end <= start) {
+        alert("End date must be after start date.");
+        return;
+    }
+
     const data = destinationData[selectedDestination];
     if (!data) {
         alert("Sorry, we don't have data for this destination.");
         return;
     }
 
-    const start = new Date(startDate);
-    const end = new Date(endDate);
     const days = Math.floor((end - start) / (1000 * 60 * 60 * 24));
 
-    let activities = data.activities.filter(activity => activity.cost <= budget);
-    let accommodations = data.accommodations.filter(acc => acc.costPerNight <= budget / 3);
+    // Reserve 60% of budget for accommodation
+    const accommodationBudget = budget * 0.6;
+    const activityBudget = budget * 0.4;
+    
+    let accommodations = data.accommodations.filter(acc => acc.costPerNight * days <= accommodationBudget);
+    let activities = data.activities.filter(activity => activity.cost <= activityBudget);
+
+    if (accommodations.length === 0 || activities.length === 0) {
+        alert("Sorry, no activities or accommodations available within your budget.");
+        return;
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function generateItinerary() {
const destinationSelect = document.getElementById('destination');
const selectedDestination = destinationSelect.value;
const budget = parseFloat(document.getElementById('budget').value);
const startDate = document.getElementById('start-date').value;
const endDate = document.getElementById('end-date').value;
if (!selectedDestination || isNaN(budget) || budget <= 0 || !startDate || !endDate) {
alert("Please select a valid destination, enter a valid budget, and select trip dates.");
return;
}
const data = destinationData[selectedDestination];
if (!data) {
alert("Sorry, we don't have data for this destination.");
return;
}
const start = new Date(startDate);
const end = new Date(endDate);
const days = Math.floor((end - start) / (1000 * 60 * 60 * 24));
let activities = data.activities.filter(activity => activity.cost <= budget);
let accommodations = data.accommodations.filter(acc => acc.costPerNight <= budget / 3);
let itinerarySummary = `
<h3>Destination: ${selectedDestination}</h3>
<h4>Dates: ${startDate} to ${endDate} (Total Days: ${days})</h4>
<h4>Activities:</h4>
<ul>
${activities.map(activity => `<li>${activity.name} - $${activity.cost}</li>`).join('')}
</ul>
<h4>Accommodation Options:</h4>
<ul>
${accommodations.map(acc => `<li>${acc.name} - $${acc.costPerNight} per night</li>`).join('')}
</ul>
<h4>Suggested Itinerary:</h4>
<ul>
<li>Day 1: Arrive and check into your accommodation</li>
${activities.slice(0, days - 1).map((activity, index) => `<li>Day ${index + 2}: ${activity.name}</li>`).join('')}
</ul>
`;
document.getElementById('itinerary-summary').innerHTML = itinerarySummary;
}
function generateItinerary() {
const destinationSelect = document.getElementById('destination');
const selectedDestination = destinationSelect.value;
const budget = parseFloat(document.getElementById('budget').value);
const startDate = document.getElementById('start-date').value;
const endDate = document.getElementById('end-date').value;
if (!selectedDestination || isNaN(budget) || budget <= 0 || !startDate || !endDate) {
alert("Please select a valid destination, enter a valid budget, and select trip dates.");
return;
}
const start = new Date(startDate);
const end = new Date(endDate);
if (end <= start) {
alert("End date must be after start date.");
return;
}
const data = destinationData[selectedDestination];
if (!data) {
alert("Sorry, we don't have data for this destination.");
return;
}
const days = Math.floor((end - start) / (1000 * 60 * 60 * 24));
// Reserve 60% of budget for accommodation
const accommodationBudget = budget * 0.6;
const activityBudget = budget * 0.4;
let accommodations = data.accommodations.filter(acc => acc.costPerNight * days <= accommodationBudget);
let activities = data.activities.filter(activity => activity.cost <= activityBudget);
if (accommodations.length === 0 || activities.length === 0) {
alert("Sorry, no activities or accommodations available within your budget.");
return;
}
let itinerarySummary = `
<h3>Destination: ${selectedDestination}</h3>
<h4>Dates: ${startDate} to ${endDate} (Total Days: ${days})</h4>
<h4>Activities:</h4>
<ul>
${activities.map(activity => `<li>${activity.name} - $${activity.cost}</li>`).join('')}
</ul>
<h4>Accommodation Options:</h4>
<ul>
${accommodations.map(acc => `<li>${acc.name} - $${acc.costPerNight} per night</li>`).join('')}
</ul>
<h4>Suggested Itinerary:</h4>
<ul>
<li>Day 1: Arrive and check into your accommodation</li>
${activities.slice(0, days - 1).map((activity, index) => `<li>Day ${index + 2}: ${activity.name}</li>`).join('')}
</ul>
`;
document.getElementById('itinerary-summary').innerHTML = itinerarySummary;
}


function exportItinerary() {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();

const itineraryContent = document.getElementById('itinerary-summary').innerText;
doc.text(itineraryContent, 10, 10);
doc.save('itinerary.pdf');
}
102 changes: 102 additions & 0 deletions styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
color: #333;
margin: 0;
padding: 0;
}

header {
background-color: #4CAF50;
color: white;
text-align: center;
padding: 20px 0;
}

h1 {
margin: 0;
}

h2 {
font-size: 1.5rem;
margin-top: 0;
color: #444;
}

h3 {
font-size: 1.2rem;
margin-bottom: 10px;
}

h4 {
font-size: 1rem;
color: #555;
}

.form-container {
background-color: white;
padding: 20px;
margin: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

input[type="text"],
input[type="number"] {
width: 100%;
padding: 10px;
margin: 10px 0;
border-radius: 4px;
border: 1px solid #ddd;
}

button {
background-color: #4CAF50;
color: white;
border: none;
padding: 10px 20px;
cursor: pointer;
border-radius: 4px;
font-size: 1rem;
margin-top: 10px;
}

button:hover {
background-color: #45a049;
}

#itinerary-view {
margin: 20px;
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

ul {
list-style-type: none;
padding: 0;
}

ul li {
padding: 5px 0;
font-size: 1rem;
}

ul li:nth-child(even) {
background-color: #f9f9f9;
}

button:active {
transform: scale(0.98);
}

footer {
text-align: center;
padding: 10px;
background-color: #4CAF50;
color: white;
position: fixed;
bottom: 0;
width: 100%;
}