import pandas as pd import gspread import gradio as gr from datetime import datetime, timedelta from oauth2client.service_account import ServiceAccountCredentials # ------------------ AUTH ------------------ VALID_USERS = { "andrew@lortechnologies.com": "Pass.123", "donovanm@bid4cars.co.za": "Pass.123", "grant@bid4cars.co.za": "Pass.123", "phonnie@c2group.co.za": "Pass.123" } # ------------------ GOOGLE SHEET SETUP ------------------ scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"] creds = ServiceAccountCredentials.from_json_keyfile_name("deep-mile-461309-t8-0e90103411e0.json", scope) client = gspread.authorize(creds) sheet_url = "https://docs.google.com/spreadsheets/d/1if4KoVQvw5ZbhknfdZbzMkcTiPfsD6bz9V3a1th-bwQ" def load_sheet(sheet_name): sheet = client.open_by_url(sheet_url).worksheet(sheet_name) df = pd.DataFrame(sheet.get_all_records()) return df # ------------------ WEEK HELPERS ------------------ def get_current_week_range(): today = datetime.today() start = today - timedelta(days=today.weekday()) end = start + timedelta(days=6) return start.date(), end.date() # ------------------ CALLS & APPOINTMENTS REPORT ------------------ def filter_by_date_range(sheet_name, start_date, end_date): df = load_sheet(sheet_name) df['Date'] = pd.to_datetime(df['Date'], errors='coerce').dt.date return df[(df['Date'] >= start_date) & (df['Date'] <= end_date)] # ------------------ APPOINTED LEADS ------------------ def appointed_leads_table(): df = load_sheet("AllocatedLeads") grouped = df.groupby('Rep')['Customer Name'].apply(list).reset_index() return grouped # ------------------ LIVE SHEET SEARCH ------------------ def search_table(sheet_name, field, keyword): df = load_sheet(sheet_name) if field not in df.columns: return pd.DataFrame(), "Field not found." results = df[df[field].astype(str).str.contains(keyword, case=False, na=False)] return results, f"Found {len(results)} results." # ------------------ USER TARGET COMPARISON ------------------ def generate_user_metrics(): users_df = load_sheet("Users") calls_df = load_sheet("Calls") appt_df = load_sheet("Appointments") calls_df['Date'] = pd.to_datetime(calls_df['Date'], errors='coerce').dt.date appt_df['Date'] = pd.to_datetime(appt_df['Date'], errors='coerce').dt.date start, end = get_current_week_range() week_calls = calls_df[(calls_df['Date'] >= start) & (calls_df['Date'] <= end)] week_appt = appt_df[(appt_df['Date'] >= start) & (appt_df['Date'] <= end)] call_count = week_calls.groupby("Rep Name").size().reset_index(name="Calls This Week") appt_count = week_appt.groupby("Rep Name").size().reset_index(name="Appointments This Week") merged = users_df.merge(call_count, how='left', left_on='Name', right_on='Rep Name') merged = merged.merge(appt_count, how='left', left_on='Name', right_on='Rep Name') merged = merged.fillna(0) return merged[['Name', 'Weekly Target', 'Calls This Week', 'Appointments This Week']] # ------------------ GRADIO UI ------------------ with gr.Blocks() as app: with gr.Row(): with gr.Column(visible=True) as login_ui: gr.Markdown("## Login Required") email = gr.Textbox(label="Email") password = gr.Textbox(label="Password", type="password") login_btn = gr.Button("Login") login_msg = gr.Markdown() with gr.Column(visible=False) as main_ui: gr.Markdown("## Graffiti Admin Dashboard") with gr.Tab("Calls Report"): week_start, week_end = get_current_week_range() calls_table = gr.Dataframe() week_btn = gr.Button("View This Week's Calls") week_btn.click(lambda: filter_by_date_range("Calls", week_start, week_end), outputs=calls_table) with gr.Tab("Appointments Report"): appt_table = gr.Dataframe() appt_btn = gr.Button("View This Week's Appointments") appt_btn.click(lambda: filter_by_date_range("Appointments", week_start, week_end), outputs=appt_table) with gr.Tab("Appointed Leads"): leads_output = gr.Dataframe() leads_btn = gr.Button("View Appointed Leads") leads_btn.click(fn=appointed_leads_table, outputs=leads_output) with gr.Tab("Query Live Sheets"): sheet_choice = gr.Dropdown(choices=["LiveQuotes", "LiveCustomer", "LiveJobBags"], label="Select Sheet") field_input = gr.Textbox(label="Field (column name)") keyword_input = gr.Textbox(label="Keyword to search") query_btn = gr.Button("Search") query_table = gr.Dataframe() query_info = gr.Markdown() query_btn.click(fn=search_table, inputs=[sheet_choice, field_input, keyword_input], outputs=[query_table, query_info]) with gr.Tab("Rep vs Targets"): metric_table = gr.Dataframe() metric_btn = gr.Button("View Weekly Targets") metric_btn.click(fn=generate_user_metrics, outputs=metric_table) def do_login(user, pw): if VALID_USERS.get(user) == pw: return gr.update(visible=False), gr.update(visible=True), "" else: return gr.update(visible=True), gr.update(visible=False), "❌ Invalid email or password." login_btn.click(fn=do_login, inputs=[email, password], outputs=[login_ui, main_ui, login_msg]) app.launch(share=True)