"""
IntelliCall Assistant - Segreteria Telefonica AI
Copyright (c) 2025 Francesco Angeli by CONDORPROF
"""
import streamlit as st
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
from datetime import datetime, timedelta
import sqlite3
import json
import random
import time
# Configurazione pagina
st.set_page_config(
page_title="IntelliCall Assistant ๐ค",
page_icon="๐",
layout="wide",
initial_sidebar_state="expanded"
)
# CSS personalizzato
st.markdown("""
""", unsafe_allow_html=True)
# Inizializzazione database
def init_db():
conn = sqlite3.connect('intelliCall.db', check_same_thread=False)
c = conn.cursor()
# Tabella chiamate
c.execute('''
CREATE TABLE IF NOT EXISTS chiamate (
id TEXT PRIMARY KEY,
numero TEXT,
nome TEXT,
azienda TEXT,
data TEXT,
durata INTEGER,
stato TEXT,
priorita TEXT,
motivo TEXT,
operatore TEXT,
trascrizione TEXT
)
''')
# Tabella clienti
c.execute('''
CREATE TABLE IF NOT EXISTS clienti (
id TEXT PRIMARY KEY,
nome TEXT,
cognome TEXT,
telefono TEXT UNIQUE,
email TEXT,
azienda TEXT,
tipo TEXT,
data_registrazione TEXT,
ultima_chiamata TEXT,
chiamate_totali INTEGER DEFAULT 0
)
''')
# Tabella voicemail
c.execute('''
CREATE TABLE IF NOT EXISTS voicemail (
id TEXT PRIMARY KEY,
chiamata_id TEXT,
cliente_id TEXT,
contenuto TEXT,
priorita TEXT,
data TEXT,
ascoltata BOOLEAN DEFAULT 0,
trascrizione TEXT
)
''')
# Dati di esempio (solo se il database รจ vuoto)
c.execute("SELECT COUNT(*) FROM chiamate")
if c.fetchone()[0] == 0:
# Aggiungi dati demo
add_demo_data(conn)
conn.commit()
return conn
def add_demo_data(conn):
c = conn.cursor()
# Clienti demo
clienti_demo = [
('CL001', 'Mario', 'Rossi', '+39123456789', 'mario@email.com', 'Tech Solutions', 'VIP', '2024-01-15', '2024-12-04', 12),
('CL002', 'Anna', 'Verdi', '+39987654321', 'anna@email.com', 'Design Studio', 'Regolare', '2024-02-20', '2024-12-03', 8),
('CL003', 'Luigi', 'Bianchi', '+39456123789', 'luigi@email.com', 'Bianchi SRL', 'Aziendale', '2024-03-10', '2024-12-04', 15),
('CL004', 'Giulia', 'Neri', '+39789456123', 'giulia@email.com', None, 'Nuovo', '2024-11-28', '2024-12-02', 3),
('CL005', 'Paolo', 'Gialli', '+39321654987', 'paolo@email.com', 'Gialli Group', 'VIP', '2024-01-05', '2024-12-01', 22),
]
c.executemany('''
INSERT OR REPLACE INTO clienti VALUES (?,?,?,?,?,?,?,?,?,?)
''', clienti_demo)
# Chiamate demo (ultimi 7 giorni)
stati = ['completata', 'in_corso', 'persa', 'richiamare']
priorita = ['bassa', 'media', 'alta', 'urgente']
motivi = ['Informazioni prodotto', 'Supporto tecnico', 'Preventivo', 'Reclamo', 'Appuntamento']
for i in range(1, 31):
data = (datetime.now() - timedelta(days=random.randint(0, 7),
hours=random.randint(0, 23),
minutes=random.randint(0, 59))).strftime('%Y-%m-%d %H:%M:%S')
c.execute('''
INSERT INTO chiamate VALUES (?,?,?,?,?,?,?,?,?,?,?)
''', (
f'CH{1000 + i}',
f'+39{random.randint(300000000, 399999999)}',
random.choice(['Mario Rossi', 'Anna Verdi', 'Luigi Bianchi', 'Giulia Neri', 'Paolo Gialli']),
random.choice(['Tech Solutions', 'Design Studio', 'Bianchi SRL', 'Gialli Group', None]),
data,
random.randint(60, 1800),
random.choice(stati),
random.choice(priorita),
random.choice(motivi),
random.choice(['Operatore 1', 'Operatore 2', 'Sistema AI', None]),
f'Trascrizione chiamata demo {i}'
))
conn.commit()
# Inizializza database
conn = init_db()
# Titolo principale
st.markdown('
๐ค IntelliCall Assistant
', unsafe_allow_html=True)
st.markdown('Sistema avanzato di segreteria telefonica AI per aziende e professionisti
', unsafe_allow_html=True)
# Sidebar
with st.sidebar:
st.image("https://img.icons8.com/color/96/000000/phone.png", width=80)
st.title("โ๏ธ Controlli")
# Filtri
st.subheader("๐ Filtri")
giorni_filtro = st.slider("Ultimi giorni", 1, 30, 7)
priorita_filtro = st.multiselect(
"Prioritร ",
["bassa", "media", "alta", "urgente"],
default=["urgente", "alta"]
)
# Azioni rapide
st.subheader("โก Azioni Rapide")
if st.button("๐ Simula Chiamata", use_container_width=True):
st.session_state.simula_chiamata = True
if st.button("๐ Aggiorna Dati", use_container_width=True):
st.rerun()
if st.button("๐ Genera Report", use_container_width=True):
st.session_state.genera_report = True
# Statistiche sidebar
st.subheader("๐ Statistiche Rapide")
c = conn.cursor()
c.execute("SELECT COUNT(*) FROM chiamate WHERE date(data) >= date('now', ?)", (f'-{giorni_filtro} days',))
chiamate_periodo = c.fetchone()[0]
c.execute("SELECT COUNT(*) FROM voicemail WHERE ascoltata = 0")
voicemail_non_ascoltate = c.fetchone()[0]
st.metric("Chiamate", chiamate_periodo)
st.metric("Voicemail", voicemail_non_ascoltate)
# Status sistema
st.subheader("๐ข Stato Sistema")
col1, col2 = st.columns(2)
with col1:
st.success("Online")
with col2:
st.info("100% Uptime")
# Layout principale
tab1, tab2, tab3, tab4, tab5 = st.tabs([
"๐ Dashboard",
"๐ Chiamate",
"๐ฅ Clienti",
"๐๏ธ Voicemail",
"โ๏ธ Configurazione"
])
# TAB 1: DASHBOARD
with tab1:
col1, col2, col3, col4 = st.columns(4)
with col1:
st.markdown('', unsafe_allow_html=True)
st.metric("Chiamate Oggi", "18", "+12% vs ieri")
st.markdown('
', unsafe_allow_html=True)
with col2:
st.markdown('', unsafe_allow_html=True)
st.metric("Voicemail Urgenti", "3", "+1")
st.markdown('
', unsafe_allow_html=True)
with col3:
st.markdown('', unsafe_allow_html=True)
st.metric("Clienti Attivi", "156", "+8")
st.markdown('
', unsafe_allow_html=True)
with col4:
st.markdown('', unsafe_allow_html=True)
st.metric("Soddisfazione", "94%", "+2.5%")
st.markdown('
', unsafe_allow_html=True)
# Grafico chiamate per ora
st.subheader("๐ Distribuzione Chiamate per Ora")
# Dati esempio per grafico
ore = [f"{h}:00" for h in range(9, 19)]
chiamate_per_ora = [random.randint(5, 25) for _ in range(len(ore))]
fig1 = go.Figure(data=[
go.Bar(
x=ore,
y=chiamate_per_ora,
marker_color='#667eea',
name='Chiamate'
)
])
fig1.update_layout(
height=400,
paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
showlegend=False
)
st.plotly_chart(fig1, use_container_width=True)
# Ultime chiamate e voicemail
col_left, col_right = st.columns(2)
with col_left:
st.subheader("๐ Ultime Chiamate")
c = conn.cursor()
c.execute('''
SELECT id, nome, data, stato, priorita
FROM chiamate
ORDER BY data DESC
LIMIT 5
''')
ultime_chiamate = c.fetchall()
for chiamata in ultime_chiamate:
with st.container():
col_a, col_b, col_c = st.columns([3, 2, 1])
with col_a:
st.write(f"**{chiamata[1]}**")
st.caption(f"{chiamata[2][11:16]}")
with col_b:
badge_class = "badge-warning"
if chiamata[3] == 'completata':
badge_class = "badge-success"
st.markdown(f'{chiamata[3]}', unsafe_allow_html=True)
with col_c:
st.markdown(f'{chiamata[4]}', unsafe_allow_html=True)
st.divider()
with col_right:
st.subheader("๐๏ธ Voicemail Recenti")
# Voicemail di esempio
voicemail_demo = [
{"cliente": "Mario Rossi", "durata": "1:45", "priorita": "urgente", "ascoltata": False},
{"cliente": "Anna Verdi", "durata": "2:20", "priorita": "alta", "ascoltata": True},
{"cliente": "Luigi Bianchi", "durata": "0:55", "priorita": "media", "ascoltata": False},
]
for vm in voicemail_demo:
with st.container():
col_x, col_y = st.columns([3, 1])
with col_x:
st.write(f"**{vm['cliente']}**")
st.caption(f"Durata: {vm['durata']}")
with col_y:
if vm['priorita'] == 'urgente':
st.error("โ ๏ธ Urgente")
elif not vm['ascoltata']:
st.warning("Nuova")
else:
st.success("โ Ascoltata")
st.divider()
# TAB 2: CHIAMATE
with tab2:
st.header("๐ Gestione Chiamate")
# Filtri avanzati
col_f1, col_f2, col_f3 = st.columns(3)
with col_f1:
data_inizio = st.date_input("Da data", datetime.now() - timedelta(days=7))
with col_f2:
data_fine = st.date_input("A data", datetime.now())
with col_f3:
stato_filtro = st.selectbox("Stato", ["Tutti", "completata", "in_corso", "persa", "richiamare"])
# Simula chiamata
if st.button("๐ฌ Simula Nuova Chiamata", type="primary"):
with st.form("simula_chiamata_form"):
col_s1, col_s2 = st.columns(2)
with col_s1:
nome = st.text_input("Nome Cliente", "Mario Rossi")
telefono = st.text_input("Telefono", "+39123456789")
with col_s2:
motivo = st.selectbox("Motivo", ["Informazioni", "Supporto", "Preventivo", "Reclamo"])
priorita = st.select_slider("Prioritร ", ["bassa", "media", "alta", "urgente"])
if st.form_submit_button("๐ Registra Chiamata"):
# Inserisci nel database
c = conn.cursor()
c.execute('''
INSERT INTO chiamate (id, numero, nome, data, stato, priorita, motivo)
VALUES (?, ?, ?, ?, ?, ?, ?)
''', (
f"CH{random.randint(10000, 99999)}",
telefono,
nome,
datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'in_corso',
priorita,
motivo
))
conn.commit()
st.success("โ
Chiamata registrata con successo!")
st.balloons()
# Tabella chiamate
st.subheader("๐ Storico Chiamate")
query = "SELECT * FROM chiamate WHERE 1=1"
params = []
if stato_filtro != "Tutti":
query += " AND stato = ?"
params.append(stato_filtro)
query += " ORDER BY data DESC LIMIT 50"
c = conn.cursor()
c.execute(query, params)
chiamate = c.fetchall()
if chiamate:
# Converti in DataFrame
columns = ['ID', 'Numero', 'Nome', 'Azienda', 'Data', 'Durata', 'Stato', 'Prioritร ', 'Motivo', 'Operatore', 'Trascrizione']
df = pd.DataFrame(chiamate, columns=columns)
# Formatta la tabella
st.dataframe(
df[['Nome', 'Numero', 'Data', 'Durata', 'Stato', 'Prioritร ', 'Motivo']],
use_container_width=True,
hide_index=True
)
else:
st.info("Nessuna chiamata trovata con i filtri selezionati.")
# TAB 3: CLIENTI
with tab3:
st.header("๐ฅ Gestione Clienti")
# Aggiungi nuovo cliente
with st.expander("โ Aggiungi Nuovo Cliente", expanded=False):
col_c1, col_c2 = st.columns(2)
with col_c1:
nuovo_nome = st.text_input("Nome")
nuovo_cognome = st.text_input("Cognome")
nuovo_email = st.text_input("Email")
with col_c2:
nuovo_telefono = st.text_input("Telefono")
nuovo_azienda = st.text_input("Azienda (opzionale)")
nuovo_tipo = st.selectbox("Tipo Cliente", ["Nuovo", "Regolare", "VIP", "Aziendale"])
if st.button("๐พ Salva Cliente", type="primary"):
c = conn.cursor()
c.execute('''
INSERT INTO clienti (id, nome, cognome, telefono, email, azienda, tipo, data_registrazione)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
''', (
f"CL{random.randint(1000, 9999)}",
nuovo_nome,
nuovo_cognome,
nuovo_telefono,
nuovo_email,
nuovo_azienda if nuovo_azienda else None,
nuovo_tipo,
datetime.now().strftime('%Y-%m-%d')
))
conn.commit()
st.success(f"Cliente {nuovo_nome} {nuovo_cognome} aggiunto con successo!")
# Lista clienti
st.subheader("๐ Clienti Registrati")
c = conn.cursor()
c.execute('SELECT * FROM clienti ORDER BY data_registrazione DESC')
clienti = c.fetchall()
if clienti:
for cliente in clienti:
with st.container():
col_cl1, col_cl2, col_cl3 = st.columns([3, 2, 1])
with col_cl1:
st.write(f"**{cliente[1]} {cliente[2]}**")
st.caption(f"๐ {cliente[3]} | โ๏ธ {cliente[4]}")
if cliente[5]:
st.caption(f"๐ข {cliente[5]}")
with col_cl2:
if cliente[6] == 'VIP':
st.markdown('VIP', unsafe_allow_html=True)
elif cliente[6] == 'Aziendale':
st.markdown('Aziendale', unsafe_allow_html=True)
else:
st.markdown(f'{cliente[6]}', unsafe_allow_html=True)
st.caption(f"Chiamate: {cliente[9]}")
with col_cl3:
st.button("๐", key=f"call_{cliente[0]}", help="Chiama cliente")
st.button("โ๏ธ", key=f"edit_{cliente[0]}", help="Modifica")
st.divider()
# TAB 4: VOCEMAIL
with tab4:
st.header("๐๏ธ Gestione Voicemail")
# Voicemail di esempio
voicemail_list = [
{
"id": "VM001",
"cliente": "Mario Rossi",
"telefono": "+39123456789",
"data": "Oggi 10:15",
"durata": "1:45",
"priorita": "urgente",
"ascoltata": False,
"trascrizione": "Buongiorno, ho un problema urgente con il servizio. Potete richiamarmi al piรน presto?"
},
{
"id": "VM002",
"cliente": "Anna Verdi",
"telefono": "+39987654321",
"data": "Oggi 11:30",
"durata": "2:20",
"priorita": "alta",
"ascoltata": True,
"trascrizione": "Salve, vorrei informazioni sul nuovo prodotto e un preventivo."
},
{
"id": "VM003",
"cliente": "Luigi Bianchi",
"telefono": "+39456123789",
"data": "Ieri 14:45",
"durata": "0:55",
"priorita": "media",
"ascoltata": False,
"trascrizione": "Ciao, รจ Luigi. Richiamami quando puoi."
},
]
for vm in voicemail_list:
with st.container():
col_v1, col_v2 = st.columns([4, 1])
with col_v1:
st.write(f"### {vm['cliente']}")
st.caption(f"๐ {vm['telefono']} โข โฑ๏ธ {vm['durata']} โข ๐ {vm['data']}")
# Mostra trascrizione
with st.expander("๐ Mostra trascrizione"):
st.write(vm['trascrizione'])
with col_v2:
if vm['priorita'] == 'urgente':
st.error("โ ๏ธ URGENTE")
elif vm['priorita'] == 'alta':
st.warning("ALTA")
else:
st.info(vm['priorita'].upper())
if not vm['ascoltata']:
if st.button("โ
Ascolta", key=f"listen_{vm['id']}"):
st.success(f"Voicemail {vm['id']} contrassegnata come ascoltata")
else:
st.success("โ Ascoltata")
st.divider()
# Analisi AI delle voicemail
with st.expander("๐ค Analisi AI delle Voicemail", expanded=False):
st.write("**Analisi automatica delle voicemail non ascoltate:**")
voicemail_non_ascoltate = [vm for vm in voicemail_list if not vm['ascoltata']]
if voicemail_non_ascoltate:
for vm in voicemail_non_ascoltate:
with st.container():
st.write(f"**{vm['cliente']}** - Prioritร : {vm['priorita']}")
# Simulazione analisi AI
sentiment = random.choice(["โ
Positivo", "โ ๏ธ Neutrale", "โ Negativo"])
urgenza = "ALTA" if vm['priorita'] in ['urgente', 'alta'] else "MEDIA"
col_a1, col_a2 = st.columns(2)
with col_a1:
st.metric("Sentiment", sentiment)
with col_a2:
st.metric("Urgenza", urgenza)
# Suggerimento AI
suggerimenti = {
"urgente": "โ ๏ธ **RICHIDAMA IMMEDIATO** - Cliente segnala problema urgente",
"alta": "๐ **Richiama entro 2 ore** - Richiesta informazioni importante",
"media": "๐
**Pianifica callback** - Richiesta standard"
}
st.info(suggerimenti.get(vm['priorita'], "Gestire quando possibile"))
st.divider()
else:
st.success("๐ Tutte le voicemail sono state ascoltate!")
# TAB 5: CONFIGURAZIONE
with tab5:
st.header("โ๏ธ Configurazione Sistema")
col_conf1, col_conf2 = st.columns(2)
with col_conf1:
st.subheader("Impostazioni Azienda")
nome_azienda = st.text_input("Nome Azienda", "IntelliCall Solutions")
orari_apertura = st.text_input("Orari Apertura", "Lun-Ven 9:00-18:00")
numero_emergenza = st.text_input("Numero Emergenza", "+39 333 1234567")
lingua = st.selectbox("Lingua Predefinita", ["Italiano", "Inglese", "Francese", "Tedesco", "Spagnolo"])
with col_conf2:
st.subheader("Impostazioni AI")
api_key = st.text_input("OpenAI API Key (opzionale)", type="password")
analisi_automatica = st.checkbox("Analisi Automatica Voicemail", value=True)
trascrizione_automatica = st.checkbox("Trascrizione Automatica", value=True)
sentiment_analysis = st.checkbox("Analisi Sentiment", value=True)
st.subheader("Notifiche")
col_not1, col_not2 = st.columns(2)
with col_not1:
email_notifiche = st.text_input("Email Notifiche", "admin@intellicall.com")
notifiche_sms = st.checkbox("Attiva notifiche SMS", value=False)
with col_not2:
notifiche_whatsapp = st.checkbox("Attiva notifiche WhatsApp", value=False)
soglia_urgenza = st.select_slider(
"Soglia Notifiche Urgenti",
options=["Solo critiche", "Alte e critiche", "Tutte le prioritร "],
value="Alte e critiche"
)
st.subheader("Sicurezza")
password = st.text_input("Password Amministratore", type="password")
autenticazione_2fa = st.checkbox("Abilita Autenticazione a Due Fattori", value=False)
# Salva configurazione
if st.button("๐พ Salva Configurazione", type="primary", use_container_width=True):
st.success("โ
Configurazione salvata con successo!")
# Simula salvataggio
config = {
"azienda": {
"nome": nome_azienda,
"orari": orari_apertura,
"emergenza": numero_emergenza,
"lingua": lingua
},
"ai": {
"analisi_automatica": analisi_automatica,
"trascrizione_automatica": trascrizione_automatica,
"sentiment_analysis": sentiment_analysis
},
"notifiche": {
"email": email_notifiche,
"sms": notifiche_sms,
"whatsapp": notifiche_whatsapp,
"soglia_urgenza": soglia_urgenza
}
}
with open("config.json", "w") as f:
json.dump(config, f, indent=2)
# Footer
st.markdown("---")
col_f1, col_f2, col_f3 = st.columns([1, 2, 1])
with col_f2:
st.markdown("""
๐ค IntelliCall Assistant v1.0 โข Sistema di segreteria telefonica AI
ยฉ 2025 Francesco Angeli by CONDORPROF โข Tutti i diritti riservati
""", unsafe_allow_html=True)
# Chiusura connessione al database
conn.close()