Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -13,27 +13,24 @@ VALID_USERS = {
|
|
| 13 |
|
| 14 |
# ------------------ GOOGLE SHEET SETUP ------------------
|
| 15 |
scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]
|
| 16 |
-
creds = ServiceAccountCredentials.from_json_keyfile_name("
|
| 17 |
client = gspread.authorize(creds)
|
| 18 |
-
sheet_url = "https://docs.google.com/spreadsheets/d/
|
| 19 |
|
| 20 |
# ------------------ DATA REFRESH FUNCTION ------------------
|
| 21 |
def refresh_data():
|
| 22 |
-
sheet = client.open_by_url(sheet_url).worksheet("
|
| 23 |
data = sheet.get_all_records()
|
| 24 |
df = pd.DataFrame(data)
|
| 25 |
|
| 26 |
-
|
| 27 |
-
df['
|
| 28 |
-
df['
|
| 29 |
-
df['Time'] = df['Timestamp'].dt.time
|
| 30 |
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
df['
|
| 34 |
-
df['Longitude'] = pd.to_numeric(location_split[1], errors='coerce')
|
| 35 |
|
| 36 |
-
# Data cleaning
|
| 37 |
df = df.dropna(subset=['Date', 'Rep Name', 'Latitude', 'Longitude'])
|
| 38 |
df = df[(df['Latitude'] != 0) & (df['Longitude'] != 0)]
|
| 39 |
df = df.sort_values(by=['Rep Name', 'Timestamp'])
|
|
@@ -42,7 +39,7 @@ def refresh_data():
|
|
| 42 |
|
| 43 |
return df
|
| 44 |
|
| 45 |
-
# ------------------
|
| 46 |
def generate_summary(date_str):
|
| 47 |
df = refresh_data()
|
| 48 |
all_reps = sorted(df['Rep Name'].dropna().unique())
|
|
@@ -58,6 +55,7 @@ def get_reps(date_str):
|
|
| 58 |
reps = df[df['Date'] == date_str]['Rep Name'].dropna().unique()
|
| 59 |
return gr.update(choices=sorted(reps))
|
| 60 |
|
|
|
|
| 61 |
def show_map(date_str, rep):
|
| 62 |
df = refresh_data()
|
| 63 |
subset = df[(df['Date'] == date_str) & (df['Rep Name'] == rep)]
|
|
@@ -72,7 +70,7 @@ def show_map(date_str, rep):
|
|
| 72 |
fig = px.line_mapbox(
|
| 73 |
subset,
|
| 74 |
lat="Latitude", lon="Longitude",
|
| 75 |
-
hover_name="Dealership
|
| 76 |
hover_data={"Time": True, "Time Diff (min)": True, "Visit Order": True},
|
| 77 |
height=700,
|
| 78 |
zoom=13,
|
|
@@ -83,7 +81,7 @@ def show_map(date_str, rep):
|
|
| 83 |
subset,
|
| 84 |
lat="Latitude", lon="Longitude",
|
| 85 |
color="Visit Order",
|
| 86 |
-
hover_name="Dealership
|
| 87 |
hover_data=["Time", "Time Diff (min)"],
|
| 88 |
color_continuous_scale="Bluered"
|
| 89 |
)
|
|
@@ -102,14 +100,14 @@ def show_map(date_str, rep):
|
|
| 102 |
fig.update_layout(mapbox_style="open-street-map", title=f"๐ {rep}'s Route on {date_str}")
|
| 103 |
|
| 104 |
table = subset[[
|
| 105 |
-
'Visit Order', 'Dealership
|
| 106 |
-
'Type
|
| 107 |
]].rename(columns={
|
| 108 |
-
'Dealership
|
| 109 |
'Time': '๐ Time',
|
| 110 |
'Time Diff (min)': 'โฑ๏ธ Time Spent',
|
| 111 |
-
'Type
|
| 112 |
-
'
|
| 113 |
})
|
| 114 |
|
| 115 |
total_time = round(table['โฑ๏ธ Time Spent'].sum(), 2)
|
|
@@ -118,13 +116,13 @@ def show_map(date_str, rep):
|
|
| 118 |
'๐งญ Dealer': f"๐งฎ Total Time: {total_time} min",
|
| 119 |
'๐ Time': '',
|
| 120 |
'โฑ๏ธ Time Spent': '',
|
| 121 |
-
'๐
|
| 122 |
-
'๐ผ
|
| 123 |
}])
|
| 124 |
table = pd.concat([table, summary_row], ignore_index=True)
|
| 125 |
return table, fig
|
| 126 |
|
| 127 |
-
# ------------------ GRADIO
|
| 128 |
with gr.Blocks() as app:
|
| 129 |
with gr.Row():
|
| 130 |
with gr.Column(visible=True) as login_ui:
|
|
@@ -135,7 +133,7 @@ with gr.Blocks() as app:
|
|
| 135 |
login_msg = gr.Markdown("")
|
| 136 |
|
| 137 |
with gr.Column(visible=False) as main_ui:
|
| 138 |
-
gr.Markdown("## ๐๏ธ Carfind Rep Tracker")
|
| 139 |
df_initial = refresh_data()
|
| 140 |
unique_dates = sorted(df_initial['Date'].unique(), reverse=True)
|
| 141 |
|
|
|
|
| 13 |
|
| 14 |
# ------------------ GOOGLE SHEET SETUP ------------------
|
| 15 |
scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]
|
| 16 |
+
creds = ServiceAccountCredentials.from_json_keyfile_name("bid4carsappsheetdash.json", scope)
|
| 17 |
client = gspread.authorize(creds)
|
| 18 |
+
sheet_url = "https://docs.google.com/spreadsheets/d/1eUXhcfWd3jtNmZC6U_Dr2F7obQcK81I4YrK-fKEbkyU"
|
| 19 |
|
| 20 |
# ------------------ DATA REFRESH FUNCTION ------------------
|
| 21 |
def refresh_data():
|
| 22 |
+
sheet = client.open_by_url(sheet_url).worksheet("Calls2")
|
| 23 |
data = sheet.get_all_records()
|
| 24 |
df = pd.DataFrame(data)
|
| 25 |
|
| 26 |
+
df['Timestamp'] = pd.to_datetime(df['Date'].astype(str) + " " + df['Time'].astype(str), errors='coerce')
|
| 27 |
+
df['Date'] = pd.to_datetime(df['Date'], errors='coerce').dt.date.astype(str)
|
| 28 |
+
df['Time'] = pd.to_datetime(df['Time'], errors='coerce').dt.time
|
|
|
|
| 29 |
|
| 30 |
+
gps_split = df['GPS'].astype(str).str.split(',', expand=True)
|
| 31 |
+
df['Latitude'] = pd.to_numeric(gps_split[0], errors='coerce')
|
| 32 |
+
df['Longitude'] = pd.to_numeric(gps_split[1], errors='coerce')
|
|
|
|
| 33 |
|
|
|
|
| 34 |
df = df.dropna(subset=['Date', 'Rep Name', 'Latitude', 'Longitude'])
|
| 35 |
df = df[(df['Latitude'] != 0) & (df['Longitude'] != 0)]
|
| 36 |
df = df.sort_values(by=['Rep Name', 'Timestamp'])
|
|
|
|
| 39 |
|
| 40 |
return df
|
| 41 |
|
| 42 |
+
# ------------------ SUMMARY GENERATION ------------------
|
| 43 |
def generate_summary(date_str):
|
| 44 |
df = refresh_data()
|
| 45 |
all_reps = sorted(df['Rep Name'].dropna().unique())
|
|
|
|
| 55 |
reps = df[df['Date'] == date_str]['Rep Name'].dropna().unique()
|
| 56 |
return gr.update(choices=sorted(reps))
|
| 57 |
|
| 58 |
+
# ------------------ MAP & TABLE VIEW ------------------
|
| 59 |
def show_map(date_str, rep):
|
| 60 |
df = refresh_data()
|
| 61 |
subset = df[(df['Date'] == date_str) & (df['Rep Name'] == rep)]
|
|
|
|
| 70 |
fig = px.line_mapbox(
|
| 71 |
subset,
|
| 72 |
lat="Latitude", lon="Longitude",
|
| 73 |
+
hover_name="Dealership",
|
| 74 |
hover_data={"Time": True, "Time Diff (min)": True, "Visit Order": True},
|
| 75 |
height=700,
|
| 76 |
zoom=13,
|
|
|
|
| 81 |
subset,
|
| 82 |
lat="Latitude", lon="Longitude",
|
| 83 |
color="Visit Order",
|
| 84 |
+
hover_name="Dealership",
|
| 85 |
hover_data=["Time", "Time Diff (min)"],
|
| 86 |
color_continuous_scale="Bluered"
|
| 87 |
)
|
|
|
|
| 100 |
fig.update_layout(mapbox_style="open-street-map", title=f"๐ {rep}'s Route on {date_str}")
|
| 101 |
|
| 102 |
table = subset[[
|
| 103 |
+
'Visit Order', 'Dealership', 'Time', 'Time Diff (min)',
|
| 104 |
+
'Interaction Type', 'Product'
|
| 105 |
]].rename(columns={
|
| 106 |
+
'Dealership': '๐งญ Dealer',
|
| 107 |
'Time': '๐ Time',
|
| 108 |
'Time Diff (min)': 'โฑ๏ธ Time Spent',
|
| 109 |
+
'Interaction Type': '๐ Interaction',
|
| 110 |
+
'Product': '๐ผ Product Type'
|
| 111 |
})
|
| 112 |
|
| 113 |
total_time = round(table['โฑ๏ธ Time Spent'].sum(), 2)
|
|
|
|
| 116 |
'๐งญ Dealer': f"๐งฎ Total Time: {total_time} min",
|
| 117 |
'๐ Time': '',
|
| 118 |
'โฑ๏ธ Time Spent': '',
|
| 119 |
+
'๐ Interaction': '',
|
| 120 |
+
'๐ผ Product Type': ''
|
| 121 |
}])
|
| 122 |
table = pd.concat([table, summary_row], ignore_index=True)
|
| 123 |
return table, fig
|
| 124 |
|
| 125 |
+
# ------------------ GRADIO UI ------------------
|
| 126 |
with gr.Blocks() as app:
|
| 127 |
with gr.Row():
|
| 128 |
with gr.Column(visible=True) as login_ui:
|
|
|
|
| 133 |
login_msg = gr.Markdown("")
|
| 134 |
|
| 135 |
with gr.Column(visible=False) as main_ui:
|
| 136 |
+
gr.Markdown("## ๐๏ธ Carfind Rep Tracker (Calls2 Sheet)")
|
| 137 |
df_initial = refresh_data()
|
| 138 |
unique_dates = sorted(df_initial['Date'].unique(), reverse=True)
|
| 139 |
|