IAMTFRMZA commited on
Commit
05bbd5c
Β·
verified Β·
1 Parent(s): 60870ef

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +97 -7
app.py CHANGED
@@ -24,11 +24,6 @@ def normalize_columns(cols):
24
  return [c.strip().title() for c in cols]
25
 
26
  def load_sheet_df(name):
27
- """
28
- Load a sheet into a DataFrame without confusing duplicates in
29
- the header row. We fetch all values, dedupe the first row,
30
- then build a DataFrame.
31
- """
32
  ws = client.open_by_url(SHEET_URL).worksheet(name)
33
  data = ws.get_all_values()
34
  if not data:
@@ -131,7 +126,6 @@ def compute_insights():
131
  # -------------------- USER MANAGEMENT --------------------
132
  def load_users():
133
  df = load_sheet_df("Users")
134
- # select & rename your columns as needed
135
  want = [
136
  "Id", "Email", "Name", "Business", "Role",
137
  "Daily Phone Call Target", "Daily Phone Appointment Target",
@@ -148,9 +142,66 @@ def load_users():
148
  def save_users(df):
149
  ws = client.open_by_url(SHEET_URL).worksheet("Users")
150
  ws.clear()
151
- set_with_dataframe(ws, df) # writes headers + data
152
  return "βœ… Users saved!"
153
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  # -------------------- UI LAYOUT --------------------
155
  with gr.Blocks(title="Graffiti Admin Dashboard") as app:
156
  gr.Markdown("# πŸ“† Graffiti Admin Dashboard")
@@ -198,6 +249,45 @@ with gr.Blocks(title="Graffiti Admin Dashboard") as app:
198
  det_l = gr.Dataframe(label="πŸ”Ž Details")
199
  btn_l.click(lambda: (get_leads_summary(), get_leads_detail()), None, [sum_l, det_l])
200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  # -- Insights --
202
  with gr.Tab("Insights"):
203
  btn_i = gr.Button("Generate Insights")
 
24
  return [c.strip().title() for c in cols]
25
 
26
  def load_sheet_df(name):
 
 
 
 
 
27
  ws = client.open_by_url(SHEET_URL).worksheet(name)
28
  data = ws.get_all_values()
29
  if not data:
 
126
  # -------------------- USER MANAGEMENT --------------------
127
  def load_users():
128
  df = load_sheet_df("Users")
 
129
  want = [
130
  "Id", "Email", "Name", "Business", "Role",
131
  "Daily Phone Call Target", "Daily Phone Appointment Target",
 
142
  def save_users(df):
143
  ws = client.open_by_url(SHEET_URL).worksheet("Users")
144
  ws.clear()
145
+ set_with_dataframe(ws, df)
146
  return "βœ… Users saved!"
147
 
148
+ # -------------------- QUOTES TAB UTILS --------------------
149
+ def get_quotes_df():
150
+ df = load_sheet_df("LiveQuotes")
151
+ df.columns = [c.strip() for c in df.columns]
152
+ return df
153
+
154
+ def rep_choices_quotes():
155
+ df = get_quotes_df()
156
+ return sorted(df["Rep"].dropna().unique().tolist()) if "Rep" in df else []
157
+
158
+ def quote_year_choices():
159
+ df = get_quotes_df()
160
+ if "Year" in df.columns:
161
+ years = sorted(df["Year"].dropna().unique().astype(str))
162
+ return years
163
+ if "Date" in df.columns:
164
+ years = pd.to_datetime(df["Date"], errors="coerce").dt.year.dropna().unique()
165
+ return sorted(years.astype(str))
166
+ return []
167
+
168
+ def quote_month_choices(year=None):
169
+ df = get_quotes_df()
170
+ if year and "Year" in df.columns and "Month" in df.columns:
171
+ months = df[df["Year"].astype(str) == str(year)]["Month"].dropna().unique()
172
+ months = [str(int(m)) for m in sorted(pd.to_numeric(months, errors="coerce").dropna().unique())]
173
+ return months
174
+ return []
175
+
176
+ def quotes_summary(year=None, month=None):
177
+ df = get_quotes_df()
178
+ if "Rep" not in df.columns or "Total" not in df.columns:
179
+ return pd.DataFrame([{"Error": "Missing Rep or Total column"}])
180
+ if year and "Year" in df.columns:
181
+ df = df[df["Year"].astype(str) == str(year)]
182
+ if month and "Month" in df.columns:
183
+ df = df[df["Month"].astype(str) == str(month)]
184
+ df["Total"] = pd.to_numeric(df["Total"].astype(str).str.replace(",", ""), errors="coerce")
185
+ summary = (
186
+ df.groupby("Rep")
187
+ .agg({"Document No.": "count", "Total": "sum"})
188
+ .rename(columns={"Document No.": "Total Quotes", "Total": "Total Value"})
189
+ .reset_index()
190
+ )
191
+ summary["Total Value"] = summary["Total Value"].fillna(0).round(2)
192
+ return summary
193
+
194
+ def get_rep_quotes_filtered(rep, year=None, month=None):
195
+ df = get_quotes_df()
196
+ if "Rep" not in df.columns:
197
+ return pd.DataFrame([{"Error": "Missing Rep column"}])
198
+ df = df[df["Rep"] == rep]
199
+ if year and "Year" in df.columns:
200
+ df = df[df["Year"].astype(str) == str(year)]
201
+ if month and "Month" in df.columns:
202
+ df = df[df["Month"].astype(str) == str(month)]
203
+ return df
204
+
205
  # -------------------- UI LAYOUT --------------------
206
  with gr.Blocks(title="Graffiti Admin Dashboard") as app:
207
  gr.Markdown("# πŸ“† Graffiti Admin Dashboard")
 
249
  det_l = gr.Dataframe(label="πŸ”Ž Details")
250
  btn_l.click(lambda: (get_leads_summary(), get_leads_detail()), None, [sum_l, det_l])
251
 
252
+ # -- Quotes Tab (NEW) --
253
+ with gr.Tab("Quotes"):
254
+ gr.Markdown("### πŸ“ˆ Quotes Summary by Rep")
255
+ year_qs = gr.Dropdown(choices=[""] + quote_year_choices(), label="Year (optional)", value="")
256
+ month_qs = gr.Dropdown(choices=[""], label="Month (optional, needs year)", value="")
257
+ btn_qs = gr.Button("Show Quotes Summary")
258
+ sum_qs = gr.Dataframe(label="Summary by Rep")
259
+
260
+ # Dynamic month options for summary
261
+ def update_month_choices_summary(year):
262
+ if year:
263
+ return gr.Dropdown.update(choices=[""] + quote_month_choices(year), value="")
264
+ else:
265
+ return gr.Dropdown.update(choices=[""], value="")
266
+ year_qs.change(update_month_choices_summary, year_qs, month_qs)
267
+
268
+ def quotes_summary_wrapper(year, month):
269
+ return quotes_summary(year if year else None, month if month else None)
270
+ btn_qs.click(quotes_summary_wrapper, [year_qs, month_qs], sum_qs)
271
+
272
+ gr.Markdown("### πŸ”Ž View All Quotes for a Rep, Year, and Month")
273
+ rep_q = gr.Dropdown(choices=rep_choices_quotes(), label="Select Rep")
274
+ year_q = gr.Dropdown(choices=[""] + quote_year_choices(), label="Year (optional)", value="")
275
+ month_q = gr.Dropdown(choices=[""], label="Month (optional, needs year)", value="")
276
+ btn_qr = gr.Button("Show Quotes")
277
+ tbl_qr = gr.Dataframe(label="Quotes for Selection")
278
+
279
+ # Dynamic month options for rep quotes
280
+ def update_month_choices(year):
281
+ if year:
282
+ return gr.Dropdown.update(choices=[""] + quote_month_choices(year), value="")
283
+ else:
284
+ return gr.Dropdown.update(choices=[""], value="")
285
+ year_q.change(update_month_choices, year_q, month_q)
286
+
287
+ def get_rep_quotes_filtered_wrapper(rep, year, month):
288
+ return get_rep_quotes_filtered(rep, year if year else None, month if month else None)
289
+ btn_qr.click(get_rep_quotes_filtered_wrapper, [rep_q, year_q, month_q], tbl_qr)
290
+
291
  # -- Insights --
292
  with gr.Tab("Insights"):
293
  btn_i = gr.Button("Generate Insights")