146 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			146 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C#
		
	
	
	
| 
								 | 
							
								using Contime.model;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								namespace Contime.view {
							 | 
						|||
| 
								 | 
							
								    public partial class MainForm : Form {
							 | 
						|||
| 
								 | 
							
								        // --- Events for the Controller ---
							 | 
						|||
| 
								 | 
							
								        public event Action WorkdayStartStopClicked;
							 | 
						|||
| 
								 | 
							
								        public event Action TaskStartStopClicked;
							 | 
						|||
| 
								 | 
							
								        public event Action GoOutOfContextClicked;
							 | 
						|||
| 
								 | 
							
								        public event Action ToggleTaskStatusClicked;
							 | 
						|||
| 
								 | 
							
								        public event Action AddTaskClicked;
							 | 
						|||
| 
								 | 
							
								        public event Action<long> TaskSelected;
							 | 
						|||
| 
								 | 
							
								        public event Action SaveContextClicked;
							 | 
						|||
| 
								 | 
							
								        public event Action ExportClicked;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        // --- Properties for the Controller ---
							 | 
						|||
| 
								 | 
							
								        public string NewTaskName => txtNewTask.Text;
							 | 
						|||
| 
								 | 
							
								        public string ContextText { get => txtContext.Text; set => txtContext.Text = value; }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        public MainForm() {
							 | 
						|||
| 
								 | 
							
								            InitializeComponent();
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        // Handles full UI redraws, especially for the task list and summary data
							 | 
						|||
| 
								 | 
							
								        public void UpdateView(TimeTrackerModel model) {
							 | 
						|||
| 
								 | 
							
								            this.SuspendLayout();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            UpdateTaskList(model);
							 | 
						|||
| 
								 | 
							
								            UpdateSummaryStats(model);
							 | 
						|||
| 
								 | 
							
								            UpdateTimersAndState(model); // Also call the lighter update to ensure consistency
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            this.ResumeLayout();
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        // Handles high-frequency updates (timers, button states)
							 | 
						|||
| 
								 | 
							
								        public void UpdateTimersAndState(TimeTrackerModel model) {
							 | 
						|||
| 
								 | 
							
								            lblWorkdayTimer.Text = model.WorkdayTime.ToString(@"hh\:mm\:ss");
							 | 
						|||
| 
								 | 
							
								            lblTaskTimer.Text = model.ActiveTaskTime.ToString(@"hh\:mm\:ss");
							 | 
						|||
| 
								 | 
							
								            lblSelectedTaskTotalTime.Text = model.SelectedTaskTotalTime.ToString(@"hh\:mm\:ss");
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            lblStatus.Text = GetStatusText(model.CurrentState);
							 | 
						|||
| 
								 | 
							
								            lblStatus.ForeColor = GetStatusColor(model.CurrentState);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            lblSelectedTask.Text = model.SelectedTask?.Name ?? "None";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // --- Update Button States and Text ---
							 | 
						|||
| 
								 | 
							
								            btnWorkdayStartStop.Text = (model.CurrentState == TimeTrackerModel.AppState.Idle) ? "Start Workday" : "Stop Workday";
							 | 
						|||
| 
								 | 
							
								            btnWorkdayStartStop.BackColor = (model.CurrentState == TimeTrackerModel.AppState.Idle) ? Color.FromArgb(0, 122, 204) : Color.FromArgb(192, 0, 0);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            btnGoOutOfContext.Enabled = model.CurrentState != TimeTrackerModel.AppState.Idle;
							 | 
						|||
| 
								 | 
							
								            btnGoOutOfContext.Text = (model.CurrentState == TimeTrackerModel.AppState.OutOfContext) ? "Return to Work" : "Go Out of Context";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            bool taskIsSelectedAndOpen = model.SelectedTask != null && model.SelectedTask.Status == "open";
							 | 
						|||
| 
								 | 
							
								            bool canStartTask = model.CurrentState == TimeTrackerModel.AppState.WorkdayActive && taskIsSelectedAndOpen;
							 | 
						|||
| 
								 | 
							
								            btnTaskStartStop.Enabled = canStartTask || model.CurrentState == TimeTrackerModel.AppState.TaskActive;
							 | 
						|||
| 
								 | 
							
								            btnTaskStartStop.Text = (model.CurrentState == TimeTrackerModel.AppState.TaskActive) ? "Stop Task" : "Start Task";
							 | 
						|||
| 
								 | 
							
								            btnTaskStartStop.BackColor = (model.CurrentState == TimeTrackerModel.AppState.TaskActive) ? Color.FromArgb(220, 53, 69) : Color.FromArgb(40, 167, 69);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            btnToggleTaskStatus.Enabled = model.SelectedTask != null && model.CurrentState != TimeTrackerModel.AppState.TaskActive;
							 | 
						|||
| 
								 | 
							
								            btnToggleTaskStatus.Text = model.SelectedTask?.Status == "open" ? "Mark as Finished" : "Re-open Task";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            lstTasks.Enabled = model.CurrentState != TimeTrackerModel.AppState.TaskActive;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // Show or hide the 'Out of Context' input fields
							 | 
						|||
| 
								 | 
							
								            bool outOfContext = model.CurrentState == TimeTrackerModel.AppState.OutOfContext;
							 | 
						|||
| 
								 | 
							
								            txtContext.Visible = outOfContext;
							 | 
						|||
| 
								 | 
							
								            btnSaveContext.Visible = outOfContext;
							 | 
						|||
| 
								 | 
							
								            if (outOfContext) ContextText = model.OutOfContextReason;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private void UpdateSummaryStats(TimeTrackerModel model) {
							 | 
						|||
| 
								 | 
							
								            lblDayTotal.Text = $"Today: {model.DayTotal:hh\\:mm\\:ss}";
							 | 
						|||
| 
								 | 
							
								            lblWeekTotal.Text = $"This Week: {model.WeekTotal:hh\\:mm\\:ss}";
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private void LstTasks_SelectedIndexChanged(object sender, EventArgs e) {
							 | 
						|||
| 
								 | 
							
								            if (lstTasks.SelectedItems.Count > 0)
							 | 
						|||
| 
								 | 
							
								                TaskSelected?.Invoke((long)lstTasks.SelectedItems[0].Tag);
							 | 
						|||
| 
								 | 
							
								            else
							 | 
						|||
| 
								 | 
							
								                TaskSelected?.Invoke(-1);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private void LstTasks_MouseDoubleClick(object sender, MouseEventArgs e) {
							 | 
						|||
| 
								 | 
							
								            if (lstTasks.SelectedItems.Count == 1) {
							 | 
						|||
| 
								 | 
							
								                var selectedItem = lstTasks.SelectedItems[0];
							 | 
						|||
| 
								 | 
							
								                string taskName = selectedItem.SubItems[0].Text;
							 | 
						|||
| 
								 | 
							
								                string totalTime = selectedItem.SubItems[1].Text;
							 | 
						|||
| 
								 | 
							
								                string status = selectedItem.SubItems[2].Text;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                string message = $"Task: {taskName}\nTotal Time: {totalTime}\nStatus: {status}";
							 | 
						|||
| 
								 | 
							
								                MessageBox.Show(message, "Task Details", MessageBoxButtons.OK, MessageBoxIcon.Information);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private void UpdateTaskList(TimeTrackerModel model) {
							 | 
						|||
| 
								 | 
							
								            lstTasks.SelectedIndexChanged -= LstTasks_SelectedIndexChanged; // Unsubscribe to prevent feedback loop
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            long? selectedTaskId = model.SelectedTask?.Id;
							 | 
						|||
| 
								 | 
							
								            lstTasks.Items.Clear();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            foreach (var task in model.Tasks) {
							 | 
						|||
| 
								 | 
							
								                var item = new ListViewItem(new[] { task.Name, task.ElapsedTime.ToString(@"hh\:mm\:ss"), task.Status }) {
							 | 
						|||
| 
								 | 
							
								                    Tag = task.Id,
							 | 
						|||
| 
								 | 
							
								                    ForeColor = task.Status == "closed" ? Color.Gray : Color.White
							 | 
						|||
| 
								 | 
							
								                };
							 | 
						|||
| 
								 | 
							
								                lstTasks.Items.Add(item);
							 | 
						|||
| 
								 | 
							
								                if (task.Id == selectedTaskId) {
							 | 
						|||
| 
								 | 
							
								                    item.Selected = true;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            lstTasks.SelectedIndexChanged += LstTasks_SelectedIndexChanged; // Re-subscribe
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private string GetStatusText(TimeTrackerModel.AppState state) {
							 | 
						|||
| 
								 | 
							
								            switch (state) {
							 | 
						|||
| 
								 | 
							
								                case TimeTrackerModel.AppState.Idle: return "Idle";
							 | 
						|||
| 
								 | 
							
								                case TimeTrackerModel.AppState.WorkdayActive: return "Workday Active";
							 | 
						|||
| 
								 | 
							
								                case TimeTrackerModel.AppState.TaskActive: return "Task in Progress";
							 | 
						|||
| 
								 | 
							
								                case TimeTrackerModel.AppState.OutOfContext: return "Out of Context";
							 | 
						|||
| 
								 | 
							
								                default: return "Unknown";
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private Color GetStatusColor(TimeTrackerModel.AppState state) {
							 | 
						|||
| 
								 | 
							
								            switch (state) {
							 | 
						|||
| 
								 | 
							
								                case TimeTrackerModel.AppState.Idle: return Color.White;
							 | 
						|||
| 
								 | 
							
								                case TimeTrackerModel.AppState.WorkdayActive: return Color.LightSkyBlue;
							 | 
						|||
| 
								 | 
							
								                case TimeTrackerModel.AppState.TaskActive: return Color.LightGreen;
							 | 
						|||
| 
								 | 
							
								                case TimeTrackerModel.AppState.OutOfContext: return Color.Orange;
							 | 
						|||
| 
								 | 
							
								                default: return Color.White;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        public void ShowNotification(string title, string message) {
							 | 
						|||
| 
								 | 
							
								            notifyIcon.BalloonTipTitle = title;
							 | 
						|||
| 
								 | 
							
								            notifyIcon.BalloonTipText = message;
							 | 
						|||
| 
								 | 
							
								            notifyIcon.ShowBalloonTip(3000);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        private void BtnExport_Click(object sender, EventArgs e) {
							 | 
						|||
| 
								 | 
							
								            ExportClicked?.Invoke();
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 |