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 |
|