""" Admin CRUD screen for Manufacturers in the NEXUS AUTOPARTS console application. Provides a list view with create (F3), edit (ENTER), and delete (F8/Del) operations for the manufacturers table. """ from console.core.screens import Screen from console.core.keybindings import Key from console.config import APP_NAME, VERSION from console.utils.formatting import truncate # Form field definitions for create/edit _FIELDS = [ {'label': 'Nombre', 'key': 'name', 'width': 30}, {'label': 'Tipo', 'key': 'type', 'width': 15, 'hint': 'oem/aftermarket/remanufactured'}, {'label': 'Calidad', 'key': 'quality_tier', 'width': 10, 'hint': 'premium/standard/economy'}, {'label': 'Pais', 'key': 'country', 'width': 20}, {'label': 'Website', 'key': 'website', 'width': 40}, ] # Footer labels per mode _FOOTER_LIST = [ ("F3", "Nuevo"), ("ENTER", "Editar"), ("F8", "Eliminar"), ("ESC", "Atras"), ] _FOOTER_FORM = [ ("TAB/Down", "Siguiente"), ("Up", "Anterior"), ("F9", "Guardar"), ("ESC", "Cancelar"), ] class AdminFabricantesScreen(Screen): """Admin CRUD screen for the manufacturers table.""" def __init__(self): super().__init__(name="admin_fabricantes", title="Administracion de Fabricantes") self._mode = 'list' # 'list' or 'form' self._selected = 0 self._manufacturers = [] self._editing_id = None # None = creating, int = editing self._focused_field = 0 self._form_data = {} self._dirty = False # ------------------------------------------------------------------ # Data loading # ------------------------------------------------------------------ def _load_manufacturers(self, db): """Load all manufacturers.""" self._manufacturers = db.get_manufacturers() def _init_form(self, mfr=None): """Initialise form_data from an existing manufacturer or blank.""" self._form_data = {} if mfr: for f in _FIELDS: val = mfr.get(f['key'], '') self._form_data[f['key']] = str(val) if val is not None else '' else: for f in _FIELDS: self._form_data[f['key']] = '' self._focused_field = 0 self._dirty = False # ------------------------------------------------------------------ # Render # ------------------------------------------------------------------ def render(self, context, db, renderer): renderer.draw_header( f" {APP_NAME} v{VERSION}", " ADMINISTRACION DE FABRICANTES ", ) if self._mode == 'list': self._render_list(db, renderer) else: self._render_form(renderer) def _render_list(self, db, renderer): """Render the manufacturers list.""" self._load_manufacturers(db) headers = ["NOMBRE", "TIPO", "CALIDAD", "PAIS", "WEBSITE"] widths = [20, 14, 10, 14, 20] rows = [] for m in self._manufacturers: rows.append(( truncate(m.get("name", ""), 20), truncate(m.get("type", "") or "", 14), truncate(m.get("quality_tier", "") or "", 10), truncate(m.get("country", "") or "", 14), truncate(m.get("website", "") or "", 20), )) renderer.draw_table( headers, rows, widths, page_info={ "page": 1, "total_pages": 1, "total_rows": len(rows), }, selected_row=self._selected, ) renderer.draw_footer(_FOOTER_LIST) def _render_form(self, renderer): """Render the create/edit form.""" title = "EDITAR FABRICANTE" if self._editing_id else "NUEVO FABRICANTE" fields = [] for f in _FIELDS: fields.append({ 'label': f['label'], 'value': self._form_data.get(f['key'], ''), 'width': f['width'], 'hint': f.get('hint', ''), }) renderer.draw_form(fields, focused_index=self._focused_field, title=title) renderer.draw_footer(_FOOTER_FORM) # ------------------------------------------------------------------ # Key handling # ------------------------------------------------------------------ def on_key(self, key, context, db, renderer, nav): if self._mode == 'list': return self._handle_list_key(key, db, renderer) else: return self._handle_form_key(key, db, renderer) def _handle_list_key(self, key, db, renderer): """Handle keys in list mode.""" # ESC: go back if key == Key.ESCAPE: return "back" # Arrow navigation if key == Key.UP: if self._selected > 0: self._selected -= 1 return None if key == Key.DOWN: if self._manufacturers and self._selected < len(self._manufacturers) - 1: self._selected += 1 return None # F3: create new manufacturer if key == Key.F3: self._mode = 'form' self._editing_id = None self._init_form() return None # ENTER: edit selected manufacturer if key == Key.ENTER: if self._manufacturers and 0 <= self._selected < len(self._manufacturers): mfr = self._manufacturers[self._selected] self._editing_id = mfr["id"] self._mode = 'form' self._init_form(mfr) return None # Number keys 1-9: edit manufacturer at that row index if 49 <= key <= 57: idx = key - 49 if 0 <= idx < len(self._manufacturers): mfr = self._manufacturers[idx] self._editing_id = mfr["id"] self._mode = 'form' self._init_form(mfr) return None # F8 or DEL: delete selected manufacturer if key in (Key.F8, 330): # 330 = KEY_DC (Delete) if self._manufacturers and 0 <= self._selected < len(self._manufacturers): mfr = self._manufacturers[self._selected] name = mfr.get("name", "") confirmed = renderer.show_message( f"Eliminar fabricante?\n{name}", "confirm", ) if confirmed: try: db.delete_manufacturer(mfr["id"]) except Exception as exc: renderer.show_message(f"Error:\n{exc}", "error") return None if self._selected >= len(self._manufacturers) - 1: self._selected = max(0, self._selected - 1) return None return None def _handle_form_key(self, key, db, renderer): """Handle keys in form mode.""" # ESC: cancel form (with dirty check) if key == Key.ESCAPE: if self._dirty: confirmed = renderer.show_message( "Descartar cambios?", "confirm" ) if not confirmed: return None self._mode = 'list' return None # TAB / Down: next field if key in (Key.TAB, Key.DOWN): if self._focused_field < len(_FIELDS) - 1: self._focused_field += 1 return None # Up: previous field if key == Key.UP: if self._focused_field > 0: self._focused_field -= 1 return None # F9: save if key == Key.F9: return self._save(db, renderer) # Backspace: delete last char from current field value if key in (Key.BACKSPACE, 8): field_key = _FIELDS[self._focused_field]['key'] val = self._form_data.get(field_key, '') if val: self._form_data[field_key] = val[:-1] self._dirty = True return None # Printable characters: append to current field if 32 <= key <= 126: field_def = _FIELDS[self._focused_field] field_key = field_def['key'] val = self._form_data.get(field_key, '') if len(val) < field_def['width']: self._form_data[field_key] = val + chr(key) self._dirty = True return None return None def _save(self, db, renderer): """Validate and save the form data.""" data = dict(self._form_data) # Validate required fields if not data.get('name', '').strip(): renderer.show_message("Nombre es requerido", "error") return None try: if self._editing_id: db.update_manufacturer(self._editing_id, data) renderer.show_message("Fabricante actualizado correctamente", "info") else: db.create_manufacturer(data) renderer.show_message("Fabricante creado correctamente", "info") except Exception as exc: renderer.show_message(f"Error al guardar:\n{exc}", "error") return None self._mode = 'list' self._dirty = False return None