0xmetaschool/ TripPlannerGPT

"TripPlannerGPT is your ultimate AI-powered trip planning assistant. Forget the hassle of research and logistics—this app creates personalized travel itineraries in seconds. Whether you're a spontaneous adventurer or a meticulous planner, TripPlannerGPT is your perfect travel companion. Built with Next.js and powered by OpenAI API, this template helps you build an AI-driven platform to make travel planning intuitive, quick, and fun."

app
api
dashboard
globals.css
layout.js
page.js
components
lib
.gitignore
components.json
jsconfig.json
LICENSE
middleware.js
next.config.mjs
package.json
postcss.config.mjs
README.md
tailwind.config.js
appseparatorpage.js
1"use client" 2import React, { useState, useEffect, useRef } from 'react'; 3import { useRouter } from 'next/navigation'; 4import axios from 'axios'; 5import Header from "./dashboard/_components/Header"; 6import { Globe, MapPin, Star, ChevronRight, Search, Calendar, Clock, ChevronDown } from 'lucide-react'; 7 8// Custom FAQ Accordion Component 9const FAQItem = ({ question, answer }) => { 10 const [isOpen, setIsOpen] = useState(false); 11 12 return ( 13 <div className="border-b border-gray-200"> 14 <button 15 className="w-full py-4 flex justify-between items-center text-left" 16 onClick={() => setIsOpen(!isOpen)} 17 > 18 <span className="font-medium">{question}</span> 19 <ChevronDown 20 className={`w-5 h-5 transition-transform ${ 21 isOpen ? 'transform rotate-180' : '' 22 }`} 23 /> 24 </button> 25 <div 26 className={`overflow-hidden transition-all duration-300 ${ 27 isOpen ? 'max-h-48 pb-4' : 'max-h-0' 28 }`} 29 > 30 <p className="text-gray-600">{answer}</p> 31 </div> 32 </div> 33 ); 34}; 35 36// SearchForm component with autocomplete 37const SearchForm = () => { 38 const router = useRouter(); 39 const [destination, setDestination] = useState(''); 40 const [dates, setDates] = useState(''); 41 const [suggestions, setSuggestions] = useState([]); 42 const [showSuggestions, setShowSuggestions] = useState(false); 43 const inputRef = useRef(null); 44 45 // Function to handle form submission 46 const handleSearch = (e) => { 47 e.preventDefault(); 48 if (destination) { 49 router.push(`/dashboard?destination=${encodeURIComponent(destination)}&dates=${encodeURIComponent(dates)}`); 50 } 51 }; 52 53 // Function to fetch destination suggestions 54 const fetchSuggestions = async (query) => { 55 try { 56 const response = await axios.get( 57 `https://api.geoapify.com/v1/geocode/autocomplete?text=${query}&apiKey=faf4c387b10e4227b13e06de2107946d` 58 ); 59 setSuggestions(response.data.features); 60 } catch (error) { 61 console.error("Error fetching suggestions:", error); 62 } 63 }; 64 65 // Function to handle input change and fetch suggestions 66 const handleInputChange = (e) => { 67 const value = e.target.value; 68 setDestination(value); 69 if (value.length > 2) { 70 fetchSuggestions(value); 71 setShowSuggestions(true); 72 } else { 73 setShowSuggestions(false); 74 } 75 }; 76 77 // Function to handle suggestion click 78 const handleSuggestionClick = (suggestion) => { 79 setDestination(suggestion.properties.formatted); 80 setShowSuggestions(false); 81 }; 82 83 // Effect to close suggestions when clicking outside the input 84 useEffect(() => { 85 const handleClickOutside = (event) => { 86 if (inputRef.current && !inputRef.current.contains(event.target)) { 87 setShowSuggestions(false); 88 } 89 }; 90 91 document.addEventListener("mousedown", handleClickOutside); 92 return () => { 93 document.removeEventListener("mousedown", handleClickOutside); 94 }; 95 }, []); 96 97 return ( 98 <form onSubmit={handleSearch} className="bg-white p-4 rounded-2xl shadow-xl flex flex-col md:flex-row gap-4"> 99 <div className="flex-1 relative" ref={inputRef}> 100 <div className="flex items-center space-x-3 p-2 border border-gray-200 rounded-lg"> 101 <MapPin className="w-5 h-5 text-gray-400" /> 102 <input 103 type="text" 104 value={destination} 105 onChange={handleInputChange} 106 placeholder="Where do you want to go?" 107 className="w-full focus:outline-none text-gray-700" 108 /> 109 </div> 110 {showSuggestions && ( 111 <div className="absolute z-10 mt-2 w-full bg-white border border-gray-200 rounded-lg shadow-lg max-h-60 overflow-y-auto"> 112 {suggestions.map((suggestion, index) => ( 113 <div 114 key={index} 115 className="p-3 cursor-pointer hover:bg-gray-100" 116 onClick={() => handleSuggestionClick(suggestion)} 117 > 118 {suggestion.properties.formatted} 119 </div> 120 ))} 121 </div> 122 )} 123 </div> 124 125 <div className="flex-1 relative"> 126 <div className="flex items-center space-x-3 p-2 border border-gray-200 rounded-lg"> 127 <Calendar className="w-5 h-5 text-gray-400" /> 128 <input 129 type="date" 130 value={dates} 131 onChange={(e) => setDates(e.target.value)} 132 className="w-full focus:outline-none text-gray-700" 133 /> 134 </div> 135 </div> 136 137 <button 138 type="submit" 139 className="bg-black text-white px-8 py-3 rounded-xl hover:bg-gray-800 transition-colors flex items-center justify-center space-x-2" 140 > 141 <Search className="w-5 h-5" /> 142 <span>Plan Now</span> 143 </button> 144 </form> 145 ); 146}; 147 148// Component to display popular destinations 149const PopularDestination = ({ image, name, rating, price, description }) => ( 150 <div className="relative group overflow-hidden rounded-xl cursor-pointer"> 151 <div className="aspect-w-16 aspect-h-9"> 152 <div className="w-full h-72 relative"> 153 <img 154 src={image} 155 alt={name} 156 className="object-cover w-full h-full transform transition-transform duration-300 group-hover:scale-110" 157 /> 158 <div className="absolute inset-0 bg-gradient-to-t from-black/60 via-black/20 to-transparent"/> 159 </div> 160 </div> 161 <div className="absolute bottom-0 left-0 right-0 p-4"> 162 <div className="flex justify-between items-end"> 163 <div> 164 <h3 className="text-white font-semibold text-xl mb-1">{name}</h3> 165 <p className="text-white/80 text-sm mb-2">{description}</p> 166 <div className="flex items-center text-white"> 167 <Star className="w-4 h-4 fill-yellow-400 text-yellow-400" /> 168 <span className="ml-1">{rating}</span> 169 </div> 170 </div> 171 <div className="text-white text-right"> 172 <p className="text-sm">Starting from</p> 173 <p className="text-xl font-bold">${price}</p> 174 </div> 175 </div> 176 </div> 177 </div> 178); 179 180// Component to display testimonials 181const TestimonialCard = ({ avatar, name, location, text }) => ( 182 <div className="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition-shadow duration-300"> 183 <div className="flex items-center space-x-4 mb-4"> 184 <img src={avatar} alt={name} className="w-12 h-12 rounded-full object-cover" /> 185 <div> 186 <h4 className="font-semibold">{name}</h4> 187 <p className="text-gray-600 text-sm">{location}</p> 188 </div> 189 </div> 190 <p className="text-gray-700">{text}</p> 191 </div> 192); 193 194// Component to display stats 195const StatsCard = ({ number, label }) => ( 196 <div className="text-center"> 197 <h3 className="text-4xl font-bold mb-2">{number}</h3> 198 <p className="text-gray-600">{label}</p> 199 </div> 200); 201 202// Main Home component 203export default function Home() { 204 const popularDestinations = [ 205 { 206 name: "Paris, France", 207 rating: "4.8", 208 price: "799", 209 description: "City of Lights & Romance", 210 image: "paris.png" 211 }, 212 { 213 name: "Bali, Indonesia", 214 rating: "4.9", 215 price: "899", 216 description: "Tropical Paradise", 217 image: "bali.png" 218 }, 219 { 220 name: "Tokyo, Japan", 221 rating: "4.7", 222 price: "999", 223 description: "Modern Meets Traditional", 224 image: "tokyo.png" 225 }, 226 { 227 name: "Santorini, Greece", 228 rating: "4.9", 229 price: "1099", 230 description: "Mediterranean Beauty", 231 image: "San.png" 232 }, 233 { 234 name: "New York City, USA", 235 rating: "4.6", 236 price: "699", 237 description: "The City That Never Sleeps", 238 image: "newyork.png" 239 }, 240 { 241 name: "Dubai, UAE", 242 rating: "4.8", 243 price: "899", 244 description: "Future of Architecture", 245 image: "dubai.png" 246 } 247 ]; 248 249 const faqs = [ 250 { 251 question: "How does the AI travel planning work?", 252 answer: "Our AI analyzes your preferences, budget, and travel dates to create personalized itineraries. It considers factors like popular attractions, local events, and weather conditions to suggest the best experiences for your trip." 253 }, 254 { 255 question: "Can I modify my itinerary after it's generated?", 256 answer: "Yes! You can easily customize any part of your itinerary. Add or remove activities, adjust timings, or change locations - our platform will automatically update your schedule accordingly." 257 }, 258 { 259 question: "What's included in the travel packages?", 260 answer: "Our packages typically include accommodation, main activities, and suggested restaurants. You can also opt for additional services like flight booking, transportation, and travel insurance." 261 }, 262 { 263 question: "How far in advance should I book?", 264 answer: "We recommend booking at least 3-6 months in advance for popular destinations, especially during peak season. However, our platform can also accommodate last-minute planners with quick itinerary generation." 265 } 266 ]; 267 268 return ( 269 <div className="min-h-screen bg-white"> 270 <Header /> 271 272 {/* Hero Section */} 273 <section className="relative min-h-[90vh] flex items-center"> 274 <div className="absolute inset-0"> 275 <img 276 src="home.jpg" 277 alt="Travel Background" 278 className="w-full h-full object-cover" 279 /> 280 <div className="absolute inset-0 bg-black/40" /> 281 </div> 282 283 <div className="container mx-auto px-4 relative z-10"> 284 <div className="max-w-3xl"> 285 <h1 className="text-5xl md:text-6xl font-bold text-white mb-6"> 286 Discover Your Perfect 287 <span className="block text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-emerald-400"> 288 Travel Experience 289 </span> 290 </h1> 291 <p className="text-xl text-white/90 mb-8"> 292 AI-powered travel planning that creates personalized itineraries in seconds 293 </p> 294 295 <SearchForm /> 296 </div> 297 </div> 298 </section> 299 300 {/* Stats Section */} 301 <section className="mt-20 py-16 bg-gray-200"> 302 <div className="container mx-auto px-4"> 303 <div className="grid grid-cols-2 md:grid-cols-4 gap-8"> 304 <StatsCard number="50K+" label="Happy Travelers" /> 305 <StatsCard number="100+" label="Destinations" /> 306 <StatsCard number="4.9" label="Average Rating" /> 307 <StatsCard number="24/7" label="Support" /> 308 </div> 309 </div> 310 </section> 311 312 {/* Popular Destinations */} 313 <section className="py-20"> 314 <div className="container mx-auto px-4"> 315 <div className="flex justify-between items-center mb-12"> 316 <h2 className="text-3xl font-bold">Popular Destinations</h2> 317 </div> 318 319 <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"> 320 {popularDestinations.map((destination, index) => ( 321 <PopularDestination key={index} {...destination} /> 322 ))} 323 </div> 324 </div> 325 </section> 326 327 {/* Testimonials */} 328 <section className="py-20 bg-gray-50"> 329 <div className="container mx-auto px-4"> 330 <h2 className="text-3xl font-bold text-center mb-12">What Our Travelers Say</h2> 331 <div className="grid grid-cols-1 md:grid-cols-3 gap-8"> 332 <TestimonialCard 333 avatar="sarah.png" 334 name="Sarah Johnson" 335 location="New York, USA" 336 text="The AI-powered itinerary was perfect! It saved me hours of planning and introduced me to hidden gems I wouldn't have found otherwise." 337 /> 338 <TestimonialCard 339 avatar="David.png" 340 name="David Chen" 341 location="Singapore" 342 text="Extremely impressed with the personalization. Every suggestion matched my interests perfectly." 343 /> 344 <TestimonialCard 345 avatar="Emma.png" 346 name="Emma Williams" 347 location="London, UK" 348 text="The real-time updates during my trip were invaluable. It made traveling so much more convenient and stress-free." 349 /> 350 </div> 351 </div> 352 </section> 353 354 {/* FAQ Section */} 355 <section className="py-20"> 356 <div className="container mx-auto px-4"> 357 <h2 className="text-3xl font-bold text-center mb-12">Frequently Asked Questions</h2> 358 <div className="max-w-3xl mx-auto"> 359 {faqs.map((faq, index) => ( 360 <FAQItem key={index} {...faq} /> 361 ))} 362 </div> 363 </div> 364 </section> 365 366 {/* Newsletter Section */} 367 <section className="py-20 bg-gray-50"> 368 <div className="container mx-auto px-4 text-center"> 369 <h2 className="text-3xl font-bold mb-6">Stay Updated</h2> 370 <p className="text-gray-600 mb-8 max-w-2xl mx-auto"> 371 Subscribe to our newsletter for travel tips, destination guides, and exclusive offers 372 </p> 373 <form className="max-w-md mx-auto flex gap-4"> 374 <input 375 type="email" 376 placeholder="Enter your email" 377 className="flex-1 px-4 py-3 rounded-lg border border-gray-200 focus:outline-none focus:ring-2 focus:ring-black/5" 378 /> 379 <button 380 type="submit" 381 className="bg-black text-white px-6 py-3 rounded-lg hover:bg-gray-800 transition-colors" 382 > 383 Subscribe 384 </button> 385 </form> 386 </div> 387 </section> 388 389 {/* CTA Section */} 390 <section className="bg-black text-white py-20"> 391 <div className="container mx-auto px-4 text-center"> 392 <h2 className="text-3xl md:text-4xl font-bold mb-6"> 393 Ready to Start Your Journey? 394 </h2> 395 <p className="text-xl text-gray-300 mb-8 max-w-2xl mx-auto"> 396 Join thousands of travelers who plan their perfect trips with our AI-powered platform 397 </p> 398 <a 399 href="/dashboard" 400 className="inline-block bg-white text-black px-8 py-4 rounded-xl text-lg font-semibold hover:bg-gray-100 transition-colors" 401 > 402 Start Planning for Free 403 </a> 404 </div> 405 </section> 406 </div> 407 ); 408}
Downloads

0

Version

1.0.0

License

MIT

Platform

OpenAI GPT-4

Contributors 3
M-Talha-Amin
fareeha25
muhammadtalhaamin
Open in

Last updated 3 months ago

We are a open source platform and encourage community to contribute to these templates!