"""UI logic for the "Validació" page.""" from __future__ import annotations from datetime import datetime from pathlib import Path from typing import Dict import streamlit as st def _build_candidates(runtime_videos: Path) -> Path: candidates = [ runtime_videos, Path(__file__).resolve().parent.parent / "videos", Path.cwd() / "videos", ] for candidate in candidates: if candidate.exists(): return candidate return candidates[0] def render_validation_page( compliance_client, runtime_videos: Path, permissions: Dict[str, bool], username: str, ) -> None: if not permissions.get("validar", False): st.warning("⚠️ No tens permisos per accedir a aquesta secció de validació.") st.stop() st.header("🔍 Validació de Vídeos") tab_videos, tab_ads = st.tabs(["📹 Validar Vídeos", "🎬 Validar Audiodescripcions"]) base_dir = _build_candidates(runtime_videos) if not base_dir.exists(): st.info("📝 No s'ha trobat la carpeta **videos**. Crea-la i afegeix-hi subcarpetes amb els teus vídeos.") st.stop() with tab_videos: st.subheader("📹 Validar Vídeos Pujats") video_folders = [] for folder in sorted(base_dir.iterdir()): if folder.is_dir() and folder.name != "completed": video_files = list(folder.glob("*.mp4")) + list(folder.glob("*.avi")) + list(folder.glob("*.mov")) if video_files: mod_time = folder.stat().st_mtime fecha = datetime.fromtimestamp(mod_time).strftime("%Y-%m-%d %H:%M") video_folders.append( { "name": folder.name, "path": str(folder), "created_at": fecha, "video_files": video_files, } ) if not video_folders: st.info("📝 No hi ha vídeos pujats pendents de validació.") else: opciones_video = [f"{video['name']} - {video['created_at']}" for video in video_folders] seleccion = st.selectbox( "Selecciona un vídeo per validar:", opciones_video, index=0 if opciones_video else None, ) if seleccion: indice = opciones_video.index(seleccion) video_seleccionat = video_folders[indice] col1, col2 = st.columns([2, 1]) with col1: st.markdown("### 📹 Informació del Vídeo") st.markdown(f"**Nom:** {video_seleccionat['name']}") st.markdown(f"**Data:** {video_seleccionat['created_at']}") st.markdown(f"**Arxius:** {len(video_seleccionat['video_files'])} vídeos trobats") if video_seleccionat["video_files"]: video_path = str(video_seleccionat["video_files"][0]) st.markdown("**Vídeo principal:**") st.video(video_path) else: st.warning("⚠️ No s'han trobat arxius de vídeo.") with col2: st.markdown("### 🔍 Accions de Validació") col_btn1, col_btn2 = st.columns(2) with col_btn1: if st.button("✅ Acceptar", type="primary", key=f"accept_video_{video_seleccionat['name']}"): success = compliance_client.record_validator_decision( document_id=f"video_{video_seleccionat['name']}", validator_email=f"{username}@veureu.local", decision="acceptat", comments=f"Vídeo validat per {username}", ) if success: st.success("✅ Vídeo acceptat i registrat al servei de compliance") else: st.error("❌ Error registrant el veredicte") with col_btn2: if st.button("❌ Rebutjar", type="secondary", key=f"reject_video_{video_seleccionat['name']}" ): success = compliance_client.record_validator_decision( document_id=f"video_{video_seleccionat['name']}", validator_email=f"{username}@veureu.local", decision="rebutjat", comments=f"Vídeo rebutjat per {username}", ) if success: st.success("✅ Vídeo rebutjat i registrat al servei de compliance") else: st.error("❌ Error registrant el veredicte") with tab_ads: st.subheader("🎬 Validar Audiodescripcions") videos_con_ad = [] if base_dir.exists(): for folder in sorted(base_dir.iterdir()): if folder.is_dir() and folder.name != "completed": for subfolder_name in ["MoE", "Salamandra"]: subfolder = folder / subfolder_name if subfolder.exists(): ad_files = list(subfolder.glob("*_ad.txt")) + list(subfolder.glob("*_ad.srt")) if ad_files: mod_time = folder.stat().st_mtime fecha = datetime.fromtimestamp(mod_time).strftime("%Y-%m-%d %H:%M") videos_con_ad.append( { "name": folder.name, "path": str(folder), "created_at": fecha, "ad_files": ad_files, "ad_folder": str(subfolder), } ) if not videos_con_ad: st.info("📝 No hi ha audiodescripcions pendents de validació.") else: videos_ad_ordenats = sorted(videos_con_ad, key=lambda x: x["created_at"], reverse=True) opciones_ad = [f"{video['name']} - {video['created_at']}" for video in videos_ad_ordenats] seleccion_ad = st.selectbox( "Selecciona una audiodescripció per validar:", opciones_ad, index=0 if opciones_ad else None, ) if seleccion_ad: indice = opciones_ad.index(seleccion_ad) video_seleccionat = videos_ad_ordenats[indice] col1, col2 = st.columns([2, 1]) with col1: st.markdown("### 🎬 Informació de l'Audiodescripció") st.markdown(f"**Vídeo:** {video_seleccionat['name']}") st.markdown(f"**Data:** {video_seleccionat['created_at']}") st.markdown(f"**Carpeta:** {Path(video_seleccionat['ad_folder']).name}") st.markdown(f"**Arxius:** {len(video_seleccionat['ad_files'])} audiodescripcions trobades") if video_seleccionat["ad_files"]: ad_path = video_seleccionat["ad_files"][0] st.markdown(f"#### 📄 Contingut ({ad_path.name}):") try: texto = ad_path.read_text(encoding="utf-8") except Exception: texto = ad_path.read_text(errors="ignore") st.text_area("Contingut de l'audiodescripció:", texto, height=300, disabled=True) else: st.warning("⚠️ No s'han trobat arxius d'audiodescripció.") with col2: st.markdown("### 🔍 Accions de Validació") col_btn1, col_btn2 = st.columns(2) with col_btn1: if st.button("✅ Acceptar", type="primary", key=f"accept_ad_{video_seleccionat['name']}"): success = compliance_client.record_validator_decision( document_id=f"ad_{video_seleccionat['name']}", validator_email=f"{username}@veureu.local", decision="acceptat", comments=f"Audiodescripció validada per {username}", ) if success: st.success("✅ Audiodescripció acceptada i registrada al servei de compliance") else: st.error("❌ Error registrant el veredicte") with col_btn2: if st.button("❌ Rebutjar", type="secondary", key=f"reject_ad_{video_seleccionat['name']}" ): success = compliance_client.record_validator_decision( document_id=f"ad_{video_seleccionat['name']}", validator_email=f"{username}@veureu.local", decision="rebutjat", comments=f"Audiodescripció rebutjada per {username}", ) if success: st.success("✅ Audiodescripció rebutjada i registrada al servei de compliance") else: st.error("❌ Error registrant el veredicte") st.markdown("---") st.markdown("### ℹ️ Informació del Procés de Validació") st.markdown( """ - **Tots els veredictes** es registren al servei de compliance per garantir la traçabilitat - **Cada validació** inclou veredicte, nom del vídeo i validador responsable - **Els registres** compleixen amb la normativa AI Act i GDPR """ )