| import streamlit.components.v1 as components |
| import streamlit as st |
| import requests |
| from bs4 import BeautifulSoup |
| import google.generativeai as genai |
| import pypdf as PyPDF2 |
| import json |
| import pandas as pd |
| from datetime import datetime |
| import os |
| from dotenv import load_dotenv |
|
|
| |
| 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 |
|
|
| |
| from modules.crm import render_crm_tab |
| from modules.radar import render_radar_tab |
| from modules.sniper import render_sniper_tab |
|
|
| |
| load_dotenv() |
| setup_logging() |
|
|
| st.set_page_config( |
| page_title="Venegard AI Hub", |
| page_icon="V", |
| layout="wide", |
| initial_sidebar_state="expanded" |
| ) |
| |
| 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, |
| ) |
|
|
| |
| 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) |
|
|
| |
| 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: |
| |
| 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() |
|
|
| |
| |
| |
|
|
| |
| 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 |
|
|
| |
| 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) |
|
|
| |
| @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') |
| |
| |
| 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 "" |
|
|
| |
| 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) |
|
|
| |
| 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] |
|
|
| |
| 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] |
|
|
| |
| |
| |
| 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) |
|
|
| |
| |
| |
| 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) |
|
|
| |
| |
| |
| 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') |
|
|
| |
| 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) |
|
|
| |
| 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) |
|
|
| |
| 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) |