use ratatui::Frame;
use ratatui::layout::{Constraint, Direction, Layout};
use ratatui::style::Style;
use ratatui::widgets::{Block, BorderType, Clear, Paragraph};
use super::app::App;
use super::theme::Palette;
use super::widgets::{chain, footer, header, secondary, waterfall};
pub fn render_all(frame: &mut Frame, app: &mut App) {
let palette = Palette::detect();
let area = frame.area();
let width = area.width;
let chain_height = if width >= 80 { 9 } else { 0 };
let outer = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(1), Constraint::Length(chain_height), Constraint::Min(8), Constraint::Length(1), ])
.split(area);
header::render(frame, outer[0], app, &palette);
if chain_height > 0 {
chain::render(frame, outer[1], app, &palette);
}
if width >= 120 {
let main = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(65), Constraint::Percentage(35)])
.split(outer[2]);
waterfall::render(frame, main[0], app, &palette);
secondary::render(frame, main[1], app, &palette);
} else {
let main = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Percentage(60), Constraint::Percentage(40)])
.split(outer[2]);
waterfall::render(frame, main[0], app, &palette);
secondary::render(frame, main[1], app, &palette);
}
footer::render(frame, outer[3], app, &palette);
if let Some(ref confirmation) = app.confirmation {
render_confirmation_overlay(frame, &confirmation.prompt, &palette);
}
if app.show_help {
render_help_overlay(frame, &palette);
}
}
fn render_help_overlay(frame: &mut Frame, palette: &Palette) {
use ratatui::layout::Rect;
use ratatui::style::Modifier;
use ratatui::text::{Line, Span};
use ratatui::widgets::{Block, BorderType, Clear, Paragraph};
let area = frame.area();
let w = 56u16.min(area.width.saturating_sub(4));
let h = 22u16.min(area.height.saturating_sub(4));
let popup = Rect::new(
(area.width.saturating_sub(w)) / 2,
(area.height.saturating_sub(h)) / 2,
w,
h,
);
frame.render_widget(Clear, popup);
let key = ratatui::style::Style::new()
.fg(palette.cyan)
.add_modifier(Modifier::BOLD);
let dim = ratatui::style::Style::new().fg(palette.fg_3);
let label = ratatui::style::Style::new().fg(palette.fg_1);
let section = ratatui::style::Style::new()
.fg(palette.fg_2)
.add_modifier(Modifier::BOLD);
let mut lines = vec![
Line::raw(""),
Line::from(Span::styled(" GATES", section)),
Line::from(vec![
Span::styled(" [enter]", key),
Span::styled(" approve focused shift", label),
]),
Line::from(vec![
Span::styled(" [c] ", key),
Span::styled(" cancel focused shift", label),
]),
Line::raw(""),
Line::from(Span::styled(
" PANELS · cycle on / off; auto-returns to dials on judging",
section,
)),
Line::from(vec![
Span::styled(" [s] ", key),
Span::styled(" shifts list", label),
]),
Line::from(vec![
Span::styled(" [b] ", key),
Span::styled(" blueprints", label),
]),
Line::from(vec![
Span::styled(" [k] ", key),
Span::styled(" backlog", label),
]),
Line::from(vec![
Span::styled(" [j] ", key),
Span::styled(" judges", label),
]),
Line::from(vec![
Span::styled(" [d] ", key),
Span::styled(" force back to sat dials", label),
]),
Line::raw(""),
Line::from(Span::styled(" WATERFALL", section)),
Line::from(vec![
Span::styled(" [f] ", key),
Span::styled(" cycle filter (all/errors/tools/routing)", label),
]),
Line::raw(""),
Line::from(Span::styled(" GENERAL", section)),
Line::from(vec![
Span::styled(" [tab] ", key),
Span::styled(" cycle pane focus", label),
]),
Line::from(vec![
Span::styled(" [?] ", key),
Span::styled(" toggle this help · [esc] dismiss", label),
]),
Line::from(vec![
Span::styled(" [q] ", key),
Span::styled(" detach (daemon keeps running)", label),
]),
Line::raw(""),
Line::from(Span::styled(
" override hotkey omitted by design — see open Q3.",
dim,
)),
];
while lines.len() as u16 > h.saturating_sub(2) {
lines.pop();
}
let block = Block::bordered()
.title(Span::styled(" KEYBINDINGS ", key))
.border_type(BorderType::Double)
.border_style(ratatui::style::Style::new().fg(palette.cyan));
let para = Paragraph::new(lines).block(block).style(
ratatui::style::Style::new()
.fg(palette.fg_0)
.bg(palette.bg_0),
);
frame.render_widget(para, popup);
}
fn render_confirmation_overlay(frame: &mut Frame, prompt: &str, palette: &Palette) {
let area = frame.area();
let popup_width = 40.min(area.width.saturating_sub(2));
let popup_height = 3;
let popup_area = ratatui::layout::Rect::new(
(area.width.saturating_sub(popup_width)) / 2,
(area.height.saturating_sub(popup_height)) / 2,
popup_width,
popup_height,
);
frame.render_widget(Clear, popup_area);
let block = Block::bordered()
.title("Confirm")
.border_type(BorderType::Double)
.border_style(Style::new().fg(palette.ember));
let paragraph = Paragraph::new(prompt)
.block(block)
.alignment(ratatui::layout::Alignment::Center)
.style(Style::new().fg(palette.fg_0).bg(palette.bg_0));
frame.render_widget(paragraph, popup_area);
}