"""Pestaña de Post-Procesamiento con agente inteligente.""" import customtkinter as ctk from gui.styles import AppStyles class PostProcessTab: """UI de la pestaña de Post-Procesamiento de CSV.""" def __init__(self, parent_tab): self.tab = parent_tab self.fonts = AppStyles.get_fonts() self.colors = AppStyles.get_colors() self.spacing = AppStyles.get_spacing() self._setup_layout() self._create_file_section() self._create_preview_section() self._create_instructions_section() self._create_code_section() self._create_log_section() self._create_result_section() # -- Layout ------------------------------------------------------------------ def _setup_layout(self): self.tab.grid_columnconfigure(0, weight=1) self.tab.grid_rowconfigure(0, weight=1) self.scroll = ctk.CTkScrollableFrame(self.tab, fg_color="transparent") self.scroll.grid(row=0, column=0, sticky="nsew", padx=10, pady=10) self.scroll.grid_columnconfigure(0, weight=1) # -- Sección archivo --------------------------------------------------------- def _create_file_section(self): frame = ctk.CTkFrame(self.scroll) frame.grid(row=0, column=0, sticky="ew", padx=5, pady=(5, 2)) frame.grid_columnconfigure(1, weight=1) lbl_title = ctk.CTkLabel(frame, text="Archivo CSV", font=self.fonts["section"]) lbl_title.grid(row=0, column=0, columnspan=3, sticky="w", padx=15, pady=(10, 5)) self.btn_select_csv = ctk.CTkButton( frame, text="Seleccionar CSV", font=self.fonts["ui"], width=160, ) self.btn_select_csv.grid(row=1, column=0, padx=15, pady=8, sticky="w") self.lbl_csv_path = ctk.CTkLabel( frame, text="Ningún archivo seleccionado", font=self.fonts["italic_small"], text_color=self.colors["gray_light"], ) self.lbl_csv_path.grid(row=1, column=1, padx=10, pady=8, sticky="w") # -- Preview datos ----------------------------------------------------------- def _create_preview_section(self): frame = ctk.CTkFrame(self.scroll) frame.grid(row=1, column=0, sticky="ew", padx=5, pady=2) frame.grid_columnconfigure(0, weight=1) lbl = ctk.CTkLabel(frame, text="Vista previa (muestra)", font=self.fonts["section"]) lbl.grid(row=0, column=0, sticky="w", padx=15, pady=(10, 5)) self.txt_preview = ctk.CTkTextbox( frame, height=200, font=self.fonts["mono_small"], state="disabled", wrap="none", ) self.txt_preview.grid(row=1, column=0, sticky="ew", padx=15, pady=(0, 10)) # -- Instrucciones ----------------------------------------------------------- def _create_instructions_section(self): frame = ctk.CTkFrame(self.scroll) frame.grid(row=2, column=0, sticky="ew", padx=5, pady=2) frame.grid_columnconfigure(0, weight=1) lbl = ctk.CTkLabel( frame, text="Instrucciones de transformación", font=self.fonts["section"], ) lbl.grid(row=0, column=0, sticky="w", padx=15, pady=(10, 2)) hint = ctk.CTkLabel( frame, text="Describe qué cambios quieres aplicar y en qué columnas. Ejemplo: " "\"En la columna 'monto', multiplicar por 1.19 para agregar IVA\"", font=self.fonts["italic_small"], text_color=self.colors["gray_light"], wraplength=900, justify="left", ) hint.grid(row=1, column=0, sticky="w", padx=15, pady=(0, 5)) self.txt_instructions = ctk.CTkTextbox( frame, height=90, font=self.fonts["ui"], wrap="word", ) self.txt_instructions.grid(row=2, column=0, sticky="ew", padx=15, pady=(0, 5)) btn_frame = ctk.CTkFrame(frame, fg_color="transparent") btn_frame.grid(row=3, column=0, sticky="ew", padx=15, pady=(0, 10)) self.btn_run = ctk.CTkButton( btn_frame, text="Generar y Aplicar", font=self.fonts["button_large"], fg_color=self.colors["primary_button"], hover_color=self.colors["primary_hover"], height=38, ) self.btn_run.pack(side="left") self.lbl_status = ctk.CTkLabel( btn_frame, text="", font=self.fonts["italic_small"], text_color=self.colors["gray_light"], ) self.lbl_status.pack(side="left", padx=15) # -- Código generado --------------------------------------------------------- def _create_code_section(self): frame = ctk.CTkFrame(self.scroll) frame.grid(row=3, column=0, sticky="ew", padx=5, pady=2) frame.grid_columnconfigure(0, weight=1) lbl = ctk.CTkLabel(frame, text="Código generado", font=self.fonts["section"]) lbl.grid(row=0, column=0, sticky="w", padx=15, pady=(10, 5)) self.txt_code = ctk.CTkTextbox( frame, height=180, font=self.fonts["mono_small"], state="disabled", wrap="none", ) self.txt_code.grid(row=1, column=0, sticky="ew", padx=15, pady=(0, 10)) # -- Log de ejecución -------------------------------------------------------- def _create_log_section(self): frame = ctk.CTkFrame(self.scroll) frame.grid(row=4, column=0, sticky="ew", padx=5, pady=2) frame.grid_columnconfigure(0, weight=1) lbl = ctk.CTkLabel(frame, text="Log de ejecución", font=self.fonts["section"]) lbl.grid(row=0, column=0, sticky="w", padx=15, pady=(10, 5)) self.txt_log = ctk.CTkTextbox( frame, height=100, font=self.fonts["mono_small"], state="disabled", wrap="word", ) self.txt_log.grid(row=1, column=0, sticky="ew", padx=15, pady=(0, 10)) # -- Resultado --------------------------------------------------------------- def _create_result_section(self): frame = ctk.CTkFrame(self.scroll) frame.grid(row=5, column=0, sticky="ew", padx=5, pady=(2, 5)) frame.grid_columnconfigure(0, weight=1) top = ctk.CTkFrame(frame, fg_color="transparent") top.grid(row=0, column=0, sticky="ew", padx=15, pady=(10, 5)) top.grid_columnconfigure(0, weight=1) lbl = ctk.CTkLabel(top, text="Vista previa del resultado", font=self.fonts["section"]) lbl.pack(side="left") self.btn_save = ctk.CTkButton( top, text="Guardar CSV", font=self.fonts["ui"], width=140, fg_color=self.colors["success"], hover_color=self.colors["success_hover"], state="disabled", ) self.btn_save.pack(side="right") self.txt_result = ctk.CTkTextbox( frame, height=200, font=self.fonts["mono_small"], state="disabled", wrap="none", ) self.txt_result.grid(row=1, column=0, sticky="ew", padx=15, pady=(0, 10)) # -- API pública ------------------------------------------------------------- def set_on_select_csv(self, callback): self.btn_select_csv.configure(command=callback) def set_on_run(self, callback): self.btn_run.configure(command=callback) def set_on_save(self, callback): self.btn_save.configure(command=callback) def set_csv_path(self, path: str): self.lbl_csv_path.configure(text=path or "Ningún archivo seleccionado") def get_instructions(self) -> str: return self.txt_instructions.get("1.0", "end").strip() def set_status(self, text: str): self.lbl_status.configure(text=text) def set_preview(self, text: str): self.txt_preview.configure(state="normal") self.txt_preview.delete("1.0", "end") self.txt_preview.insert("1.0", text) self.txt_preview.configure(state="disabled") def set_code(self, text: str): self.txt_code.configure(state="normal") self.txt_code.delete("1.0", "end") self.txt_code.insert("1.0", text) self.txt_code.configure(state="disabled") def append_log(self, text: str): self.txt_log.configure(state="normal") self.txt_log.insert("end", text + "\n") self.txt_log.see("end") self.txt_log.configure(state="disabled") def clear_log(self): self.txt_log.configure(state="normal") self.txt_log.delete("1.0", "end") self.txt_log.configure(state="disabled") def set_result(self, text: str): self.txt_result.configure(state="normal") self.txt_result.delete("1.0", "end") self.txt_result.insert("1.0", text) self.txt_result.configure(state="disabled") def enable_save(self, enabled: bool): self.btn_save.configure(state="normal" if enabled else "disabled") def enable_controls(self, enabled: bool): state = "normal" if enabled else "disabled" self.btn_select_csv.configure(state=state) self.btn_run.configure(state=state) self.txt_instructions.configure(state=state)