condorhacker commited on
Commit
bb77c34
·
verified ·
1 Parent(s): b21b145

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +682 -35
src/streamlit_app.py CHANGED
@@ -1,40 +1,687 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
 
 
4
  import streamlit as st
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
 
 
 
 
 
8
 
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
1
+ """
2
+ IntelliCall Assistant - Segreteria Telefonica AI
3
+ Copyright (c) 2025 Francesco Angeli by CONDORPROF
4
+ """
5
+
6
  import streamlit as st
7
+ import pandas as pd
8
+ import plotly.graph_objects as go
9
+ import plotly.express as px
10
+ from datetime import datetime, timedelta
11
+ import sqlite3
12
+ import json
13
+ import random
14
+ import time
15
 
16
+ # Configurazione pagina
17
+ st.set_page_config(
18
+ page_title="IntelliCall Assistant 🤖",
19
+ page_icon="📞",
20
+ layout="wide",
21
+ initial_sidebar_state="expanded"
22
+ )
23
 
24
+ # CSS personalizzato
25
+ st.markdown("""
26
+ <style>
27
+ /* Titolo principale */
28
+ .main-title {
29
+ font-size: 3.5rem;
30
+ background: linear-gradient(45deg, #667eea, #764ba2);
31
+ -webkit-background-clip: text;
32
+ -webkit-text-fill-color: transparent;
33
+ text-align: center;
34
+ margin-bottom: 0.5rem;
35
+ font-weight: 800;
36
+ }
37
+
38
+ /* Sottotitolo */
39
+ .subtitle {
40
+ text-align: center;
41
+ color: #666;
42
+ font-size: 1.2rem;
43
+ margin-bottom: 2rem;
44
+ }
45
+
46
+ /* Card metriche */
47
+ .metric-card {
48
+ background: white;
49
+ border-radius: 15px;
50
+ padding: 1.5rem;
51
+ box-shadow: 0 4px 20px rgba(0,0,0,0.08);
52
+ transition: transform 0.3s;
53
+ border-left: 5px solid;
54
+ }
55
+
56
+ .metric-card:hover {
57
+ transform: translateY(-5px);
58
+ }
59
+
60
+ /* Colori priorità */
61
+ .priority-low { border-left-color: #10b981; }
62
+ .priority-medium { border-left-color: #f59e0b; }
63
+ .priority-high { border-left-color: #ef4444; }
64
+ .priority-critical { border-left-color: #7c3aed; }
65
+
66
+ /* Badge */
67
+ .badge {
68
+ display: inline-block;
69
+ padding: 4px 12px;
70
+ border-radius: 20px;
71
+ font-size: 0.8rem;
72
+ font-weight: bold;
73
+ text-transform: uppercase;
74
+ }
75
+
76
+ .badge-success { background: #d1fae5; color: #065f46; }
77
+ .badge-warning { background: #fef3c7; color: #92400e; }
78
+ .badge-danger { background: #fee2e2; color: #991b1b; }
79
+ .badge-vip { background: linear-gradient(45deg, #8b5cf6, #ec4899); color: white; }
80
+
81
+ /* Animazioni */
82
+ @keyframes pulse {
83
+ 0% { transform: scale(1); }
84
+ 50% { transform: scale(1.05); }
85
+ 100% { transform: scale(1); }
86
+ }
87
+
88
+ .pulse {
89
+ animation: pulse 2s infinite;
90
+ }
91
+ </style>
92
+ """, unsafe_allow_html=True)
93
 
94
+ # Inizializzazione database
95
+ def init_db():
96
+ conn = sqlite3.connect('intelliCall.db', check_same_thread=False)
97
+ c = conn.cursor()
98
+
99
+ # Tabella chiamate
100
+ c.execute('''
101
+ CREATE TABLE IF NOT EXISTS chiamate (
102
+ id TEXT PRIMARY KEY,
103
+ numero TEXT,
104
+ nome TEXT,
105
+ azienda TEXT,
106
+ data TEXT,
107
+ durata INTEGER,
108
+ stato TEXT,
109
+ priorita TEXT,
110
+ motivo TEXT,
111
+ operatore TEXT,
112
+ trascrizione TEXT
113
+ )
114
+ ''')
115
+
116
+ # Tabella clienti
117
+ c.execute('''
118
+ CREATE TABLE IF NOT EXISTS clienti (
119
+ id TEXT PRIMARY KEY,
120
+ nome TEXT,
121
+ cognome TEXT,
122
+ telefono TEXT UNIQUE,
123
+ email TEXT,
124
+ azienda TEXT,
125
+ tipo TEXT,
126
+ data_registrazione TEXT,
127
+ ultima_chiamata TEXT,
128
+ chiamate_totali INTEGER DEFAULT 0
129
+ )
130
+ ''')
131
+
132
+ # Tabella voicemail
133
+ c.execute('''
134
+ CREATE TABLE IF NOT EXISTS voicemail (
135
+ id TEXT PRIMARY KEY,
136
+ chiamata_id TEXT,
137
+ cliente_id TEXT,
138
+ contenuto TEXT,
139
+ priorita TEXT,
140
+ data TEXT,
141
+ ascoltata BOOLEAN DEFAULT 0,
142
+ trascrizione TEXT
143
+ )
144
+ ''')
145
+
146
+ # Dati di esempio (solo se il database è vuoto)
147
+ c.execute("SELECT COUNT(*) FROM chiamate")
148
+ if c.fetchone()[0] == 0:
149
+ # Aggiungi dati demo
150
+ add_demo_data(conn)
151
+
152
+ conn.commit()
153
+ return conn
154
+
155
+ def add_demo_data(conn):
156
+ c = conn.cursor()
157
+
158
+ # Clienti demo
159
+ clienti_demo = [
160
+ ('CL001', 'Mario', 'Rossi', '+39123456789', 'mario@email.com', 'Tech Solutions', 'VIP', '2024-01-15', '2024-12-04', 12),
161
+ ('CL002', 'Anna', 'Verdi', '+39987654321', 'anna@email.com', 'Design Studio', 'Regolare', '2024-02-20', '2024-12-03', 8),
162
+ ('CL003', 'Luigi', 'Bianchi', '+39456123789', 'luigi@email.com', 'Bianchi SRL', 'Aziendale', '2024-03-10', '2024-12-04', 15),
163
+ ('CL004', 'Giulia', 'Neri', '+39789456123', 'giulia@email.com', None, 'Nuovo', '2024-11-28', '2024-12-02', 3),
164
+ ('CL005', 'Paolo', 'Gialli', '+39321654987', 'paolo@email.com', 'Gialli Group', 'VIP', '2024-01-05', '2024-12-01', 22),
165
+ ]
166
+
167
+ c.executemany('''
168
+ INSERT OR REPLACE INTO clienti VALUES (?,?,?,?,?,?,?,?,?,?)
169
+ ''', clienti_demo)
170
+
171
+ # Chiamate demo (ultimi 7 giorni)
172
+ stati = ['completata', 'in_corso', 'persa', 'richiamare']
173
+ priorita = ['bassa', 'media', 'alta', 'urgente']
174
+ motivi = ['Informazioni prodotto', 'Supporto tecnico', 'Preventivo', 'Reclamo', 'Appuntamento']
175
+
176
+ for i in range(1, 31):
177
+ data = (datetime.now() - timedelta(days=random.randint(0, 7),
178
+ hours=random.randint(0, 23),
179
+ minutes=random.randint(0, 59))).strftime('%Y-%m-%d %H:%M:%S')
180
+
181
+ c.execute('''
182
+ INSERT INTO chiamate VALUES (?,?,?,?,?,?,?,?,?,?,?)
183
+ ''', (
184
+ f'CH{1000 + i}',
185
+ f'+39{random.randint(300000000, 399999999)}',
186
+ random.choice(['Mario Rossi', 'Anna Verdi', 'Luigi Bianchi', 'Giulia Neri', 'Paolo Gialli']),
187
+ random.choice(['Tech Solutions', 'Design Studio', 'Bianchi SRL', 'Gialli Group', None]),
188
+ data,
189
+ random.randint(60, 1800),
190
+ random.choice(stati),
191
+ random.choice(priorita),
192
+ random.choice(motivi),
193
+ random.choice(['Operatore 1', 'Operatore 2', 'Sistema AI', None]),
194
+ f'Trascrizione chiamata demo {i}'
195
+ ))
196
+
197
+ conn.commit()
198
+
199
+ # Inizializza database
200
+ conn = init_db()
201
+
202
+ # Titolo principale
203
+ st.markdown('<h1 class="main-title">🤖 IntelliCall Assistant</h1>', unsafe_allow_html=True)
204
+ st.markdown('<p class="subtitle">Sistema avanzato di segreteria telefonica AI per aziende e professionisti</p>', unsafe_allow_html=True)
205
+
206
+ # Sidebar
207
+ with st.sidebar:
208
+ st.image("https://img.icons8.com/color/96/000000/phone.png", width=80)
209
+ st.title("⚙️ Controlli")
210
+
211
+ # Filtri
212
+ st.subheader("🔍 Filtri")
213
+ giorni_filtro = st.slider("Ultimi giorni", 1, 30, 7)
214
+ priorita_filtro = st.multiselect(
215
+ "Priorità",
216
+ ["bassa", "media", "alta", "urgente"],
217
+ default=["urgente", "alta"]
218
+ )
219
+
220
+ # Azioni rapide
221
+ st.subheader("⚡ Azioni Rapide")
222
+ if st.button("📞 Simula Chiamata", use_container_width=True):
223
+ st.session_state.simula_chiamata = True
224
+
225
+ if st.button("🔄 Aggiorna Dati", use_container_width=True):
226
+ st.rerun()
227
+
228
+ if st.button("📊 Genera Report", use_container_width=True):
229
+ st.session_state.genera_report = True
230
+
231
+ # Statistiche sidebar
232
+ st.subheader("📈 Statistiche Rapide")
233
+
234
+ c = conn.cursor()
235
+ c.execute("SELECT COUNT(*) FROM chiamate WHERE date(data) >= date('now', ?)", (f'-{giorni_filtro} days',))
236
+ chiamate_periodo = c.fetchone()[0]
237
+
238
+ c.execute("SELECT COUNT(*) FROM voicemail WHERE ascoltata = 0")
239
+ voicemail_non_ascoltate = c.fetchone()[0]
240
+
241
+ st.metric("Chiamate", chiamate_periodo)
242
+ st.metric("Voicemail", voicemail_non_ascoltate)
243
+
244
+ # Status sistema
245
+ st.subheader("🟢 Stato Sistema")
246
+ col1, col2 = st.columns(2)
247
+ with col1:
248
+ st.success("Online")
249
+ with col2:
250
+ st.info("100% Uptime")
251
+
252
+ # Layout principale
253
+ tab1, tab2, tab3, tab4, tab5 = st.tabs([
254
+ "📊 Dashboard",
255
+ "📞 Chiamate",
256
+ "👥 Clienti",
257
+ "🎙️ Voicemail",
258
+ "⚙️ Configurazione"
259
+ ])
260
+
261
+ # TAB 1: DASHBOARD
262
+ with tab1:
263
+ col1, col2, col3, col4 = st.columns(4)
264
+
265
+ with col1:
266
+ st.markdown('<div class="metric-card priority-high">', unsafe_allow_html=True)
267
+ st.metric("Chiamate Oggi", "18", "+12% vs ieri")
268
+ st.markdown('</div>', unsafe_allow_html=True)
269
+
270
+ with col2:
271
+ st.markdown('<div class="metric-card priority-critical">', unsafe_allow_html=True)
272
+ st.metric("Voicemail Urgenti", "3", "+1")
273
+ st.markdown('</div>', unsafe_allow_html=True)
274
+
275
+ with col3:
276
+ st.markdown('<div class="metric-card priority-medium">', unsafe_allow_html=True)
277
+ st.metric("Clienti Attivi", "156", "+8")
278
+ st.markdown('</div>', unsafe_allow_html=True)
279
+
280
+ with col4:
281
+ st.markdown('<div class="metric-card priority-low">', unsafe_allow_html=True)
282
+ st.metric("Soddisfazione", "94%", "+2.5%")
283
+ st.markdown('</div>', unsafe_allow_html=True)
284
+
285
+ # Grafico chiamate per ora
286
+ st.subheader("📈 Distribuzione Chiamate per Ora")
287
+
288
+ # Dati esempio per grafico
289
+ ore = [f"{h}:00" for h in range(9, 19)]
290
+ chiamate_per_ora = [random.randint(5, 25) for _ in range(len(ore))]
291
+
292
+ fig1 = go.Figure(data=[
293
+ go.Bar(
294
+ x=ore,
295
+ y=chiamate_per_ora,
296
+ marker_color='#667eea',
297
+ name='Chiamate'
298
+ )
299
+ ])
300
+
301
+ fig1.update_layout(
302
+ height=400,
303
+ paper_bgcolor='rgba(0,0,0,0)',
304
+ plot_bgcolor='rgba(0,0,0,0)',
305
+ showlegend=False
306
+ )
307
+
308
+ st.plotly_chart(fig1, use_container_width=True)
309
+
310
+ # Ultime chiamate e voicemail
311
+ col_left, col_right = st.columns(2)
312
+
313
+ with col_left:
314
+ st.subheader("📞 Ultime Chiamate")
315
+ c = conn.cursor()
316
+ c.execute('''
317
+ SELECT id, nome, data, stato, priorita
318
+ FROM chiamate
319
+ ORDER BY data DESC
320
+ LIMIT 5
321
+ ''')
322
+ ultime_chiamate = c.fetchall()
323
+
324
+ for chiamata in ultime_chiamate:
325
+ with st.container():
326
+ col_a, col_b, col_c = st.columns([3, 2, 1])
327
+ with col_a:
328
+ st.write(f"**{chiamata[1]}**")
329
+ st.caption(f"{chiamata[2][11:16]}")
330
+ with col_b:
331
+ badge_class = "badge-warning"
332
+ if chiamata[3] == 'completata':
333
+ badge_class = "badge-success"
334
+ st.markdown(f'<span class="badge {badge_class}">{chiamata[3]}</span>', unsafe_allow_html=True)
335
+ with col_c:
336
+ st.markdown(f'<span class="badge badge-danger">{chiamata[4]}</span>', unsafe_allow_html=True)
337
+ st.divider()
338
+
339
+ with col_right:
340
+ st.subheader("🎙️ Voicemail Recenti")
341
+ # Voicemail di esempio
342
+ voicemail_demo = [
343
+ {"cliente": "Mario Rossi", "durata": "1:45", "priorita": "urgente", "ascoltata": False},
344
+ {"cliente": "Anna Verdi", "durata": "2:20", "priorita": "alta", "ascoltata": True},
345
+ {"cliente": "Luigi Bianchi", "durata": "0:55", "priorita": "media", "ascoltata": False},
346
+ ]
347
+
348
+ for vm in voicemail_demo:
349
+ with st.container():
350
+ col_x, col_y = st.columns([3, 1])
351
+ with col_x:
352
+ st.write(f"**{vm['cliente']}**")
353
+ st.caption(f"Durata: {vm['durata']}")
354
+ with col_y:
355
+ if vm['priorita'] == 'urgente':
356
+ st.error("⚠️ Urgente")
357
+ elif not vm['ascoltata']:
358
+ st.warning("Nuova")
359
+ else:
360
+ st.success("✓ Ascoltata")
361
+ st.divider()
362
+
363
+ # TAB 2: CHIAMATE
364
+ with tab2:
365
+ st.header("📞 Gestione Chiamate")
366
+
367
+ # Filtri avanzati
368
+ col_f1, col_f2, col_f3 = st.columns(3)
369
+ with col_f1:
370
+ data_inizio = st.date_input("Da data", datetime.now() - timedelta(days=7))
371
+ with col_f2:
372
+ data_fine = st.date_input("A data", datetime.now())
373
+ with col_f3:
374
+ stato_filtro = st.selectbox("Stato", ["Tutti", "completata", "in_corso", "persa", "richiamare"])
375
+
376
+ # Simula chiamata
377
+ if st.button("🎬 Simula Nuova Chiamata", type="primary"):
378
+ with st.form("simula_chiamata_form"):
379
+ col_s1, col_s2 = st.columns(2)
380
+ with col_s1:
381
+ nome = st.text_input("Nome Cliente", "Mario Rossi")
382
+ telefono = st.text_input("Telefono", "+39123456789")
383
+ with col_s2:
384
+ motivo = st.selectbox("Motivo", ["Informazioni", "Supporto", "Preventivo", "Reclamo"])
385
+ priorita = st.select_slider("Priorità", ["bassa", "media", "alta", "urgente"])
386
+
387
+ if st.form_submit_button("📞 Registra Chiamata"):
388
+ # Inserisci nel database
389
+ c = conn.cursor()
390
+ c.execute('''
391
+ INSERT INTO chiamate (id, numero, nome, data, stato, priorita, motivo)
392
+ VALUES (?, ?, ?, ?, ?, ?, ?)
393
+ ''', (
394
+ f"CH{random.randint(10000, 99999)}",
395
+ telefono,
396
+ nome,
397
+ datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
398
+ 'in_corso',
399
+ priorita,
400
+ motivo
401
+ ))
402
+ conn.commit()
403
+ st.success("✅ Chiamata registrata con successo!")
404
+ st.balloons()
405
+
406
+ # Tabella chiamate
407
+ st.subheader("📋 Storico Chiamate")
408
+
409
+ query = "SELECT * FROM chiamate WHERE 1=1"
410
+ params = []
411
+
412
+ if stato_filtro != "Tutti":
413
+ query += " AND stato = ?"
414
+ params.append(stato_filtro)
415
+
416
+ query += " ORDER BY data DESC LIMIT 50"
417
+
418
+ c = conn.cursor()
419
+ c.execute(query, params)
420
+ chiamate = c.fetchall()
421
+
422
+ if chiamate:
423
+ # Converti in DataFrame
424
+ columns = ['ID', 'Numero', 'Nome', 'Azienda', 'Data', 'Durata', 'Stato', 'Priorità', 'Motivo', 'Operatore', 'Trascrizione']
425
+ df = pd.DataFrame(chiamate, columns=columns)
426
+
427
+ # Formatta la tabella
428
+ st.dataframe(
429
+ df[['Nome', 'Numero', 'Data', 'Durata', 'Stato', 'Priorità', 'Motivo']],
430
+ use_container_width=True,
431
+ hide_index=True
432
+ )
433
+ else:
434
+ st.info("Nessuna chiamata trovata con i filtri selezionati.")
435
+
436
+ # TAB 3: CLIENTI
437
+ with tab3:
438
+ st.header("👥 Gestione Clienti")
439
+
440
+ # Aggiungi nuovo cliente
441
+ with st.expander("➕ Aggiungi Nuovo Cliente", expanded=False):
442
+ col_c1, col_c2 = st.columns(2)
443
+
444
+ with col_c1:
445
+ nuovo_nome = st.text_input("Nome")
446
+ nuovo_cognome = st.text_input("Cognome")
447
+ nuovo_email = st.text_input("Email")
448
+
449
+ with col_c2:
450
+ nuovo_telefono = st.text_input("Telefono")
451
+ nuovo_azienda = st.text_input("Azienda (opzionale)")
452
+ nuovo_tipo = st.selectbox("Tipo Cliente", ["Nuovo", "Regolare", "VIP", "Aziendale"])
453
+
454
+ if st.button("💾 Salva Cliente", type="primary"):
455
+ c = conn.cursor()
456
+ c.execute('''
457
+ INSERT INTO clienti (id, nome, cognome, telefono, email, azienda, tipo, data_registrazione)
458
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
459
+ ''', (
460
+ f"CL{random.randint(1000, 9999)}",
461
+ nuovo_nome,
462
+ nuovo_cognome,
463
+ nuovo_telefono,
464
+ nuovo_email,
465
+ nuovo_azienda if nuovo_azienda else None,
466
+ nuovo_tipo,
467
+ datetime.now().strftime('%Y-%m-%d')
468
+ ))
469
+ conn.commit()
470
+ st.success(f"Cliente {nuovo_nome} {nuovo_cognome} aggiunto con successo!")
471
+
472
+ # Lista clienti
473
+ st.subheader("📋 Clienti Registrati")
474
+
475
+ c = conn.cursor()
476
+ c.execute('SELECT * FROM clienti ORDER BY data_registrazione DESC')
477
+ clienti = c.fetchall()
478
+
479
+ if clienti:
480
+ for cliente in clienti:
481
+ with st.container():
482
+ col_cl1, col_cl2, col_cl3 = st.columns([3, 2, 1])
483
+
484
+ with col_cl1:
485
+ st.write(f"**{cliente[1]} {cliente[2]}**")
486
+ st.caption(f"📞 {cliente[3]} | ✉️ {cliente[4]}")
487
+ if cliente[5]:
488
+ st.caption(f"🏢 {cliente[5]}")
489
+
490
+ with col_cl2:
491
+ if cliente[6] == 'VIP':
492
+ st.markdown('<span class="badge badge-vip">VIP</span>', unsafe_allow_html=True)
493
+ elif cliente[6] == 'Aziendale':
494
+ st.markdown('<span class="badge badge-warning">Aziendale</span>', unsafe_allow_html=True)
495
+ else:
496
+ st.markdown(f'<span class="badge badge-success">{cliente[6]}</span>', unsafe_allow_html=True)
497
+
498
+ st.caption(f"Chiamate: {cliente[9]}")
499
+
500
+ with col_cl3:
501
+ st.button("📞", key=f"call_{cliente[0]}", help="Chiama cliente")
502
+ st.button("✏️", key=f"edit_{cliente[0]}", help="Modifica")
503
+
504
+ st.divider()
505
+
506
+ # TAB 4: VOCEMAIL
507
+ with tab4:
508
+ st.header("🎙️ Gestione Voicemail")
509
+
510
+ # Voicemail di esempio
511
+ voicemail_list = [
512
+ {
513
+ "id": "VM001",
514
+ "cliente": "Mario Rossi",
515
+ "telefono": "+39123456789",
516
+ "data": "Oggi 10:15",
517
+ "durata": "1:45",
518
+ "priorita": "urgente",
519
+ "ascoltata": False,
520
+ "trascrizione": "Buongiorno, ho un problema urgente con il servizio. Potete richiamarmi al più presto?"
521
+ },
522
+ {
523
+ "id": "VM002",
524
+ "cliente": "Anna Verdi",
525
+ "telefono": "+39987654321",
526
+ "data": "Oggi 11:30",
527
+ "durata": "2:20",
528
+ "priorita": "alta",
529
+ "ascoltata": True,
530
+ "trascrizione": "Salve, vorrei informazioni sul nuovo prodotto e un preventivo."
531
+ },
532
+ {
533
+ "id": "VM003",
534
+ "cliente": "Luigi Bianchi",
535
+ "telefono": "+39456123789",
536
+ "data": "Ieri 14:45",
537
+ "durata": "0:55",
538
+ "priorita": "media",
539
+ "ascoltata": False,
540
+ "trascrizione": "Ciao, è Luigi. Richiamami quando puoi."
541
+ },
542
+ ]
543
+
544
+ for vm in voicemail_list:
545
+ with st.container():
546
+ col_v1, col_v2 = st.columns([4, 1])
547
+
548
+ with col_v1:
549
+ st.write(f"### {vm['cliente']}")
550
+ st.caption(f"📞 {vm['telefono']} • ⏱️ {vm['durata']} • 🕐 {vm['data']}")
551
+
552
+ # Mostra trascrizione
553
+ with st.expander("📝 Mostra trascrizione"):
554
+ st.write(vm['trascrizione'])
555
+
556
+ with col_v2:
557
+ if vm['priorita'] == 'urgente':
558
+ st.error("⚠️ URGENTE")
559
+ elif vm['priorita'] == 'alta':
560
+ st.warning("ALTA")
561
+ else:
562
+ st.info(vm['priorita'].upper())
563
+
564
+ if not vm['ascoltata']:
565
+ if st.button("✅ Ascolta", key=f"listen_{vm['id']}"):
566
+ st.success(f"Voicemail {vm['id']} contrassegnata come ascoltata")
567
+ else:
568
+ st.success("✓ Ascoltata")
569
+
570
+ st.divider()
571
+
572
+ # Analisi AI delle voicemail
573
+ with st.expander("🤖 Analisi AI delle Voicemail", expanded=False):
574
+ st.write("**Analisi automatica delle voicemail non ascoltate:**")
575
+
576
+ voicemail_non_ascoltate = [vm for vm in voicemail_list if not vm['ascoltata']]
577
+
578
+ if voicemail_non_ascoltate:
579
+ for vm in voicemail_non_ascoltate:
580
+ with st.container():
581
+ st.write(f"**{vm['cliente']}** - Priorità: {vm['priorita']}")
582
+
583
+ # Simulazione analisi AI
584
+ sentiment = random.choice(["✅ Positivo", "⚠️ Neutrale", "❌ Negativo"])
585
+ urgenza = "ALTA" if vm['priorita'] in ['urgente', 'alta'] else "MEDIA"
586
+
587
+ col_a1, col_a2 = st.columns(2)
588
+ with col_a1:
589
+ st.metric("Sentiment", sentiment)
590
+ with col_a2:
591
+ st.metric("Urgenza", urgenza)
592
+
593
+ # Suggerimento AI
594
+ suggerimenti = {
595
+ "urgente": "⚠️ **RICHIDAMA IMMEDIATO** - Cliente segnala problema urgente",
596
+ "alta": "📞 **Richiama entro 2 ore** - Richiesta informazioni importante",
597
+ "media": "📅 **Pianifica callback** - Richiesta standard"
598
+ }
599
+
600
+ st.info(suggerimenti.get(vm['priorita'], "Gestire quando possibile"))
601
+ st.divider()
602
+ else:
603
+ st.success("🎉 Tutte le voicemail sono state ascoltate!")
604
+
605
+ # TAB 5: CONFIGURAZIONE
606
+ with tab5:
607
+ st.header("⚙️ Configurazione Sistema")
608
+
609
+ col_conf1, col_conf2 = st.columns(2)
610
+
611
+ with col_conf1:
612
+ st.subheader("Impostazioni Azienda")
613
+
614
+ nome_azienda = st.text_input("Nome Azienda", "IntelliCall Solutions")
615
+ orari_apertura = st.text_input("Orari Apertura", "Lun-Ven 9:00-18:00")
616
+ numero_emergenza = st.text_input("Numero Emergenza", "+39 333 1234567")
617
+ lingua = st.selectbox("Lingua Predefinita", ["Italiano", "Inglese", "Francese", "Tedesco", "Spagnolo"])
618
+
619
+ with col_conf2:
620
+ st.subheader("Impostazioni AI")
621
+
622
+ api_key = st.text_input("OpenAI API Key (opzionale)", type="password")
623
+ analisi_automatica = st.checkbox("Analisi Automatica Voicemail", value=True)
624
+ trascrizione_automatica = st.checkbox("Trascrizione Automatica", value=True)
625
+ sentiment_analysis = st.checkbox("Analisi Sentiment", value=True)
626
+
627
+ st.subheader("Notifiche")
628
+ col_not1, col_not2 = st.columns(2)
629
+
630
+ with col_not1:
631
+ email_notifiche = st.text_input("Email Notifiche", "admin@intellicall.com")
632
+ notifiche_sms = st.checkbox("Attiva notifiche SMS", value=False)
633
+
634
+ with col_not2:
635
+ notifiche_whatsapp = st.checkbox("Attiva notifiche WhatsApp", value=False)
636
+ soglia_urgenza = st.select_slider(
637
+ "Soglia Notifiche Urgenti",
638
+ options=["Solo critiche", "Alte e critiche", "Tutte le priorità"],
639
+ value="Alte e critiche"
640
+ )
641
+
642
+ st.subheader("Sicurezza")
643
+ password = st.text_input("Password Amministratore", type="password")
644
+ autenticazione_2fa = st.checkbox("Abilita Autenticazione a Due Fattori", value=False)
645
+
646
+ # Salva configurazione
647
+ if st.button("💾 Salva Configurazione", type="primary", use_container_width=True):
648
+ st.success("✅ Configurazione salvata con successo!")
649
+
650
+ # Simula salvataggio
651
+ config = {
652
+ "azienda": {
653
+ "nome": nome_azienda,
654
+ "orari": orari_apertura,
655
+ "emergenza": numero_emergenza,
656
+ "lingua": lingua
657
+ },
658
+ "ai": {
659
+ "analisi_automatica": analisi_automatica,
660
+ "trascrizione_automatica": trascrizione_automatica,
661
+ "sentiment_analysis": sentiment_analysis
662
+ },
663
+ "notifiche": {
664
+ "email": email_notifiche,
665
+ "sms": notifiche_sms,
666
+ "whatsapp": notifiche_whatsapp,
667
+ "soglia_urgenza": soglia_urgenza
668
+ }
669
+ }
670
+
671
+ with open("config.json", "w") as f:
672
+ json.dump(config, f, indent=2)
673
+
674
+ # Footer
675
+ st.markdown("---")
676
+ col_f1, col_f2, col_f3 = st.columns([1, 2, 1])
677
+ with col_f2:
678
+ st.markdown("""
679
+ <div style="text-align: center; color: #666;">
680
+ <p>🤖 <b>IntelliCall Assistant v1.0</b> • Sistema di segreteria telefonica AI</p>
681
+ <p>© 2025 Francesco Angeli by CONDORPROF • Tutti i diritti riservati</p>
682
+ </div>
683
+ """, unsafe_allow_html=True)
684
 
685
+ # Chiusura connessione al database
686
+ conn.close()
687
+