| import gradio as gr |
| import pandas as pd |
|
|
| |
| custom_css = """ |
| footer {visibility: hidden} |
| .app-title { |
| text-align: center; |
| color: #2F4F4F; |
| font-size: 2em !important; |
| font-weight: 500; |
| margin-bottom: 0.5em !important; |
| text-transform: lowercase; |
| } |
| .logo-container { |
| text-align: center; |
| margin-bottom: 1em; |
| } |
| .logo-img { |
| width: 200px; |
| height: auto; |
| margin: 0 auto; |
| display: block; |
| } |
| .filter-section { |
| background: #f8f9fa; |
| padding: 20px; |
| border-radius: 12px; |
| margin-bottom: 2em; |
| box-shadow: 0 2px 8px rgba(0,0,0,0.1); |
| } |
| .results-section { |
| margin-top: 2em; |
| } |
| .dataframe { |
| border-radius: 8px !important; |
| overflow: hidden !important; |
| box-shadow: 0 4px 6px rgba(0,0,0,0.05) !important; |
| } |
| .button-primary { |
| background: linear-gradient(45deg, #4B0082, #6A5ACD) !important; |
| color: white !important; |
| border: none !important; |
| padding: 12px 24px !important; |
| border-radius: 8px !important; |
| transition: transform 0.2s ease !important; |
| } |
| .button-primary:hover { |
| transform: translateY(-1px); |
| } |
| .button-secondary { |
| background: linear-gradient(45deg, #228B22, #32CD32) !important; |
| border: none !important; |
| } |
| .empty-state { |
| text-align: center; |
| padding: 40px 20px; |
| background: #f8f9fa; |
| border-radius: 12px; |
| margin: 2em 0; |
| color: #666; |
| } |
| .footer-text { |
| text-align: center; |
| color: #666; |
| margin-top: 2em !important; |
| font-style: italic; |
| } |
| """ |
|
|
| |
| data = pd.read_excel('Indigenous Business Directory by Gov of Canada.xlsx') |
|
|
| |
| service_types = ["All", "Electrical", "Mechanical", "HVAC", "Sprinkler", "Plumbing", |
| "Demo", "Paint", "Millwork", "Flooring", "Drywall/Framing", |
| "Concrete/Scanning", "Excavation", "Steel"] |
|
|
| def update_city_options(province): |
| if not province: |
| return gr.Dropdown(choices=[], label="Select City", multiselect=True) |
| cities = ["All"] + data[data['Province'] == province]['City'].unique().tolist() |
| return gr.Dropdown(choices=cities, label="Select City", multiselect=True) |
|
|
| def search_directory(province, cities, service_types): |
| if not province: |
| return pd.DataFrame(columns=["Company Name", "Mail", "Website", "Phone", "Fax", "Address"]) |
|
|
| filtered_data = data[data['Province'] == province] |
|
|
| if cities and "All" not in cities: |
| filtered_data = filtered_data[filtered_data['City'].isin(cities)] |
|
|
| if service_types and "All" not in service_types: |
| service_filter = filtered_data['Company Description'].apply( |
| lambda desc: any(service.lower() in str(desc).lower() for service in service_types) |
| ) |
| filtered_data = filtered_data[service_filter] |
|
|
| if filtered_data.empty: |
| return pd.DataFrame(columns=["Company Name", "Mail", "Website", "Phone", "Fax", "Address"]) |
|
|
| filtered_data['Address'] = ( |
| filtered_data['Address 1'].astype(str) + ", " + |
| filtered_data['City'].astype(str) + ", " + |
| filtered_data['Province'].astype(str) |
| ) |
|
|
| result_df = filtered_data.rename( |
| columns={ |
| 'Company Operating Name': 'Company Name', |
| 'Email': 'Mail', |
| 'URL': 'Website', |
| 'Phone Number': 'Phone', |
| 'Fax Number': 'Fax' |
| } |
| )[['Company Name', 'Mail', 'Website', 'Phone', 'Fax', 'Address']] |
|
|
| return result_df |
|
|
| def export_results_to_excel(province, cities, service_types): |
| results_df = search_directory(province, cities, service_types) |
| if results_df.empty: |
| raise gr.Error("No results to export!") |
| |
| cities = cities or [] |
| service_types = service_types or [] |
| |
| filename = f"Search_Results_{province}_{'_'.join(map(str, cities))}_{'_'.join(map(str, service_types))}.xlsx" |
| results_df.to_excel(filename, index=False) |
| return filename |
|
|
| with gr.Blocks( |
| theme=gr.themes.Default( |
| primary_hue="indigo", |
| secondary_hue="emerald", |
| neutral_hue="slate", |
| radius_size="md", |
| text_size="md" |
| ), |
| css=custom_css |
| ) as app: |
| |
| |
| gr.HTML(""" |
| <div class="logo-container"> |
| <img src="https://i.ibb.co/zTtwDGMM/HKC-updatedlogo-original.png" class="logo-img" alt="Logo"> |
| </div> |
| """) |
| gr.Markdown("<div class='app-title'>Indigenous business directory</div>") |
| gr.Markdown( |
| """<div class='app-description'> |
| Discover and connect with Indigenous-owned businesses across Canada |
| </div>""" |
| ) |
|
|
| |
| with gr.Row(variant="panel", elem_classes="filter-section"): |
| with gr.Column(): |
| province_input = gr.Dropdown( |
| label="Select Province", |
| choices=[""] + sorted(data['Province'].unique()), |
| interactive=True, |
| allow_custom_value=False |
| ) |
| city_input = gr.Dropdown( |
| label="Select City", |
| choices=[], |
| multiselect=True, |
| interactive=True |
| ) |
| service_input = gr.Dropdown( |
| label="Select Service Type", |
| choices=service_types, |
| multiselect=True, |
| interactive=True |
| ) |
|
|
| |
| with gr.Row(): |
| search_btn = gr.Button( |
| "🔍 Search Businesses", |
| variant="primary", |
| elem_classes="button-primary" |
| ) |
| export_btn = gr.Button( |
| "📤 Export Results", |
| variant="secondary", |
| elem_classes="button-secondary" |
| ) |
|
|
| |
| with gr.Column(elem_classes="results-section"): |
| gr.Markdown("### Search Results") |
| output = gr.Dataframe( |
| headers=["Company Name", "Mail", "Website", "Phone", "Fax", "Address"], |
| datatype=["str", "str", "str", "str", "str", "str"], |
| interactive=False, |
| row_count=(10, "paginated"), |
| wrap=True, |
| elem_id="results-table" |
| ) |
|
|
| |
| empty_state = gr.HTML( |
| """<div class='empty-state'> |
| <h3>No results found</h3> |
| <p>Try adjusting your filters or search criteria</p> |
| </div>""", |
| visible=False |
| ) |
|
|
| |
| gr.Markdown("---") |
| gr.Markdown( |
| """<div class='footer-text'> |
| 🇨🇦 Proudly supporting Indigenous businesses in Canada |
| </div>""" |
| ) |
|
|
| |
| province_input.change( |
| fn=update_city_options, |
| inputs=province_input, |
| outputs=city_input |
| ) |
|
|
| def toggle_empty_state(results): |
| return gr.HTML.update(visible=results.empty) |
|
|
| search_btn.click( |
| fn=search_directory, |
| inputs=[province_input, city_input, service_input], |
| outputs=output |
| ).then( |
| fn=toggle_empty_state, |
| inputs=output, |
| outputs=empty_state |
| ) |
|
|
| export_output = gr.File(label="Download Exported File") |
|
|
| export_btn.click( |
| fn=export_results_to_excel, |
| inputs=[province_input, city_input, service_input], |
| outputs=export_output |
| ) |
|
|
| if __name__ == "__main__": |
| app.launch() |
|
|