Spaces:
No application file
No application file
Update app.py
Browse files
app.py
CHANGED
|
@@ -285,18 +285,22 @@ st.markdown("""
|
|
| 285 |
color: white;
|
| 286 |
}
|
| 287 |
|
| 288 |
-
.
|
| 289 |
-
|
| 290 |
border-radius: 8px;
|
| 291 |
-
|
| 292 |
-
margin-bottom: 6px;
|
| 293 |
-
background-color: #1a1a1a;
|
| 294 |
}
|
| 295 |
|
| 296 |
.bookmark-image {
|
| 297 |
-
border:
|
| 298 |
border-radius: 4px;
|
| 299 |
margin-bottom: 8px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 300 |
}
|
| 301 |
|
| 302 |
.product-image {
|
|
@@ -304,7 +308,37 @@ st.markdown("""
|
|
| 304 |
border-radius: 8px;
|
| 305 |
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
| 306 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 307 |
</style>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 308 |
""", unsafe_allow_html=True)
|
| 309 |
|
| 310 |
# Initialize session state
|
|
@@ -674,46 +708,9 @@ def export_bookmarked_models_pdf():
|
|
| 674 |
elements.append(img)
|
| 675 |
elements.append(Spacer(1, 0.2*inch))
|
| 676 |
|
| 677 |
-
#
|
| 678 |
-
|
| 679 |
-
|
| 680 |
-
specs = model_data['data'].get('specs', {})
|
| 681 |
-
specs = clean_spec_data(specs)
|
| 682 |
-
|
| 683 |
-
if specs:
|
| 684 |
-
st.markdown("### Technical Specifications")
|
| 685 |
-
|
| 686 |
-
st.markdown("**Electrical Specifications:**")
|
| 687 |
-
if specs.get('voltage') and specs.get('voltage') != 'N/A':
|
| 688 |
-
st.write(f"Voltage: {specs['voltage']}")
|
| 689 |
-
if specs.get('amperage') and specs.get('amperage') != 'N/A':
|
| 690 |
-
st.write(f"Amperage: {specs['amperage']}")
|
| 691 |
-
if specs.get('phase') and specs.get('phase') != 'N/A':
|
| 692 |
-
st.write(f"Phase: {specs['phase']}")
|
| 693 |
-
if specs.get('frequency') and specs.get('frequency') != 'N/A':
|
| 694 |
-
st.write(f"Frequency: {specs['frequency']}")
|
| 695 |
-
|
| 696 |
-
st.markdown("**Physical Specifications:**")
|
| 697 |
-
if specs.get('dimensions') and specs.get('dimensions') != 'N/A':
|
| 698 |
-
st.write(f"Dimensions: {specs['dimensions']}")
|
| 699 |
-
if specs.get('weight') and specs.get('weight') != 'N/A':
|
| 700 |
-
st.write(f"Weight: {specs['weight']}")
|
| 701 |
-
|
| 702 |
-
st.markdown("**Performance Specifications:**")
|
| 703 |
-
if specs.get('refrigerant') and specs.get('refrigerant') != 'N/A':
|
| 704 |
-
st.write(f"Refrigerant: {specs['refrigerant']}")
|
| 705 |
-
if specs.get('temperature_range') and specs.get('temperature_range') != 'N/A':
|
| 706 |
-
st.write(f"Temperature: {specs['temperature_range']}")
|
| 707 |
-
if specs.get('compressor') and specs.get('compressor') != 'N/A':
|
| 708 |
-
st.write(f"Compressor: {specs['compressor']}")
|
| 709 |
-
if specs.get('btu') and specs.get('btu') != 'N/A':
|
| 710 |
-
st.write(f"BTU: {specs['btu']}")
|
| 711 |
-
if specs.get('capacity') and specs.get('capacity') != 'N/A':
|
| 712 |
-
st.write(f"Capacity: {specs['capacity']}")
|
| 713 |
-
else:
|
| 714 |
-
# No file path - show specifications in original two-column layout
|
| 715 |
-
specs = model_data['data'].get('specs', {})
|
| 716 |
-
specs = clean_spec_data(specs)
|
| 717 |
|
| 718 |
# Create specifications data for table
|
| 719 |
spec_data = [['Specification', 'Value']]
|
|
@@ -835,101 +832,115 @@ def display_bookmarked_models():
|
|
| 835 |
st.info("📌 No models bookmarked yet. Select models to create your custom list!")
|
| 836 |
return
|
| 837 |
|
| 838 |
-
|
| 839 |
-
|
| 840 |
-
|
| 841 |
-
with view_col2:
|
| 842 |
-
st.markdown(f"**{len(st.session_state.bookmarked_models)} models selected**")
|
| 843 |
-
|
| 844 |
-
with view_col3:
|
| 845 |
-
# Toggle for text-only view - optimized to avoid loading
|
| 846 |
-
toggle_label = "📷 Show Images" if st.session_state.text_only_view else "📝 Text Only"
|
| 847 |
-
if st.button(toggle_label, key="toggle_view", use_container_width=True):
|
| 848 |
-
st.session_state.text_only_view = not st.session_state.text_only_view
|
| 849 |
-
# Don't use st.rerun() to avoid loading screen
|
| 850 |
-
|
| 851 |
-
# Display bookmarked models with or without images
|
| 852 |
-
if st.session_state.text_only_view:
|
| 853 |
-
# Text-only view (original compact list)
|
| 854 |
-
display_limit = 5
|
| 855 |
-
for idx, model in enumerate(st.session_state.bookmarked_models[:display_limit]):
|
| 856 |
-
col_model, col_remove = st.columns([5, 1])
|
| 857 |
-
with col_model:
|
| 858 |
-
st.text(f"• {model}")
|
| 859 |
-
with col_remove:
|
| 860 |
-
if st.button("❌", key=f"remove_bookmark_list_{idx}", help=f"Remove {model}"):
|
| 861 |
-
st.session_state.bookmarked_models.remove(model)
|
| 862 |
-
st.rerun()
|
| 863 |
|
| 864 |
-
|
| 865 |
-
|
| 866 |
-
|
| 867 |
-
|
| 868 |
-
|
| 869 |
-
|
| 870 |
-
|
| 871 |
-
|
| 872 |
-
|
| 873 |
-
|
| 874 |
-
|
| 875 |
-
|
| 876 |
-
|
| 877 |
-
|
| 878 |
-
|
| 879 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 880 |
|
| 881 |
-
|
| 882 |
-
|
| 883 |
-
model
|
| 884 |
-
|
| 885 |
-
|
| 886 |
-
|
| 887 |
-
|
| 888 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 889 |
|
| 890 |
-
|
| 891 |
-
|
| 892 |
-
|
| 893 |
-
pdf_url = f"https://huggingface.co/spaces/TurboAir/TurboAirViewer/resolve/main/pdfs/{pdf_filename}"
|
| 894 |
-
|
| 895 |
-
# Check if image is already cached
|
| 896 |
-
cache_key = f"thumb_{model}"
|
| 897 |
-
img_base64 = st.session_state.product_images.get(cache_key)
|
| 898 |
|
| 899 |
-
|
| 900 |
-
|
| 901 |
-
|
| 902 |
-
|
| 903 |
-
|
| 904 |
-
|
| 905 |
-
|
| 906 |
-
|
| 907 |
-
|
| 908 |
-
|
| 909 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 910 |
|
| 911 |
-
|
| 912 |
-
|
| 913 |
-
|
| 914 |
-
|
| 915 |
-
|
| 916 |
-
|
| 917 |
-
|
| 918 |
-
|
| 919 |
-
|
| 920 |
-
|
| 921 |
-
|
| 922 |
-
|
| 923 |
-
|
| 924 |
-
|
| 925 |
-
|
| 926 |
-
|
| 927 |
-
|
| 928 |
-
|
| 929 |
-
|
| 930 |
-
|
| 931 |
|
| 932 |
-
# Export section
|
| 933 |
st.markdown("---")
|
| 934 |
export_col1, export_col2, export_col3 = st.columns(3)
|
| 935 |
|
|
@@ -975,7 +986,10 @@ if not all_models:
|
|
| 975 |
st.stop()
|
| 976 |
|
| 977 |
# Bookmarks section
|
| 978 |
-
|
|
|
|
|
|
|
|
|
|
| 979 |
|
| 980 |
# Main content area
|
| 981 |
col1, col2 = st.columns([1, 3])
|
|
@@ -1000,55 +1014,57 @@ with col2:
|
|
| 1000 |
grouped_models[product_type] = []
|
| 1001 |
grouped_models[product_type].append(model)
|
| 1002 |
|
| 1003 |
-
# Create formatted options
|
| 1004 |
-
formatted_options = ['']
|
| 1005 |
for product_type in sorted(grouped_models.keys()):
|
| 1006 |
for model in sorted(grouped_models[product_type]):
|
| 1007 |
formatted_options.append(model)
|
| 1008 |
|
| 1009 |
-
# Search selectbox
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1010 |
selected = st.selectbox(
|
| 1011 |
"Select or type a model number:",
|
| 1012 |
options=formatted_options,
|
| 1013 |
-
format_func=lambda x: format_model_option(x) if x else "
|
| 1014 |
key="model_search",
|
| 1015 |
-
index=
|
| 1016 |
-
help="
|
| 1017 |
)
|
| 1018 |
|
| 1019 |
if selected:
|
| 1020 |
st.session_state.selected_model = selected
|
| 1021 |
|
| 1022 |
# Display selected model
|
| 1023 |
-
if
|
| 1024 |
st.markdown("---")
|
| 1025 |
|
| 1026 |
-
model_data = get_model_data(
|
| 1027 |
|
| 1028 |
if model_data:
|
| 1029 |
# Model header with bookmark
|
| 1030 |
col1, col2 = st.columns([4, 1])
|
| 1031 |
with col1:
|
| 1032 |
-
st.markdown(f"## {
|
| 1033 |
-
st.caption(f"Product Type: {get_product_type(
|
| 1034 |
if model_data.get('quality'):
|
| 1035 |
quality_class = f"quality-{model_data['quality']}"
|
| 1036 |
st.markdown(f'<span class="quality-badge {quality_class}">Data Quality: {model_data["quality"].title()}</span>',
|
| 1037 |
unsafe_allow_html=True)
|
| 1038 |
|
| 1039 |
with col2:
|
| 1040 |
-
is_bookmarked =
|
| 1041 |
bookmark_label = "❌ Remove" if is_bookmarked else "📌 Bookmark"
|
| 1042 |
-
if st.button(bookmark_label, key=f"bookmark_{
|
| 1043 |
if is_bookmarked:
|
| 1044 |
-
st.session_state.bookmarked_models.remove(
|
| 1045 |
st.success("Bookmark removed!")
|
| 1046 |
else:
|
| 1047 |
-
|
| 1048 |
-
|
| 1049 |
-
else:
|
| 1050 |
-
st.session_state.bookmarked_models.append(selected)
|
| 1051 |
-
st.success("Model bookmarked!")
|
| 1052 |
time.sleep(0.5)
|
| 1053 |
st.rerun()
|
| 1054 |
|
|
@@ -1063,13 +1079,13 @@ if selected and selected != '':
|
|
| 1063 |
with img_col:
|
| 1064 |
st.markdown("### Product Image")
|
| 1065 |
# Check if image is already cached
|
| 1066 |
-
cache_key = f"thumb_{
|
| 1067 |
img_base64 = st.session_state.product_images.get(cache_key)
|
| 1068 |
|
| 1069 |
if not img_base64:
|
| 1070 |
# Extract image if not cached
|
| 1071 |
with st.spinner("Loading product image..."):
|
| 1072 |
-
img_base64 = extract_pdf_thumbnail(pdf_url,
|
| 1073 |
|
| 1074 |
if img_base64:
|
| 1075 |
st.markdown(
|
|
@@ -1189,14 +1205,14 @@ if selected and selected != '':
|
|
| 1189 |
|
| 1190 |
with action_col1:
|
| 1191 |
# PDF toggle button
|
| 1192 |
-
pdf_key = f'show_pdf_{
|
| 1193 |
button_text = "📄 Hide PDF" if st.session_state.get(pdf_key, False) else "📄 View PDF"
|
| 1194 |
-
if st.button(button_text, use_container_width=True, key=f"view_pdf_{
|
| 1195 |
st.session_state[pdf_key] = not st.session_state.get(pdf_key, False)
|
| 1196 |
|
| 1197 |
with action_col2:
|
| 1198 |
# Google search button
|
| 1199 |
-
google_search = f"https://www.google.com/search?q=turboair+{
|
| 1200 |
st.markdown(f'''
|
| 1201 |
<a href="{google_search}" target="_blank" style="text-decoration: none;">
|
| 1202 |
<button class="google-search-button">
|
|
@@ -1206,13 +1222,13 @@ if selected and selected != '':
|
|
| 1206 |
''', unsafe_allow_html=True)
|
| 1207 |
|
| 1208 |
# Display PDF preview if requested
|
| 1209 |
-
pdf_key = f'show_pdf_{
|
| 1210 |
if st.session_state.get(pdf_key, False):
|
| 1211 |
st.markdown("---")
|
| 1212 |
st.markdown("### 📄 PDF Specification Sheet")
|
| 1213 |
|
| 1214 |
if 'file_path' in model_data and model_data['file_path']:
|
| 1215 |
-
display_pdf_preview(model_data['file_path'],
|
| 1216 |
else:
|
| 1217 |
st.error("❌ No PDF file path found for this model.")
|
| 1218 |
st.info("PDF file may not be available.")
|
|
@@ -1221,7 +1237,7 @@ if selected and selected != '':
|
|
| 1221 |
st.markdown("---")
|
| 1222 |
st.caption(f"Source: {model_data['filename']}")
|
| 1223 |
else:
|
| 1224 |
-
st.error(f"No data found for model {
|
| 1225 |
|
| 1226 |
# Stats at bottom
|
| 1227 |
st.markdown("---")
|
|
|
|
| 285 |
color: white;
|
| 286 |
}
|
| 287 |
|
| 288 |
+
.stExpander {
|
| 289 |
+
background-color: #2d2d2d;
|
| 290 |
border-radius: 8px;
|
| 291 |
+
border: 1px solid #444;
|
|
|
|
|
|
|
| 292 |
}
|
| 293 |
|
| 294 |
.bookmark-image {
|
| 295 |
+
border: 1px solid #444;
|
| 296 |
border-radius: 4px;
|
| 297 |
margin-bottom: 8px;
|
| 298 |
+
transition: transform 0.2s ease;
|
| 299 |
+
}
|
| 300 |
+
|
| 301 |
+
.bookmark-image:hover {
|
| 302 |
+
transform: scale(1.05);
|
| 303 |
+
border-color: #4CAF50;
|
| 304 |
}
|
| 305 |
|
| 306 |
.product-image {
|
|
|
|
| 308 |
border-radius: 8px;
|
| 309 |
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
| 310 |
}
|
| 311 |
+
|
| 312 |
+
/* Equal height columns */
|
| 313 |
+
[data-testid="column"] {
|
| 314 |
+
display: flex;
|
| 315 |
+
flex-direction: column;
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
[data-testid="column"] > div {
|
| 319 |
+
flex: 1;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
/* Selectbox enhancement */
|
| 323 |
+
.stSelectbox input {
|
| 324 |
+
cursor: text !important;
|
| 325 |
+
}
|
| 326 |
</style>
|
| 327 |
+
|
| 328 |
+
<script>
|
| 329 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 330 |
+
// Auto-select text in selectbox when focused
|
| 331 |
+
const observer = new MutationObserver(function(mutations) {
|
| 332 |
+
const selectInput = document.querySelector('[data-baseweb="select"] input');
|
| 333 |
+
if (selectInput) {
|
| 334 |
+
selectInput.addEventListener('focus', function() {
|
| 335 |
+
this.select();
|
| 336 |
+
});
|
| 337 |
+
}
|
| 338 |
+
});
|
| 339 |
+
observer.observe(document.body, { childList: true, subtree: true });
|
| 340 |
+
});
|
| 341 |
+
</script>
|
| 342 |
""", unsafe_allow_html=True)
|
| 343 |
|
| 344 |
# Initialize session state
|
|
|
|
| 708 |
elements.append(img)
|
| 709 |
elements.append(Spacer(1, 0.2*inch))
|
| 710 |
|
| 711 |
+
# Get specifications for table
|
| 712 |
+
specs = model_data['data'].get('specs', {})
|
| 713 |
+
specs = clean_spec_data(specs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 714 |
|
| 715 |
# Create specifications data for table
|
| 716 |
spec_data = [['Specification', 'Value']]
|
|
|
|
| 832 |
st.info("📌 No models bookmarked yet. Select models to create your custom list!")
|
| 833 |
return
|
| 834 |
|
| 835 |
+
# Collapsible header
|
| 836 |
+
with st.expander(f"📌 Bookmarked Models ({len(st.session_state.bookmarked_models)} selected)", expanded=True):
|
| 837 |
+
view_col1, view_col2, view_col3 = st.columns([2, 1, 1])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 838 |
|
| 839 |
+
with view_col3:
|
| 840 |
+
# Toggle for text-only view - optimized to avoid loading
|
| 841 |
+
toggle_label = "📷 Show Images" if st.session_state.text_only_view else "📝 Text Only"
|
| 842 |
+
if st.button(toggle_label, key="toggle_view", use_container_width=True):
|
| 843 |
+
st.session_state.text_only_view = not st.session_state.text_only_view
|
| 844 |
+
|
| 845 |
+
# Display bookmarked models with or without images
|
| 846 |
+
if st.session_state.text_only_view:
|
| 847 |
+
# Text-only view (original compact list)
|
| 848 |
+
display_limit = 5
|
| 849 |
+
for idx, model in enumerate(st.session_state.bookmarked_models[:display_limit]):
|
| 850 |
+
col_select, col_remove = st.columns([5, 1])
|
| 851 |
+
with col_select:
|
| 852 |
+
if st.button(f"• {model}", key=f"select_text_{idx}", use_container_width=True, help=f"Click to view {model}"):
|
| 853 |
+
st.session_state.selected_model = model
|
| 854 |
+
st.rerun()
|
| 855 |
+
with col_remove:
|
| 856 |
+
if st.button("❌", key=f"remove_bookmark_list_{idx}", help=f"Remove {model}"):
|
| 857 |
+
st.session_state.bookmarked_models.remove(model)
|
| 858 |
+
st.rerun()
|
| 859 |
|
| 860 |
+
if len(st.session_state.bookmarked_models) > display_limit:
|
| 861 |
+
with st.expander(f"Show all {len(st.session_state.bookmarked_models)} bookmarks"):
|
| 862 |
+
for idx, model in enumerate(st.session_state.bookmarked_models[display_limit:], display_limit):
|
| 863 |
+
col_select, col_remove = st.columns([5, 1])
|
| 864 |
+
with col_select:
|
| 865 |
+
if st.button(f"• {model}", key=f"select_text_exp_{idx}", use_container_width=True, help=f"Click to view {model}"):
|
| 866 |
+
st.session_state.selected_model = model
|
| 867 |
+
st.rerun()
|
| 868 |
+
with col_remove:
|
| 869 |
+
if st.button("❌", key=f"remove_bookmark_exp_{idx}", help=f"Remove {model}"):
|
| 870 |
+
st.session_state.bookmarked_models.remove(model)
|
| 871 |
+
st.rerun()
|
| 872 |
+
|
| 873 |
+
else: # ← THIS IS THE KEY FIX - Added else block
|
| 874 |
+
# Image view
|
| 875 |
+
# Display in grid layout
|
| 876 |
+
cols_per_row = 6 # Changed from 4 to 6 columns for narrower items
|
| 877 |
+
for i in range(0, len(st.session_state.bookmarked_models), cols_per_row):
|
| 878 |
+
cols = st.columns(cols_per_row)
|
| 879 |
+
|
| 880 |
+
for j, col in enumerate(cols):
|
| 881 |
+
if i + j < len(st.session_state.bookmarked_models):
|
| 882 |
+
model = st.session_state.bookmarked_models[i + j]
|
| 883 |
+
model_data = get_model_data(model)
|
| 884 |
|
| 885 |
+
with col:
|
| 886 |
+
# Container for each bookmarked item
|
| 887 |
+
st.markdown('<div class="bookmark-item">', unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 888 |
|
| 889 |
+
# Container for each bookmarked item
|
| 890 |
+
with st.container():
|
| 891 |
+
# Try to get and display thumbnail
|
| 892 |
+
if model_data and model_data.get('file_path'):
|
| 893 |
+
pdf_filename = model_data['file_path'].replace('\\', '/').split('/')[-1]
|
| 894 |
+
pdf_url = f"https://huggingface.co/spaces/TurboAir/TurboAirViewer/resolve/main/pdfs/{pdf_filename}"
|
| 895 |
+
|
| 896 |
+
# Check if image is already cached
|
| 897 |
+
cache_key = f"thumb_{model}"
|
| 898 |
+
img_base64 = st.session_state.product_images.get(cache_key)
|
| 899 |
+
|
| 900 |
+
if img_base64:
|
| 901 |
+
# Use cached image
|
| 902 |
+
st.markdown(
|
| 903 |
+
f'<img src="data:image/png;base64,{img_base64}" '
|
| 904 |
+
f'style="width:100%; max-height:150px; object-fit:contain; cursor:pointer;" '
|
| 905 |
+
f'class="bookmark-image">',
|
| 906 |
+
unsafe_allow_html=True
|
| 907 |
+
)
|
| 908 |
+
else:
|
| 909 |
+
# Extract image with minimal loading indication
|
| 910 |
+
img_base64 = extract_pdf_thumbnail(pdf_url, model, max_width=200, max_height=250)
|
| 911 |
+
|
| 912 |
+
if img_base64:
|
| 913 |
+
st.markdown(
|
| 914 |
+
f'<img src="data:image/png;base64,{img_base64}" '
|
| 915 |
+
f'style="width:100%; max-height:200px; object-fit:contain; cursor:pointer;" '
|
| 916 |
+
f'class="bookmark-image">',
|
| 917 |
+
unsafe_allow_html=True
|
| 918 |
+
)
|
| 919 |
+
else:
|
| 920 |
+
st.info("📄 No preview")
|
| 921 |
|
| 922 |
+
# Model name button
|
| 923 |
+
if st.button(f"{model}", key=f"select_model_{i}_{j}", use_container_width=True, type="secondary"):
|
| 924 |
+
st.session_state.selected_model = model
|
| 925 |
+
st.rerun()
|
| 926 |
+
|
| 927 |
+
# Product type caption
|
| 928 |
+
st.caption(get_product_type(model))
|
| 929 |
+
|
| 930 |
+
# Action buttons row
|
| 931 |
+
col_view, col_remove = st.columns(2)
|
| 932 |
+
with col_view:
|
| 933 |
+
if st.button("👁️ View", key=f"view_{i}_{j}", use_container_width=True):
|
| 934 |
+
st.session_state.selected_model = model
|
| 935 |
+
st.rerun()
|
| 936 |
+
with col_remove:
|
| 937 |
+
if st.button("❌", key=f"remove_img_{i}_{j}", use_container_width=True, type="secondary"):
|
| 938 |
+
st.session_state.bookmarked_models.remove(model)
|
| 939 |
+
st.rerun()
|
| 940 |
+
|
| 941 |
+
st.markdown('</div>', unsafe_allow_html=True)
|
| 942 |
|
| 943 |
+
# Export section - MOVED OUTSIDE THE IF/ELSE AND PROPERLY INDENTED
|
| 944 |
st.markdown("---")
|
| 945 |
export_col1, export_col2, export_col3 = st.columns(3)
|
| 946 |
|
|
|
|
| 986 |
st.stop()
|
| 987 |
|
| 988 |
# Bookmarks section
|
| 989 |
+
if st.session_state.bookmarked_models:
|
| 990 |
+
display_bookmarked_models()
|
| 991 |
+
else:
|
| 992 |
+
st.info("📌 No models bookmarked yet. Select models to create your custom list!")
|
| 993 |
|
| 994 |
# Main content area
|
| 995 |
col1, col2 = st.columns([1, 3])
|
|
|
|
| 1014 |
grouped_models[product_type] = []
|
| 1015 |
grouped_models[product_type].append(model)
|
| 1016 |
|
| 1017 |
+
# Create formatted options with empty first option for easy typing
|
| 1018 |
+
formatted_options = [''] # Empty first option
|
| 1019 |
for product_type in sorted(grouped_models.keys()):
|
| 1020 |
for model in sorted(grouped_models[product_type]):
|
| 1021 |
formatted_options.append(model)
|
| 1022 |
|
| 1023 |
+
# Search selectbox with clear typing experience
|
| 1024 |
+
if st.session_state.selected_model and st.session_state.selected_model in formatted_options:
|
| 1025 |
+
default_index = formatted_options.index(st.session_state.selected_model)
|
| 1026 |
+
else:
|
| 1027 |
+
default_index = 0
|
| 1028 |
+
|
| 1029 |
selected = st.selectbox(
|
| 1030 |
"Select or type a model number:",
|
| 1031 |
options=formatted_options,
|
| 1032 |
+
format_func=lambda x: format_model_option(x) if x else "↓ Click here and start typing model number...",
|
| 1033 |
key="model_search",
|
| 1034 |
+
index=default_index,
|
| 1035 |
+
help="Click and start typing to search models"
|
| 1036 |
)
|
| 1037 |
|
| 1038 |
if selected:
|
| 1039 |
st.session_state.selected_model = selected
|
| 1040 |
|
| 1041 |
# Display selected model
|
| 1042 |
+
if st.session_state.selected_model and st.session_state.selected_model != '':
|
| 1043 |
st.markdown("---")
|
| 1044 |
|
| 1045 |
+
model_data = get_model_data(st.session_state.selected_model)
|
| 1046 |
|
| 1047 |
if model_data:
|
| 1048 |
# Model header with bookmark
|
| 1049 |
col1, col2 = st.columns([4, 1])
|
| 1050 |
with col1:
|
| 1051 |
+
st.markdown(f"## {st.session_state.selected_model}")
|
| 1052 |
+
st.caption(f"Product Type: {get_product_type(st.session_state.selected_model)}")
|
| 1053 |
if model_data.get('quality'):
|
| 1054 |
quality_class = f"quality-{model_data['quality']}"
|
| 1055 |
st.markdown(f'<span class="quality-badge {quality_class}">Data Quality: {model_data["quality"].title()}</span>',
|
| 1056 |
unsafe_allow_html=True)
|
| 1057 |
|
| 1058 |
with col2:
|
| 1059 |
+
is_bookmarked = st.session_state.selected_model in st.session_state.bookmarked_models
|
| 1060 |
bookmark_label = "❌ Remove" if is_bookmarked else "📌 Bookmark"
|
| 1061 |
+
if st.button(bookmark_label, key=f"bookmark_{st.session_state.selected_model}", use_container_width=True):
|
| 1062 |
if is_bookmarked:
|
| 1063 |
+
st.session_state.bookmarked_models.remove(st.session_state.selected_model)
|
| 1064 |
st.success("Bookmark removed!")
|
| 1065 |
else:
|
| 1066 |
+
st.session_state.bookmarked_models.append(st.session_state.selected_model)
|
| 1067 |
+
st.success("Model bookmarked!")
|
|
|
|
|
|
|
|
|
|
| 1068 |
time.sleep(0.5)
|
| 1069 |
st.rerun()
|
| 1070 |
|
|
|
|
| 1079 |
with img_col:
|
| 1080 |
st.markdown("### Product Image")
|
| 1081 |
# Check if image is already cached
|
| 1082 |
+
cache_key = f"thumb_{st.session_state.selected_model}"
|
| 1083 |
img_base64 = st.session_state.product_images.get(cache_key)
|
| 1084 |
|
| 1085 |
if not img_base64:
|
| 1086 |
# Extract image if not cached
|
| 1087 |
with st.spinner("Loading product image..."):
|
| 1088 |
+
img_base64 = extract_pdf_thumbnail(pdf_url, st.session_state.selected_model, max_width=400, max_height=500)
|
| 1089 |
|
| 1090 |
if img_base64:
|
| 1091 |
st.markdown(
|
|
|
|
| 1205 |
|
| 1206 |
with action_col1:
|
| 1207 |
# PDF toggle button
|
| 1208 |
+
pdf_key = f'show_pdf_{st.session_state.selected_model}'
|
| 1209 |
button_text = "📄 Hide PDF" if st.session_state.get(pdf_key, False) else "📄 View PDF"
|
| 1210 |
+
if st.button(button_text, use_container_width=True, key=f"view_pdf_{st.session_state.selected_model}"):
|
| 1211 |
st.session_state[pdf_key] = not st.session_state.get(pdf_key, False)
|
| 1212 |
|
| 1213 |
with action_col2:
|
| 1214 |
# Google search button
|
| 1215 |
+
google_search = f"https://www.google.com/search?q=turboair+{st.session_state.selected_model.replace(' ', '+')}+price"
|
| 1216 |
st.markdown(f'''
|
| 1217 |
<a href="{google_search}" target="_blank" style="text-decoration: none;">
|
| 1218 |
<button class="google-search-button">
|
|
|
|
| 1222 |
''', unsafe_allow_html=True)
|
| 1223 |
|
| 1224 |
# Display PDF preview if requested
|
| 1225 |
+
pdf_key = f'show_pdf_{st.session_state.selected_model}'
|
| 1226 |
if st.session_state.get(pdf_key, False):
|
| 1227 |
st.markdown("---")
|
| 1228 |
st.markdown("### 📄 PDF Specification Sheet")
|
| 1229 |
|
| 1230 |
if 'file_path' in model_data and model_data['file_path']:
|
| 1231 |
+
display_pdf_preview(model_data['file_path'], st.session_state.selected_model)
|
| 1232 |
else:
|
| 1233 |
st.error("❌ No PDF file path found for this model.")
|
| 1234 |
st.info("PDF file may not be available.")
|
|
|
|
| 1237 |
st.markdown("---")
|
| 1238 |
st.caption(f"Source: {model_data['filename']}")
|
| 1239 |
else:
|
| 1240 |
+
st.error(f"No data found for model {st.session_state.selected_model}")
|
| 1241 |
|
| 1242 |
# Stats at bottom
|
| 1243 |
st.markdown("---")
|