use ratatui::{
layout::{Constraint, Direction, Layout, Rect},
style::{Color, Modifier, Style},
widgets::{Block, Borders, Paragraph, Wrap},
Frame,
};
use crate::app::App;
use crate::models::BoardType;
use metis_core::domain::documents::types::DocumentType;
pub fn draw_creation_dialog(f: &mut Frame, app: &App, area: Rect) {
let dialog_width = 60;
let dialog_height = 12;
let x = (area.width.saturating_sub(dialog_width)) / 2;
let y = (area.height.saturating_sub(dialog_height)) / 2;
let dialog_area = Rect {
x,
y,
width: dialog_width,
height: dialog_height,
};
f.render_widget(
Block::default()
.style(Style::default().bg(Color::Black))
.borders(Borders::ALL),
dialog_area,
);
let dialog_chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(1), Constraint::Length(1), Constraint::Length(5), Constraint::Length(1), Constraint::Min(1), ])
.margin(2)
.split(dialog_area);
let doc_type_name = match app.ui_state.current_board {
BoardType::Strategy => "Strategy",
BoardType::Initiative => "Initiative",
BoardType::Task => "Task",
BoardType::Adr => "ADR",
BoardType::Backlog => "Backlog Item",
};
let title = Paragraph::new(format!("Create New {}", doc_type_name)).style(
Style::default()
.fg(Color::Cyan)
.add_modifier(Modifier::BOLD),
);
f.render_widget(title, dialog_chunks[0]);
let input_value = app.ui_state.input_title.value();
let cursor_pos = app.ui_state.input_title.cursor();
let displayed_text = if input_value.is_empty() {
"█".to_string() } else {
let mut chars: Vec<char> = input_value.chars().collect();
if cursor_pos <= chars.len() {
chars.insert(cursor_pos, '█'); }
chars.into_iter().collect()
};
let input_widget = Paragraph::new(displayed_text)
.style(Style::default().fg(Color::White))
.block(
Block::default()
.borders(Borders::ALL)
.title(format!(
"{} Title ({}/30)",
doc_type_name,
input_value.len()
))
.style(Style::default().fg(Color::Cyan)),
);
f.render_widget(input_widget, dialog_chunks[2]);
let instructions = Paragraph::new(format!(
"Enter a title for your new {}.\nPress Enter to create or Escape to cancel.",
doc_type_name.to_lowercase()
))
.style(Style::default().fg(Color::Gray))
.wrap(Wrap { trim: true });
f.render_widget(instructions, dialog_chunks[4]);
}
pub fn draw_child_creation_dialog(f: &mut Frame, app: &App, area: Rect) {
let dialog_width = 60;
let dialog_height = 15;
let x = (area.width.saturating_sub(dialog_width)) / 2;
let y = (area.height.saturating_sub(dialog_height)) / 2;
let dialog_area = Rect {
x,
y,
width: dialog_width,
height: dialog_height,
};
f.render_widget(
Block::default()
.style(Style::default().bg(Color::Black))
.borders(Borders::ALL),
dialog_area,
);
let dialog_chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(1), Constraint::Length(1), Constraint::Length(2), Constraint::Length(1), Constraint::Length(5), Constraint::Length(1), Constraint::Min(1), ])
.margin(2)
.split(dialog_area);
let (child_doc_type, parent_type) = if let Some(selected_item) = app.get_selected_item() {
match selected_item.doc_type() {
DocumentType::Strategy => ("Initiative", "Strategy"),
DocumentType::Initiative => ("Task", "Initiative"),
_ => ("Document", "Parent"),
}
} else {
("Document", "Parent")
};
let title = Paragraph::new(format!("Create New {}", child_doc_type)).style(
Style::default()
.fg(Color::Cyan)
.add_modifier(Modifier::BOLD),
);
f.render_widget(title, dialog_chunks[0]);
let parent_info = if let Some(selected_item) = app.get_selected_item() {
format!("Parent {}: {}", parent_type, selected_item.title())
} else {
"No parent selected".to_string()
};
let parent_widget = Paragraph::new(parent_info)
.style(Style::default().fg(Color::Yellow))
.block(
Block::default()
.borders(Borders::ALL)
.title("Parent Document")
.style(Style::default().fg(Color::Yellow)),
);
f.render_widget(parent_widget, dialog_chunks[2]);
let input_value = app.ui_state.input_title.value();
let cursor_pos = app.ui_state.input_title.cursor();
let displayed_text = if input_value.is_empty() {
"█".to_string()
} else {
let mut chars: Vec<char> = input_value.chars().collect();
if cursor_pos <= chars.len() {
chars.insert(cursor_pos, '█');
}
chars.into_iter().collect()
};
let input_widget = Paragraph::new(displayed_text)
.style(Style::default().fg(Color::White))
.block(
Block::default()
.borders(Borders::ALL)
.title(format!(
"{} Title ({}/30)",
child_doc_type,
input_value.len()
))
.style(Style::default().fg(Color::Cyan)),
);
f.render_widget(input_widget, dialog_chunks[4]);
let instructions = Paragraph::new(
format!("Enter a title for your new {}.\nThis will be created under the selected {}.\nPress Enter to create or Escape to cancel.",
child_doc_type.to_lowercase(), parent_type.to_lowercase()),
)
.style(Style::default().fg(Color::Gray))
.wrap(Wrap { trim: true });
f.render_widget(instructions, dialog_chunks[6]);
}
pub fn draw_adr_creation_dialog(f: &mut Frame, app: &App, area: Rect) {
let dialog_width = 60;
let dialog_height = 16;
let x = (area.width.saturating_sub(dialog_width)) / 2;
let y = (area.height.saturating_sub(dialog_height)) / 2;
let dialog_area = Rect {
x,
y,
width: dialog_width,
height: dialog_height,
};
f.render_widget(
Block::default()
.style(Style::default().bg(Color::Black))
.borders(Borders::ALL),
dialog_area,
);
let dialog_chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(1), Constraint::Length(1), Constraint::Length(3), Constraint::Length(1), Constraint::Length(5), Constraint::Length(1), Constraint::Min(1), ])
.margin(2)
.split(dialog_area);
let title = Paragraph::new("Create Architecture Decision Record").style(
Style::default()
.fg(Color::Cyan)
.add_modifier(Modifier::BOLD),
);
f.render_widget(title, dialog_chunks[0]);
let context_info = if let Some(selected_item) = app.get_selected_item() {
format!(
"Context will be extracted from:\n{}: {}",
selected_item.doc_type(),
selected_item.title()
)
} else {
"No context document selected.\nADR will be created without context.".to_string()
};
let context_widget = Paragraph::new(context_info)
.style(Style::default().fg(Color::Yellow))
.block(
Block::default()
.borders(Borders::ALL)
.title("Context Source")
.style(Style::default().fg(Color::Yellow)),
)
.wrap(Wrap { trim: true });
f.render_widget(context_widget, dialog_chunks[2]);
let input_value = app.ui_state.input_title.value();
let cursor_pos = app.ui_state.input_title.cursor();
let displayed_text = if input_value.is_empty() {
"█".to_string()
} else {
let mut chars: Vec<char> = input_value.chars().collect();
if cursor_pos <= chars.len() {
chars.insert(cursor_pos, '█');
}
chars.into_iter().collect()
};
let input_widget = Paragraph::new(displayed_text)
.style(Style::default().fg(Color::White))
.block(
Block::default()
.borders(Borders::ALL)
.title(format!("ADR Title ({}/50)", input_value.len()))
.style(Style::default().fg(Color::Cyan)),
);
f.render_widget(input_widget, dialog_chunks[4]);
let instructions = Paragraph::new(
"Enter a title for your new ADR.\nThe ADR will be automatically numbered.\nPress Enter to create or Escape to cancel."
)
.style(Style::default().fg(Color::Gray))
.wrap(Wrap { trim: true });
f.render_widget(instructions, dialog_chunks[6]);
}