trackWork 0.15.0

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

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

pub fn draw_tasks(f: &mut Frame, app: &App) {
    if let InputMode::Tasks { tasks, selected_index, editing, confirm_delete } = &app.input_mode {
        let chunks = Layout::default()
            .direction(Direction::Vertical)
            .constraints([
                Constraint::Length(3),  // Title
                Constraint::Min(10),   // Task table
                Constraint::Length(5), // Edit form or help
                Constraint::Length(3), // Footer
            ])
            .split(f.area());

        // Title
        let title = Paragraph::new("Tasks")
            .style(Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD))
            .block(Block::default().borders(Borders::ALL));
        f.render_widget(title, chunks[0]);

        // Task table
        let header = Row::new(vec!["Project", "Issue Key", "Name"])
            .style(Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD))
            .bottom_margin(1);

        let rows: Vec<Row> = tasks.iter().enumerate().map(|(i, task)| {
            let style = if i == *selected_index {
                Style::default().bg(Color::DarkGray).fg(Color::White)
            } else {
                Style::default()
            };
            Row::new(vec![
                task.project.clone(),
                task.issue_key.clone(),
                task.name.clone(),
            ]).style(style)
        }).collect();

        let table = Table::new(
            rows,
            [
                Constraint::Percentage(25),
                Constraint::Percentage(30),
                Constraint::Percentage(45),
            ],
        )
        .header(header)
        .block(Block::default().borders(Borders::ALL).title("Task List"));

        f.render_widget(table, chunks[1]);

        // Edit form or empty area
        if let Some(edit) = editing {
            draw_edit_form(f, edit, chunks[2]);
        } else {
            let empty = Block::default().borders(Borders::ALL);
            f.render_widget(empty, chunks[2]);
        }

        // Footer
        let footer_text = if *confirm_delete {
            Line::from(vec![
                Span::styled("Delete this task? ", Style::default().fg(Color::Red).add_modifier(Modifier::BOLD)),
                Span::styled("y", Style::default().fg(Color::Green)),
                Span::raw(": Yes  "),
                Span::styled("any key", Style::default().fg(Color::Gray)),
                Span::raw(": Cancel"),
            ])
        } else if editing.is_some() {
            Line::from(vec![
                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"),
            ])
        } else {
            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("d", Style::default().fg(Color::Cyan)),
                Span::raw(": Delete  "),
                Span::styled("Esc/q", Style::default().fg(Color::Cyan)),
                Span::raw(": Back"),
            ])
        };

        let footer = Paragraph::new(footer_text)
            .block(Block::default().borders(Borders::ALL));
        f.render_widget(footer, chunks[3]);
    }
}

fn draw_edit_form(f: &mut Frame, edit: &crate::app::TaskEditState, area: Rect) {
    let is_new = edit.task_id.is_none();

    let fields: Vec<Line> = vec![
        Line::from(vec![
            if edit.current_field == 0 {
                Span::styled("> ", Style::default().fg(Color::Cyan))
            } else {
                Span::raw("  ")
            },
            Span::styled("Issue Key: ", Style::default().fg(if edit.current_field == 0 { Color::Yellow } else { Color::Gray })),
            Span::raw(&edit.issue_key),
            if edit.current_field == 0 { Span::styled("_", Style::default().fg(Color::Cyan)) } else { Span::raw("") },
        ]),
        Line::from(vec![
            if edit.current_field == 1 {
                Span::styled("> ", Style::default().fg(Color::Cyan))
            } else {
                Span::raw("  ")
            },
            Span::styled("Name: ", Style::default().fg(if edit.current_field == 1 { Color::Yellow } else { Color::Gray })),
            Span::raw(&edit.name),
            if edit.current_field == 1 { Span::styled("_", Style::default().fg(Color::Cyan)) } else { Span::raw("") },
        ]),
        Line::from(vec![
            if edit.current_field == 2 {
                Span::styled("> ", Style::default().fg(Color::Cyan))
            } else {
                Span::raw("  ")
            },
            Span::styled("Project: ", Style::default().fg(if edit.current_field == 2 { Color::Yellow } else { Color::Gray })),
            Span::raw(&edit.project),
            if edit.current_field == 2 { Span::styled("_", Style::default().fg(Color::Cyan)) } else { Span::raw("") },
        ]),
    ];

    let title = if is_new { "New Task" } else { "Edit Task" };
    let form = Paragraph::new(fields)
        .block(Block::default().borders(Borders::ALL).title(title));
    f.render_widget(form, area);
}