use ratatui::Frame;
use ratatui::layout::{Constraint, Layout, Rect};
use ratatui::style::{Modifier, Style};
use ratatui::text::{Line, Span};
use ratatui::widgets::{Block, Borders, Clear, Paragraph, Wrap};
use crate::theme;
#[derive(Debug, Clone)]
pub struct ConfirmDialog {
pub title: String,
pub message: String,
pub file_count: usize,
pub score_impact: Option<f64>,
}
pub fn render_confirm_dialog(frame: &mut Frame, dialog: &ConfirmDialog) {
let t = theme::theme();
let area = centered_rect(50, 12, frame.area());
frame.render_widget(Clear, area);
let block = Block::default()
.title(format!(" {} ", dialog.title))
.title_style(
Style::default()
.fg(t.zone_yellow)
.add_modifier(Modifier::BOLD),
)
.borders(Borders::ALL)
.border_style(Style::default().fg(t.zone_yellow))
.style(Style::default().bg(t.bg));
let inner = block.inner(area);
frame.render_widget(block, area);
let chunks = Layout::vertical([Constraint::Min(4), Constraint::Length(1)]).split(inner);
let mut lines = vec![
Line::raw(""),
Line::from(Span::styled(
format!(" {}", dialog.message),
Style::default().fg(t.fg).add_modifier(Modifier::BOLD),
)),
];
if let Some(impact) = dialog.score_impact {
lines.push(Line::from(vec![
Span::styled(" Score impact: ", Style::default().fg(t.muted)),
Span::styled(
format!("+{impact:.0} points"),
Style::default()
.fg(t.zone_green)
.add_modifier(Modifier::BOLD),
),
]));
}
lines.push(Line::from(Span::styled(
format!(" Files affected: {}", dialog.file_count),
Style::default().fg(t.muted),
)));
let body = Paragraph::new(lines).wrap(Wrap { trim: false });
frame.render_widget(body, chunks[0]);
let footer = Paragraph::new(Line::from(vec![
Span::styled(" [y]", Style::default().fg(t.accent)),
Span::styled(" Confirm ", Style::default().fg(t.muted)),
Span::styled("[N]", Style::default().fg(t.accent)),
Span::styled(" Cancel (default)", Style::default().fg(t.muted)),
]));
frame.render_widget(footer, chunks[1]);
}
fn centered_rect(width: u16, height: u16, area: Rect) -> Rect {
let x = area.x + area.width.saturating_sub(width) / 2;
let y = area.y + area.height.saturating_sub(height) / 2;
Rect::new(x, y, width.min(area.width), height.min(area.height))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_confirm_dialog_creation() {
let dialog = ConfirmDialog {
title: "Confirm Batch Apply".to_string(),
message: "Apply 5 fixes?".to_string(),
file_count: 5,
score_impact: Some(12.0),
};
assert_eq!(dialog.file_count, 5);
assert!(dialog.score_impact.is_some());
assert!(dialog.message.contains('5'));
}
}