// src/state/pages/add_table.rs use crate::state::pages::canvas_state::CanvasState; use ratatui::widgets::TableState; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct ColumnDefinition { pub name: String, pub data_type: String, pub selected: bool, } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct IndexDefinition { pub name: String, pub selected: bool, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct LinkDefinition { pub linked_table_name: String, pub is_required: bool, pub selected: bool, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub enum AddTableFocus { #[default] InputTableName, // Field 0 for CanvasState InputColumnName, // Field 1 for CanvasState InputColumnType, // Field 2 for CanvasState AddColumnButton, // Result Tables ColumnsTable, IndexesTable, LinksTable, // Inside Tables (Scrolling Focus) InsideColumnsTable, InsideIndexesTable, InsideLinksTable, // Buttons SaveButton, DeleteSelectedButton, CancelButton, } #[derive(Debug, Clone)] pub struct AddTableState { pub profile_name: String, pub table_name: String, pub table_name_input: String, pub column_name_input: String, pub column_type_input: String, pub columns: Vec, pub indexes: Vec, pub links: Vec, pub current_focus: AddTableFocus, pub last_canvas_field: usize, pub column_table_state: TableState, pub index_table_state: TableState, pub link_table_state: TableState, pub table_name_cursor_pos: usize, pub column_name_cursor_pos: usize, pub column_type_cursor_pos: usize, pub has_unsaved_changes: bool, } impl Default for AddTableState { fn default() -> Self { // Initialize with some dummy data for demonstration AddTableState { profile_name: "default".to_string(), table_name: String::new(), table_name_input: String::new(), column_name_input: String::new(), column_type_input: String::new(), columns: Vec::new(), indexes: Vec::new(), links: Vec::new(), current_focus: AddTableFocus::InputTableName, last_canvas_field: 2, column_table_state: TableState::default(), index_table_state: TableState::default(), link_table_state: TableState::default(), table_name_cursor_pos: 0, column_name_cursor_pos: 0, column_type_cursor_pos: 0, has_unsaved_changes: false, } } } impl AddTableState { pub const INPUT_FIELD_COUNT: usize = 3; } // Implement CanvasState for the input fields impl CanvasState for AddTableState { fn current_field(&self) -> usize { match self.current_focus { AddTableFocus::InputTableName => 0, AddTableFocus::InputColumnName => 1, AddTableFocus::InputColumnType => 2, // If focus is elsewhere, default to the first field for canvas rendering logic _ => self.last_canvas_field, } } fn current_cursor_pos(&self) -> usize { match self.current_focus { AddTableFocus::InputTableName => self.table_name_cursor_pos, AddTableFocus::InputColumnName => self.column_name_cursor_pos, AddTableFocus::InputColumnType => self.column_type_cursor_pos, _ => 0, // Default if focus is not on an input field } } fn has_unsaved_changes(&self) -> bool { self.has_unsaved_changes } fn inputs(&self) -> Vec<&String> { vec![&self.table_name_input, &self.column_name_input, &self.column_type_input] } fn get_current_input(&self) -> &str { match self.current_focus { AddTableFocus::InputTableName => &self.table_name_input, AddTableFocus::InputColumnName => &self.column_name_input, AddTableFocus::InputColumnType => &self.column_type_input, _ => "", // Should not happen if called correctly } } fn get_current_input_mut(&mut self) -> &mut String { match self.current_focus { AddTableFocus::InputTableName => &mut self.table_name_input, AddTableFocus::InputColumnName => &mut self.column_name_input, AddTableFocus::InputColumnType => &mut self.column_type_input, _ => &mut self.table_name_input, } } fn fields(&self) -> Vec<&str> { // These must match the order used in render_add_table vec!["Table name", "Name", "Type"] } fn set_current_field(&mut self, index: usize) { // Update both current focus and last canvas field self.current_focus = match index { 0 => { self.last_canvas_field = 0; AddTableFocus::InputTableName }, 1 => { self.last_canvas_field = 1; AddTableFocus::InputColumnName }, 2 => { self.last_canvas_field = 2; AddTableFocus::InputColumnType }, _ => self.current_focus, // Stay on current focus if index is out of bounds }; } fn set_current_cursor_pos(&mut self, pos: usize) { match self.current_focus { AddTableFocus::InputTableName => self.table_name_cursor_pos = pos, AddTableFocus::InputColumnName => self.column_name_cursor_pos = pos, AddTableFocus::InputColumnType => self.column_type_cursor_pos = pos, _ => {} // Do nothing if focus is not on an input field } } fn set_has_unsaved_changes(&mut self, changed: bool) { self.has_unsaved_changes = changed; } // --- Autocomplete Support (Not needed for this form yet) --- fn get_suggestions(&self) -> Option<&[String]> { None } fn get_selected_suggestion_index(&self) -> Option { None } }