Spaces:
Running
Running
File size: 6,149 Bytes
74b1d78 4e9edac 6ea973b 108f5b4 6ea973b 108f5b4 d90111a 108f5b4 d90111a 108f5b4 10e2e8f 4e9edac 10e2e8f 74b1d78 ddb6622 74b1d78 4e9edac 74b1d78 4e9edac 74b1d78 4e9edac 8e2cc26 74b1d78 8e2cc26 4e9edac 74b1d78 4e9edac 74b1d78 4e9edac 3500e60 74b1d78 10e2e8f 4e9edac 10e2e8f 4e9edac 10e2e8f 8e2cc26 4e9edac 8e2cc26 6ea973b 4e9edac 74b1d78 4e9edac 10e2e8f 74b1d78 4e9edac 74b1d78 10e2e8f 4e9edac 108f5b4 4e9edac 10e2e8f 4e9edac 10e2e8f 8e2cc26 10e2e8f d90111a 10e2e8f d90111a 8e2cc26 4e9edac 10e2e8f 8e2cc26 4e9edac d90111a ae5eb96 d90111a 8e2cc26 ae5eb96 108f5b4 3500e60 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | import streamlit as st
import pandas as pd
import gspread
from google.oauth2.service_account import Credentials
import os
import json
import sys
# Ajout du chemin pour trouver les modules
sys.path.append(os.path.join(os.path.dirname(__file__), 'modules'))
# IMPORT DU NOUVEAU MODULE
try:
from modules import kyc_form, map_dashboard # <-- Ajout ici
except ImportError:
# Fallback si l'import direct échoue (structure de dossier simple)
import kyc_form
import map_dashboard # <-- Ajout ici
# ==============================================================================
# 1. CONFIGURATION DU "DIRECT DRIVER" & DESIGN
# ==============================================================================
st.set_page_config(
page_title="Vortex-Flux | Ontology",
page_icon="🔺",
layout="wide",
initial_sidebar_state="expanded"
)
# Nom exact de votre fichier Google Sheets (Doit être partagé avec l'email du bot)
SHEET_NAME = "Vortex-Flux"
# Scopes requis pour l'accès Google Drive/Sheets
SCOPES = [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive"
]
# Injection CSS : Design Gotham (Palantir) & Space Grotesk
st.markdown("""
<style>
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;700&display=swap');
.stApp { background-color: #10161A; color: #F5F8FA; font-family: 'Space Grotesk', sans-serif; }
[data-testid="stSidebar"] { background-color: #182026; border-right: 1px solid #2B95D6; }
/* Boutons Cobalt */
div.stButton > button:first-child {
background-color: #2B95D6 !important;
color: white !important;
border: none !important;
font-weight: 700;
text-transform: uppercase;
width: 100%;
transition: 0.2s;
}
div.stButton > button:hover { background-color: #1F78B4 !important; }
h1, h2, h3 { font-family: 'Space Grotesk', sans-serif !important; color: #2B95D6 !important; }
</style>
""", unsafe_allow_html=True)
# ==============================================================================
# 2. MOTEUR DE CONNEXION (GSPREAD PUR)
# ==============================================================================
@st.cache_resource
def get_gspread_client():
"""Authentification robuste via gspread sans passer par st.connection"""
raw_json = os.environ.get("GSHEETS_JSON")
if not raw_json:
st.error("🛑 SECRET MANQUANT : 'GSHEETS_JSON' est introuvable.")
return None
try:
# Création du fichier temporaire sécurisé
creds_dict = json.loads(raw_json)
with open("temp_creds.json", "w") as f:
json.dump(creds_dict, f)
# Authentification Google
credentials = Credentials.from_service_account_file("temp_creds.json", scopes=SCOPES)
client = gspread.authorize(credentials)
return client
except Exception as e:
st.error(f"⚠️ Erreur d'authentification GSpread : {e}")
return None
def get_data_from_sheet(worksheet_name):
"""Récupère les données d'un onglet sous forme de DataFrame"""
client = get_gspread_client()
if not client: return pd.DataFrame()
try:
# Ouverture du classeur par son nom
sh = client.open(SHEET_NAME)
# Sélection de l'onglet
worksheet = sh.worksheet(worksheet_name)
# Lecture des données
data = worksheet.get_all_records()
return pd.DataFrame(data)
except gspread.WorksheetNotFound:
# Si l'onglet n'existe pas encore, on renvoie vide sans planter
return pd.DataFrame()
except gspread.SpreadsheetNotFound:
st.error(f"⚠️ Fichier Google Sheet '{SHEET_NAME}' introuvable. Vérifiez le nom et le partage.")
return pd.DataFrame()
except Exception as e:
st.error(f"Erreur de lecture : {e}")
return pd.DataFrame()
# ==============================================================================
# 3. LOGIQUE ONTOLOGIQUE (IDs)
# ==============================================================================
def generate_ontology_id(prefix, sheet_tab):
df = get_data_from_sheet(sheet_tab)
# Calcul ID : Nombre de lignes + 1
next_id = len(df) + 1
return f"{prefix}-2025-{next_id:04d}" #2025 a changé pour 2026 plus tard
# ==============================================================================
# 4. INTERFACE UTILISATEUR
# ==============================================================================
client = get_gspread_client()
if client:
# --- BARRE LATÉRALE ---
st.sidebar.title("🔺🔻 VORTEX-FLUX")
st.sidebar.caption("Jumeau Numérique & Ontologie")
st.sidebar.divider()
menu = st.sidebar.radio("NAVIGATION",
["TABLEAU DE BORD", "CARTE TACTIQUE","KYC CLIENTS"]
)
# --- A. TABLEAU DE BORD ---
if menu == "TABLEAU DE BORD":
st.header("OBJECT EXPLORER")
st.success(f"✅ Liaison Directe établie avec '{SHEET_NAME}'")
col1, col2, col3 = st.columns(3)
col1.metric("CAPITAL DEHORS", "1.2M XOF", "▲ 5%")
col2.metric("FLUX ATTENDU (J+7)", "450k XOF", "▼ 2%")
col3.metric("SCORE LIQUIDITÉ", "8.5/10")
st.divider()
st.subheader("VUE ONTOLOGIQUE : CLIENTS")
df_clients = get_data_from_sheet("Clients_KYC")
if not df_clients.empty:
st.dataframe(df_clients, use_container_width=True)
else:
st.info("ℹ️ L'onglet 'Clients_KYC' est vide ou n'existe pas encore.")
# --- B. CODE DU MODULE CARTE TACTIQUE ---
elif menu == "CARTE TACTIQUE":
# Appel du nouveau module
map_dashboard.show_map_dashboard(client, SHEET_NAME)
# --- C. CODE DU MODULE KYC ---
elif menu == "KYC CLIENTS":
# APPEL DU MODULE EXTERNE
# C'est ici que la magie opère : on passe le client et la fonction ID au module
kyc_form.show_kyc_form(client, SHEET_NAME, generate_ontology_id)
|