ConTime/controller/TimeTrackerController.cs

112 lines
4.5 KiB
C#
Raw Permalink Normal View History

2025-10-12 21:47:06 +00:00
using Contime.data;
using Contime.model;
using Contime.view;
namespace Contime.controller {
public class TimeTrackerController {
private readonly TimeTrackerModel _model;
private readonly MainForm _view;
private readonly System.Windows.Forms.Timer _timer;
private const int IDLE_NOTIFICATION_MINUTES = 15;
private const int ACTIVE_TASK_NOTIFICATION_MINUTES = 60;
private bool _idleNotificationSent = false;
private bool _activeTaskNotificationSent = false;
public TimeTrackerController(TimeTrackerModel model, MainForm view) {
_model = model;
_view = view;
// Subscribe to model and view events
_model.StateChanged += OnModelStateChanged;
_model.MajorStateChanged += OnModelMajorStateChanged;
_view.WorkdayStartStopClicked += () => _model.StartStopWorkday();
_view.TaskStartStopClicked += () => _model.StartStopTask();
_view.GoOutOfContextClicked += () => _model.SwitchContext();
_view.ToggleTaskStatusClicked += () => _model.ToggleSelectedTaskStatus();
_view.AddTaskClicked += () => _model.AddTask(_view.NewTaskName);
_view.TaskSelected += (taskId) => _model.SelectTask(taskId);
_view.SaveContextClicked += () => _model.OutOfContextReason = _view.ContextText;
_view.ExportClicked += OnExportClicked;
// Setup the main timer
_timer = new System.Windows.Forms.Timer { Interval = 1000 };
_timer.Tick += OnTimerTick;
// Initial UI update
_view.UpdateView(_model);
}
private void OnTimerTick(object sender, EventArgs e) {
if (_model.CurrentState == TimeTrackerModel.AppState.Idle) {
_timer.Stop();
return;
}
_view.UpdateTimersAndState(_model);
CheckNotifications();
}
private void OnModelStateChanged() {
if (_model.CurrentState != TimeTrackerModel.AppState.Idle && !_timer.Enabled) {
_timer.Start();
}
_view.UpdateTimersAndState(_model);
// Reset notification flags on state change
_idleNotificationSent = false;
_activeTaskNotificationSent = false;
}
private void OnModelMajorStateChanged() {
// A major state change might require starting the timer (e.g., starting the workday)
if (_model.CurrentState != TimeTrackerModel.AppState.Idle && !_timer.Enabled) {
_timer.Start();
}
// This event is for when the task list needs a full refresh
_view.UpdateView(_model);
}
private void CheckNotifications() {
// Notification for being idle (workday active, no task)
if (_model.CurrentState == TimeTrackerModel.AppState.WorkdayActive &&
_model.IdleTime.TotalMinutes >= IDLE_NOTIFICATION_MINUTES &&
!_idleNotificationSent) {
_view.ShowNotification("Task Reminder", "You've been idle for over 15 minutes. Remember to select a task.");
_idleNotificationSent = true;
}
// Notification for a long-running task
if (_model.CurrentState == TimeTrackerModel.AppState.TaskActive &&
_model.ActiveTaskTime.TotalMinutes >= ACTIVE_TASK_NOTIFICATION_MINUTES &&
!_activeTaskNotificationSent) {
_view.ShowNotification("Task Check-in", $"The current task has been running for over an hour. Still on it?");
_activeTaskNotificationSent = true;
}
}
private void OnExportClicked() {
using (var sfd = new SaveFileDialog()) {
sfd.Filter = "Excel Workbook|*.xlsx";
sfd.ValidateNames = true;
sfd.FileName = $"Contime_Report_{DateTime.Now:yyyy-MM-dd}.xlsx";
if (sfd.ShowDialog() == DialogResult.OK) {
try {
var exporter = new ExcelExporter(_model.DataAccess);
exporter.Export(sfd.FileName);
_view.ShowNotification("Export Successful", $"Report saved to {sfd.FileName}");
}
catch (Exception ex) {
MessageBox.Show($"An error occurred during export: {ex.Message}", "Export Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
}
}