import streamlit as st import pandas as pd import numpy as np import os # Configure the page to be mobile-friendly st.set_page_config(layout="centered", page_title="Restaurant Data Viewer") # URLs for the logos MAIN_LOGO_URL = "https://islamictrusthk.org/assets/images/top-logo.png" SIDEBAR_LOGO_URL = "https://bot.islamictrusthk.org/assets/content_files/20240606095159123011.png" # Print the versions of the packages st.write(f"Streamlit version: {st.__version__}") st.write(f"Pandas version: {pd.__version__}") st.write(f"Numpy version: {np.__version__}") # Inject custom CSS for better mobile compatibility st.markdown( """ """, unsafe_allow_html=True, ) # Directory to save uploaded files UPLOAD_DIR = "uploaded_files" os.makedirs(UPLOAD_DIR, exist_ok=True) # Function to load data @st.cache_data def load_data(file_path): df = pd.read_excel(file_path) df.fillna("Not Available", inplace=True) return df # Function to convert dataframe to CSV def convert_df_to_csv(df): return df.to_csv(index=False).encode('utf-8') # Function to format date def format_date_column(df, column): df[column] = pd.to_datetime(df[column], errors='coerce').dt.date return df # Function to verify required columns exist def verify_columns(df, required_columns): missing_columns = [col for col in required_columns if col not in df.columns] return missing_columns # Function to display data in tiles def display_tiles(df, cols): for i, (_, row) in enumerate(df.iterrows()): col = cols[i % len(cols)] with col: st.markdown(f"**Name:** {row['Name']}") st.markdown(f"**Cuisine:** {row['Cuisine']}") st.markdown(f"**Location:** {row['Location']}") st.markdown(f"**Restaurant Type:** {row['Restaurant Type']}") st.markdown(f"**Expiry Date:** {row['Expiry Date']}") st.markdown(f"**Website:** {row['Website']}") st.markdown(f"**Directions:** {row['Directions']}") st.markdown("---") # Initialize session state if 'df' not in st.session_state: st.session_state.df = None if 'authenticated' not in st.session_state: st.session_state.authenticated = False # List of valid usernames and passwords user_credentials = { 'user1': 'password1', 'user2': 'password2' } # Authentication function def authenticate(username, password): if username in user_credentials and user_credentials[username] == password: return True return False # Function to trigger rerun def trigger_rerun(): st.experimental_rerun() # Authentication block if not st.session_state.authenticated: st.title("Login") username = st.text_input("Username") password = st.text_input("Password", type="password") if st.button("Login"): if authenticate(username, password): st.session_state.authenticated = True trigger_rerun() else: st.error("Invalid username or password") else: st.write("User authenticated successfully") st.image(MAIN_LOGO_URL, use_column_width=True) st.title("Restaurant Data Viewer") # File upload logic with st.sidebar: st.image(SIDEBAR_LOGO_URL, use_column_width=True) st.title("File Management") # File uploader uploaded_file = st.file_uploader("Choose an Excel file", type="xlsx") if uploaded_file: try: # Save the uploaded file file_path = os.path.join(UPLOAD_DIR, uploaded_file.name) with open(file_path, "wb") as f: f.write(uploaded_file.getbuffer()) st.success(f"File '{uploaded_file.name}' uploaded successfully.") df = load_data(file_path) st.session_state.df = df except Exception as e: st.error(f"An error occurred: {e}") # Manage existing files st.subheader("Manage Existing Files") existing_files = [f for f in os.listdir(UPLOAD_DIR) if f.endswith(".xlsx")] if existing_files: selected_file = st.selectbox("Select a file to view or delete", existing_files) if st.button("Delete Selected File"): os.remove(os.path.join(UPLOAD_DIR, selected_file)) st.success(f"File '{selected_file}' deleted successfully.") trigger_rerun() if st.button("Load Selected File") or st.session_state.df is None: try: file_path = os.path.join(UPLOAD_DIR, selected_file) df = load_data(file_path) st.session_state.df = df except Exception as e: st.error(f"An error occurred: {e}") else: st.info("No files available.") # Display and filter the loaded dataframe if available if st.session_state.df is not None: df = st.session_state.df # Define required columns required_columns = ['Name', 'Cuisine', 'Location', 'Restaurant Type', 'Expiry Date', 'Website', 'Directions'] # Verify required columns missing_columns = verify_columns(df, required_columns) if missing_columns: st.error(f"The following required columns are missing from the uploaded file: {', '.join(missing_columns)}") else: # Format the expiry date column to remove time df = format_date_column(df, 'Expiry Date') # Display the dataframe st.subheader("Loaded Data") st.dataframe(df) # Filter functionality st.subheader("Filters") # Use columns for a more responsive layout col1, col2, col3, col4, col5 = st.columns(5) with col1: # Filter by Name name_filter = st.text_input("Name contains") with col2: # Filter by Cuisine cuisine_filter = st.multiselect("Cuisine", sorted(df['Cuisine'].drop_duplicates().unique())) with col3: # Filter by Location location_filter = st.multiselect("Location", df['Location'].drop_duplicates()) with col4: # Filter by Restaurant Type restaurant_type_filter = st.multiselect("Restaurant Type", df['Restaurant Type'].drop_duplicates()) with col5: # Filter by Expiry Date expiry_date_filter = st.date_input("Expiry Date", []) # Apply filters filtered_df = df.copy() if name_filter: filtered_df = filtered_df[filtered_df['Name'].str.contains(name_filter, case=False, na=False)] if cuisine_filter: filtered_df = filtered_df[filtered_df['Cuisine'].isin(cuisine_filter)] if location_filter: filtered_df = filtered_df[filtered_df['Location'].isin(location_filter)] if restaurant_type_filter: filtered_df = filtered_df[filtered_df['Restaurant Type'].isin(restaurant_type_filter)] if expiry_date_filter: if len(expiry_date_filter) == 1: filtered_df = filtered_df[filtered_df['Expiry Date'] == expiry_date_filter[0]] elif len(expiry_date_filter) == 2: start_date, end_date = expiry_date_filter filtered_df = filtered_df[(filtered_df['Expiry Date'] >= start_date) & (filtered_df['Expiry Date'] <= end_date)] # Display the filtered dataframe in a tile format st.subheader("Filtered Data") if not filtered_df.empty: num_cols = 3 # Number of columns for the tile layout cols = st.columns(num_cols) display_tiles(filtered_df, cols) # Download button for filtered data csv = convert_df_to_csv(filtered_df) st.download_button( label="Download filtered data as CSV", data=csv, file_name='filtered_data.csv', mime='text/csv', ) else: st.info("No data matches the filter criteria.")