MrTravelX commited on
Commit
88dbdcc
ยท
verified ยท
1 Parent(s): 9925925

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +713 -178
app.py CHANGED
@@ -3,13 +3,14 @@ import os
3
  import json
4
  from datetime import datetime, timedelta
5
  import base64
 
6
  from travel import (
7
  destination_research_task, accommodation_task, transportation_task,
8
- activities_task, dining_task, itinerary_task, final_report_task,
9
  run_task
10
  )
11
 
12
- # Set page configuration
13
  st.set_page_config(
14
  page_title="BlockX Travel Itinerary Generator",
15
  page_icon="โœˆ๏ธ",
@@ -17,107 +18,342 @@ st.set_page_config(
17
  initial_sidebar_state="expanded"
18
  )
19
 
20
- # Custom CSS for better styling
21
  st.markdown("""
22
  <style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  .main-header {
24
  font-size: 2.5rem;
25
- color: #1E88E5;
26
  text-align: center;
27
- margin-bottom: 1rem;
 
 
28
  }
 
29
  .sub-header {
30
- font-size: 1.5rem;
31
- color: #0D47A1;
32
- margin-top: 2rem;
33
- margin-bottom: 1rem;
 
 
 
34
  }
35
- .info-box {
36
- background-color: #E3F2FD;
37
- padding: 1rem;
38
- border-radius: 0.5rem;
39
- margin-bottom: 1rem;
 
 
 
 
 
40
  }
41
- .success-box {
42
- background-color: #E8F5E9;
43
- padding: 1rem;
44
- border-radius: 0.5rem;
45
- margin-bottom: 1rem;
46
- border-left: 5px solid #4CAF50;
47
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  .progress-container {
49
- margin: 1rem 0;
 
 
 
 
50
  }
 
51
  .step-complete {
52
  color: #4CAF50;
53
- font-weight: bold;
54
  }
 
55
  .step-pending {
56
  color: #9E9E9E;
57
  }
 
58
  .step-active {
59
- color: #1E88E5;
60
- font-weight: bold;
61
- }
62
- .agent-log {
63
- background-color: #F5F5F5;
64
- border-left: 3px solid #1E88E5;
65
- padding: 0.5rem;
66
- margin-bottom: 0.5rem;
67
- font-family: monospace;
68
  }
 
 
69
  .agent-output {
70
- background-color: #E8F5E9;
71
- border-left: 5px solid #4CAF50;
72
- padding: 1rem;
73
  margin: 1rem 0;
74
- border-radius: 0.5rem;
75
  max-height: 400px;
76
  overflow-y: auto;
77
  }
 
 
78
  .footer {
79
  text-align: center;
80
  margin-top: 3rem;
81
- color: #757575;
82
- font-size: 0.8rem;
 
 
 
 
 
 
 
 
 
 
 
 
83
  }
84
- .stButton button {
85
- background-color: #1E88E5;
 
 
86
  color: white;
87
- font-weight: bold;
 
 
 
 
 
 
 
 
 
 
88
  }
89
  </style>
90
  """, unsafe_allow_html=True)
91
 
92
  # Helper function to download HTML file
93
- def get_download_link(html_content, filename):
94
- b64 = base64.b64encode(html_content.encode()).decode()
95
- href = f'<a href="data:text/html;base64,{b64}" download="{filename}">Download Itinerary as HTML</a>'
96
  return href
97
 
98
- # Helper function to display progress
99
- def display_progress(current_step, total_steps=7):
100
- progress_html = '<div class="progress-container">'
101
- steps = [
102
- "Destination Research",
103
- "Accommodation",
104
- "Transportation",
105
- "Activities",
106
- "Dining",
107
- "Itinerary Creation",
108
- "Final Report"
109
- ]
110
 
111
- for i, step in enumerate(steps):
 
112
  if i < current_step:
113
- progress_html += f'<p class="step-complete">โœ“ {step} - Complete</p>'
114
  elif i == current_step:
115
- progress_html += f'<p class="step-active">โŸณ {step} - In Progress...</p>'
116
  else:
117
- progress_html += f'<p class="step-pending">โ—‹ {step} - Pending</p>'
118
 
119
- progress_html += '</div>'
120
- return progress_html
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
 
122
  # Custom run_task function that updates the UI with logs and shows live agent outputs
123
  def run_task_with_logs(task, input_text, log_container, output_container, results_key=None):
@@ -176,100 +412,267 @@ if 'log_messages' not in st.session_state:
176
  st.session_state.log_messages = []
177
  if 'current_output' not in st.session_state:
178
  st.session_state.current_output = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
 
180
- # Header
181
- st.markdown('<h1 class="main-header">BlockX Travel Itinerary Generator</h1>', unsafe_allow_html=True)
182
- st.markdown('<p style="text-align: center;">Create your personalized AI-powered travel itinerary in minutes!</p>', unsafe_allow_html=True)
183
 
184
- # Sidebar with information
185
  with st.sidebar:
186
- st.image("https://img.icons8.com/fluency/96/travel-card.png", width=80)
187
- st.markdown("### About")
 
 
 
 
 
 
 
 
 
 
 
 
188
  st.info(
189
  "This AI-powered tool creates a personalized travel itinerary based on your preferences. "
190
  "Fill in the form and let our specialized travel agents plan your perfect trip!"
191
  )
 
192
 
193
- st.markdown("### How it works")
194
- st.markdown(
195
- "1. Enter your travel details\n"
196
- "2. Our AI agents analyze your preferences\n"
197
- "3. Receive a comprehensive itinerary\n"
198
- "4. Download and enjoy your trip!"
199
- )
 
 
 
 
 
200
 
201
- st.markdown("### Travel Agents")
202
- st.markdown(
203
- "- ๐Ÿ” Destination Research Agent\n"
204
- "- ๐Ÿจ Accommodation Agent\n"
205
- "- ๐Ÿš— Transportation Agent\n"
206
- "- ๐ŸŽญ Activities & Attractions Agent\n"
207
- "- ๐Ÿฝ๏ธ Dining & Culinary Agent\n"
208
- "- ๐Ÿ“… Itinerary Integration Agent\n"
209
- "- ๐Ÿ“„ Final Report Generation Agent"
210
- )
211
-
212
- # Input Form
 
 
 
 
 
213
  if not st.session_state.generation_complete:
214
- st.markdown('<h2 class="sub-header">Enter Your Travel Details</h2>', unsafe_allow_html=True)
 
 
215
 
216
- col1, col2 = st.columns(2)
 
 
 
217
 
218
- with col1:
219
- origin = st.text_input("Origin City/Country", placeholder="e.g., New York, USA")
220
- destination = st.text_input("Destination City/Country", placeholder="e.g., Paris, France")
221
- duration = st.number_input("Trip Duration (days)", min_value=1, max_value=30, value=7)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
 
223
- with col2:
224
- budget_options = ["Budget", "Moderate", "Luxury"]
225
- budget = st.selectbox("Budget Level", budget_options)
226
- preferences = st.text_area("Travel Preferences & Interests",
227
- placeholder="e.g., museums, hiking, food, shopping, beaches, history, nightlife, family-friendly")
228
- special_requirements = st.text_area("Special Requirements",
229
- placeholder="e.g., dietary restrictions, accessibility needs, etc.")
230
 
231
- # Generate button
232
- if st.button("Generate My Travel Itinerary"):
233
  if not origin or not destination:
234
  st.error("Please enter both origin and destination.")
235
  else:
 
236
  user_input = {
237
  "origin": origin,
238
  "destination": destination,
239
  "duration": str(duration),
 
 
240
  "budget": budget.lower(),
 
241
  "preferences": preferences,
242
  "special_requirements": special_requirements
243
  }
244
 
245
- # Format the user input for tasks
246
  input_context = f"""Travel Request Details:
247
  Origin: {user_input['origin']}
248
  Destination: {user_input['destination']}
249
  Duration: {user_input['duration']} days
 
 
250
  Budget Level: {user_input['budget']}
 
251
  Preferences/Interests: {user_input['preferences']}
252
  Special Requirements: {user_input['special_requirements']}
253
  """
254
 
255
- # Create containers for progress, logs, and live output
256
- col1, col2 = st.columns([1, 2])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
 
258
- with col1:
259
- progress_placeholder = st.empty()
260
- progress_placeholder.markdown(display_progress(0), unsafe_allow_html=True)
 
 
 
 
 
261
  log_container = st.container()
262
  st.session_state.log_messages = []
263
 
264
- with col2:
265
- output_container = st.container()
266
- with output_container:
267
- st.markdown("### Live Agent Outputs")
268
- st.info("Agent outputs will appear here as they are generated")
 
 
 
269
 
270
- # Step 1: Destination Research
271
  st.session_state.current_step = 0
272
- progress_placeholder.markdown(display_progress(st.session_state.current_step), unsafe_allow_html=True)
 
 
 
 
 
 
273
 
274
  destination_info = run_task_with_logs(
275
  destination_research_task,
@@ -282,8 +685,12 @@ Special Requirements: {user_input['special_requirements']}
282
  "destination_info"
283
  )
284
 
 
 
285
  st.session_state.current_step = 1
286
- progress_placeholder.markdown(display_progress(st.session_state.current_step), unsafe_allow_html=True)
 
 
287
 
288
  # Step 2: Accommodation Recommendations
289
  accommodation_info = run_task_with_logs(
@@ -298,8 +705,12 @@ Special Requirements: {user_input['special_requirements']}
298
  "accommodation_info"
299
  )
300
 
 
 
301
  st.session_state.current_step = 2
302
- progress_placeholder.markdown(display_progress(st.session_state.current_step), unsafe_allow_html=True)
 
 
303
 
304
  # Step 3: Transportation Planning
305
  transportation_info = run_task_with_logs(
@@ -313,8 +724,12 @@ Special Requirements: {user_input['special_requirements']}
313
  "transportation_info"
314
  )
315
 
 
 
316
  st.session_state.current_step = 3
317
- progress_placeholder.markdown(display_progress(st.session_state.current_step), unsafe_allow_html=True)
 
 
318
 
319
  # Step 4: Activities & Attractions
320
  activities_info = run_task_with_logs(
@@ -328,8 +743,12 @@ Special Requirements: {user_input['special_requirements']}
328
  "activities_info"
329
  )
330
 
 
 
331
  st.session_state.current_step = 4
332
- progress_placeholder.markdown(display_progress(st.session_state.current_step), unsafe_allow_html=True)
 
 
333
 
334
  # Step 5: Dining Recommendations
335
  dining_info = run_task_with_logs(
@@ -343,8 +762,12 @@ Special Requirements: {user_input['special_requirements']}
343
  "dining_info"
344
  )
345
 
 
 
346
  st.session_state.current_step = 5
347
- progress_placeholder.markdown(display_progress(st.session_state.current_step), unsafe_allow_html=True)
 
 
348
 
349
  # Step 6: Create Day-by-Day Itinerary
350
  combined_info = f"""{input_context}
@@ -377,99 +800,211 @@ Dining Recommendations:
377
  "itinerary"
378
  )
379
 
 
 
380
  st.session_state.current_step = 6
381
- progress_placeholder.markdown(display_progress(st.session_state.current_step), unsafe_allow_html=True)
382
-
383
- # Step 7: Generate Final Report
384
- final_context = f"""{combined_info}
385
-
386
- Day-by-Day Itinerary:
387
- {itinerary}
388
- """
389
-
390
- final_itinerary = run_task_with_logs(
391
- final_report_task,
392
- final_context.format(
393
- duration=user_input['duration'],
394
- origin=user_input['origin'],
395
- destination=user_input['destination']
396
- ),
397
- log_container,
398
- output_container,
399
- "final_itinerary"
400
- )
401
-
402
  # Save the generated itinerary to session state
403
- st.session_state.generated_itinerary = final_itinerary
404
  st.session_state.generation_complete = True
405
 
406
  # Create a filename based on the destination and date
407
  date_str = datetime.now().strftime("%Y-%m-%d")
408
- st.session_state.filename = f"{user_input['destination'].replace(' ', '_')}_{date_str}_itinerary.html"
409
 
410
  # No need to rerun, we'll update the UI directly
411
 
412
  # Display results if generation is complete
413
  if st.session_state.generation_complete:
414
- st.markdown('<h2 class="sub-header">Your Travel Itinerary is Ready! ๐ŸŽ‰</h2>', unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
415
 
416
- # Display download link
417
- st.markdown(
418
- get_download_link(st.session_state.generated_itinerary, st.session_state.filename),
419
- unsafe_allow_html=True
420
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
421
 
422
- # Option to view the itinerary directly
423
- with st.expander("Preview Your Itinerary", expanded=True):
424
- st.components.v1.html(st.session_state.generated_itinerary, height=600, scrolling=True)
425
 
426
- # Option to view individual agent outputs
427
- with st.expander("View Detailed Agent Outputs"):
428
  agent_tabs = st.tabs([
429
- "Destination", "Accommodation", "Transportation",
430
- "Activities", "Dining", "Day-by-Day"
431
  ])
432
 
433
  with agent_tabs[0]:
434
- st.markdown("### Destination Research")
435
  st.markdown(st.session_state.results["destination_info"])
436
 
437
  with agent_tabs[1]:
438
- st.markdown("### Accommodation Options")
439
  st.markdown(st.session_state.results["accommodation_info"])
440
 
441
  with agent_tabs[2]:
442
- st.markdown("### Transportation Plan")
443
  st.markdown(st.session_state.results["transportation_info"])
444
 
445
  with agent_tabs[3]:
446
- st.markdown("### Recommended Activities")
447
  st.markdown(st.session_state.results["activities_info"])
448
 
449
  with agent_tabs[4]:
450
- st.markdown("### Dining Recommendations")
451
  st.markdown(st.session_state.results["dining_info"])
452
 
453
- with agent_tabs[5]:
454
- st.markdown("### Day-by-Day Itinerary")
455
- st.markdown(st.session_state.results["itinerary"])
456
 
457
- # Option to start over
458
- if st.button("Create Another Itinerary"):
459
- # Reset session state
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
460
  st.session_state.generated_itinerary = None
461
  st.session_state.generation_complete = False
462
  st.session_state.current_step = 0
463
- st.session_state.results = {
464
- "destination_info": "",
465
- "accommodation_info": "",
466
- "transportation_info": "",
467
- "activities_info": "",
468
- "dining_info": "",
469
- "itinerary": "",
470
- "final_itinerary": ""
471
- }
472
- st.rerun()
 
 
473
 
474
- # Footer
475
- st.markdown('<div class="footer">BlockX Travel Itinerary Generator ยฉ 2025</div>', unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  import json
4
  from datetime import datetime, timedelta
5
  import base64
6
+ import pandas as pd
7
  from travel import (
8
  destination_research_task, accommodation_task, transportation_task,
9
+ activities_task, dining_task, itinerary_task,
10
  run_task
11
  )
12
 
13
+ # Set page configuration with modern theme
14
  st.set_page_config(
15
  page_title="BlockX Travel Itinerary Generator",
16
  page_icon="โœˆ๏ธ",
 
18
  initial_sidebar_state="expanded"
19
  )
20
 
21
+ # Modern CSS with refined color scheme and sleek animations
22
  st.markdown("""
23
  <style>
24
+ /* Sleek Color Palette */
25
+ :root {
26
+ --primary: #3a86ff;
27
+ --primary-light: #4895ef;
28
+ --primary-dark: #2667ff;
29
+ --secondary: #4cc9f0;
30
+ --accent: #4361ee;
31
+ --background: #f8f9fa;
32
+ --card-bg: #ffffff;
33
+ --text: #212529;
34
+ --text-light: #6c757d;
35
+ --text-muted: #adb5bd;
36
+ --border: #e9ecef;
37
+ --success: #2ecc71;
38
+ --warning: #f39c12;
39
+ --info: #3498db;
40
+ }
41
+
42
+ /* Refined Animations */
43
+ @keyframes smoothFadeIn {
44
+ from { opacity: 0; transform: translateY(10px); }
45
+ to { opacity: 1; transform: translateY(0); }
46
+ }
47
+
48
+ @keyframes slideInRight {
49
+ from { opacity: 0; transform: translateX(20px); }
50
+ to { opacity: 1; transform: translateX(0); }
51
+ }
52
+
53
+ .animate-in {
54
+ animation: smoothFadeIn 0.5s cubic-bezier(0.215, 0.61, 0.355, 1);
55
+ }
56
+
57
+ .slide-in {
58
+ animation: slideInRight 0.5s cubic-bezier(0.215, 0.61, 0.355, 1);
59
+ }
60
+
61
+ /* Sleek Header Styles */
62
  .main-header {
63
  font-size: 2.5rem;
64
+ color: var(--primary-dark);
65
  text-align: center;
66
+ margin-bottom: 0.8rem;
67
+ font-weight: 700;
68
+ letter-spacing: -0.5px;
69
  }
70
+
71
  .sub-header {
72
+ font-size: 1.4rem;
73
+ color: var(--accent);
74
+ font-weight: 600;
75
+ margin-top: 1.8rem;
76
+ margin-bottom: 0.8rem;
77
+ border-bottom: 1px solid var(--border);
78
+ padding-bottom: 0.4rem;
79
  }
80
+
81
+ /* Sleek Card Styles */
82
+ .modern-card {
83
+ background-color: var(--card-bg);
84
+ border-radius: 10px;
85
+ padding: 1.2rem;
86
+ margin-bottom: 1.2rem;
87
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
88
+ transition: all 0.25s ease;
89
+ border: 1px solid var(--border);
90
  }
91
+
92
+ .modern-card:hover {
93
+ transform: translateY(-3px);
94
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08);
 
 
95
  }
96
+
97
+ /* Refined Form Styles */
98
+ .stTextInput > div > div > input,
99
+ .stDateInput > div > div > input,
100
+ .stTextArea > div > div > textarea {
101
+ border-radius: 6px;
102
+ border: 1px solid var(--border);
103
+ padding: 10px 12px;
104
+ font-size: 14px;
105
+ transition: all 0.2s ease;
106
+ box-shadow: none;
107
+ }
108
+
109
+ .stTextInput > div > div > input:focus,
110
+ .stDateInput > div > div > input:focus,
111
+ .stTextArea > div > div > textarea:focus {
112
+ border: 1px solid var(--primary);
113
+ box-shadow: 0 0 0 1px rgba(58, 134, 255, 0.15);
114
+ }
115
+
116
+ /* Sleek Button Styles */
117
+ .stButton > button {
118
+ background-color: var(--primary);
119
+ color: white;
120
+ font-weight: 500;
121
+ padding: 0.5rem 1.2rem;
122
+ border-radius: 6px;
123
+ border: none;
124
+ transition: all 0.2s ease;
125
+ font-size: 14px;
126
+ letter-spacing: 0.3px;
127
+ }
128
+
129
+ .stButton > button:hover {
130
+ background-color: var(--primary-dark);
131
+ transform: translateY(-1px);
132
+ box-shadow: 0 3px 8px rgba(58, 134, 255, 0.25);
133
+ }
134
+
135
+ /* Sleek Tab Styles */
136
+ .stTabs [data-baseweb="tab-list"] {
137
+ gap: 2px;
138
+ background-color: var(--background);
139
+ border-radius: 8px;
140
+ padding: 2px;
141
+ }
142
+
143
+ .stTabs [data-baseweb="tab"] {
144
+ border-radius: 6px;
145
+ padding: 8px 16px;
146
+ font-size: 14px;
147
+ font-weight: 500;
148
+ }
149
+
150
+ .stTabs [aria-selected="true"] {
151
+ background-color: var(--primary);
152
+ color: white !important;
153
+ }
154
+
155
+ /* Progress Bar Styles */
156
+ .stProgress > div > div > div > div {
157
+ background-color: var(--primary);
158
+ }
159
+
160
+ /* Progress Styles */
161
  .progress-container {
162
+ margin: 1.2rem 0;
163
+ background-color: var(--background);
164
+ border-radius: 8px;
165
+ padding: 0.8rem;
166
+ border: 1px solid var(--border);
167
  }
168
+
169
  .step-complete {
170
  color: #4CAF50;
171
+ font-weight: 600;
172
  }
173
+
174
  .step-pending {
175
  color: #9E9E9E;
176
  }
177
+
178
  .step-active {
179
+ color: var(--primary);
180
+ font-weight: 600;
 
 
 
 
 
 
 
181
  }
182
+
183
+ /* Agent Output */
184
  .agent-output {
185
+ background-color: #f8f9fa;
186
+ border-left: 5px solid var(--primary);
187
+ padding: 1.2rem;
188
  margin: 1rem 0;
189
+ border-radius: 10px;
190
  max-height: 400px;
191
  overflow-y: auto;
192
  }
193
+
194
+ /* Footer */
195
  .footer {
196
  text-align: center;
197
  margin-top: 3rem;
198
+ color: var(--text-light);
199
+ font-size: 0.9rem;
200
+ padding: 1rem;
201
+ border-top: 1px solid #eaeaea;
202
+ }
203
+
204
+ /* Agent Log */
205
+ .agent-log {
206
+ background-color: #F5F5F5;
207
+ border-left: 3px solid var(--primary);
208
+ padding: 0.5rem;
209
+ margin-bottom: 0.5rem;
210
+ font-family: monospace;
211
+ border-radius: 4px;
212
  }
213
+
214
+ /* Info and Success Boxes */
215
+ .info-box {
216
+ background-color: var(--primary-light);
217
  color: white;
218
+ padding: 1rem;
219
+ border-radius: 0.5rem;
220
+ margin-bottom: 1rem;
221
+ }
222
+
223
+ .success-box {
224
+ background-color: #E8F5E9;
225
+ padding: 1rem;
226
+ border-radius: 0.5rem;
227
+ margin-bottom: 1rem;
228
+ border-left: 5px solid #4CAF50;
229
  }
230
  </style>
231
  """, unsafe_allow_html=True)
232
 
233
  # Helper function to download HTML file
234
+ def get_download_link(text_content, filename):
235
+ b64 = base64.b64encode(text_content.encode()).decode()
236
+ href = f'<a class="download-link" href="data:text/plain;base64,{b64}" download="{filename}"><i>๐Ÿ“ฅ</i> Download Itinerary as Text</a>'
237
  return href
238
 
239
+ # Updated helper function to display modern progress with a single UI element
240
+ def display_modern_progress(current_step, total_steps=6):
241
+ if 'progress_steps' not in st.session_state:
242
+ st.session_state.progress_steps = {
243
+ 0: {'status': 'pending', 'name': 'Destination Research'},
244
+ 1: {'status': 'pending', 'name': 'Accommodation'},
245
+ 2: {'status': 'pending', 'name': 'Transportation'},
246
+ 3: {'status': 'pending', 'name': 'Activities'},
247
+ 4: {'status': 'pending', 'name': 'Dining'},
248
+ 5: {'status': 'pending', 'name': 'Itinerary Creation'}
249
+ }
 
250
 
251
+ # Update the current step status
252
+ for i in range(total_steps):
253
  if i < current_step:
254
+ st.session_state.progress_steps[i]['status'] = 'complete'
255
  elif i == current_step:
256
+ st.session_state.progress_steps[i]['status'] = 'active'
257
  else:
258
+ st.session_state.progress_steps[i]['status'] = 'pending'
259
 
260
+ # Calculate overall progress percentage
261
+ progress_percentage = (current_step / total_steps) * 100
262
+
263
+ # Show overall progress bar
264
+ st.progress(progress_percentage / 100)
265
+
266
+ # Create a modern, compact, inline progress tracker
267
+ st.markdown('''
268
+ <style>
269
+ .compact-progress {
270
+ background: white;
271
+ border-radius: 10px;
272
+ padding: 15px;
273
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
274
+ margin-bottom: 20px;
275
+ }
276
+ .progress-title {
277
+ font-size: 16px;
278
+ font-weight: bold;
279
+ margin-bottom: 15px;
280
+ color: #333;
281
+ border-bottom: 1px solid #eee;
282
+ padding-bottom: 10px;
283
+ }
284
+ .step-grid {
285
+ display: grid;
286
+ grid-template-columns: repeat(3, 1fr);
287
+ gap: 10px;
288
+ }
289
+ .step-item {
290
+ display: flex;
291
+ align-items: center;
292
+ padding: 8px 10px;
293
+ border-radius: 6px;
294
+ background: #f8f9fa;
295
+ box-shadow: 0 1px 3px rgba(0,0,0,0.05);
296
+ }
297
+ .step-item.complete {
298
+ border-left: 3px solid #4CAF50;
299
+ background: #f1f8e9;
300
+ }
301
+ .step-item.active {
302
+ border-left: 3px solid #2196F3;
303
+ background: #e3f2fd;
304
+ font-weight: bold;
305
+ }
306
+ .step-item.pending {
307
+ border-left: 3px solid #9e9e9e;
308
+ opacity: 0.7;
309
+ }
310
+ .step-icon {
311
+ margin-right: 8px;
312
+ font-size: 14px;
313
+ }
314
+ .step-text {
315
+ font-size: 13px;
316
+ white-space: nowrap;
317
+ overflow: hidden;
318
+ text-overflow: ellipsis;
319
+ }
320
+ </style>
321
+ <div class="compact-progress">
322
+ ''', unsafe_allow_html=True)
323
+
324
+ # Create grid layout
325
+ st.markdown('<div class="step-grid">', unsafe_allow_html=True)
326
+
327
+ # Display each step in a compact grid
328
+ for i, step_info in st.session_state.progress_steps.items():
329
+ status = step_info['status']
330
+ name = step_info['name']
331
+
332
+ if status == 'complete':
333
+ icon = "โœ…"
334
+ status_class = "complete"
335
+ elif status == 'active':
336
+ icon = "๐Ÿ”„"
337
+ status_class = "active"
338
+ else:
339
+ icon = "โญ•"
340
+ status_class = "pending"
341
+
342
+ st.markdown(f'''
343
+ <div class="step-item {status_class}">
344
+ <span class="step-icon">{icon}</span>
345
+ <span class="step-text">{name}</span>
346
+ </div>
347
+ ''', unsafe_allow_html=True)
348
+
349
+ st.markdown('</div></div>', unsafe_allow_html=True)
350
+
351
+ return progress_percentage
352
+
353
+ # Function to update the status of a specific step
354
+ def update_step_status(step_index, status):
355
+ if 'progress_steps' in st.session_state and step_index in st.session_state.progress_steps:
356
+ st.session_state.progress_steps[step_index]['status'] = status
357
 
358
  # Custom run_task function that updates the UI with logs and shows live agent outputs
359
  def run_task_with_logs(task, input_text, log_container, output_container, results_key=None):
 
412
  st.session_state.log_messages = []
413
  if 'current_output' not in st.session_state:
414
  st.session_state.current_output = None
415
+ if 'form_submitted' not in st.session_state:
416
+ st.session_state.form_submitted = False
417
+
418
+ # Modern animated header
419
+ st.markdown('''
420
+ <div class="animate-in" style="text-align: center;">
421
+ <div style="margin-bottom: 20px;">
422
+ <img src="https://img.icons8.com/fluency/96/travel-card.png" width="90"
423
+ style="filter: drop-shadow(0 4px 8px rgba(0,0,0,0.1));">
424
+ </div>
425
+ <h1 class="main-header">BlockX Travel Itinerary Generator</h1>
426
+ <p style="font-size: 1.2rem; color: #6c757d; margin-bottom: 25px;">
427
+ โœจ Create your personalized AI-powered travel itinerary in minutes! โœจ
428
+ </p>
429
+ </div>
430
+ ''', unsafe_allow_html=True)
431
 
432
+ # Add a nice separator
433
+ st.markdown('<hr style="height:3px;border:none;background-color:#f0f0f0;margin-bottom:25px;">', unsafe_allow_html=True)
 
434
 
435
+ # Enhanced sidebar with modern design
436
  with st.sidebar:
437
+ # Add a profile/brand area at the top
438
+ st.markdown('''
439
+ <div style="text-align: center; padding: 20px 0; margin-bottom: 20px;
440
+ border-bottom: 1px solid #eaeaea;">
441
+ <img src="https://img.icons8.com/fluency/96/travel-card.png" width="80"
442
+ style="margin-bottom: 15px;">
443
+ <h3 style="margin-bottom: 5px; color: #4361ee;">BlockX Travel</h3>
444
+ <p style="color: #6c757d; font-size: 0.9rem;">AI-Powered Travel Planning</p>
445
+ </div>
446
+ ''', unsafe_allow_html=True)
447
+
448
+ # About section with modern container
449
+ st.markdown('<div class="modern-card">', unsafe_allow_html=True)
450
+ st.markdown("### ๐ŸŒŸ About")
451
  st.info(
452
  "This AI-powered tool creates a personalized travel itinerary based on your preferences. "
453
  "Fill in the form and let our specialized travel agents plan your perfect trip!"
454
  )
455
+ st.markdown('</div>', unsafe_allow_html=True)
456
 
457
+ # How it works with steps and icons
458
+ st.markdown('<div class="modern-card">', unsafe_allow_html=True)
459
+ st.markdown("### ๐Ÿ” How it works")
460
+ st.markdown("""
461
+ <ol style="padding-left: 25px;">
462
+ <li><b>๐Ÿ–Š๏ธ Enter</b> your travel details</li>
463
+ <li><b>๐Ÿง  AI analysis</b> of your preferences</li>
464
+ <li><b>๐Ÿ“‹ Generate</b> comprehensive itinerary</li>
465
+ <li><b>๐Ÿ“ฅ Download</b> and enjoy your trip!</li>
466
+ </ol>
467
+ """, unsafe_allow_html=True)
468
+ st.markdown('</div>', unsafe_allow_html=True)
469
 
470
+ # Travel Agents section with icons
471
+ st.markdown('<div class="modern-card">', unsafe_allow_html=True)
472
+ st.markdown("### ๐Ÿค– Travel Agents")
473
+ agents = [
474
+ ("๐Ÿ”ญ Research Specialist", "Finds the best destinations based on your preferences"),
475
+ ("๐Ÿจ Accommodation Expert", "Suggests suitable hotels and stays"),
476
+ ("๐Ÿš† Transportation Planner", "Plans efficient travel routes"),
477
+ ("๐ŸŽฏ Activities Curator", "Recommends activities tailored to your interests"),
478
+ ("๐Ÿฝ๏ธ Dining Connoisseur", "Finds the best dining experiences"),
479
+ ("๐Ÿ“… Itinerary Creator", "Puts everything together in a daily plan")
480
+ ]
481
+
482
+ for name, desc in agents:
483
+ st.markdown(f"**{name}**")
484
+ st.markdown(f"<small>{desc}</small>", unsafe_allow_html=True)
485
+ st.markdown('</div>', unsafe_allow_html=True)
486
+ # Main content area
487
  if not st.session_state.generation_complete:
488
+ # Sleek form with minimal design
489
+ st.markdown('<div class="modern-card animate-in">', unsafe_allow_html=True)
490
+ st.markdown("<h3 style='font-weight: 600; color: var(--primary-dark); display: flex; align-items: center; gap: 10px;'><span style='font-size: 20px;'>โœˆ๏ธ</span> Create Your Itinerary</h3>", unsafe_allow_html=True)
491
 
492
+ # Minimalist description
493
+ st.markdown("""
494
+ <p style="color: var(--text-light); margin-bottom: 16px; font-size: 14px; font-weight: 400;">Complete the form below for a personalized travel plan.</p>
495
+ """, unsafe_allow_html=True)
496
 
497
+ # Form with improved layout and visual cues
498
+ with st.form("travel_form"):
499
+ col1, col2 = st.columns(2)
500
+
501
+ with col1:
502
+ st.markdown('<p style="font-weight: 500; color: var(--primary); font-size: 14px; margin-bottom: 12px;">Trip Details</p>', unsafe_allow_html=True)
503
+ origin = st.text_input("Origin", placeholder="e.g., New York, USA")
504
+ destination = st.text_input("Destination", placeholder="e.g., Paris, France")
505
+
506
+ # Minimalist date picker
507
+ st.markdown('<p style="margin-bottom: 5px; font-size: 14px;">Travel Dates</p>', unsafe_allow_html=True)
508
+ start_date = st.date_input("Start Date", min_value=datetime.now(), label_visibility="collapsed")
509
+ end_date = start_date + timedelta(days=7)
510
+ duration = st.slider("Duration (days)", min_value=1, max_value=30, value=7)
511
+ end_date = start_date + timedelta(days=duration-1)
512
+ st.markdown(f'<p style="font-size: 13px; color: var(--text-muted); margin-top: 5px;">{start_date.strftime("%b %d")} - {end_date.strftime("%b %d, %Y")}</p>', unsafe_allow_html=True)
513
+
514
+ with col2:
515
+ st.markdown('<p style="font-weight: 500; color: var(--primary); font-size: 14px; margin-bottom: 12px;">Preferences</p>', unsafe_allow_html=True)
516
+ travelers = st.number_input("Travelers", min_value=1, max_value=15, value=2)
517
+ budget_options = ["Budget", "Moderate", "Luxury"]
518
+ budget = st.selectbox("Budget", budget_options,
519
+ help="Budget: Economy options | Moderate: Mid-range | Luxury: High-end experiences")
520
+
521
+ # Travel style with visual selection
522
+ travel_style = st.multiselect("๐ŸŒˆ Travel Style",
523
+ options=["Culture", "Adventure", "Relaxation", "Food & Dining",
524
+ "Nature", "Shopping", "Nightlife", "Family-friendly"],
525
+ default=["Culture", "Food & Dining"])
526
+
527
+ # Additional information in an expander
528
+ with st.expander("๐ŸŒŸ Additional Preferences & Requirements", expanded=False):
529
+ preferences = st.text_area("Specific Interests", placeholder="e.g., I love history museums, local cuisine, hiking, contemporary art...")
530
+ special_requirements = st.text_area("Special Requirements",
531
+ placeholder="e.g., dietary restrictions, accessibility needs, traveling with children...")
532
+
533
+ # Submit button with enhanced styling
534
+ submit_button = st.form_submit_button("๐Ÿš€ Create My Personal Travel Itinerary")
535
 
536
+ st.markdown('</div>', unsafe_allow_html=True)
 
 
 
 
 
 
537
 
538
+ # Process form submission
539
+ if submit_button:
540
  if not origin or not destination:
541
  st.error("Please enter both origin and destination.")
542
  else:
543
+ st.session_state.form_submitted = True
544
  user_input = {
545
  "origin": origin,
546
  "destination": destination,
547
  "duration": str(duration),
548
+ "travel_dates": f"{start_date.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')}",
549
+ "travelers": str(travelers),
550
  "budget": budget.lower(),
551
+ "travel_style": ", ".join(travel_style),
552
  "preferences": preferences,
553
  "special_requirements": special_requirements
554
  }
555
 
556
+ # Format the user input for tasks with enhanced details
557
  input_context = f"""Travel Request Details:
558
  Origin: {user_input['origin']}
559
  Destination: {user_input['destination']}
560
  Duration: {user_input['duration']} days
561
+ Travel Dates: {user_input['travel_dates']}
562
+ Travelers: {user_input['travelers']}
563
  Budget Level: {user_input['budget']}
564
+ Travel Style: {user_input['travel_style']}
565
  Preferences/Interests: {user_input['preferences']}
566
  Special Requirements: {user_input['special_requirements']}
567
  """
568
 
569
+ # Display a minimal, sleek processing animation
570
+ st.markdown("""
571
+ <div class="sleek-processing-container">
572
+ <div class="pulse-container">
573
+ <div class="pulse-ring"></div>
574
+ <div class="pulse-core"></div>
575
+ </div>
576
+ </div>
577
+
578
+ <style>
579
+ .sleek-processing-container {
580
+ display: flex;
581
+ justify-content: center;
582
+ align-items: center;
583
+ padding: 20px 0;
584
+ }
585
+ .pulse-container {
586
+ position: relative;
587
+ width: 50px;
588
+ height: 50px;
589
+ }
590
+ .pulse-core {
591
+ position: absolute;
592
+ left: 50%;
593
+ top: 50%;
594
+ transform: translate(-50%, -50%);
595
+ width: 12px;
596
+ height: 12px;
597
+ background-color: #4361ee;
598
+ border-radius: 50%;
599
+ box-shadow: 0 0 8px rgba(67, 97, 238, 0.6);
600
+ }
601
+ .pulse-ring {
602
+ position: absolute;
603
+ left: 0;
604
+ top: 0;
605
+ width: 100%;
606
+ height: 100%;
607
+ border: 2px solid #4361ee;
608
+ border-radius: 50%;
609
+ animation: pulse 1.5s ease-out infinite;
610
+ opacity: 0;
611
+ }
612
+ @keyframes pulse {
613
+ 0% {
614
+ transform: scale(0.1);
615
+ opacity: 0;
616
+ }
617
+ 50% {
618
+ opacity: 0.5;
619
+ }
620
+ 100% {
621
+ transform: scale(1);
622
+ opacity: 0;
623
+ }
624
+ }
625
+ </style>
626
+ """, unsafe_allow_html=True)
627
+
628
+ # Create modern containers for progress, logs, and live output
629
+ st.markdown('<div class="modern-card">', unsafe_allow_html=True)
630
+
631
+ # Create tabs for better organization
632
+ progress_tab, logs_tab, details_tab = st.tabs(["๐Ÿ“Š Progress", "๐Ÿ”„ Live Activity", "๐Ÿ“‹ Request Details"])
633
+
634
+ # Show request details in the details tab
635
+ with details_tab:
636
+ st.markdown("#### Your Travel Request")
637
+ st.markdown(f"**Destination:** {user_input['destination']}")
638
+ st.markdown(f"**From:** {user_input['origin']}")
639
+ st.markdown(f"**When:** {user_input['travel_dates']} ({user_input['duration']} days)")
640
+ st.markdown(f"**Budget:** {user_input['budget'].title()}")
641
+ st.markdown(f"**Travel Style:** {user_input['travel_style']}")
642
+ if user_input['preferences']:
643
+ st.markdown(f"**Interests:** {user_input['preferences']}")
644
+ if user_input['special_requirements']:
645
+ st.markdown(f"**Special Requirements:** {user_input['special_requirements']}")
646
 
647
+ with progress_tab:
648
+ # Create a persistent placeholder for progress display to avoid duplication
649
+ if 'progress_placeholder' not in st.session_state:
650
+ st.session_state.progress_placeholder = st.empty()
651
+ with st.session_state.progress_placeholder.container():
652
+ display_modern_progress(0)
653
+
654
+ with logs_tab:
655
  log_container = st.container()
656
  st.session_state.log_messages = []
657
 
658
+ # Create a container for output that spans the full width
659
+ st.markdown('</div>', unsafe_allow_html=True) # Close the progress card
660
+ output_container = st.container()
661
+ with output_container:
662
+ st.markdown('<div class="modern-card">', unsafe_allow_html=True)
663
+ st.markdown("### ๐ŸŒŸ Live Agent Outputs")
664
+ st.info("Our AI agents will show their work here as they create your itinerary")
665
+ st.markdown('</div>', unsafe_allow_html=True)
666
 
667
+ # Initialize progress tracking
668
  st.session_state.current_step = 0
669
+
670
+ # Display initial progress - using the session state placeholder
671
+
672
+ # Step 1: Destination Research
673
+ update_step_status(0, 'active') # Mark step 1 as active
674
+ with st.session_state.progress_placeholder.container():
675
+ display_modern_progress(st.session_state.current_step)
676
 
677
  destination_info = run_task_with_logs(
678
  destination_research_task,
 
685
  "destination_info"
686
  )
687
 
688
+ # Update progress after step 1 completes
689
+ update_step_status(0, 'complete') # Mark step 1 as complete
690
  st.session_state.current_step = 1
691
+ update_step_status(1, 'active') # Mark step 2 as active
692
+ with st.session_state.progress_placeholder.container():
693
+ display_modern_progress(st.session_state.current_step)
694
 
695
  # Step 2: Accommodation Recommendations
696
  accommodation_info = run_task_with_logs(
 
705
  "accommodation_info"
706
  )
707
 
708
+ # Update progress after step 2 completes
709
+ update_step_status(1, 'complete') # Mark step 2 as complete
710
  st.session_state.current_step = 2
711
+ update_step_status(2, 'active') # Mark step 3 as active
712
+ with st.session_state.progress_placeholder.container():
713
+ display_modern_progress(st.session_state.current_step)
714
 
715
  # Step 3: Transportation Planning
716
  transportation_info = run_task_with_logs(
 
724
  "transportation_info"
725
  )
726
 
727
+ # Update progress after step 3 completes
728
+ update_step_status(2, 'complete') # Mark step 3 as complete
729
  st.session_state.current_step = 3
730
+ update_step_status(3, 'active') # Mark step 4 as active
731
+ with st.session_state.progress_placeholder.container():
732
+ display_modern_progress(st.session_state.current_step)
733
 
734
  # Step 4: Activities & Attractions
735
  activities_info = run_task_with_logs(
 
743
  "activities_info"
744
  )
745
 
746
+ # Update progress after step 4 completes
747
+ update_step_status(3, 'complete') # Mark step 4 as complete
748
  st.session_state.current_step = 4
749
+ update_step_status(4, 'active') # Mark step 5 as active
750
+ with st.session_state.progress_placeholder.container():
751
+ display_modern_progress(st.session_state.current_step)
752
 
753
  # Step 5: Dining Recommendations
754
  dining_info = run_task_with_logs(
 
762
  "dining_info"
763
  )
764
 
765
+ # Update progress after step 5 completes
766
+ update_step_status(4, 'complete') # Mark step 5 as complete
767
  st.session_state.current_step = 5
768
+ update_step_status(5, 'active') # Mark step 6 as active
769
+ with st.session_state.progress_placeholder.container():
770
+ display_modern_progress(st.session_state.current_step)
771
 
772
  # Step 6: Create Day-by-Day Itinerary
773
  combined_info = f"""{input_context}
 
800
  "itinerary"
801
  )
802
 
803
+ # Update final step status to complete
804
+ update_step_status(5, 'complete') # Mark final step as complete
805
  st.session_state.current_step = 6
806
+ with st.session_state.progress_placeholder.container():
807
+ display_modern_progress(st.session_state.current_step)
808
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
809
  # Save the generated itinerary to session state
810
+ st.session_state.generated_itinerary = itinerary
811
  st.session_state.generation_complete = True
812
 
813
  # Create a filename based on the destination and date
814
  date_str = datetime.now().strftime("%Y-%m-%d")
815
+ st.session_state.filename = f"{user_input['destination'].replace(' ', '_')}_{date_str}_itinerary.txt"
816
 
817
  # No need to rerun, we'll update the UI directly
818
 
819
  # Display results if generation is complete
820
  if st.session_state.generation_complete:
821
+ # Success animation and header
822
+ st.markdown("""
823
+ <div class="modern-card animate-in">
824
+ <div style="display: flex; justify-content: center; margin-bottom: 20px;">
825
+ <div class="success-animation">
826
+ <svg class="checkmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
827
+ <circle class="checkmark__circle" cx="26" cy="26" r="25" fill="none" />
828
+ <path class="checkmark__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8" />
829
+ </svg>
830
+ </div>
831
+ </div>
832
+ <h2 style="text-align: center; color: #4361ee;">Your Travel Itinerary is Ready! ๐ŸŽ‰</h2>
833
+ <p style="text-align: center; color: #6c757d; margin-bottom: 20px;">We've created a personalized travel experience just for you. Explore your itinerary below.</p>
834
+ </div>
835
 
836
+ <style>
837
+ .success-animation {
838
+ width: 100px;
839
+ height: 100px;
840
+ position: relative;
841
+ }
842
+ .checkmark {
843
+ width: 100px;
844
+ height: 100px;
845
+ border-radius: 50%;
846
+ display: block;
847
+ stroke-width: 2;
848
+ stroke: #4361ee;
849
+ stroke-miterlimit: 10;
850
+ box-shadow: 0 0 20px rgba(67, 97, 238, 0.3);
851
+ animation: fill .4s ease-in-out .4s forwards, scale .3s ease-in-out .9s both;
852
+ }
853
+ .checkmark__circle {
854
+ stroke-dasharray: 166;
855
+ stroke-dashoffset: 166;
856
+ stroke-width: 2;
857
+ stroke-miterlimit: 10;
858
+ stroke: #4361ee;
859
+ fill: none;
860
+ animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;
861
+ }
862
+ .checkmark__check {
863
+ transform-origin: 50% 50%;
864
+ stroke-dasharray: 48;
865
+ stroke-dashoffset: 48;
866
+ animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards;
867
+ }
868
+ @keyframes stroke {
869
+ 100% {
870
+ stroke-dashoffset: 0;
871
+ }
872
+ }
873
+ @keyframes scale {
874
+ 0%, 100% {
875
+ transform: none;
876
+ }
877
+ 50% {
878
+ transform: scale3d(1.1, 1.1, 1);
879
+ }
880
+ }
881
+ @keyframes fill {
882
+ 100% {
883
+ box-shadow: 0 0 20px rgba(67, 97, 238, 0.3);
884
+ }
885
+ }
886
+ </style>
887
+ """, unsafe_allow_html=True)
888
+
889
+ # Main container for itinerary content
890
+ st.markdown('<div class="modern-card">', unsafe_allow_html=True)
891
+
892
+ # Modern tabs for different views
893
+ itinerary_tab, details_tab, download_tab = st.tabs(["๐Ÿ—’๏ธ Full Itinerary", "๐Ÿ’ผDetails", "๐Ÿ’พ Download & Share"])
894
 
895
+ with itinerary_tab:
896
+ # Preview the itinerary as text
897
+ st.text_area("Your Itinerary", st.session_state.generated_itinerary, height=600)
898
 
899
+ with details_tab:
900
+ # More detailed view with agent outputs in a nested tab structure
901
  agent_tabs = st.tabs([
902
+ "๐ŸŒŽ Destination", "๐Ÿจ Accommodation", "๐Ÿš— Transportation",
903
+ "๐ŸŽญ Activities", "๐Ÿฝ๏ธ Dining"
904
  ])
905
 
906
  with agent_tabs[0]:
907
+ st.markdown("### ๐ŸŒŽ Destination Research")
908
  st.markdown(st.session_state.results["destination_info"])
909
 
910
  with agent_tabs[1]:
911
+ st.markdown("### ๐Ÿจ Accommodation Options")
912
  st.markdown(st.session_state.results["accommodation_info"])
913
 
914
  with agent_tabs[2]:
915
+ st.markdown("### ๐Ÿš— Transportation Plan")
916
  st.markdown(st.session_state.results["transportation_info"])
917
 
918
  with agent_tabs[3]:
919
+ st.markdown("### ๐ŸŽญ Recommended Activities")
920
  st.markdown(st.session_state.results["activities_info"])
921
 
922
  with agent_tabs[4]:
923
+ st.markdown("### ๐Ÿฝ๏ธ Dining Recommendations")
924
  st.markdown(st.session_state.results["dining_info"])
925
 
926
+
 
 
927
 
928
+ with download_tab:
929
+ col1, col2 = st.columns([2, 1])
930
+
931
+ with col1:
932
+ st.markdown("### Save Your Itinerary")
933
+ st.markdown("Download your personalized travel plan to access it offline or share with your travel companions.")
934
+
935
+ # Display stylized download button
936
+ st.markdown("""
937
+ <div style="background-color: #f8f9fa; padding: 15px; border-radius: 10px; margin-top: 20px;">
938
+ <h4 style="margin-top: 0;">Your Itinerary File</h4>
939
+ <p style="font-size: 0.9rem; color: #6c757d;">Text format - Can be opened in any text editor</p>
940
+ """, unsafe_allow_html=True)
941
+
942
+ # Enhanced download link
943
+ st.markdown(
944
+ f"""<div style="margin: 10px 0;">{ get_download_link(st.session_state.generated_itinerary, st.session_state.filename) }</div>""",
945
+ unsafe_allow_html=True
946
+ )
947
+
948
+ st.markdown("</div>", unsafe_allow_html=True)
949
+
950
+ # Share options
951
+ st.markdown("### Share Your Itinerary")
952
+ st.markdown("*Coming soon: Email your itinerary or share via social media.*")
953
+
954
+ with col2:
955
+ # QR code placeholder for future implementation
956
+ st.markdown("### Save for Mobile")
957
+ st.markdown("*Coming soon: QR code for easy access on your phone*")
958
+
959
+ st.markdown('</div>', unsafe_allow_html=True)
960
+
961
+ # Add a reset button to create a new itinerary
962
+ if st.button("๐Ÿ”„ Plan Another Trip", key="reset_button"):
963
+ # Reset the session state
964
  st.session_state.generated_itinerary = None
965
  st.session_state.generation_complete = False
966
  st.session_state.current_step = 0
967
+ st.session_state.form_submitted = False
968
+ st.session_state.results = {}
969
+ st.experimental_rerun()
970
+
971
+ # Footer for the app
972
+ st.markdown("""
973
+ <div style="margin-top: 50px; text-align: center; padding: 20px; color: #6c757d; font-size: 0.8rem;">
974
+ <p>ยฉ 2023 AI Travel Planner | Built with โค๏ธ using Streamlit and advanced AI</p>
975
+ </div>
976
+ """, unsafe_allow_html=True)
977
+
978
+ # End of app
979
 
980
+ # Modern footer with more information
981
+ st.markdown("""
982
+ <div style="margin-top: 50px; border-top: 1px solid #e9ecef; padding: 30px 0; color: #6c757d;">
983
+ <div style="display: flex; justify-content: space-between; flex-wrap: wrap; max-width: 1200px; margin: 0 auto; padding: 0 20px;">
984
+ <div style="flex: 1; min-width: 200px; margin-bottom: 20px;">
985
+ <h4 style="color: #4361ee; margin-bottom: 15px;">BlockX Travel</h4>
986
+ <p>AI-powered travel planning made easy. Create personalized itineraries for your dream destinations.</p>
987
+ </div>
988
+ <div style="flex: 1; min-width: 200px; margin-bottom: 20px;">
989
+ <h4 style="color: #4361ee; margin-bottom: 15px;">Quick Links</h4>
990
+ <ul style="list-style: none; padding: 0;">
991
+ <li style="margin-bottom: 8px;">About</li>
992
+ <li style="margin-bottom: 8px;">Travel Guides</li>
993
+ <li style="margin-bottom: 8px;">FAQs</li>
994
+ <li style="margin-bottom: 8px;">Contact Us</li>
995
+ </ul>
996
+ </div>
997
+ <div style="flex: 1; min-width: 200px; margin-bottom: 20px;">
998
+ <h4 style="color: #4361ee; margin-bottom: 15px;">Connect</h4>
999
+ <p>Stay updated with our latest travel guides and features.</p>
1000
+ <div style="margin-top: 15px;">
1001
+ <!-- Social media icons would go here -->
1002
+ <span>๐Ÿฐ ๐Ÿฟ ๐Ÿธ ๐Ÿฆ‰</span>
1003
+ </div>
1004
+ </div>
1005
+ </div>
1006
+ <div style="text-align: center; margin-top: 30px;">
1007
+ <p>ยฉ 2025 BlockX AI Travel | All rights reserved | Built with โค๏ธ from the team of BlockX AI Ltd https://blockxint.com.</p>
1008
+ </div>
1009
+ </div>
1010
+ """, unsafe_allow_html=True)