trackWork 0.15.0

A terminal-based time tracking application for managing work sessions
use ratatui::{
    layout::Rect,
    style::{Color, Modifier, Style},
    text::{Line, Span},
    widgets::{Block, Borders, Paragraph},
    Frame,
};

use crate::app::{App, InputMode};
use crate::cursor::render_with_cursor;

/// Build the live field label (with blinking cursor) for Creating/Editing entry modes.
fn entry_field_label(
    current_field: usize,
    description: &str,
    start_time: &str,
    end_time: &str,
    issue_key: &str,
    cursor_pos: usize,
) -> String {
    match current_field {
        0 => format!("Description [{}]", render_with_cursor(description, cursor_pos, true)),
        1 => format!("Start Time [{}]", render_with_cursor(start_time, cursor_pos, true)),
        2 => format!("End Time [{}]", render_with_cursor(end_time, cursor_pos, true)),
        _ => format!("Issue Key [{}]", render_with_cursor(issue_key, cursor_pos, true)),
    }
}

pub fn draw_bottom_bar(f: &mut Frame, app: &App, area: Rect) {
    let help_text = match &app.input_mode {
        InputMode::Normal => {
            // If there's a status message, show it along with help
            if let Some(status) = &app.status_message {
                vec![
                    Line::from(vec![
                        Span::styled("Status: ", Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD)),
                        Span::raw(status),
                        Span::styled("  [ESC to clear]", Style::default().fg(Color::DarkGray)),
                    ]),
                    Line::from(vec![
                        Span::styled("n", Style::default().fg(Color::Cyan)),
                        Span::raw(": New  "),
                        Span::styled("e", Style::default().fg(Color::Cyan)),
                        Span::raw(": Edit  "),
                        Span::styled("l", Style::default().fg(Color::Cyan)),
                        Span::raw(": Log Work  "),
                        Span::styled("o", Style::default().fg(Color::Cyan)),
                        Span::raw(": Open Issue  "),
                        Span::styled("q", Style::default().fg(Color::Cyan)),
                        Span::raw(": Quit"),
                    ]),
                ]
            } else {
                let mut spans = vec![
                    Span::styled("n", Style::default().fg(Color::Cyan)),
                    Span::raw(": New  "),
                    Span::styled("e", Style::default().fg(Color::Cyan)),
                    Span::raw(": Edit  "),
                    Span::styled("d/D", Style::default().fg(Color::Cyan)),
                    Span::raw(": Delete  "),
                    Span::styled("s", Style::default().fg(Color::Cyan)),
                    Span::raw(": Stop/ReStart  "),
                    Span::styled("l", Style::default().fg(Color::Cyan)),
                    Span::raw(": Log Work  "),
                    Span::styled("o", Style::default().fg(Color::Cyan)),
                    Span::raw(": Open Issue  "),
                    Span::styled("f", Style::default().fg(Color::Cyan)),
                    Span::raw(": New Off Work  "),
                    Span::styled("m", Style::default().fg(Color::Cyan)),
                    Span::raw(": Menu  "),
                    Span::styled("w", Style::default().fg(Color::Cyan)),
                    Span::raw(": Show Changelog  "),
                ];
                // Quit lives at the very end; on first `q` it arms a double-tap confirm.
                if app.quit_armed() {
                    spans.push(Span::styled(
                        "q",
                        Style::default().fg(Color::Red).add_modifier(Modifier::BOLD),
                    ));
                    spans.push(Span::styled(
                        ": Quit (again)",
                        Style::default().fg(Color::Red).add_modifier(Modifier::BOLD),
                    ));
                } else {
                    spans.push(Span::styled("q", Style::default().fg(Color::Cyan)));
                    spans.push(Span::raw(": Quit"));
                }
                vec![Line::from(spans)]
            }
        }
        InputMode::Editing {
            description, start_time, end_time, issue_key, current_field, cursor_pos, ..
        } => {
            let label = entry_field_label(
                *current_field, description, start_time, end_time, issue_key, *cursor_pos,
            );
            vec![Line::from(vec![
                Span::raw(format!("Editing: {} | ", label)),
                Span::styled("Enter", Style::default().fg(Color::Green)),
                Span::raw(": Save  "),
                Span::styled("Tab", Style::default().fg(Color::Cyan)),
                Span::raw(": Next Field  "),
                Span::styled("Esc", Style::default().fg(Color::Red)),
                Span::raw(": Cancel"),
            ])]
        }
        InputMode::EditingDay { start_time, end_time, current_field, cursor_pos, .. } => {
            let label = match *current_field {
                0 => format!("Start Time [{}]", render_with_cursor(start_time, *cursor_pos, true)),
                _ => format!("End Time [{}]", render_with_cursor(end_time, *cursor_pos, true)),
            };
            vec![Line::from(vec![
                Span::raw(format!("At Work: {} | ", label)),
                Span::styled("Enter", Style::default().fg(Color::Green)),
                Span::raw(": Save  "),
                Span::styled("↑/↓", Style::default().fg(Color::Cyan)),
                Span::raw(": Adjust  "),
                Span::styled("Tab", Style::default().fg(Color::Cyan)),
                Span::raw(": Next Field  "),
                Span::styled("Esc", Style::default().fg(Color::Red)),
                Span::raw(": Cancel"),
            ])]
        }
        InputMode::Creating {
            description, start_time, end_time, issue_key, current_field, cursor_pos, ..
        } => {
            let label = entry_field_label(
                *current_field, description, start_time, end_time, issue_key, *cursor_pos,
            );
            vec![Line::from(vec![
                Span::raw(format!("New Entry: {} | ", label)),
                Span::styled("Enter", Style::default().fg(Color::Green)),
                Span::raw(": Save  "),
                Span::styled("Tab", Style::default().fg(Color::Cyan)),
                Span::raw(": Next Field  "),
                Span::styled("Esc", Style::default().fg(Color::Red)),
                Span::raw(": Cancel"),
            ])]
        }
        InputMode::ConfirmDelete { .. } => {
            vec![Line::from(vec![
                Span::styled(
                    "⚠ Delete this entry? ",
                    Style::default().fg(Color::Red).add_modifier(Modifier::BOLD),
                ),
                Span::styled("Y", Style::default().fg(Color::Green)),
                Span::raw(": Yes  "),
                Span::styled("N", Style::default().fg(Color::Red)),
                Span::raw(": No  "),
                Span::styled("Esc", Style::default().fg(Color::Gray)),
                Span::raw(": Cancel"),
            ])]
        }
        InputMode::Settings { .. } => {
            // Settings mode has its own footer, so return empty
            vec![]
        }
        InputMode::WhatsNew => {
            // What's New modal has its own footer, so return empty
            vec![]
        }
        InputMode::Tasks { .. } => {
            // Tasks view has its own footer
            vec![]
        }
        InputMode::PassphrasePrompt { .. } | InputMode::PassphraseChange { .. } => {
            // Passphrase screens have their own UI
            vec![]
        }
        InputMode::OperationsMenu { .. } => {
            vec![]
        }
        InputMode::WeekSummary { .. } => {
            // Weekly summary draws full-screen with its own title bar hints
            vec![]
        }
        InputMode::Triggers { .. } => {
            // Triggers screen draws full-screen with its own footer
            vec![]
        }
        InputMode::Hotkeys => {
            // Hotkeys modal draws its own footer
            vec![]
        }
    };

    let footer = Paragraph::new(help_text).block(Block::default().borders(Borders::ALL));
    f.render_widget(footer, area);
}