trackWork 0.14.2

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

use crate::app::App;

pub fn draw_weekly_stats(f: &mut Frame, app: &App, area: Rect) {
    let days_from_monday = app.current_date.weekday().num_days_from_monday();
    let week_start = app.current_date - chrono::Duration::days(days_from_monday as i64);
    let week_end = week_start + chrono::Duration::days(6);

    // Get week number (ISO 8601 week)
    let week_number = app.current_date.iso_week().week();

    let title = format!(
        "W{} ({} - {})",
        week_number,
        week_start.format(&app.config.date_format),
        week_end.format(&app.config.date_format)
    );

    let mut lines = vec![];
    let mut total_minutes = 0i64;
    let mut has_issued = false;

    for (label, minutes) in &app.weekly_stats {
        total_minutes += minutes;
        let hours = minutes / 60;
        let mins = minutes % 60;
        let duration_str = if hours > 0 {
            format!("{}h {:02}m", hours, mins)
        } else {
            format!("{}m", mins)
        };

        // Check if this is the first non-issued item
        if label.is_empty() {
            if !has_issued {
                // First non-issued item, no separator needed
            } else if !lines.is_empty() {
                // Add separator before non-issued items
                lines.push(Line::from(Span::styled(
                    "".repeat(26),
                    Style::default().fg(Color::DarkGray),
                )));
            }
        } else {
            has_issued = true;
        }

        let (display_label, color) = if label.is_empty() {
            ("(no label)".to_string(), Color::DarkGray)
        } else {
            (label.clone(), Color::Yellow)
        };

        // Truncate label if too long (use char count, not byte count)
        let display_label = if display_label.chars().count() > 12 {
            let truncated: String = display_label.chars().take(9).collect();
            format!("{}...", truncated)
        } else {
            format!("{:<12}", display_label)
        };

        lines.push(Line::from(vec![
            Span::styled(
                display_label,
                Style::default().fg(color).add_modifier(Modifier::BOLD),
            ),
            Span::raw(" "),
            Span::styled(
                format!("{:>10}", duration_str),
                Style::default().fg(Color::Cyan),
            ),
        ]));
    }

    if lines.is_empty() {
        lines.push(Line::from(Span::styled(
            "No entries this week",
            Style::default().fg(Color::DarkGray),
        )));
    } else {
        // Add separator and total
        lines.push(Line::from(Span::raw("".repeat(26))));
        let total_hours = total_minutes / 60;
        let total_mins = total_minutes % 60;
        let total_str = if total_hours > 0 {
            format!("{}h {:02}m", total_hours, total_mins)
        } else {
            format!("{}m", total_mins)
        };
        lines.push(Line::from(vec![
            Span::styled(
                "Total        ",
                Style::default()
                    .fg(Color::Green)
                    .add_modifier(Modifier::BOLD),
            ),
            Span::raw(" "),
            Span::styled(
                format!("{:>10}", total_str),
                Style::default()
                    .fg(Color::Green)
                    .add_modifier(Modifier::BOLD),
            ),
        ]));
    }

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