// src/state/pages/add_table.rs use canvas::{DataProvider, AppMode}; 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, pub app_mode: canvas::AppMode, } impl Default for AddTableState { fn default() -> Self { 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, app_mode: canvas::AppMode::Edit, } } } impl AddTableState { pub const INPUT_FIELD_COUNT: usize = 3; /// Helper method to add a column from current inputs pub fn add_column_from_inputs(&mut self) -> Option { if self.column_name_input.trim().is_empty() || self.column_type_input.trim().is_empty() { return Some("Both column name and type are required".to_string()); } // Check for duplicate column names if self.columns.iter().any(|col| col.name == self.column_name_input.trim()) { return Some("Column name already exists".to_string()); } // Add the column self.columns.push(ColumnDefinition { name: self.column_name_input.trim().to_string(), data_type: self.column_type_input.trim().to_string(), selected: false, }); // Clear inputs and reset focus to column name for next entry self.column_name_input.clear(); self.column_type_input.clear(); self.column_name_cursor_pos = 0; self.column_type_cursor_pos = 0; self.current_focus = AddTableFocus::InputColumnName; self.last_canvas_field = 1; self.has_unsaved_changes = true; Some(format!("Column '{}' added successfully", self.columns.last().unwrap().name)) } /// Helper method to delete selected items pub fn delete_selected_items(&mut self) -> Option { let mut deleted_items = Vec::new(); // Remove selected columns let initial_column_count = self.columns.len(); self.columns.retain(|col| { if col.selected { deleted_items.push(format!("column '{}'", col.name)); false } else { true } }); // Remove selected indexes let initial_index_count = self.indexes.len(); self.indexes.retain(|idx| { if idx.selected { deleted_items.push(format!("index '{}'", idx.name)); false } else { true } }); // Remove selected links let initial_link_count = self.links.len(); self.links.retain(|link| { if link.selected { deleted_items.push(format!("link to '{}'", link.linked_table_name)); false } else { true } }); if deleted_items.is_empty() { Some("No items selected for deletion".to_string()) } else { self.has_unsaved_changes = true; Some(format!("Deleted: {}", deleted_items.join(", "))) } } } impl DataProvider for AddTableState { fn field_count(&self) -> usize { 3 // Table name, Column name, Column type } fn field_name(&self, index: usize) -> &str { match index { 0 => "Table name", 1 => "Name", 2 => "Type", _ => "", } } fn field_value(&self, index: usize) -> &str { match index { 0 => &self.table_name_input, 1 => &self.column_name_input, 2 => &self.column_type_input, _ => "", } } fn set_field_value(&mut self, index: usize, value: String) { match index { 0 => self.table_name_input = value, 1 => self.column_name_input = value, 2 => self.column_type_input = value, _ => {} } self.has_unsaved_changes = true; } fn supports_suggestions(&self, _field_index: usize) -> bool { false // AddTableState doesn’t use suggestions } }