use crate::icons;
use crate::theme::Theme;
use arct_core::Achievement;
use ratatui::{
layout::{Alignment, Constraint, Direction, Layout, Rect},
text::{Line, Span},
widgets::{Block, Borders, Clear, Paragraph},
Frame,
};
pub struct NotificationPanel {
achievement: Achievement,
}
impl NotificationPanel {
pub fn new(achievement: Achievement) -> Self {
Self { achievement }
}
pub fn render(&self, frame: &mut Frame, theme: &Theme) {
let area = Self::centered_rect(50, 30, frame.size());
frame.render_widget(Clear, area);
let block = Block::default()
.title(" ACHIEVEMENT UNLOCKED! ")
.title_alignment(Alignment::Center)
.borders(Borders::ALL)
.border_style(theme.style_accent().add_modifier(ratatui::style::Modifier::BOLD));
let inner = block.inner(area);
frame.render_widget(block, area);
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(3), Constraint::Length(4), Constraint::Min(2), Constraint::Length(3), ])
.split(inner);
let celebration = Paragraph::new(vec![
Line::from(""),
Line::from(vec![
Span::styled("", theme.style_accent()),
Span::raw(" "),
Span::styled("", theme.style_accent()),
Span::raw(" "),
Span::styled("", theme.style_accent()),
]),
])
.alignment(Alignment::Center);
frame.render_widget(celebration, chunks[0]);
let achievement_info = Paragraph::new(vec![
Line::from(""),
Line::from(vec![
Span::styled(
self.achievement.icon,
theme.style_accent().add_modifier(ratatui::style::Modifier::BOLD),
),
Span::raw(" "),
Span::styled(
&self.achievement.title,
theme.style_accent().add_modifier(ratatui::style::Modifier::BOLD),
),
]),
])
.alignment(Alignment::Center);
frame.render_widget(achievement_info, chunks[1]);
let description = Paragraph::new(vec![
Line::from(""),
Line::from(vec![Span::styled(
&self.achievement.description,
theme.style_secondary(),
)]),
])
.alignment(Alignment::Center);
frame.render_widget(description, chunks[2]);
let footer = Paragraph::new(vec![
Line::from(vec![
icons::celebration(),
Span::styled(
format!("+{} points!", self.achievement.points),
theme.style_accent(),
),
]),
Line::from(""),
Line::from(vec![
Span::styled("Press any key to continue", theme.style_dim()),
]),
])
.alignment(Alignment::Center);
frame.render_widget(footer, chunks[3]);
if area.width > 4 && area.height > 2 {
frame.render_widget(
Paragraph::new("").block(
Block::default()
.borders(Borders::NONE)
.border_style(theme.style_accent()),
),
Rect::new(area.x, area.y, 2, 1),
);
frame.render_widget(
Paragraph::new("").block(
Block::default()
.borders(Borders::NONE)
.border_style(theme.style_accent()),
),
Rect::new(area.x + area.width - 2, area.y, 2, 1),
);
}
}
fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
let popup_layout = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Percentage((100 - percent_y) / 2),
Constraint::Percentage(percent_y),
Constraint::Percentage((100 - percent_y) / 2),
])
.split(r);
Layout::default()
.direction(Direction::Horizontal)
.constraints([
Constraint::Percentage((100 - percent_x) / 2),
Constraint::Percentage(percent_x),
Constraint::Percentage((100 - percent_x) / 2),
])
.split(popup_layout[1])[1]
}
}