# Import Dependencies import tkinter as tk from tkinter import * from tkinter import filedialog import customtkinter import pandas as pd import os from PIL import Image from main import run_appraiser, run_tax_recorder customtkinter.set_appearance_mode("Dark") # Modes: "System" (standard), "Dark", "Light" customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue" class App(customtkinter.CTk): def __init__(self): super().__init__() # configure window self.title("Nexval Title Search Bot") self.geometry(f"{1100}x{580}") image_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "test_images") self.logo_image = customtkinter.CTkImage(Image.open(os.path.join(image_path, "NEX_WEB_LOGO_NEXVAL.png")), size=(60, 26)) # create sidebar frame with widgets self.sidebar_frame = customtkinter.CTkFrame(self, width=140, corner_radius=0) self.sidebar_frame.grid(row=0, column=0, rowspan=8, sticky="nsew") # Increased rowspan for spacing self.sidebar_frame.grid_rowconfigure((0, 1, 2, 3, 4, 5, 6, 7), weight=1) # All rows have equal weight # Application Title self.logo_label = customtkinter.CTkLabel(self.sidebar_frame, text="Nexval Title Search Bot", font=customtkinter.CTkFont(size=20, weight="bold")) self.logo_label.grid(row=0, column=0, padx=20, pady=(20, 10), sticky="ew") # Dropdown for selecting states self.state_label = customtkinter.CTkLabel(self.sidebar_frame, text="Select State:", anchor="w") self.state_label.grid(row=2, column=0, padx=20, pady=(0, 10), sticky="ew") self.state_options = ["Florida"] self.state_var = StringVar() self.state_dropdown = customtkinter.CTkOptionMenu(self.sidebar_frame, values=self.state_options) self.state_dropdown.grid(row=3, column=0, padx=20, pady=(0, 10), sticky="ew") # Dropdown for selecting counties self.county_label = customtkinter.CTkLabel(self.sidebar_frame, text="Select County:", anchor="w") self.county_label.grid(row=5, column=0, padx=20, pady=(0, 10), sticky="ew") self.county_options = ["Broward"] self.county_var = StringVar() self.county_dropdown = customtkinter.CTkOptionMenu(self.sidebar_frame, values=self.county_options) self.county_dropdown.grid(row=6, column=0, padx=20, pady=(0, 10), sticky="ew") # Radio for selecting web sources self.county_label = customtkinter.CTkLabel(self.sidebar_frame, text="Select Web Source:", anchor="w") self.county_label.grid(row=7, column=0, padx=20, pady=(0, 10), sticky="ew") self.county_options = ["Property Tax", "Code/Appraiser", "Permit", "Utility", "Clerk", "Special Assessments"] self.county_var = StringVar() self.county_dropdown = customtkinter.CTkComboBox(self.sidebar_frame, values=self.county_options) self.county_dropdown.grid(row=8, column=0, padx=20, pady=(0, 10), sticky="ew") # About Section self.about_label = customtkinter.CTkLabel(self.sidebar_frame, text="", anchor="w") self.about_label.grid(row=9, column=0, padx=20, pady=(10, 0), sticky="ew") self.about_text = """Nexval's Title search automation bot which can connect to different websites, navigate to relevant sections, input appropriate data and perform search, scraping/data collection, take screenshots. Additionally, organizations can communicate their business requirements through the rule-engine.""" self.about_textbox = customtkinter.CTkTextbox(self.sidebar_frame, width=20, height=170) self.about_textbox.insert("1.0", self.about_text) self.about_textbox.grid(row=10, column=0, padx=20, pady=(0, 10), sticky="ew") #self.grid_columnconfigure(0, weight=1) # Allow column 0 to expand horizontally # create tabview self.tabview = customtkinter.CTkTabview(self, height=100, width=950) self.tabview.grid(row=0, column=4, padx=(20, 0), pady=(20, 0), sticky="nsew") self.tabview.add("Single Data Ingest") self.tabview.add("Bulk Data Ingest") self.tabview.tab("Single Data Ingest").grid_columnconfigure(0, weight=1) # configure grid of individual tabs self.tabview.tab("Bulk Data Ingest").grid_columnconfigure(0, weight=1) # Single data section self.single_file_entry = customtkinter.CTkEntry(self.tabview.tab("Single Data Ingest"), width=250, height=10, placeholder_text="Enter Name/Address/Folio Number") # Adjust width as needed self.single_file_entry.grid(row=1, columnspan=2, padx=(20, 0), pady=(20, 20), sticky="nsew") self.file_submit = customtkinter.CTkButton(self.tabview.tab("Single Data Ingest"), text="Run", command=self.upload_file) self.file_submit.grid(row=1, column=3, pady=10, padx=20, sticky="e") # File Uploader Section (In the main section) self.file_upload_label = customtkinter.CTkLabel(self.tabview.tab("Bulk Data Ingest"), text="Upload File containing data:") self.file_upload_label.grid(row=2, column=0, pady=10, padx=20, sticky="w") self.file_upload_button = customtkinter.CTkButton(self.tabview.tab("Bulk Data Ingest"), text="Browse", command=self.upload_file) self.file_upload_button.grid(row=2, column=1, pady=10, padx=20, sticky="e") #self.file_upload_button = customtkinter.CTkButton(self.tabview.tab("Bulk Data Ingest"), text="Preview", command=self.preview_file_bulk) #self.file_upload_button.grid(row=2, column=2, pady=10, padx=20, sticky="e") self.file_upload_button = customtkinter.CTkButton(self.tabview.tab("Bulk Data Ingest"), text="Run", command=self.handle_option_button_click) self.file_upload_button.grid(row=2, column=3, pady=10, padx=20, sticky="e") # Create Data Viewer Section self.foliodata_frame = customtkinter.CTkFrame(self) self.foliodata_frame.grid(row=3, column=4, padx=(20, 20), pady=(20, 0), sticky="nsew") # Add the Results Viewer label self.results_viewer_label = customtkinter.CTkLabel(self.foliodata_frame, text="Results Viewer", anchor="w") self.results_viewer_label.grid(row=1, column=2, columnspan=2, padx=20, pady=(10, 10), sticky="ew") # Select Folio Numbers Section #self.select_folio_number = customtkinter.CTkLabel(self.foliodata_frame, text="Choose/Select Folio Numbers", anchor="w") #self.select_folio_number.grid(row=2, column=2, columnspan=2, padx=20, pady=(0, 10), sticky="ew") # T he folder path where folio numbers are stored results_folder_path = "Results" # Get a list of filenames in the Results folder #folio_files = os.listdir(results_folder_path) folio_folders = [folder for folder in os.listdir(results_folder_path) if os.path.isdir(os.path.join(results_folder_path, folder))] # Add a dropdown for selecting folio numbers self.folio_label = customtkinter.CTkLabel(self.foliodata_frame, text="Select Folio Number:", anchor="w") self.folio_label.grid(row=2, column=2, padx=20, pady=(0, 10), sticky="w") self.folio_var = StringVar() self.folio_dropdown = customtkinter.CTkComboBox(self.foliodata_frame, values=folio_folders) self.folio_dropdown.grid(row=2, column=3, padx=20, pady=(0, 10), sticky="w") #self.folio_options = [filename.split('.')[0] for filename in folio_files] #self.folio_var = StringVar() #self.folio_dropdown = customtkinter.CTkComboBox(self.foliodata_frame, values=self.folio_options) #self.folio_dropdown.grid(row=2, column=4, padx=20, pady=(0, 10), sticky="w") # Function to update subfolders dropdown def update_subfolders(): selected_folio = self.folio_var.get() if selected_folio: subfolders_path = os.path.join(results_folder_path, selected_folio) if os.path.exists(subfolders_path) and os.path.isdir(subfolders_path): subfolders = [folder for folder in os.listdir(subfolders_path) if os.path.isdir(os.path.join(subfolders_path, folder))] self.subfolder_dropdown.config(values=subfolders) print("Subfolders:", subfolders) # Print subfolders for debugging else: self.subfolder_dropdown.config(values=[]) # Add a dropdown for selecting subfolders self.subfolder_label = customtkinter.CTkLabel(self.foliodata_frame, text="Select Data Source:", anchor="w") self.subfolder_label.grid(row=2, column=4, padx=20, pady=(0, 10), sticky="w") self.subfolder_var = StringVar() self.subfolder_dropdown = customtkinter.CTkComboBox(self.foliodata_frame, values=[], state='readonly') self.subfolder_dropdown.grid(row=2, column=5, padx=20, pady=(0, 10), sticky="w") self.folio_var.trace_add('write', lambda *args: update_subfolders()) # Appearance Mode Label and Option Menu self.appearance_mode_label = customtkinter.CTkLabel(self.sidebar_frame, text="Appearance Mode:", anchor="w") self.appearance_mode_label.grid(row=11, column=0, padx=20, pady=(10, 0), sticky="ew") self.appearance_mode_optionemenu = customtkinter.CTkOptionMenu(self.sidebar_frame, values=["Light", "Dark", "System"], command=self.change_appearance_mode_event) self.appearance_mode_optionemenu.grid(row=12, column=0, padx=20, pady=(0, 10), sticky="ew") self.spacer_label1 = customtkinter.CTkLabel(self.sidebar_frame, text="", font=customtkinter.CTkFont(size=1)) self.spacer_label1.grid(row=13, column=0, padx=20, pady=5, sticky="ew") self.powered_by = customtkinter.CTkLabel(self.sidebar_frame, text="Powered by", image=self.logo_image, compound="right", anchor="w") self.powered_by.grid(row=14, column=0, padx=20, pady=(10, 0), sticky="ew") # configure grid layout (4x4) self.grid_columnconfigure(1, weight=1) self.grid_columnconfigure((1, 3), weight=0) def change_appearance_mode_event(self, new_appearance_mode: str): customtkinter.set_appearance_mode(new_appearance_mode) def upload_file(self): file_path = filedialog.askopenfilename( filetypes=[("CSV files", "*.csv")], # Specify CSV file type filter title="Select a CSV File" ) print("Selected file:", file_path) if file_path: try: df = pd.read_csv(file_path) self.uploaded_data = df data_text = customtkinter.CTkTextbox(self.tabview.tab("Bulk Data Ingest"), width=80, height=200, wrap="none") data_text.insert("1.0", df.head()) data_text.grid(row=3, column=0, columnspan=4, padx=20, pady=10, sticky="nsew") except Exception as e: print("Error:", e) def handle_option_button_click(self): # This method will handle the click event of the option buttons if hasattr(self, 'uploaded_data'): data = self.uploaded_data['address_key'].tolist() # Use the uploaded data for address_key in data: run_appraiser(address_key) # Run appraiser for each key run_tax_recorder(address_key) # Run tax recorder for each key else: print("Please upload a CSV file first.") if __name__ == "__main__": app = App() app.mainloop()