Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -4,13 +4,20 @@ import json
|
|
| 4 |
from datetime import datetime, timedelta
|
| 5 |
import base64
|
| 6 |
import pandas as pd
|
| 7 |
-
|
| 8 |
from travel import (
|
| 9 |
destination_research_task, accommodation_task, transportation_task,
|
| 10 |
activities_task, dining_task, itinerary_task,
|
| 11 |
run_task
|
| 12 |
)
|
| 13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
# ------------------------------------------
|
| 15 |
# λ€κ΅μ΄ μ§μμ μν λ²μ μ¬μ λ° ν¬νΌ ν¨μ
|
| 16 |
# ------------------------------------------
|
|
@@ -273,7 +280,6 @@ translations = {
|
|
| 273 |
}
|
| 274 |
}
|
| 275 |
|
| 276 |
-
# λ²μ ν¬νΌ ν¨μ: μ νλ μΈμ΄μ λ°λΌ ν€ κ°μ λ°νν©λλ€.
|
| 277 |
def t(key):
|
| 278 |
lang = st.session_state.get("selected_language", "en")
|
| 279 |
return translations[lang].get(key, key)
|
|
@@ -305,17 +311,9 @@ with st.sidebar:
|
|
| 305 |
st.session_state.selected_language = lang_map.get(language, "en")
|
| 306 |
|
| 307 |
# ------------------------------------------
|
| 308 |
-
#
|
| 309 |
# ------------------------------------------
|
| 310 |
|
| 311 |
-
|
| 312 |
-
st.set_page_config(
|
| 313 |
-
page_title="Globetrotter AI: Your AI Agent for Travelling",
|
| 314 |
-
page_icon="βοΈ",
|
| 315 |
-
layout="wide",
|
| 316 |
-
initial_sidebar_state="expanded"
|
| 317 |
-
)
|
| 318 |
-
|
| 319 |
# Modern CSS with refined color scheme and sleek animations
|
| 320 |
st.markdown("""
|
| 321 |
<style>
|
|
@@ -539,10 +537,10 @@ def display_modern_progress(current_step, total_steps=6):
|
|
| 539 |
if 'progress_steps' not in st.session_state:
|
| 540 |
st.session_state.progress_steps = {
|
| 541 |
0: {'status': 'pending', 'name': t("trip_details")},
|
| 542 |
-
1: {'status': 'pending', 'name': t("about")}, #
|
| 543 |
-
2: {'status': 'pending', 'name': t("travel_style")}, #
|
| 544 |
-
3: {'status': 'pending', 'name': t("live_agent_outputs")}, #
|
| 545 |
-
4: {'status': 'pending', 'name': t("download_share")}, #
|
| 546 |
5: {'status': 'pending', 'name': t("full_itinerary")}
|
| 547 |
}
|
| 548 |
|
|
@@ -689,7 +687,9 @@ def run_task_with_logs(task, input_text, log_container, output_container, result
|
|
| 689 |
|
| 690 |
return result
|
| 691 |
|
| 692 |
-
#
|
|
|
|
|
|
|
| 693 |
if 'generated_itinerary' not in st.session_state:
|
| 694 |
st.session_state.generated_itinerary = None
|
| 695 |
if 'generation_complete' not in st.session_state:
|
|
@@ -781,6 +781,7 @@ with st.sidebar:
|
|
| 781 |
st.markdown(f"**{name}**")
|
| 782 |
st.markdown(f"<small>{desc}</small>", unsafe_allow_html=True)
|
| 783 |
st.markdown('</div>', unsafe_allow_html=True)
|
|
|
|
| 784 |
# Main content area
|
| 785 |
if not st.session_state.generation_complete:
|
| 786 |
# Sleek form with minimal design
|
|
@@ -821,13 +822,13 @@ if not st.session_state.generation_complete:
|
|
| 821 |
"Nature", "Shopping", "Nightlife", "Family-friendly"],
|
| 822 |
default=["Culture", "Food & Dining"])
|
| 823 |
|
| 824 |
-
# Simplified expander
|
| 825 |
with st.expander("Additional Preferences", expanded=False):
|
| 826 |
preferences = st.text_area("Interests", placeholder="History museums, local cuisine, hiking, art...")
|
| 827 |
special_requirements = st.text_area("Special Requirements",
|
| 828 |
placeholder="Dietary restrictions, accessibility needs...")
|
| 829 |
|
| 830 |
-
# Submit button
|
| 831 |
submit_button = st.form_submit_button(t("submit"))
|
| 832 |
|
| 833 |
st.markdown('</div>', unsafe_allow_html=True)
|
|
@@ -850,7 +851,7 @@ if not st.session_state.generation_complete:
|
|
| 850 |
"special_requirements": special_requirements
|
| 851 |
}
|
| 852 |
|
| 853 |
-
# Format the user input for tasks
|
| 854 |
input_context = f"""Travel Request Details:
|
| 855 |
Origin: {user_input['origin']}
|
| 856 |
Destination: {user_input['destination']}
|
|
@@ -863,7 +864,7 @@ Preferences/Interests: {user_input['preferences']}
|
|
| 863 |
Special Requirements: {user_input['special_requirements']}
|
| 864 |
"""
|
| 865 |
|
| 866 |
-
# Display
|
| 867 |
st.markdown("""
|
| 868 |
<div class="sleek-processing-container">
|
| 869 |
<div class="pulse-container">
|
|
@@ -922,13 +923,10 @@ Special Requirements: {user_input['special_requirements']}
|
|
| 922 |
</style>
|
| 923 |
""", unsafe_allow_html=True)
|
| 924 |
|
| 925 |
-
# Create
|
| 926 |
st.markdown('<div class="modern-card">', unsafe_allow_html=True)
|
| 927 |
-
|
| 928 |
-
# Create tabs for better organization
|
| 929 |
progress_tab, logs_tab, details_tab = st.tabs(["π Progress", "π Live Activity", "π Request Details"])
|
| 930 |
|
| 931 |
-
# Show request details in the details tab
|
| 932 |
with details_tab:
|
| 933 |
st.markdown("#### " + t("request_details"))
|
| 934 |
st.markdown(f"**{t('destination')}:** {user_input['destination']}")
|
|
@@ -942,7 +940,6 @@ Special Requirements: {user_input['special_requirements']}
|
|
| 942 |
st.markdown(f"**Special Requirements:** {user_input['special_requirements']}")
|
| 943 |
|
| 944 |
with progress_tab:
|
| 945 |
-
# Create a persistent placeholder for progress display to avoid duplication
|
| 946 |
if 'progress_placeholder' not in st.session_state:
|
| 947 |
st.session_state.progress_placeholder = st.empty()
|
| 948 |
with st.session_state.progress_placeholder.container():
|
|
@@ -952,8 +949,7 @@ Special Requirements: {user_input['special_requirements']}
|
|
| 952 |
log_container = st.container()
|
| 953 |
st.session_state.log_messages = []
|
| 954 |
|
| 955 |
-
|
| 956 |
-
st.markdown('</div>', unsafe_allow_html=True) # Close the progress card
|
| 957 |
output_container = st.container()
|
| 958 |
with output_container:
|
| 959 |
st.markdown('<div class="modern-card">', unsafe_allow_html=True)
|
|
@@ -961,13 +957,10 @@ Special Requirements: {user_input['special_requirements']}
|
|
| 961 |
st.info("Our AI agents will show their work here as they create your itinerary")
|
| 962 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 963 |
|
| 964 |
-
# Initialize progress tracking
|
| 965 |
st.session_state.current_step = 0
|
| 966 |
|
| 967 |
-
# Display initial progress - using the session state placeholder
|
| 968 |
-
|
| 969 |
# Step 1: Destination Research
|
| 970 |
-
update_step_status(0, 'active')
|
| 971 |
with st.session_state.progress_placeholder.container():
|
| 972 |
display_modern_progress(st.session_state.current_step)
|
| 973 |
|
|
@@ -982,10 +975,9 @@ Special Requirements: {user_input['special_requirements']}
|
|
| 982 |
"destination_info"
|
| 983 |
)
|
| 984 |
|
| 985 |
-
|
| 986 |
-
update_step_status(0, 'complete') # Mark step 1 as complete
|
| 987 |
st.session_state.current_step = 1
|
| 988 |
-
update_step_status(1, 'active')
|
| 989 |
with st.session_state.progress_placeholder.container():
|
| 990 |
display_modern_progress(st.session_state.current_step)
|
| 991 |
|
|
@@ -1002,10 +994,9 @@ Special Requirements: {user_input['special_requirements']}
|
|
| 1002 |
"accommodation_info"
|
| 1003 |
)
|
| 1004 |
|
| 1005 |
-
|
| 1006 |
-
update_step_status(1, 'complete') # Mark step 2 as complete
|
| 1007 |
st.session_state.current_step = 2
|
| 1008 |
-
update_step_status(2, 'active')
|
| 1009 |
with st.session_state.progress_placeholder.container():
|
| 1010 |
display_modern_progress(st.session_state.current_step)
|
| 1011 |
|
|
@@ -1021,10 +1012,9 @@ Special Requirements: {user_input['special_requirements']}
|
|
| 1021 |
"transportation_info"
|
| 1022 |
)
|
| 1023 |
|
| 1024 |
-
|
| 1025 |
-
update_step_status(2, 'complete') # Mark step 3 as complete
|
| 1026 |
st.session_state.current_step = 3
|
| 1027 |
-
update_step_status(3, 'active')
|
| 1028 |
with st.session_state.progress_placeholder.container():
|
| 1029 |
display_modern_progress(st.session_state.current_step)
|
| 1030 |
|
|
@@ -1040,10 +1030,9 @@ Special Requirements: {user_input['special_requirements']}
|
|
| 1040 |
"activities_info"
|
| 1041 |
)
|
| 1042 |
|
| 1043 |
-
|
| 1044 |
-
update_step_status(3, 'complete') # Mark step 4 as complete
|
| 1045 |
st.session_state.current_step = 4
|
| 1046 |
-
update_step_status(4, 'active')
|
| 1047 |
with st.session_state.progress_placeholder.container():
|
| 1048 |
display_modern_progress(st.session_state.current_step)
|
| 1049 |
|
|
@@ -1059,10 +1048,9 @@ Special Requirements: {user_input['special_requirements']}
|
|
| 1059 |
"dining_info"
|
| 1060 |
)
|
| 1061 |
|
| 1062 |
-
|
| 1063 |
-
update_step_status(4, 'complete') # Mark step 5 as complete
|
| 1064 |
st.session_state.current_step = 5
|
| 1065 |
-
update_step_status(5, 'active')
|
| 1066 |
with st.session_state.progress_placeholder.container():
|
| 1067 |
display_modern_progress(st.session_state.current_step)
|
| 1068 |
|
|
@@ -1097,25 +1085,19 @@ Dining Recommendations:
|
|
| 1097 |
"itinerary"
|
| 1098 |
)
|
| 1099 |
|
| 1100 |
-
|
| 1101 |
-
update_step_status(5, 'complete') # Mark final step as complete
|
| 1102 |
st.session_state.current_step = 6
|
| 1103 |
with st.session_state.progress_placeholder.container():
|
| 1104 |
display_modern_progress(st.session_state.current_step)
|
| 1105 |
|
| 1106 |
-
# Save the generated itinerary to session state
|
| 1107 |
st.session_state.generated_itinerary = itinerary
|
| 1108 |
st.session_state.generation_complete = True
|
| 1109 |
|
| 1110 |
-
# Create a filename based on the destination and date
|
| 1111 |
date_str = datetime.now().strftime("%Y-%m-%d")
|
| 1112 |
st.session_state.filename = f"{user_input['destination'].replace(' ', '_')}_{date_str}_itinerary.txt"
|
| 1113 |
-
|
| 1114 |
-
# No need to rerun, we'll update the UI directly
|
| 1115 |
|
| 1116 |
# Display results if generation is complete
|
| 1117 |
if st.session_state.generation_complete:
|
| 1118 |
-
# Success animation and header
|
| 1119 |
st.markdown("""
|
| 1120 |
<div class="modern-card animate-in">
|
| 1121 |
<div style="display: flex; justify-content: center; margin-bottom: 20px;">
|
|
@@ -1183,18 +1165,13 @@ if st.session_state.generation_complete:
|
|
| 1183 |
</style>
|
| 1184 |
""", unsafe_allow_html=True)
|
| 1185 |
|
| 1186 |
-
# Main container for itinerary content
|
| 1187 |
st.markdown('<div class="modern-card">', unsafe_allow_html=True)
|
| 1188 |
-
|
| 1189 |
-
# Modern tabs for different views
|
| 1190 |
itinerary_tab, details_tab, download_tab = st.tabs([f"ποΈ {t('full_itinerary')}", f"πΌ {t('details')}", f"πΎ {t('download_share')}"])
|
| 1191 |
|
| 1192 |
with itinerary_tab:
|
| 1193 |
-
# Preview the itinerary as text
|
| 1194 |
st.text_area("Your Itinerary", st.session_state.generated_itinerary, height=600)
|
| 1195 |
|
| 1196 |
with details_tab:
|
| 1197 |
-
# More detailed view with agent outputs in a nested tab structure
|
| 1198 |
agent_tabs = st.tabs([
|
| 1199 |
"π Destination", "π¨ Accommodation", "π Transportation",
|
| 1200 |
"π Activities", "π½οΈ Dining"
|
|
@@ -1226,36 +1203,26 @@ if st.session_state.generation_complete:
|
|
| 1226 |
with col1:
|
| 1227 |
st.markdown("### " + t("save_itinerary"))
|
| 1228 |
st.markdown("Download your personalized travel plan to access it offline or share with your travel companions.")
|
| 1229 |
-
|
| 1230 |
-
# Display stylized download button
|
| 1231 |
st.markdown("""
|
| 1232 |
<div style="background-color: #f8f9fa; padding: 15px; border-radius: 10px; margin-top: 20px;">
|
| 1233 |
<h4 style="margin-top: 0;">Your Itinerary File</h4>
|
| 1234 |
<p style="font-size: 0.9rem; color: #6c757d;">Text format - Can be opened in any text editor</p>
|
| 1235 |
""", unsafe_allow_html=True)
|
| 1236 |
-
|
| 1237 |
-
# Enhanced download link
|
| 1238 |
st.markdown(
|
| 1239 |
f"""<div style="margin: 10px 0;">{ get_download_link(st.session_state.generated_itinerary, st.session_state.filename) }</div>""",
|
| 1240 |
unsafe_allow_html=True
|
| 1241 |
)
|
| 1242 |
-
|
| 1243 |
st.markdown("</div>", unsafe_allow_html=True)
|
| 1244 |
-
|
| 1245 |
-
# Share options
|
| 1246 |
st.markdown("### " + t("share_itinerary"))
|
| 1247 |
st.markdown("*Coming soon: Email your itinerary or share via social media.*")
|
| 1248 |
|
| 1249 |
with col2:
|
| 1250 |
-
# QR code placeholder for future implementation
|
| 1251 |
st.markdown("### " + t("save_for_mobile"))
|
| 1252 |
st.markdown("*Coming soon: QR code for easy access on your phone*")
|
| 1253 |
|
| 1254 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 1255 |
|
| 1256 |
-
# Add a reset button to create a new itinerary
|
| 1257 |
if st.button(t("plan_another_trip"), key="reset_button"):
|
| 1258 |
-
# Reset the session state
|
| 1259 |
st.session_state.generated_itinerary = None
|
| 1260 |
st.session_state.generation_complete = False
|
| 1261 |
st.session_state.current_step = 0
|
|
@@ -1263,16 +1230,12 @@ if st.session_state.generation_complete:
|
|
| 1263 |
st.session_state.results = {}
|
| 1264 |
st.experimental_rerun()
|
| 1265 |
|
| 1266 |
-
# Footer for the app
|
| 1267 |
st.markdown(f"""
|
| 1268 |
<div style="margin-top: 50px; text-align: center; padding: 20px; color: #6c757d; font-size: 0.8rem;">
|
| 1269 |
<p>{t("built_with")}</p>
|
| 1270 |
</div>
|
| 1271 |
""", unsafe_allow_html=True)
|
| 1272 |
-
|
| 1273 |
-
# End of app
|
| 1274 |
|
| 1275 |
-
# Modern footer with more information
|
| 1276 |
st.markdown("""
|
| 1277 |
<div style="margin-top: 50px; border-top: 1px solid #e9ecef; padding: 30px 0; color: #6c757d;">
|
| 1278 |
<div style="display: flex; justify-content: space-between; flex-wrap: wrap; max-width: 1200px; margin: 0 auto; padding: 0 20px;">
|
|
@@ -1293,7 +1256,6 @@ st.markdown("""
|
|
| 1293 |
<h4 style="color: #4361ee; margin-bottom: 15px;">Connect</h4>
|
| 1294 |
<p>Stay updated with our latest travel guides and features.</p>
|
| 1295 |
<div style="margin-top: 15px;">
|
| 1296 |
-
<!-- Social media icons would go here -->
|
| 1297 |
<span>π° πΏ πΈ π¦</span>
|
| 1298 |
</div>
|
| 1299 |
</div>
|
|
|
|
| 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 |
+
# st.set_page_config()λ λ€λ₯Έ Streamlit ν¨μ νΈμΆλ³΄λ€ κ°μ₯ λ¨Όμ μ€νλμ΄μΌ ν©λλ€.
|
| 14 |
+
st.set_page_config(
|
| 15 |
+
page_title="Globetrotter AI: Your AI Agent for Travelling", # κΈ°λ³Έκ°μ μμ΄
|
| 16 |
+
page_icon="βοΈ",
|
| 17 |
+
layout="wide",
|
| 18 |
+
initial_sidebar_state="expanded"
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
# ------------------------------------------
|
| 22 |
# λ€κ΅μ΄ μ§μμ μν λ²μ μ¬μ λ° ν¬νΌ ν¨μ
|
| 23 |
# ------------------------------------------
|
|
|
|
| 280 |
}
|
| 281 |
}
|
| 282 |
|
|
|
|
| 283 |
def t(key):
|
| 284 |
lang = st.session_state.get("selected_language", "en")
|
| 285 |
return translations[lang].get(key, key)
|
|
|
|
| 311 |
st.session_state.selected_language = lang_map.get(language, "en")
|
| 312 |
|
| 313 |
# ------------------------------------------
|
| 314 |
+
# μ΄ν Streamlit UI μ½λ μμ
|
| 315 |
# ------------------------------------------
|
| 316 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 317 |
# Modern CSS with refined color scheme and sleek animations
|
| 318 |
st.markdown("""
|
| 319 |
<style>
|
|
|
|
| 537 |
if 'progress_steps' not in st.session_state:
|
| 538 |
st.session_state.progress_steps = {
|
| 539 |
0: {'status': 'pending', 'name': t("trip_details")},
|
| 540 |
+
1: {'status': 'pending', 'name': t("about")}, # μ: μμ κ΄λ ¨
|
| 541 |
+
2: {'status': 'pending', 'name': t("travel_style")}, # μ: κ΅ν΅νΈ κ΄λ ¨
|
| 542 |
+
3: {'status': 'pending', 'name': t("live_agent_outputs")}, # μ: μ‘ν°λΉν° κ΄λ ¨
|
| 543 |
+
4: {'status': 'pending', 'name': t("download_share")}, # μ: μμ¬ κ΄λ ¨
|
| 544 |
5: {'status': 'pending', 'name': t("full_itinerary")}
|
| 545 |
}
|
| 546 |
|
|
|
|
| 687 |
|
| 688 |
return result
|
| 689 |
|
| 690 |
+
# ------------------------------------------
|
| 691 |
+
# Session state μ΄κΈ°ν
|
| 692 |
+
# ------------------------------------------
|
| 693 |
if 'generated_itinerary' not in st.session_state:
|
| 694 |
st.session_state.generated_itinerary = None
|
| 695 |
if 'generation_complete' not in st.session_state:
|
|
|
|
| 781 |
st.markdown(f"**{name}**")
|
| 782 |
st.markdown(f"<small>{desc}</small>", unsafe_allow_html=True)
|
| 783 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 784 |
+
|
| 785 |
# Main content area
|
| 786 |
if not st.session_state.generation_complete:
|
| 787 |
# Sleek form with minimal design
|
|
|
|
| 822 |
"Nature", "Shopping", "Nightlife", "Family-friendly"],
|
| 823 |
default=["Culture", "Food & Dining"])
|
| 824 |
|
| 825 |
+
# Simplified expander for additional preferences
|
| 826 |
with st.expander("Additional Preferences", expanded=False):
|
| 827 |
preferences = st.text_area("Interests", placeholder="History museums, local cuisine, hiking, art...")
|
| 828 |
special_requirements = st.text_area("Special Requirements",
|
| 829 |
placeholder="Dietary restrictions, accessibility needs...")
|
| 830 |
|
| 831 |
+
# Submit button
|
| 832 |
submit_button = st.form_submit_button(t("submit"))
|
| 833 |
|
| 834 |
st.markdown('</div>', unsafe_allow_html=True)
|
|
|
|
| 851 |
"special_requirements": special_requirements
|
| 852 |
}
|
| 853 |
|
| 854 |
+
# Format the user input for tasks
|
| 855 |
input_context = f"""Travel Request Details:
|
| 856 |
Origin: {user_input['origin']}
|
| 857 |
Destination: {user_input['destination']}
|
|
|
|
| 864 |
Special Requirements: {user_input['special_requirements']}
|
| 865 |
"""
|
| 866 |
|
| 867 |
+
# Display processing animation
|
| 868 |
st.markdown("""
|
| 869 |
<div class="sleek-processing-container">
|
| 870 |
<div class="pulse-container">
|
|
|
|
| 923 |
</style>
|
| 924 |
""", unsafe_allow_html=True)
|
| 925 |
|
| 926 |
+
# Create containers for progress, logs, and live output
|
| 927 |
st.markdown('<div class="modern-card">', unsafe_allow_html=True)
|
|
|
|
|
|
|
| 928 |
progress_tab, logs_tab, details_tab = st.tabs(["π Progress", "π Live Activity", "π Request Details"])
|
| 929 |
|
|
|
|
| 930 |
with details_tab:
|
| 931 |
st.markdown("#### " + t("request_details"))
|
| 932 |
st.markdown(f"**{t('destination')}:** {user_input['destination']}")
|
|
|
|
| 940 |
st.markdown(f"**Special Requirements:** {user_input['special_requirements']}")
|
| 941 |
|
| 942 |
with progress_tab:
|
|
|
|
| 943 |
if 'progress_placeholder' not in st.session_state:
|
| 944 |
st.session_state.progress_placeholder = st.empty()
|
| 945 |
with st.session_state.progress_placeholder.container():
|
|
|
|
| 949 |
log_container = st.container()
|
| 950 |
st.session_state.log_messages = []
|
| 951 |
|
| 952 |
+
st.markdown('</div>', unsafe_allow_html=True)
|
|
|
|
| 953 |
output_container = st.container()
|
| 954 |
with output_container:
|
| 955 |
st.markdown('<div class="modern-card">', unsafe_allow_html=True)
|
|
|
|
| 957 |
st.info("Our AI agents will show their work here as they create your itinerary")
|
| 958 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 959 |
|
|
|
|
| 960 |
st.session_state.current_step = 0
|
| 961 |
|
|
|
|
|
|
|
| 962 |
# Step 1: Destination Research
|
| 963 |
+
update_step_status(0, 'active')
|
| 964 |
with st.session_state.progress_placeholder.container():
|
| 965 |
display_modern_progress(st.session_state.current_step)
|
| 966 |
|
|
|
|
| 975 |
"destination_info"
|
| 976 |
)
|
| 977 |
|
| 978 |
+
update_step_status(0, 'complete')
|
|
|
|
| 979 |
st.session_state.current_step = 1
|
| 980 |
+
update_step_status(1, 'active')
|
| 981 |
with st.session_state.progress_placeholder.container():
|
| 982 |
display_modern_progress(st.session_state.current_step)
|
| 983 |
|
|
|
|
| 994 |
"accommodation_info"
|
| 995 |
)
|
| 996 |
|
| 997 |
+
update_step_status(1, 'complete')
|
|
|
|
| 998 |
st.session_state.current_step = 2
|
| 999 |
+
update_step_status(2, 'active')
|
| 1000 |
with st.session_state.progress_placeholder.container():
|
| 1001 |
display_modern_progress(st.session_state.current_step)
|
| 1002 |
|
|
|
|
| 1012 |
"transportation_info"
|
| 1013 |
)
|
| 1014 |
|
| 1015 |
+
update_step_status(2, 'complete')
|
|
|
|
| 1016 |
st.session_state.current_step = 3
|
| 1017 |
+
update_step_status(3, 'active')
|
| 1018 |
with st.session_state.progress_placeholder.container():
|
| 1019 |
display_modern_progress(st.session_state.current_step)
|
| 1020 |
|
|
|
|
| 1030 |
"activities_info"
|
| 1031 |
)
|
| 1032 |
|
| 1033 |
+
update_step_status(3, 'complete')
|
|
|
|
| 1034 |
st.session_state.current_step = 4
|
| 1035 |
+
update_step_status(4, 'active')
|
| 1036 |
with st.session_state.progress_placeholder.container():
|
| 1037 |
display_modern_progress(st.session_state.current_step)
|
| 1038 |
|
|
|
|
| 1048 |
"dining_info"
|
| 1049 |
)
|
| 1050 |
|
| 1051 |
+
update_step_status(4, 'complete')
|
|
|
|
| 1052 |
st.session_state.current_step = 5
|
| 1053 |
+
update_step_status(5, 'active')
|
| 1054 |
with st.session_state.progress_placeholder.container():
|
| 1055 |
display_modern_progress(st.session_state.current_step)
|
| 1056 |
|
|
|
|
| 1085 |
"itinerary"
|
| 1086 |
)
|
| 1087 |
|
| 1088 |
+
update_step_status(5, 'complete')
|
|
|
|
| 1089 |
st.session_state.current_step = 6
|
| 1090 |
with st.session_state.progress_placeholder.container():
|
| 1091 |
display_modern_progress(st.session_state.current_step)
|
| 1092 |
|
|
|
|
| 1093 |
st.session_state.generated_itinerary = itinerary
|
| 1094 |
st.session_state.generation_complete = True
|
| 1095 |
|
|
|
|
| 1096 |
date_str = datetime.now().strftime("%Y-%m-%d")
|
| 1097 |
st.session_state.filename = f"{user_input['destination'].replace(' ', '_')}_{date_str}_itinerary.txt"
|
|
|
|
|
|
|
| 1098 |
|
| 1099 |
# Display results if generation is complete
|
| 1100 |
if st.session_state.generation_complete:
|
|
|
|
| 1101 |
st.markdown("""
|
| 1102 |
<div class="modern-card animate-in">
|
| 1103 |
<div style="display: flex; justify-content: center; margin-bottom: 20px;">
|
|
|
|
| 1165 |
</style>
|
| 1166 |
""", unsafe_allow_html=True)
|
| 1167 |
|
|
|
|
| 1168 |
st.markdown('<div class="modern-card">', unsafe_allow_html=True)
|
|
|
|
|
|
|
| 1169 |
itinerary_tab, details_tab, download_tab = st.tabs([f"ποΈ {t('full_itinerary')}", f"πΌ {t('details')}", f"πΎ {t('download_share')}"])
|
| 1170 |
|
| 1171 |
with itinerary_tab:
|
|
|
|
| 1172 |
st.text_area("Your Itinerary", st.session_state.generated_itinerary, height=600)
|
| 1173 |
|
| 1174 |
with details_tab:
|
|
|
|
| 1175 |
agent_tabs = st.tabs([
|
| 1176 |
"π Destination", "π¨ Accommodation", "π Transportation",
|
| 1177 |
"π Activities", "π½οΈ Dining"
|
|
|
|
| 1203 |
with col1:
|
| 1204 |
st.markdown("### " + t("save_itinerary"))
|
| 1205 |
st.markdown("Download your personalized travel plan to access it offline or share with your travel companions.")
|
|
|
|
|
|
|
| 1206 |
st.markdown("""
|
| 1207 |
<div style="background-color: #f8f9fa; padding: 15px; border-radius: 10px; margin-top: 20px;">
|
| 1208 |
<h4 style="margin-top: 0;">Your Itinerary File</h4>
|
| 1209 |
<p style="font-size: 0.9rem; color: #6c757d;">Text format - Can be opened in any text editor</p>
|
| 1210 |
""", unsafe_allow_html=True)
|
|
|
|
|
|
|
| 1211 |
st.markdown(
|
| 1212 |
f"""<div style="margin: 10px 0;">{ get_download_link(st.session_state.generated_itinerary, st.session_state.filename) }</div>""",
|
| 1213 |
unsafe_allow_html=True
|
| 1214 |
)
|
|
|
|
| 1215 |
st.markdown("</div>", unsafe_allow_html=True)
|
|
|
|
|
|
|
| 1216 |
st.markdown("### " + t("share_itinerary"))
|
| 1217 |
st.markdown("*Coming soon: Email your itinerary or share via social media.*")
|
| 1218 |
|
| 1219 |
with col2:
|
|
|
|
| 1220 |
st.markdown("### " + t("save_for_mobile"))
|
| 1221 |
st.markdown("*Coming soon: QR code for easy access on your phone*")
|
| 1222 |
|
| 1223 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 1224 |
|
|
|
|
| 1225 |
if st.button(t("plan_another_trip"), key="reset_button"):
|
|
|
|
| 1226 |
st.session_state.generated_itinerary = None
|
| 1227 |
st.session_state.generation_complete = False
|
| 1228 |
st.session_state.current_step = 0
|
|
|
|
| 1230 |
st.session_state.results = {}
|
| 1231 |
st.experimental_rerun()
|
| 1232 |
|
|
|
|
| 1233 |
st.markdown(f"""
|
| 1234 |
<div style="margin-top: 50px; text-align: center; padding: 20px; color: #6c757d; font-size: 0.8rem;">
|
| 1235 |
<p>{t("built_with")}</p>
|
| 1236 |
</div>
|
| 1237 |
""", unsafe_allow_html=True)
|
|
|
|
|
|
|
| 1238 |
|
|
|
|
| 1239 |
st.markdown("""
|
| 1240 |
<div style="margin-top: 50px; border-top: 1px solid #e9ecef; padding: 30px 0; color: #6c757d;">
|
| 1241 |
<div style="display: flex; justify-content: space-between; flex-wrap: wrap; max-width: 1200px; margin: 0 auto; padding: 0 20px;">
|
|
|
|
| 1256 |
<h4 style="color: #4361ee; margin-bottom: 15px;">Connect</h4>
|
| 1257 |
<p>Stay updated with our latest travel guides and features.</p>
|
| 1258 |
<div style="margin-top: 15px;">
|
|
|
|
| 1259 |
<span>π° πΏ πΈ π¦</span>
|
| 1260 |
</div>
|
| 1261 |
</div>
|