Skip to main content

metis_docs_tui/app/actions/
navigation.rs

1use crate::app::App;
2use crate::error::AppError;
3use crate::models::AppState;
4
5impl App {
6    // Board navigation methods
7    pub fn next_board(&mut self) {
8        self.ui_state
9            .next_board_with_config(&self.core_state.flight_config);
10    }
11
12    pub fn previous_board(&mut self) {
13        self.ui_state
14            .previous_board_with_config(&self.core_state.flight_config);
15    }
16
17    pub fn jump_to_strategy_board(&mut self) {
18        use crate::app::state::UiState;
19        if UiState::is_board_enabled(
20            crate::models::BoardType::Strategy,
21            &self.core_state.flight_config,
22        ) {
23            self.ui_state.current_board = crate::models::BoardType::Strategy;
24        }
25    }
26
27    pub fn jump_to_initiative_board(&mut self) {
28        use crate::app::state::UiState;
29        if UiState::is_board_enabled(
30            crate::models::BoardType::Initiative,
31            &self.core_state.flight_config,
32        ) {
33            self.ui_state.current_board = crate::models::BoardType::Initiative;
34        }
35    }
36
37    pub fn jump_to_task_board(&mut self) {
38        // Task board is always enabled
39        self.ui_state.current_board = crate::models::BoardType::Task;
40    }
41
42    pub fn jump_to_adr_board(&mut self) {
43        // ADR board is always enabled
44        self.ui_state.current_board = crate::models::BoardType::Adr;
45    }
46
47    pub fn jump_to_backlog_board(&mut self) {
48        // Backlog board is always enabled
49        self.ui_state.current_board = crate::models::BoardType::Backlog;
50    }
51
52    // Selection movement methods
53    pub fn move_selection_left(&mut self) {
54        let current_board = self.ui_state.current_board;
55        self.selection_state.move_selection_left(current_board);
56    }
57
58    pub fn move_selection_right(&mut self) {
59        let current_board = self.ui_state.current_board;
60        let board = self.ui_state.get_current_board();
61        self.selection_state
62            .move_selection_right(current_board, board.columns.len());
63    }
64
65    pub fn move_selection_up(&mut self) {
66        let current_board = self.ui_state.current_board;
67        self.selection_state.move_selection_up(current_board);
68    }
69
70    pub fn move_selection_down(&mut self) {
71        let current_board = self.ui_state.current_board;
72        let (col_idx, _) = self.selection_state.get_current_selection(current_board);
73        let board = self.ui_state.get_current_board();
74        let max_items = if col_idx < board.columns.len() {
75            board.columns[col_idx].items.len()
76        } else {
77            0
78        };
79        self.selection_state
80            .move_selection_down(current_board, max_items);
81    }
82
83    // Vision document navigation
84    pub fn view_vision_document(&mut self) {
85        // Look for vision.md in the workspace
86        if let Some(workspace_dir) = &self.core_state.workspace_dir {
87            let vision_path = workspace_dir.join("vision.md");
88            if vision_path.exists() {
89                // Create a temporary KanbanItem for the vision document
90                match std::fs::read_to_string(&vision_path) {
91                    Ok(_) => {
92                        // Set viewing state to simulate selecting the vision document
93                        // We'll use a special board type and position that doesn't exist
94                        self.ui_state.viewing_ticket =
95                            Some((crate::models::BoardType::Strategy, 999, 999));
96
97                        // Go directly to edit mode
98                        self.start_content_editing_for_vision(vision_path);
99                    }
100                    Err(e) => {
101                        self.error_handler.handle_error(AppError::IoError(format!(
102                            "Failed to read vision document: {}",
103                            e
104                        )));
105                    }
106                }
107            } else {
108                self.error_handler.handle_error(AppError::DocumentError(
109                    "No vision document found. Create one with 'metis create vision' first."
110                        .to_string(),
111                ));
112            }
113        }
114    }
115
116    fn start_content_editing_for_vision(&mut self, vision_path: std::path::PathBuf) {
117        self.ui_state.set_app_state(AppState::EditingContent);
118
119        // Load vision content
120        if let Ok(content) = std::fs::read_to_string(&vision_path) {
121            // Create and initialize textarea
122            let mut textarea = tui_textarea::TextArea::default();
123            textarea.set_block(
124                ratatui::widgets::Block::default()
125                    .borders(ratatui::widgets::Borders::ALL)
126                    .title("Vision Document Editor"),
127            );
128
129            // Set the content
130            for line in content.lines() {
131                textarea.insert_str(line);
132                textarea.insert_newline();
133            }
134
135            self.ui_state.strategy_editor = Some(textarea);
136            // Store the vision file path for saving
137            self.ui_state.editing_vision_path = Some(vision_path);
138        }
139    }
140}