pub mod components; use ratatui::layout::{Constraint, Direction, Layout}; use ratatui::Frame; use crate::app::SyncStats; use crate::domain::models::*; use components::*; #[derive(Debug, Clone, PartialEq)] pub enum Focus { Tabs, TaskList, Detail, } #[derive(Debug, Clone, PartialEq)] pub enum Popup { Input, DatePicker, ConfirmDelete, DeviceAuth { url: String, code: String }, } #[derive(Debug, Clone, PartialEq)] pub enum NetworkStatus { Online, Offline, Syncing, } pub struct AppView<'a> { pub lists: &'a [TaskList], pub tasks: &'a [Task], pub selected_list: usize, pub selected_task: usize, pub focus: Focus, pub show_popup: Option<&'a Popup>, pub popup_input: &'a str, pub popup_cursor: usize, pub draft_date: chrono::NaiveDateTime, pub network_status: &'a NetworkStatus, pub task_list_scroll: u16, pub detail_scroll: u16, pub auth_error: Option<&'a str>, pub sync_stats: &'a SyncStats, } pub fn draw(frame: &mut Frame, view: AppView) { let area = frame.area(); let main_layout = Layout::default() .direction(Direction::Vertical) .constraints([ Constraint::Length(3), Constraint::Min(0), Constraint::Length(1), ]) .split(area); let tabs_area = main_layout[0]; let body_area = main_layout[1]; let status_area = main_layout[2]; let is_tabs_focused = view.focus == Focus::Tabs; render_tabs_bar(frame, tabs_area, view.lists, view.selected_list, is_tabs_focused); let body_layout = Layout::default() .direction(Direction::Horizontal) .constraints([Constraint::Percentage(50), Constraint::Percentage(50)]) .split(body_area); let is_task_list_focused = view.focus == Focus::TaskList; render_task_list( frame, body_layout[0], view.tasks, view.selected_task, is_task_list_focused, view.task_list_scroll, ); let is_detail_focused = view.focus == Focus::Detail; render_detail( frame, body_layout[1], view.tasks.get(view.selected_task), is_detail_focused, view.detail_scroll, ); render_status_bar(frame, status_area, view.network_status, view.sync_stats); if let Some(popup) = view.show_popup { match popup { Popup::Input => render_input_popup(frame, area, view.popup_input, view.popup_cursor), Popup::DatePicker => render_date_picker(frame, area, view.draft_date), Popup::ConfirmDelete => render_confirm_popup(frame, area), Popup::DeviceAuth { url, code } => render_device_auth_popup(frame, area, url, code, view.auth_error), } } }