import streamlit as st
import os
import json
from datetime import datetime, timedelta
import base64
import pandas as pd
from travel import (
destination_research_task, accommodation_task, transportation_task,
activities_task, dining_task, itinerary_task,
run_task
)
# Set page configuration with modern theme
st.set_page_config(
page_title="BlockX Travel Itinerary Generator",
page_icon="βοΈ",
layout="wide",
initial_sidebar_state="expanded"
)
# Modern CSS with refined color scheme and sleek animations
st.markdown("""
""", unsafe_allow_html=True)
# Helper function to download HTML file
def get_download_link(text_content, filename):
b64 = base64.b64encode(text_content.encode()).decode()
href = f'π₯ Download Itinerary as Text'
return href
# Updated helper function to display modern progress with a single UI element
def display_modern_progress(current_step, total_steps=6):
if 'progress_steps' not in st.session_state:
st.session_state.progress_steps = {
0: {'status': 'pending', 'name': 'Destination Research'},
1: {'status': 'pending', 'name': 'Accommodation'},
2: {'status': 'pending', 'name': 'Transportation'},
3: {'status': 'pending', 'name': 'Activities'},
4: {'status': 'pending', 'name': 'Dining'},
5: {'status': 'pending', 'name': 'Itinerary Creation'}
}
# Update the current step status
for i in range(total_steps):
if i < current_step:
st.session_state.progress_steps[i]['status'] = 'complete'
elif i == current_step:
st.session_state.progress_steps[i]['status'] = 'active'
else:
st.session_state.progress_steps[i]['status'] = 'pending'
# Calculate overall progress percentage
progress_percentage = (current_step / total_steps) * 100
# Show overall progress bar
st.progress(progress_percentage / 100)
# Create a modern, compact, inline progress tracker
st.markdown('''
''', unsafe_allow_html=True)
# Create grid layout
st.markdown('
', unsafe_allow_html=True)
# Display each step in a compact grid
for i, step_info in st.session_state.progress_steps.items():
status = step_info['status']
name = step_info['name']
if status == 'complete':
icon = "β
"
status_class = "complete"
elif status == 'active':
icon = "π"
status_class = "active"
else:
icon = "β"
status_class = "pending"
st.markdown(f'''
{icon}
{name}
''', unsafe_allow_html=True)
st.markdown('
', unsafe_allow_html=True)
return progress_percentage
# Function to update the status of a specific step
def update_step_status(step_index, status):
if 'progress_steps' in st.session_state and step_index in st.session_state.progress_steps:
st.session_state.progress_steps[step_index]['status'] = status
# Custom run_task function that updates the UI with logs and shows live agent outputs
def run_task_with_logs(task, input_text, log_container, output_container, results_key=None):
# Add log message
log_message = f"π€ Starting {task.agent.role}..."
st.session_state.log_messages.append(log_message)
# Update the log container
with log_container:
st.markdown("### Agent Activity")
for msg in st.session_state.log_messages:
st.markdown(msg)
# Run the actual task
result = run_task(task, input_text)
# Store result if needed
if results_key:
st.session_state.results[results_key] = result
# Add completion log message
log_message = f"β
{task.agent.role} completed!"
st.session_state.log_messages.append(log_message)
# Update the log container again
with log_container:
st.markdown("### Agent Activity")
for msg in st.session_state.log_messages:
st.markdown(msg)
# Display the agent's output in the output container
with output_container:
st.markdown(f"### {task.agent.role} Output")
st.markdown("""""" + result + """
""", unsafe_allow_html=True)
return result
# Initialize session state
if 'generated_itinerary' not in st.session_state:
st.session_state.generated_itinerary = None
if 'generation_complete' not in st.session_state:
st.session_state.generation_complete = False
if 'current_step' not in st.session_state:
st.session_state.current_step = 0
if 'results' not in st.session_state:
st.session_state.results = {
"destination_info": "",
"accommodation_info": "",
"transportation_info": "",
"activities_info": "",
"dining_info": "",
"itinerary": "",
"final_itinerary": ""
}
if 'log_messages' not in st.session_state:
st.session_state.log_messages = []
if 'current_output' not in st.session_state:
st.session_state.current_output = None
if 'form_submitted' not in st.session_state:
st.session_state.form_submitted = False
# Modern animated header
st.markdown('''
BlockX Travel Itinerary Generator
β¨ Create your personalized AI-powered travel itinerary in minutes! β¨
''', unsafe_allow_html=True)
# Add a nice separator
st.markdown('
', unsafe_allow_html=True)
# Enhanced sidebar with modern design
with st.sidebar:
# Add a profile/brand area at the top
st.markdown('''
BlockX Travel
AI-Powered Travel Planning
''', unsafe_allow_html=True)
# About section with modern container
st.markdown('', unsafe_allow_html=True)
st.markdown("### π About")
st.info(
"This AI-powered tool creates a personalized travel itinerary based on your preferences. "
"Fill in the form and let our specialized travel agents plan your perfect trip!"
)
st.markdown('
', unsafe_allow_html=True)
# How it works with steps and icons
st.markdown('', unsafe_allow_html=True)
st.markdown("### π How it works")
st.markdown("""
- ποΈ Enter your travel details
- π§ AI analysis of your preferences
- π Generate comprehensive itinerary
- π₯ Download and enjoy your trip!
""", unsafe_allow_html=True)
st.markdown('
', unsafe_allow_html=True)
# Travel Agents section with icons
st.markdown('', unsafe_allow_html=True)
st.markdown("### π€ Travel Agents")
agents = [
("π Research Specialist", "Finds the best destinations based on your preferences"),
("π¨ Accommodation Expert", "Suggests suitable hotels and stays"),
("π Transportation Planner", "Plans efficient travel routes"),
("π― Activities Curator", "Recommends activities tailored to your interests"),
("π½οΈ Dining Connoisseur", "Finds the best dining experiences"),
("π
Itinerary Creator", "Puts everything together in a daily plan")
]
for name, desc in agents:
st.markdown(f"**{name}**")
st.markdown(f"{desc}", unsafe_allow_html=True)
st.markdown('
', unsafe_allow_html=True)
# Main content area
if not st.session_state.generation_complete:
# Sleek form with minimal design
st.markdown('', unsafe_allow_html=True)
st.markdown("
βοΈ Create Your Itinerary
", unsafe_allow_html=True)
# Minimalist description
st.markdown("""
Complete the form below for a personalized travel plan.
""", unsafe_allow_html=True)
# Form with improved layout and visual cues
with st.form("travel_form"):
col1, col2 = st.columns(2)
with col1:
st.markdown('
Trip Details
', unsafe_allow_html=True)
origin = st.text_input("Origin", placeholder="e.g., New York, USA")
destination = st.text_input("Destination", placeholder="e.g., Paris, France")
# Minimalist date picker
st.markdown('
Travel Dates
', unsafe_allow_html=True)
start_date = st.date_input("Start Date", min_value=datetime.now(), label_visibility="collapsed")
end_date = start_date + timedelta(days=7)
duration = st.slider("Duration (days)", min_value=1, max_value=30, value=7)
end_date = start_date + timedelta(days=duration-1)
st.markdown(f'
{start_date.strftime("%b %d")} - {end_date.strftime("%b %d, %Y")}
', unsafe_allow_html=True)
with col2:
st.markdown('
Preferences
', unsafe_allow_html=True)
travelers = st.number_input("Travelers", min_value=1, max_value=15, value=2)
budget_options = ["Budget", "Moderate", "Luxury"]
budget = st.selectbox("Budget", budget_options,
help="Budget: Economy options | Moderate: Mid-range | Luxury: High-end experiences")
# Travel style with visual selection
travel_style = st.multiselect("π Travel Style",
options=["Culture", "Adventure", "Relaxation", "Food & Dining",
"Nature", "Shopping", "Nightlife", "Family-friendly"],
default=["Culture", "Food & Dining"])
# Additional information in an expander
with st.expander("π Additional Preferences & Requirements", expanded=False):
preferences = st.text_area("Specific Interests", placeholder="e.g., I love history museums, local cuisine, hiking, contemporary art...")
special_requirements = st.text_area("Special Requirements",
placeholder="e.g., dietary restrictions, accessibility needs, traveling with children...")
# Submit button with enhanced styling
submit_button = st.form_submit_button("π Create My Personal Travel Itinerary")
st.markdown('
', unsafe_allow_html=True)
# Process form submission
if submit_button:
if not origin or not destination:
st.error("Please enter both origin and destination.")
else:
st.session_state.form_submitted = True
user_input = {
"origin": origin,
"destination": destination,
"duration": str(duration),
"travel_dates": f"{start_date.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')}",
"travelers": str(travelers),
"budget": budget.lower(),
"travel_style": ", ".join(travel_style),
"preferences": preferences,
"special_requirements": special_requirements
}
# Format the user input for tasks with enhanced details
input_context = f"""Travel Request Details:
Origin: {user_input['origin']}
Destination: {user_input['destination']}
Duration: {user_input['duration']} days
Travel Dates: {user_input['travel_dates']}
Travelers: {user_input['travelers']}
Budget Level: {user_input['budget']}
Travel Style: {user_input['travel_style']}
Preferences/Interests: {user_input['preferences']}
Special Requirements: {user_input['special_requirements']}
"""
# Display a minimal, sleek processing animation
st.markdown("""
""", unsafe_allow_html=True)
# Create modern containers for progress, logs, and live output
st.markdown('', unsafe_allow_html=True)
# Create tabs for better organization
progress_tab, logs_tab, details_tab = st.tabs(["π Progress", "π Live Activity", "π Request Details"])
# Show request details in the details tab
with details_tab:
st.markdown("#### Your Travel Request")
st.markdown(f"**Destination:** {user_input['destination']}")
st.markdown(f"**From:** {user_input['origin']}")
st.markdown(f"**When:** {user_input['travel_dates']} ({user_input['duration']} days)")
st.markdown(f"**Budget:** {user_input['budget'].title()}")
st.markdown(f"**Travel Style:** {user_input['travel_style']}")
if user_input['preferences']:
st.markdown(f"**Interests:** {user_input['preferences']}")
if user_input['special_requirements']:
st.markdown(f"**Special Requirements:** {user_input['special_requirements']}")
with progress_tab:
# Create a persistent placeholder for progress display to avoid duplication
if 'progress_placeholder' not in st.session_state:
st.session_state.progress_placeholder = st.empty()
with st.session_state.progress_placeholder.container():
display_modern_progress(0)
with logs_tab:
log_container = st.container()
st.session_state.log_messages = []
# Create a container for output that spans the full width
st.markdown('
', unsafe_allow_html=True) # Close the progress card
output_container = st.container()
with output_container:
st.markdown('', unsafe_allow_html=True)
st.markdown("### π Live Agent Outputs")
st.info("Our AI agents will show their work here as they create your itinerary")
st.markdown('
', unsafe_allow_html=True)
# Initialize progress tracking
st.session_state.current_step = 0
# Display initial progress - using the session state placeholder
# Step 1: Destination Research
update_step_status(0, 'active') # Mark step 1 as active
with st.session_state.progress_placeholder.container():
display_modern_progress(st.session_state.current_step)
destination_info = run_task_with_logs(
destination_research_task,
input_context.format(
destination=user_input['destination'],
preferences=user_input['preferences']
),
log_container,
output_container,
"destination_info"
)
# Update progress after step 1 completes
update_step_status(0, 'complete') # Mark step 1 as complete
st.session_state.current_step = 1
update_step_status(1, 'active') # Mark step 2 as active
with st.session_state.progress_placeholder.container():
display_modern_progress(st.session_state.current_step)
# Step 2: Accommodation Recommendations
accommodation_info = run_task_with_logs(
accommodation_task,
input_context.format(
destination=user_input['destination'],
budget=user_input['budget'],
preferences=user_input['preferences']
),
log_container,
output_container,
"accommodation_info"
)
# Update progress after step 2 completes
update_step_status(1, 'complete') # Mark step 2 as complete
st.session_state.current_step = 2
update_step_status(2, 'active') # Mark step 3 as active
with st.session_state.progress_placeholder.container():
display_modern_progress(st.session_state.current_step)
# Step 3: Transportation Planning
transportation_info = run_task_with_logs(
transportation_task,
input_context.format(
origin=user_input['origin'],
destination=user_input['destination']
),
log_container,
output_container,
"transportation_info"
)
# Update progress after step 3 completes
update_step_status(2, 'complete') # Mark step 3 as complete
st.session_state.current_step = 3
update_step_status(3, 'active') # Mark step 4 as active
with st.session_state.progress_placeholder.container():
display_modern_progress(st.session_state.current_step)
# Step 4: Activities & Attractions
activities_info = run_task_with_logs(
activities_task,
input_context.format(
destination=user_input['destination'],
preferences=user_input['preferences']
),
log_container,
output_container,
"activities_info"
)
# Update progress after step 4 completes
update_step_status(3, 'complete') # Mark step 4 as complete
st.session_state.current_step = 4
update_step_status(4, 'active') # Mark step 5 as active
with st.session_state.progress_placeholder.container():
display_modern_progress(st.session_state.current_step)
# Step 5: Dining Recommendations
dining_info = run_task_with_logs(
dining_task,
input_context.format(
destination=user_input['destination'],
preferences=user_input['preferences']
),
log_container,
output_container,
"dining_info"
)
# Update progress after step 5 completes
update_step_status(4, 'complete') # Mark step 5 as complete
st.session_state.current_step = 5
update_step_status(5, 'active') # Mark step 6 as active
with st.session_state.progress_placeholder.container():
display_modern_progress(st.session_state.current_step)
# Step 6: Create Day-by-Day Itinerary
combined_info = f"""{input_context}
Destination Information:
{destination_info}
Accommodation Options:
{accommodation_info}
Transportation Plan:
{transportation_info}
Recommended Activities:
{activities_info}
Dining Recommendations:
{dining_info}
"""
itinerary = run_task_with_logs(
itinerary_task,
combined_info.format(
duration=user_input['duration'],
origin=user_input['origin'],
destination=user_input['destination']
),
log_container,
output_container,
"itinerary"
)
# Update final step status to complete
update_step_status(5, 'complete') # Mark final step as complete
st.session_state.current_step = 6
with st.session_state.progress_placeholder.container():
display_modern_progress(st.session_state.current_step)
# Save the generated itinerary to session state
st.session_state.generated_itinerary = itinerary
st.session_state.generation_complete = True
# Create a filename based on the destination and date
date_str = datetime.now().strftime("%Y-%m-%d")
st.session_state.filename = f"{user_input['destination'].replace(' ', '_')}_{date_str}_itinerary.txt"
# No need to rerun, we'll update the UI directly
# Display results if generation is complete
if st.session_state.generation_complete:
# Success animation and header
st.markdown("""
Your Travel Itinerary is Ready! π
We've created a personalized travel experience just for you. Explore your itinerary below.
""", unsafe_allow_html=True)
# Main container for itinerary content
st.markdown('', unsafe_allow_html=True)
# Modern tabs for different views
itinerary_tab, details_tab, download_tab = st.tabs(["ποΈ Full Itinerary", "πΌDetails", "πΎ Download & Share"])
with itinerary_tab:
# Preview the itinerary as text
st.text_area("Your Itinerary", st.session_state.generated_itinerary, height=600)
with details_tab:
# More detailed view with agent outputs in a nested tab structure
agent_tabs = st.tabs([
"π Destination", "π¨ Accommodation", "π Transportation",
"π Activities", "π½οΈ Dining"
])
with agent_tabs[0]:
st.markdown("### π Destination Research")
st.markdown(st.session_state.results["destination_info"])
with agent_tabs[1]:
st.markdown("### π¨ Accommodation Options")
st.markdown(st.session_state.results["accommodation_info"])
with agent_tabs[2]:
st.markdown("### π Transportation Plan")
st.markdown(st.session_state.results["transportation_info"])
with agent_tabs[3]:
st.markdown("### π Recommended Activities")
st.markdown(st.session_state.results["activities_info"])
with agent_tabs[4]:
st.markdown("### π½οΈ Dining Recommendations")
st.markdown(st.session_state.results["dining_info"])
with download_tab:
col1, col2 = st.columns([2, 1])
with col1:
st.markdown("### Save Your Itinerary")
st.markdown("Download your personalized travel plan to access it offline or share with your travel companions.")
# Display stylized download button
st.markdown("""
Your Itinerary File
Text format - Can be opened in any text editor
""", unsafe_allow_html=True)
# Enhanced download link
st.markdown(
f"""
{ get_download_link(st.session_state.generated_itinerary, st.session_state.filename) }
""",
unsafe_allow_html=True
)
st.markdown("
", unsafe_allow_html=True)
# Share options
st.markdown("### Share Your Itinerary")
st.markdown("*Coming soon: Email your itinerary or share via social media.*")
with col2:
# QR code placeholder for future implementation
st.markdown("### Save for Mobile")
st.markdown("*Coming soon: QR code for easy access on your phone*")
st.markdown('
', unsafe_allow_html=True)
# Add a reset button to create a new itinerary
if st.button("π Plan Another Trip", key="reset_button"):
# Reset the session state
st.session_state.generated_itinerary = None
st.session_state.generation_complete = False
st.session_state.current_step = 0
st.session_state.form_submitted = False
st.session_state.results = {}
st.experimental_rerun()
# Footer for the app
st.markdown("""
Β© 2023 AI Travel Planner | Built with β€οΈ using Streamlit and advanced AI
""", unsafe_allow_html=True)
# End of app
# Modern footer with more information
st.markdown("""
BlockX Travel
AI-powered travel planning made easy. Create personalized itineraries for your dream destinations.
Quick Links
- About
- Travel Guides
- FAQs
- Contact Us
Connect
Stay updated with our latest travel guides and features.
π° πΏ πΈ π¦
Β© 2025 BlockX AI Travel | All rights reserved | Built with β€οΈ from the team of BlockX AI Ltd https://blockxint.com.
""", unsafe_allow_html=True)