cube-tui 0.1.9

Terminal UI timer and session manager for speedcubing, with optional web dashboard and BLE (GAN) timer support.
use ratatui::{
    buffer::Buffer,
    layout::{Alignment, Constraint, Direction, Layout, Rect},
    style::{Style, Stylize},
    widgets::{Block, Borders, Clear, Padding, Paragraph, Widget},
};

use crate::model::settings::ThemeSettings;

#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum Selection {
    #[default]
    No,
    Yes,
}

pub struct ConfirmationWidget<'a> {
    pub message: &'a str,
    selection: Selection,
}

impl<'a> ConfirmationWidget<'a> {
    pub const fn new(message: &'a str, selection: Selection) -> Self {
        Self { message, selection }
    }

    pub fn render_with_theme(self, area: Rect, buf: &mut Buffer, theme: &ThemeSettings) {
        let popup_width = u16::max(area.width / 4, 30);
        let popup_height = u16::max(area.height / 5, 7);

        let x = area.x + (area.width.saturating_sub(popup_width)) / 2;
        let y = area.y + (area.height.saturating_sub(popup_height)) / 2;
        let popup_area = Rect::new(
            x,
            y,
            popup_width.min(area.width),
            popup_height.min(area.height),
        );

        Widget::render(Clear, popup_area, buf);

        let block = Block::default()
            .title("Are you sure?")
            .borders(Borders::ALL)
            .bg(theme.background())
            .padding(Padding::uniform(1))
            .border_style(Style::default().fg(theme.border()));

        let inner = block.inner(popup_area);
        block.render(popup_area, buf);

        let chunks = Layout::default()
            .direction(Direction::Vertical)
            .constraints([
                Constraint::Length(3),
                Constraint::Length(4),
                Constraint::Length(1),
            ])
            .split(inner);

        let message = Paragraph::new(self.message).style(Style::default().fg(theme.text()));
        message.render(chunks[0], buf);

        let button_area = chunks[2];
        let buttons = Layout::default()
            .direction(Direction::Horizontal)
            .constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
            .split(button_area);

        let selected_style = Style::default()
            .bg(theme.selection())
            .fg(theme.selection_text());

        let unselected_style = Style::default().fg(theme.text());

        let no_style = if self.selection == Selection::No {
            selected_style
        } else {
            unselected_style
        };

        let yes_style = if self.selection == Selection::Yes {
            selected_style
        } else {
            unselected_style
        };

        let no_paragraph = Paragraph::new("No")
            .alignment(Alignment::Center)
            .style(no_style);
        no_paragraph.render(buttons[0], buf);

        let yes_paragraph = Paragraph::new("Yes")
            .alignment(Alignment::Center)
            .style(yes_style);
        yes_paragraph.render(buttons[1], buf);
    }
}