Update app.py
Browse files
app.py
CHANGED
@@ -185,15 +185,218 @@ def run_app():
|
|
185 |
st.set_page_config(page_title="Sales Call Assistant", layout="wide")
|
186 |
st.title("AI Sales Call Assistant")
|
187 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
st.sidebar.title("Navigation")
|
189 |
app_mode = st.sidebar.radio("Choose a mode:", ["Real-Time Call Analysis", "Dashboard"])
|
190 |
|
191 |
if app_mode == "Real-Time Call Analysis":
|
192 |
st.header("Real-Time Sales Call Analysis")
|
193 |
-
|
|
|
194 |
|
195 |
elif app_mode == "Dashboard":
|
196 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
|
198 |
if __name__ == "__main__":
|
199 |
-
run_app()
|
|
|
185 |
st.set_page_config(page_title="Sales Call Assistant", layout="wide")
|
186 |
st.title("AI Sales Call Assistant")
|
187 |
|
188 |
+
# Display a warning message to visitors
|
189 |
+
st.warning("The space is currently not working due to issues with real-time transcription and data fetching from Google Sheets. We are working on resolving these issues.")
|
190 |
+
|
191 |
+
st.markdown("""
|
192 |
+
<style>
|
193 |
+
/* Header Container Styling */
|
194 |
+
.header-container {
|
195 |
+
background: linear-gradient(135deg, #F8F9FA 0%, #E9ECEF 100%);
|
196 |
+
padding: 20px;
|
197 |
+
border-radius: 15px;
|
198 |
+
margin-bottom: 30px;
|
199 |
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
200 |
+
}
|
201 |
+
/* Section Container Styling */
|
202 |
+
.section {
|
203 |
+
background: linear-gradient(135deg, #FFFFFF 0%, #F8F9FA 100%);
|
204 |
+
padding: 25px;
|
205 |
+
border-radius: 15px;
|
206 |
+
margin-bottom: 30px;
|
207 |
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
208 |
+
}
|
209 |
+
/* Header Text Styling */
|
210 |
+
.header {
|
211 |
+
font-size: 2.5em;
|
212 |
+
font-weight: 800;
|
213 |
+
text-align: center;
|
214 |
+
background: linear-gradient(120deg, #0D6EFD 0%, #0B5ED7 100%);
|
215 |
+
-webkit-background-clip: text;
|
216 |
+
-webkit-text-fill-color: transparent;
|
217 |
+
margin: 0;
|
218 |
+
padding: 10px;
|
219 |
+
letter-spacing: 1px;
|
220 |
+
}
|
221 |
+
/* Subheader Styling */
|
222 |
+
.subheader {
|
223 |
+
font-size: 1.8em;
|
224 |
+
font-weight: 600;
|
225 |
+
background: linear-gradient(120deg, #0D6EFD 0%, #0B5ED7 100%);
|
226 |
+
-webkit-background-clip: text;
|
227 |
+
-webkit-text-fill-color: transparent;
|
228 |
+
margin-top: 20px;
|
229 |
+
margin-bottom: 10px;
|
230 |
+
text-align: left;
|
231 |
+
}
|
232 |
+
/* Table Container Styling */
|
233 |
+
.table-container {
|
234 |
+
background: linear-gradient(135deg, #FFFFFF 0%, #F8F9FA 100%);
|
235 |
+
padding: 20px;
|
236 |
+
border-radius: 10px;
|
237 |
+
margin: 20px 0;
|
238 |
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
239 |
+
}
|
240 |
+
/* Dark mode adjustments */
|
241 |
+
@media (prefers-color-scheme: dark) {
|
242 |
+
.header-container {
|
243 |
+
background: linear-gradient(135deg, #212529 0%, #343A40 100%);
|
244 |
+
}
|
245 |
+
.section {
|
246 |
+
background: linear-gradient(135deg, #212529 0%, #2B3035 100%);
|
247 |
+
}
|
248 |
+
.table-container {
|
249 |
+
background: linear-gradient(135deg, #212529 0%, #2B3035 100%);
|
250 |
+
}
|
251 |
+
.header {
|
252 |
+
background: linear-gradient(120deg, #6EA8FE 0%, #9EC5FE 100%);
|
253 |
+
-webkit-background-clip: text;
|
254 |
+
-webkit-text-fill-color: transparent;
|
255 |
+
}
|
256 |
+
.subheader {
|
257 |
+
background: linear-gradient(120deg, #6EA8FE 0%, #9EC5FE 100%);
|
258 |
+
-webkit-background-clip: text;
|
259 |
+
-webkit-text-fill-color: transparent;
|
260 |
+
}
|
261 |
+
}
|
262 |
+
/* Button Styling */
|
263 |
+
.stButton > button {
|
264 |
+
background: linear-gradient(135deg, #2196F3 0%, #1976D2 100%);
|
265 |
+
color: white;
|
266 |
+
border: none;
|
267 |
+
padding: 10px 20px;
|
268 |
+
border-radius: 5px;
|
269 |
+
transition: all 0.3s ease;
|
270 |
+
}
|
271 |
+
.stButton > button:hover {
|
272 |
+
background: linear-gradient(135deg, #1976D2 0%, #1565C0 100%);
|
273 |
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
|
274 |
+
}
|
275 |
+
/* Tab Styling */
|
276 |
+
.stTabs [data-baseweb="tab-list"] {
|
277 |
+
gap: 24px;
|
278 |
+
background: linear-gradient(135deg, #F8F9FA 0%, #E9ECEF 100%);
|
279 |
+
padding: 10px;
|
280 |
+
border-radius: 10px;
|
281 |
+
}
|
282 |
+
.stTabs [data-baseweb="tab"] {
|
283 |
+
background-color: transparent;
|
284 |
+
border-radius: 4px;
|
285 |
+
color: #1976D2;
|
286 |
+
font-weight: 600;
|
287 |
+
padding: 10px 16px;
|
288 |
+
}
|
289 |
+
.stTabs [aria-selected="true"] {
|
290 |
+
background: linear-gradient(120deg, #2196F3 0%, #1976D2 100%);
|
291 |
+
color: white;
|
292 |
+
}
|
293 |
+
/* Dark mode tab adjustments */
|
294 |
+
@media (prefers-color-scheme: dark) {
|
295 |
+
.stTabs [data-baseweb="tab-list"] {
|
296 |
+
background: linear-gradient(135deg, #212529 0%, #343A40 100%);
|
297 |
+
}
|
298 |
+
.stTabs [data-baseweb="tab"] {
|
299 |
+
color: #82B1FF;
|
300 |
+
}
|
301 |
+
.stTabs [aria-selected="true"] {
|
302 |
+
background: linear-gradient(120deg, #448AFF 0%, #2979FF 100%);
|
303 |
+
}
|
304 |
+
}
|
305 |
+
/* Message Styling */
|
306 |
+
.success {
|
307 |
+
background: linear-gradient(135deg, #43A047 0%, #2E7D32 100%);
|
308 |
+
color: white;
|
309 |
+
padding: 10px;
|
310 |
+
border-radius: 5px;
|
311 |
+
margin: 10px 0;
|
312 |
+
}
|
313 |
+
.error {
|
314 |
+
background: linear-gradient(135deg, #E53935 0%, #C62828 100%);
|
315 |
+
color: white;
|
316 |
+
padding: 10px;
|
317 |
+
border-radius: 5px;
|
318 |
+
margin: 10px 0;
|
319 |
+
}
|
320 |
+
.warning {
|
321 |
+
background: linear-gradient(135deg, #FB8C00 0%, #F57C00 100%);
|
322 |
+
color: white;
|
323 |
+
padding: 10px;
|
324 |
+
border-radius: 5px;
|
325 |
+
margin: 10px 0;
|
326 |
+
}
|
327 |
+
</style>
|
328 |
+
""")
|
329 |
+
|
330 |
st.sidebar.title("Navigation")
|
331 |
app_mode = st.sidebar.radio("Choose a mode:", ["Real-Time Call Analysis", "Dashboard"])
|
332 |
|
333 |
if app_mode == "Real-Time Call Analysis":
|
334 |
st.header("Real-Time Sales Call Analysis")
|
335 |
+
if st.button("Start Listening"):
|
336 |
+
real_time_analysis()
|
337 |
|
338 |
elif app_mode == "Dashboard":
|
339 |
+
st.header("Call Summaries and Sentiment Analysis")
|
340 |
+
try:
|
341 |
+
data = fetch_call_data(config["google_sheet_id"])
|
342 |
+
if data.empty:
|
343 |
+
st.warning("No data available in the Google Sheet.")
|
344 |
+
else:
|
345 |
+
sentiment_counts = data['Sentiment'].value_counts()
|
346 |
+
|
347 |
+
product_mentions = filter_product_mentions(data[['Chunk']].values.tolist(), product_titles)
|
348 |
+
product_mentions_df = pd.DataFrame(list(product_mentions.items()), columns=['Product', 'Count'])
|
349 |
+
|
350 |
+
col1, col2 = st.columns(2)
|
351 |
+
with col1:
|
352 |
+
st.subheader("Sentiment Distribution")
|
353 |
+
fig_bar = px.bar(
|
354 |
+
x=sentiment_counts.index,
|
355 |
+
y=sentiment_counts.values,
|
356 |
+
title='Number of Calls by Sentiment',
|
357 |
+
labels={'x': 'Sentiment', 'y': 'Number of Calls'},
|
358 |
+
color=sentiment_counts.index,
|
359 |
+
color_discrete_map={
|
360 |
+
'POSITIVE': 'green',
|
361 |
+
'NEGATIVE': 'red',
|
362 |
+
'NEUTRAL': 'blue'
|
363 |
+
}
|
364 |
+
)
|
365 |
+
st.plotly_chart(fig_bar)
|
366 |
+
|
367 |
+
with col2:
|
368 |
+
st.subheader("Most Mentioned Products")
|
369 |
+
fig_products = px.pie(
|
370 |
+
values=product_mentions_df['Count'],
|
371 |
+
names=product_mentions_df['Product'],
|
372 |
+
title='Most Mentioned Products'
|
373 |
+
)
|
374 |
+
st.plotly_chart(fig_products)
|
375 |
+
|
376 |
+
st.subheader("All Calls")
|
377 |
+
display_data = data.copy()
|
378 |
+
display_data['Summary Preview'] = display_data['Summary'].str[:100] + '...'
|
379 |
+
st.dataframe(display_data[['Call ID', 'Chunk', 'Sentiment', 'Summary Preview', 'Overall Sentiment']])
|
380 |
+
|
381 |
+
unique_call_ids = data[data['Call ID'] != '']['Call ID'].unique()
|
382 |
+
call_id = st.selectbox("Select a Call ID to view details:", unique_call_ids)
|
383 |
+
|
384 |
+
call_details = data[data['Call ID'] == call_id]
|
385 |
+
if not call_details.empty:
|
386 |
+
st.subheader("Detailed Call Information")
|
387 |
+
st.write(f"**Call ID:** {call_id}")
|
388 |
+
st.write(f"**Overall Sentiment:** {call_details.iloc[0]['Overall Sentiment']}")
|
389 |
+
|
390 |
+
st.subheader("Full Call Summary")
|
391 |
+
st.text_area("Summary:",
|
392 |
+
value=call_details.iloc[0]['Summary'],
|
393 |
+
height=200,
|
394 |
+
disabled=True)
|
395 |
+
|
396 |
+
else:
|
397 |
+
st.error("No details available for the selected Call ID.")
|
398 |
+
except Exception as e:
|
399 |
+
st.error(f"Error loading dashboard: {e}")
|
400 |
|
401 |
if __name__ == "__main__":
|
402 |
+
run_app()
|