"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."
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}
Last updated 3 months ago