use ratatui::Frame;
use ratatui::layout::{Constraint, Direction, Layout, Rect};
use crate::presentation::tui::components::bottom_bar::bottom_bar;
use crate::presentation::tui::components::title_bar::render_title_bar;
use crate::presentation::tui::styles::TOP_BAR_HEIGHT;
pub struct ScreenTemplate<'a> {
pub subtitle: &'a str,
pub help: &'a str,
pub mode: &'a str,
}
impl<'a> ScreenTemplate<'a> {
pub fn render<F>(&self, f: &mut Frame, render_content: F)
where
F: FnOnce(&mut Frame, Rect),
{
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(TOP_BAR_HEIGHT),
Constraint::Min(0),
Constraint::Length(1),
])
.split(f.area());
render_title_bar(f, chunks[0], self.subtitle);
render_content(f, chunks[1]);
let combined = format!("{} | MODE: {}", self.help, self.mode);
let help_widget = bottom_bar(&combined);
if chunks[2].height > 0 {
f.render_widget(help_widget, chunks[2]);
} else {
let y = chunks[1].y + chunks[1].height.saturating_sub(1);
let alt = Rect::new(chunks[1].x, y, chunks[1].width, 1);
f.render_widget(help_widget, alt);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use ratatui::Terminal;
use ratatui::backend::TestBackend;
#[test]
fn render_normal_height_no_panic() {
let backend = TestBackend::new(80, 24);
let mut terminal = Terminal::new(backend).unwrap();
terminal
.draw(|f| {
ScreenTemplate {
subtitle: "Test",
help: "[q] Quit",
mode: "NORMAL",
}
.render(f, |_, _| {});
})
.unwrap();
}
#[test]
fn render_very_short_terminal_uses_fallback_help_bar() {
let backend = TestBackend::new(80, 1);
let mut terminal = Terminal::new(backend).unwrap();
terminal
.draw(|f| {
ScreenTemplate {
subtitle: "Test",
help: "[q] Quit",
mode: "NORMAL",
}
.render(f, |_, _| {});
})
.unwrap();
}
}