112 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			112 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C#
		
	
	
	
| 
								 | 
							
								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);
							 | 
						|||
| 
								 | 
							
								                    }
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 |