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>
|