""" 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()