venesis / app.py
JohnGFX's picture
Force button color and absolute centering
8748a11
import streamlit.components.v1 as components
import streamlit as st # type: ignore
import requests # type: ignore
from bs4 import BeautifulSoup # type: ignore
import google.generativeai as genai # type: ignore
import pypdf as PyPDF2 # type: ignore
import json
import pandas as pd # type: ignore
from datetime import datetime
import os
from dotenv import load_dotenv # type: ignore
# Interní moduly aplikace
from utils import JSONDatabase, validate_url, validate_pdf, logger, setup_logging
from auth import init_auth_config, load_auth_config, is_authenticated, get_current_user
# Naše nové Venegard moduly
from modules.crm import render_crm_tab
from modules.radar import render_radar_tab
from modules.sniper import render_sniper_tab
# --- 1. CONFIGURATION AND LOGGING ---
load_dotenv()
setup_logging()
st.set_page_config(
page_title="Venegard AI Hub",
page_icon="V",
layout="wide",
initial_sidebar_state="expanded"
)
# --- NUKLEÁRNÍ JS HACK NA SKRYTÍ CLOUD IKON ---
components.html(
"""
<script>
function killStreamlitBadges() {
// Musíme jít do nadřazeného okna (parent), protože tenhle script běží v iframe
var parentDoc = window.parent.document;
var targets = [
".stAppDeployButton",
"[data-testid='stAppDeployButton']",
"[data-testid='manage-app-button']",
"div[class^='viewerBadge']",
"div[class^='styles_viewerBadge']",
"#st-deploy-button"
];
targets.forEach(function(selector) {
var elements = parentDoc.querySelectorAll(selector);
elements.forEach(function(el) {
el.style.display = 'none';
el.style.opacity = '0';
el.style.visibility = 'hidden';
});
});
}
// Spustíme hned
killStreamlitBadges();
// Pro jistotu to budeme střílet každého půl vteřiny po dobu 5 vteřin,
// kdyby si Streamlit dal s načtením korunky načas.
var interval = setInterval(killStreamlitBadges, 500);
setTimeout(function() { clearInterval(interval); }, 5000);
</script>
""",
height=0,
width=0,
)
# --- 2. EXTRÉMNÍ VENEGARD CSS A PLOVOUCÍ TLAČÍTKO ---
st.markdown("""
<style>
/* FONTY */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
/* ZABITÍ OŠKLIVÉHO SCROLLBARU */
::-webkit-scrollbar { display: none !important; }
* { scrollbar-width: none !important; -ms-overflow-style: none !important; }
/* VYPNE ODKAZOVÁ LOGA (ANCHORY) U NADPISŮ - BRUTÁLNÍ SÍLA */
a.anchor-link, svg.icon-link, a[href^="#"] { display: none !important; }
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { display: none !important; pointer-events: none !important; }
.st-emotion-cache-1vt4ygl a { display: none !important; }
/* SCHOVÁNÍ HLAVIČKY, PATIČKY, MENU A TOOLBARU */
header[data-testid="stHeader"] { display: none !important; }
footer[data-testid="stFooter"] { display: none !important; }
[data-testid="stToolbar"], #MainMenu { display: none !important; }
/* --- ZABITÍ VŠECH STREAMLIT CLOUD IKON (Korunka, Profil, Manage App) VPRAVO DOLE --- */
.stAppDeployButton,
[data-testid="stAppDeployButton"],
[data-testid="manage-app-button"],
#st-deploy-button,
div[class^="viewerBadge_container"],
div[class^="styles_viewerBadge"],
div[data-testid="stStatusWidget"] {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
pointer-events: none !important;
}
/* Zákaz zavírání menu ZEVNITŘ */
[data-testid="stSidebarCollapseButton"] { display: none !important; }
/* Globální font a pozadí */
.stApp {
background-color: #030712 !important;
background-image: radial-gradient(circle at 50% 0%, #0f172a 0%, #030712 60%) !important;
font-family: 'Inter', -apple-system, sans-serif !important;
}
h1, h2, h3, h4, h5, h6, p, label {
color: #F9FAFB !important;
font-family: 'Inter', sans-serif !important;
}
/* SIDEBAR */
[data-testid="stSidebar"] {
position: fixed !important;
top: 0 !important;
left: 0 !important;
height: 100vh !important;
width: 280px !important;
min-width: 280px !important;
background-color: #000000 !important;
border-right: 1px solid #1F2937 !important;
overflow-y: auto !important;
transform: translateX(0) !important;
visibility: visible !important;
z-index: 100 !important;
cursor: default !important;
}
[data-testid="stSidebar"] hr { border-color: #1F2937 !important; }
[data-testid="stSidebar"] [data-testid="stSidebarNavResizer"],
[data-testid="stSidebar"] [data-testid="stSidebarResizer"] { display: none !important; }
[data-testid="stAppViewContainer"] { margin-left: 280px !important; }
[data-testid="stSidebar"] > div { display: flex !important; flex-direction: column !important; height: 100% !important; }
.vg-sidebar-main { flex: 1 1 auto !important; }
/* === OPRAVENÉ VŠECHNY INPUTY A HESLA === */
/* Cílíme na obal (wrapper), ne na samotný text, aby to zabralo i to "oko" pro heslo */
div[data-baseweb="select"] > div, div[data-baseweb="input"], textarea {
background-color: rgba(17, 24, 39, 0.7) !important;
border: 1px solid #374151 !important;
border-radius: 8px !important;
backdrop-filter: blur(10px) !important;
-webkit-backdrop-filter: blur(10px) !important;
transition: all 0.2s ease !important;
}
div[data-baseweb="select"] > div:hover, div[data-baseweb="input"]:focus-within, textarea:focus {
border-color: #1E60F2 !important;
background-color: rgba(17, 24, 39, 0.9) !important;
}
/* Vynulování vnitřku, aby se text a oko netloukly s naším obalem */
div[data-baseweb="input"] input, div[data-baseweb="input"] > div {
background-color: transparent !important;
color: #F9FAFB !important;
}
/* FILE UPLOADER */
[data-testid="stFileUploadDropzone"] {
background-color: rgba(17, 24, 39, 0.4) !important;
border: 1px dashed #374151 !important;
border-radius: 12px !important;
}
[data-testid="stFileUploadDropzone"]:hover {
border-color: #1E60F2 !important;
background-color: rgba(30, 96, 242, 0.05) !important;
}
[data-testid="stFileUploadDropzone"] div, [data-testid="stFileUploadDropzone"] span { color: #9CA3AF !important; }
/* =========================================
ULTIMÁTNÍ FIX TLAČÍTEK (VČETNĚ LOGINU)
========================================= */
button[kind="primary"],
button[kind="secondary"],
button[kind="primaryFormSubmit"],
button[kind="secondaryFormSubmit"],
button[data-testid="baseButton-primary"],
button[data-testid="baseButton-secondary"],
div.stButton > button {
background-color: #1E60F2 !important;
background: #1E60F2 !important;
border: 1px solid #1E60F2 !important;
border-radius: 8px !important;
padding: 0.5rem 1.5rem !important;
transition: all 0.2s ease !important;
}
button[kind="primary"]:hover,
button[kind="secondary"]:hover,
button[kind="primaryFormSubmit"]:hover,
button[kind="secondaryFormSubmit"]:hover,
button[data-testid="baseButton-primary"]:hover,
button[data-testid="baseButton-secondary"]:hover,
div.stButton > button:hover {
background-color: #2563EB !important;
background: #2563EB !important;
border-color: #2563EB !important;
box-shadow: 0 0 20px rgba(30, 96, 242, 0.5) !important;
transform: translateY(-1px) !important;
}
/* Vynucení bílého textu úplně všude uvnitř tlačítek */
button[kind="primary"] *,
button[kind="secondary"] *,
button[data-testid="baseButton-primary"] *,
button[data-testid="baseButton-secondary"] *,
div.stButton > button *,
div.stButton > button p {
color: #FFFFFF !important;
font-weight: 500 !important;
letter-spacing: 0.02em !important;
}
/* ZÁLOŽKY */
button[data-baseweb="tab"] {
background-color: transparent !important;
color: #6B7280 !important;
font-weight: 500 !important;
border: none !important;
padding-bottom: 12px !important;
margin-right: 20px !important;
}
button[data-baseweb="tab"][aria-selected="true"] {
color: #F9FAFB !important;
border-bottom: 2px solid #1E60F2 !important;
}
/* Tlačítko odhlásit */
[data-testid="stSidebar"] div.stButton > button {
background: transparent !important; border: 1px solid #374151 !important; color: #9CA3AF !important; width: 100% !important; box-shadow: none !important;
}
[data-testid="stSidebar"] div.stButton > button:hover {
background: rgba(30, 96, 242, 0.1) !important; border-color: #1E60F2 !important; color: #1E60F2 !important; box-shadow: none !important;
}
/* KURZOR */
div[data-baseweb="select"] input { caret-color: transparent !important; pointer-events: none !important; }
div[data-baseweb="select"] > div { cursor: pointer !important; }
input[type="text"], input[type="password"] { caret-color: #F9FAFB !important; pointer-events: auto !important; cursor: text !important; }
/* =========================================
NÁPOVĚDA V PRAVÉM DOLNÍM ROHU (FLOATING WIDGET)
========================================= */
.floating-help {
position: fixed;
bottom: 30px;
right: 30px;
z-index: 99999;
font-family: 'Inter', sans-serif;
}
.floating-help summary {
display: flex;
align-items: center;
justify-content: center;
width: 50px;
height: 50px;
background: #1E60F2;
color: white;
border-radius: 50%;
font-size: 1.5rem;
font-weight: bold;
cursor: pointer;
box-shadow: 0 4px 15px rgba(0,0,0,0.6);
list-style: none;
transition: all 0.2s ease;
}
.floating-help summary::-webkit-details-marker { display: none; }
.floating-help summary:hover { background: #2563EB; transform: scale(1.05); }
.floating-help .help-content {
position: absolute;
bottom: 65px;
right: 0;
width: 380px;
background: #0f172a;
border: 1px solid #1E60F2;
padding: 20px;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0,0,0,0.8);
color: #D1D5DB;
font-size: 0.85rem;
line-height: 1.5;
animation: fadeIn 0.2s ease-in-out;
}
.floating-help .help-content h4 { color: #FFFFFF; margin-top: 0; margin-bottom: 15px; font-size: 1.1rem; border-bottom: 1px solid #374151; padding-bottom: 8px;}
.floating-help .help-content b { color: #1E60F2; display: block; margin-top: 10px; font-size: 0.9rem;}
.floating-help .help-content p { margin-bottom: 5px; font-size: 0.85rem; margin-top: 2px;}
.floating-help .help-content ul { margin-top: 5px; margin-bottom: 10px; padding-left: 20px; }
.floating-help .help-content li { margin-bottom: 4px; }
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
:root {
--primary-color: #1E60F2 !important;
}
</style>
""", unsafe_allow_html=True)
# --- 3. LOGIN LOGIKA (STREAMLIT AUTHENTICATOR) ---
authenticator, config = init_auth_config()
if authenticator is None:
st.error("Chyba inicializace autentizace. Zkontrolujte auth.py a config.yaml")
st.stop()
auth_status = st.session_state.get("authentication_status")
if auth_status is not True:
# --- OPRAVA CENTROVÁNÍ LOGINU ---
st.markdown("""
<style>
/* Úplné skrytí sidebaru, aby neodtlačoval login doprava */
[data-testid="stSidebar"] { display: none !important; }
[data-testid="stSidebarNav"] { display: none !important; }
section[data-testid="stSidebar"] { display: none !important; width: 0 !important; }
/* Zrušíme margin zleva, který dělá ten sidebar */
[data-testid="stAppViewContainer"] { margin-left: 0 !important; width: 100vw !important; }
.stApp { overflow: hidden !important; }
/* Vycentrování hlavního bloku naprosto přesně doprostřed okna */
.block-container {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
justify-content: center !important;
height: 100vh !important;
padding: 0 !important;
max-width: 450px !important; /* Šířka login boxu */
margin: 0 auto !important; /* Horizontální centrování */
}
/* Vynucení šířky formuláře */
div[data-testid="stVerticalBlock"] {
width: 100% !important;
margin: 0 auto !important;
}
</style>
""", unsafe_allow_html=True)
st.markdown(
"<h1 style='text-align: center; margin-bottom: 2rem; font-size: 2.5rem; letter-spacing: -0.04em; width: 100%;'>Venegard AI Hub</h1>",
unsafe_allow_html=True,
)
authenticator.login(location="main")
current_status = st.session_state.get("authentication_status")
if current_status is False:
st.error("Uživatelské jméno nebo heslo je nesprávné.")
st.stop()
elif current_status is None:
st.info("Pro bezpečný přístup do firemní sítě se přihlaste.")
st.stop()
else:
st.rerun()
else:
if not st.session_state.get("login_rerun_done"):
st.session_state["login_rerun_done"] = True
st.rerun()
# ==========================================================
# VNITŘNÍ APLIKACE
# ==========================================================
# --- 4. INITIALIZE DATABASE ---
db = JSONDatabase("data/crm_database.json")
loaded_records = db.load()
if 'crm_data' not in st.session_state:
st.session_state.crm_data = loaded_records
# --- 5. GEMINI API CONFIGURATION ---
GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
if not GOOGLE_API_KEY:
st.error("Error: GOOGLE_API_KEY not found in .env file.")
st.stop()
genai.configure(api_key=GOOGLE_API_KEY)
## --- 6. HELPER FUNCTIONS ---
@st.cache_data(ttl=3600)
def scrape_website(url: str) -> str:
if not validate_url(url): return "Error: Invalid URL format."
headers = {"User-Agent": "Mozilla/5.0"}
try:
if not url.startswith(('http://', 'https://')): url = 'https://' + url
response = requests.get(url, headers=headers, timeout=10)
if response.status_code != 200: return f"Error: Status code {response.status_code}."
soup = BeautifulSoup(response.text, 'html.parser')
# Mažeme už jen skripty a styly. Patičku (footer) necháváme, jsou tam e-maily!
for element in soup(["script", "style"]): element.decompose()
return " ".join(soup.get_text(separator=' ').split())[:6000]
except Exception as e: return f"Error: {str(e)}"
def extract_pdf_text(uploaded_file) -> str:
if uploaded_file is None: return ""
is_valid, message = validate_pdf(uploaded_file)
if not is_valid:
st.warning(f"PDF Error: {message}")
return ""
try:
pdf_reader = PyPDF2.PdfReader(uploaded_file)
return "".join(page.extract_text() + "\n" for page in pdf_reader.pages)[:5000]
except Exception as e:
return ""
# --- 7. SIDEBAR ---
with st.sidebar:
st.markdown('<div class="vg-sidebar-main">', unsafe_allow_html=True)
st.markdown("""
<div style="margin-bottom: 24px;">
<h2 style="margin-bottom: 0; font-weight: 700; font-size: 1.5rem; letter-spacing: -0.03em;">
<span style="color: #FFFFFF;">VENE</span><span style="color: #1E60F2;">GARD</span>
</h2>
<p style="color: #6B7280; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.1em; margin-top: -5px;">
AI Sales Hub
</p>
</div>
""", unsafe_allow_html=True)
# --- PŘEPÍNAČ JAZYKŮ ---
ui_lang = st.radio("UI Language", ["CZ", "EN"], horizontal=True, label_visibility="collapsed", key="ui_lang")
lbl = {
"CZ": {"config": "Konfigurace", "tone": "Tón komunikace", "lang": "Jazyk sekvence", "params": "Cílení & Strategie", "seg": "Cílový segment", "foc": "Hlavní zaměření (Naše služba)", "arg": "Hlavní prodejní argument", "cta": "Cíl zprávy (CTA)", "custom_val": "Vlastní...", "custom_prompt": "Vlastní", "creat": "Kreativita modelu"},
"EN": {"config": "Configuration", "tone": "Brand Voice", "lang": "Sequence Language", "params": "Targeting & Strategy", "seg": "Target Segment", "foc": "Solution Focus (Our Service)", "arg": "Core Value Prop", "cta": "Message CTA", "custom_val": "Custom...", "custom_prompt": "Custom", "creat": "Model Creativity"}
}[ui_lang]
# --- DEFINICE MOŽNOSTÍ PODLE VENEGARD DNA (CZ / EN) ---
opts_tone = {
"CZ": ["Moderní B2B", "Úderný a přímý", "Vizionářský a Tech", "Prémiový a exkluzivní"],
"EN": ["Modern B2B", "Direct & Punchy", "Visionary Tech", "Premium & Exclusive"]
}[ui_lang]
opts_seg = {
"CZ": ["Startup", "Malá firma (SME)", "Střední podnik", "Velká korporace", "E-commerce projekt", "Agentura"],
"EN": ["Startup", "SME (Small/Medium)", "Mid-Market", "Corporate Enterprise", "E-commerce Business", "Agency"]
}[ui_lang]
opts_foc = {
"CZ": ["High-Conversion Web (Dev & Architektura)", "AI Infrastruktura a Automatizace", "Filmová produkce a Branding", "Dlouhodobý strategický růst"],
"EN": ["High-Conversion Website (Dev & Arch)", "AI Infrastructure & Automation", "Cinematic Visuals & Branding", "Long-Term Growth Partnership"]
}[ui_lang]
opts_arg = {
"CZ": ["Digitální autorita a prestiž", "Maximalizace prodejů a konverzí", "Eliminace manuální práce (24/7 AI)", "Technologická dominance a rychlost"],
"EN": ["Digital Authority & Prestige", "Maximized Sales & Conversions", "Eliminating Manual Work (24/7 AI)", "Technical Dominance & Speed"]
}[ui_lang]
opts_cta = {
"CZ": ["Domluvit Discovery Call", "Položit otevřenou otázku", "Ukázat Tech Demo", "Přímý prodej (Pitch)"],
"EN": ["Book a Discovery Call", "Ask an Open Question", "Show a Tech Demo", "Direct Pitch"]
}[ui_lang]
# -------------------------------
# VYKRESLENÍ: KONFIGURACE
# -------------------------------
st.markdown(f"<p style='color:#6B7280; font-size:0.75rem; text-transform:uppercase; letter-spacing:0.12em; margin-bottom:4px;'>{lbl['config']}</p>", unsafe_allow_html=True)
def_tone_idx = min(st.session_state.get("tone_auto_idx", 0), len(opts_tone) - 1)
tone_disp = opts_tone + [lbl["custom_val"]]
tone_choice = st.selectbox(lbl["tone"], tone_disp, index=def_tone_idx)
tone_custom = st.text_input(f"{lbl['custom_prompt']} {lbl['tone'].lower()}") if tone_choice == lbl["custom_val"] else ""
tone = tone_custom.strip() if tone_custom.strip() else tone_choice
lang_opts = ["Čeština", "English", "Deutsch", "Español", "Français", lbl["custom_val"]]
language_choice = st.selectbox(lbl["lang"], lang_opts, index=0)
language_custom = st.text_input(f"{lbl['custom_prompt']} {lbl['lang'].lower()}") if language_choice == lbl["custom_val"] else ""
language = language_custom.strip() if language_custom.strip() else language_choice
st.markdown("<hr style='border-color:#1F2937; margin: 1.25rem 0 0.75rem 0;' />", unsafe_allow_html=True)
# -------------------------------
# VYKRESLENÍ: PARAMETRY
# -------------------------------
st.markdown(f"<p style='color:#6B7280; font-size:0.75rem; text-transform:uppercase; letter-spacing:0.12em; margin-bottom:4px;'>{lbl['params']}</p>", unsafe_allow_html=True)
def_seg_idx = min(st.session_state.get("segment_auto_idx", 0), len(opts_seg) - 1)
segment_choice = st.selectbox(lbl["seg"], opts_seg + [lbl["custom_val"]], index=def_seg_idx)
segment_custom = st.text_input(f"{lbl['custom_prompt']} {lbl['seg'].lower()}") if segment_choice == lbl["custom_val"] else ""
company_size = segment_custom.strip() if segment_custom.strip() else segment_choice
def_foc_idx = min(st.session_state.get("focus_auto_idx", 0), len(opts_foc) - 1)
focus_choice = st.selectbox(lbl["foc"], opts_foc + [lbl["custom_val"]], index=def_foc_idx)
focus_custom = st.text_input(f"{lbl['custom_prompt']} {lbl['foc'].lower()}") if focus_choice == lbl["custom_val"] else ""
focus = focus_custom.strip() if focus_custom.strip() else focus_choice
def_arg_idx = min(st.session_state.get("argument_auto_idx", 0), len(opts_arg) - 1)
argument_choice = st.selectbox(lbl["arg"], opts_arg + [lbl["custom_val"]], index=def_arg_idx)
argument_custom = st.text_input(f"{lbl['custom_prompt']} {lbl['arg'].lower()}") if argument_choice == lbl["custom_val"] else ""
focus_arg = argument_custom.strip() if argument_custom.strip() else argument_choice
def_cta_idx = min(st.session_state.get("cta_auto_idx", 0), len(opts_cta) - 1)
cta_choice = st.selectbox(lbl["cta"], opts_cta + [lbl["custom_val"]], index=def_cta_idx)
cta_custom = st.text_input(f"{lbl['custom_prompt']} {lbl['cta'].lower()}") if cta_choice == lbl["custom_val"] else ""
cta_type = cta_custom.strip() if cta_custom.strip() else cta_choice
creativity = st.slider(lbl["creat"], 0.0, 1.0, 0.7, step=0.05)
st.markdown("</div>", unsafe_allow_html=True)
# -------------------------------
# PATIČKA SIDEBARU
# -------------------------------
current_user_info = get_current_user()
display_name = (
current_user_info["name"]
if current_user_info and current_user_info.get("name")
else st.session_state.get("name", "Uživatel")
)
logout_text = "Odhlásit se" if ui_lang == "CZ" else "Logout"
user_lbl = "Uživatel" if ui_lang == "CZ" else "User"
st.markdown(f"""
<div style="padding: 16px; border-radius: 12px; border: 1px solid #1F2937; background: rgba(17,24,39,0.5);">
<p style="margin: 0; color: #6B7280; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em;">{user_lbl}</p>
<p style="margin: 4px 0 0 0; color: #FFFFFF; font-weight: 700; font-size: 1.1rem;">{display_name}</p>
<p style="margin: 2px 0 0 0; color: #1E60F2; font-size: 0.75rem; font-weight: 600;">ENTERPRISE ACCESS</p>
</div>
""", unsafe_allow_html=True)
st.container(height=20, border=False)
if 'authenticator' in globals() and authenticator is not None:
authenticator.logout(logout_text, 'sidebar')
# --- 8. HLAVNÍ PLOCHA A TABS ---
main_t = {
"CZ": {
"title": "Venegard AI Execution Console",
"desc": "Centralizované řídicí rozhraní pro AI asistovaný outbound, autonomní prospecting a datové operace.",
"upload": "Doplňující kontext (PDF)"
},
"EN": {
"title": "Venegard AI Execution Console",
"desc": "Centralised control surface for AI-assisted outbound, autonomous prospecting and data operations.",
"upload": "Additional context (PDF)"
}
}[ui_lang]
st.markdown(f"""
<h1 style='font-weight: 700; letter-spacing: -0.04em; font-size: 2.4rem; margin-bottom: 0.5rem;'>
{main_t['title']}
</h1>
<p style='color: #9CA3AF; font-size: 1.0rem; max-width: 640px; margin-bottom: 2rem;'>
{main_t['desc']}
</p>
""", unsafe_allow_html=True)
uploaded_file = st.file_uploader(main_t['upload'], type=["pdf"])
st.markdown("<br>", unsafe_allow_html=True)
# --- INJEKCE PLOVOUCÍ NÁPOVĚDY O FUNKCÍCH APLIKACE ---
help_html = {
"CZ": """
<h4>💡 Jak používat tento Hub?</h4>
<b>🎯 Direct Outreach (Sniper)</b>
<p>Slouží pro precizní zacílení na <b>jednu konkrétní firmu</b>. Vložíš URL adresu a projdeš 2 kroky:</p>
<ul>
<li><b>1. Analyzovat web:</b> Autopilot prozkoumá zadanou URL, pochopí byznys klienta a automaticky nastaví ideální parametry v levém panelu.</li>
<li><b>2. Vygenerovat emaily:</b> Na základě analýzy a nastavení vygeneruje finální e-mailovou sekvenci připravenou k odeslání.</li>
</ul>
<b>📡 Auto-Prospector (Radar)</b>
<p>Autonomní vyhledávání leadů. Systém dokáže hromadně analyzovat trh, procházet data a připravovat podklady pro oslovení více firem najednou. Zastoupí dny manuální práce.</p>
<b>🗄️ Data & CRM</b>
<p>Tvoje databáze. Zde se ti do přehledné tabulky automaticky ukládají všechny vygenerované e-maily a historie oslovených firem pro pozdější použití či export.</p>
""",
"EN": """
<h4>💡 How to use this Hub?</h4>
<b>🎯 Direct Outreach (Sniper)</b>
<p>Used for precision targeting of a <b>single company</b>. Insert a URL and proceed in 2 steps:</p>
<ul>
<li><b>1. Analyze Target DNA:</b> The Autopilot scans the URL, understands the client's business, and automatically configures all parameters in the sidebar.</li>
<li><b>2. Synthesize Sequence:</b> Generates the final, ready-to-send email sequence based on the analysis and sidebar settings.</li>
</ul>
<b>📡 Auto-Prospector (Radar)</b>
<p>Autonomous lead generation. The system can analyze the market in bulk, comb through data, and prepare outreach assets for multiple companies at once. Saves days of manual work.</p>
<b>🗄️ Data & CRM</b>
<p>Your database. All generated emails and outreach history are automatically saved here into a clean table for future reference or export.</p>
"""
}[ui_lang]
st.markdown(f"""
<details class="floating-help">
<summary>?</summary>
<div class="help-content">
{help_html}
</div>
</details>
""", unsafe_allow_html=True)
# ČISTÉ ZÁLOŽKY
tab_sniper, tab_radar, tab_crm = st.tabs(["Direct Outreach", "Auto-Prospector", "Data & CRM"])
with tab_sniper:
render_sniper_tab(db, scrape_website, extract_pdf_text, uploaded_file, company_size, language, tone, focus, focus_arg, cta_type, creativity)
with tab_radar:
render_radar_tab(db, scrape_website, extract_pdf_text, uploaded_file)
with tab_crm:
render_crm_tab()
if st.session_state.crm_data:
db.save(st.session_state.crm_data)