MMOON commited on
Commit
20b4d85
·
verified ·
1 Parent(s): 6c3fb56

Create APPOK0503.py

Browse files
Files changed (1) hide show
  1. APPOK0503.py +184 -0
APPOK0503.py ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import requests
4
+ from io import BytesIO
5
+ import re
6
+
7
+ # 🖌️ Configurer le mode wide et le titre de la page
8
+ st.set_page_config(layout="wide", page_title="Veille Sanitaire SCA - BuSCA")
9
+
10
+ # 🖌️ Importer Google Fonts et personnaliser la sidebar
11
+ st.markdown("""
12
+ <style>
13
+ @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap');
14
+ * { font-family: 'Roboto', sans-serif; }
15
+ /* Personnalisation de la sidebar */
16
+ [data-testid="stSidebar"] {
17
+ background-color: #2E3B4E; /* Fond sombre et lisible */
18
+ color: #FFFFFF; /* Texte blanc pour contraste */
19
+ width: 250px; /* Largeur légèrement augmentée */
20
+ border-right: 2px solid #1E88E5; /* Bordure droite bleue élégante */
21
+ }
22
+ /* Couleur des titres dans la sidebar */
23
+ [data-testid="stSidebar"] h1,
24
+ [data-testid="stSidebar"] h2,
25
+ [data-testid="stSidebar"] h3 {
26
+ color: #1E88E5; /* Bleu lisible pour les titres */
27
+ }
28
+ /* Personnalisation des boutons dans la sidebar */
29
+ .stButton > button {
30
+ background-color: #1E88E5; /* Bleu pour les boutons */
31
+ color: white;
32
+ border-radius: 5px;
33
+ padding: 3px 8px;
34
+ margin-bottom: 10px;
35
+ width: 100%; /* Largeur du bouton égale à celle de la sidebar */
36
+ }
37
+ .stButton > button:hover {
38
+ background-color: #1565C0; /* Bleu plus foncé au survol */
39
+ }
40
+ /* Personnalisation du bouton de la sidebar (❮) */
41
+ .css-1siy2j7, .css-18ni7ap {
42
+ color: #1E88E5; /* Change la couleur de l’icône ❮ */
43
+ }
44
+ .css-1siy2j7:hover, .css-18ni7ap:hover {
45
+ color: #1565C0; /* Couleur au survol de l’icône ❮ */
46
+ }
47
+ /* Liens dans la sidebar */
48
+ [data-testid="stSidebar"] a {
49
+ color: #90CAF9; /* Liens bleus clairs pour lisibilité */
50
+ text-decoration: none;
51
+ }
52
+ [data-testid="stSidebar"] a:hover {
53
+ text-decoration: underline;
54
+ }
55
+ /* Fond et bordures des expanders dans la sidebar */
56
+ [data-testid="stSidebar"] .streamlit-expander {
57
+ background-color: #374962; /* Fond sombre pour les expanders */
58
+ border: 1px solid #1E88E5; /* Bordure bleue pour les expanders */
59
+ }
60
+ [data-testid="stSidebar"] .streamlit-expanderHeader {
61
+ color: #FFFFFF; /* Texte blanc dans les titres d'expander */
62
+ }
63
+ /* Bannière personnalisée */
64
+ .banner {
65
+ background-image: url('https://github.com/M00N69/BUSCAR/blob/main/logo%2002%20copie.jpg?raw=true');
66
+ background-size: cover;
67
+ height: 120px; /* Hauteur de la bannière */
68
+ border-radius: 5px;
69
+ margin-top: -60px; /* Remonte la bannière plus haut dans l'écran */
70
+ margin-bottom: 20px;
71
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
72
+ }
73
+ /* Liens par défaut dans le corps de la page */
74
+ a {
75
+ color: #1E88E5;
76
+ text-decoration: none;
77
+ }
78
+ a:hover {
79
+ text-decoration: underline;
80
+ }
81
+ </style>
82
+ <div class="banner"></div>
83
+ """, unsafe_allow_html=True)
84
+
85
+ # 🏷️ Titre principal et astuce d'utilisation
86
+ st.title("🔍 Veille SCA, Surveillance de la Chaine Alimentaire: BuSCA")
87
+ st.warning("👉 **Astuce :** Cliquez sur la flèche **<** en haut à gauche pour ouvrir/fermer la barre latérale et mieux voir les résultats !")
88
+
89
+ # 📦 Fonction pour charger les données avec cache
90
+ @st.cache_data
91
+ def load_data():
92
+ file_url = "https://www.plateforme-sca.fr/media/11/download"
93
+ try:
94
+ response = requests.get(file_url)
95
+ response.raise_for_status()
96
+ df = pd.read_excel(BytesIO(response.content), engine='openpyxl')
97
+ return df
98
+ except Exception as e:
99
+ st.error(f"Erreur lors du chargement des données : {e}")
100
+ return pd.DataFrame()
101
+
102
+ # 📦 Charger tous les BuSCA
103
+ df_full = load_data()
104
+
105
+ if df_full.empty:
106
+ st.write("Impossible de charger les données.")
107
+ else:
108
+ df_full.columns = df_full.columns.str.strip() # Supprimer les espaces dans les noms de colonnes
109
+ df_full = df_full.sort_values(by='BuSCA', ascending=False)
110
+
111
+ # 🌟 Appliquer par défaut le filtre sur les 5 derniers BuSCA
112
+ max_busca = int(df_full['BuSCA'].max())
113
+ min_busca = max_busca - 4 if max_busca > 4 else 1
114
+ df = df_full[(df_full['BuSCA'] >= min_busca) & (df_full['BuSCA'] <= max_busca)]
115
+
116
+ # 🌟 Menu latéral avec filtres complets
117
+ with st.sidebar:
118
+ st.header("🛠️ Filtres")
119
+
120
+ # 📌 Filtre par plage de numéros de BuSCA
121
+ with st.expander("📌 Plage de numéros de BuSCA"):
122
+ busca_range = st.slider("Numéros de BuSCA", min_value=int(df_full['BuSCA'].min()), max_value=int(df_full['BuSCA'].max()), value=(min_busca, max_busca))
123
+
124
+ # 📌 Autres filtres
125
+ with st.expander("🌍 Matrices"):
126
+ matrices = st.multiselect("Sélectionner les matrices", options=df_full['Matrice (catégories)'].unique())
127
+
128
+ with st.expander("⚠️ Dangers"):
129
+ dangers = st.multiselect("Sélectionner les dangers", options=df_full['Danger'].unique())
130
+
131
+ with st.expander("📂 Sections"):
132
+ sections = st.multiselect("Sélectionner les sections", options=df_full['Section'].unique())
133
+
134
+ with st.expander("🔎 Recherche par mots-clés"):
135
+ keywords = st.text_area("Mots-clés (séparés par des virgules)")
136
+
137
+ apply_filter = st.button("Appliquer les filtres", use_container_width=True)
138
+
139
+ # 🎯 Appliquer les filtres sur l'ensemble des BuSCA
140
+ if apply_filter:
141
+ df = df_full.copy() # Repartir sur toutes les données
142
+ with st.spinner('📊 Application des filtres...'):
143
+ df = df[(df['BuSCA'] >= busca_range[0]) & (df['BuSCA'] <= busca_range[1])]
144
+ if matrices:
145
+ df = df[df['Matrice (catégories)'].isin(matrices)]
146
+ if dangers:
147
+ df = df[df['Danger'].isin(dangers)]
148
+ if sections:
149
+ df = df[df['Section'].isin(sections)]
150
+ if keywords:
151
+ keyword_list = [kw.strip().lower() for kw in keywords.split(',')]
152
+ keyword_patterns = [re.compile(r'\b' + re.escape(kw) + r's?\b', re.IGNORECASE) for kw in keyword_list]
153
+ df = df[df.apply(lambda row: any(pattern.search(str(row)) for pattern in keyword_patterns), axis=1)]
154
+ st.success("Filtres appliqués avec succès !")
155
+
156
+ # 🗂️ Afficher les données avec `st.expander` optimisés
157
+ st.markdown("### 📑 Résultats filtrés")
158
+ for index, row in df.iterrows():
159
+ with st.expander(f"📄 {row['Titre']} (BuSCA n°{row['BuSCA']})"):
160
+ summary = row['Texte'][:200] + "..." if len(row['Texte']) > 200 else row['Texte']
161
+ st.markdown(f"**Résumé :** {summary}")
162
+ if len(row['Texte']) > 200:
163
+ st.markdown(f"**Texte complet :**\n{row['Texte']}")
164
+
165
+ # 🔗 Boutons pour les liens
166
+ link_col1, link_col2 = st.columns([1, 1])
167
+ with link_col1:
168
+ if pd.notna(row['Lien']):
169
+ st.markdown(f"[🔗 Lien 1]({row['Lien']})", unsafe_allow_html=True)
170
+ with link_col2:
171
+ if pd.notna(row['Lien2']):
172
+ st.markdown(f"[🔗 Lien 2]({row['Lien2']})", unsafe_allow_html=True)
173
+
174
+ # 🔗 Logo dans la barre latérale
175
+ st.sidebar.markdown(
176
+ """
177
+ <div style="text-align: center;">
178
+ <a href="https://www.visipilot.com" target="_blank">
179
+ <img src="https://raw.githubusercontent.com/M00N69/RAPPELCONSO/main/logo%2004%20copie.jpg" alt="Visipilot Logo" style="width: 250px; margin-top: 20px;">
180
+ </a>
181
+ </div>
182
+ """, unsafe_allow_html=True
183
+ )
184
+