142 lines
4.4 KiB
C#
142 lines
4.4 KiB
C#
using System.ComponentModel.DataAnnotations;
|
|
|
|
namespace Lagerbestand.Models;
|
|
|
|
/// <summary>
|
|
/// Priority levels for Kanban tasks
|
|
/// </summary>
|
|
public enum KanbanTaskPriority
|
|
{
|
|
Low = 0,
|
|
Medium = 1,
|
|
High = 2,
|
|
Urgent = 3
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a task/card in the Kanban board
|
|
/// </summary>
|
|
public class KanbanTask
|
|
{
|
|
public Guid Id { get; set; } = Guid.NewGuid();
|
|
|
|
[Required]
|
|
[MaxLength(200)]
|
|
public string Title { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Rich text description of the task
|
|
/// </summary>
|
|
public string? Description { get; set; }
|
|
|
|
/// <summary>
|
|
/// The column this task belongs to
|
|
/// </summary>
|
|
public Guid ColumnId { get; set; }
|
|
|
|
/// <summary>
|
|
/// Sort order within the column
|
|
/// </summary>
|
|
public int SortOrder { get; set; }
|
|
|
|
/// <summary>
|
|
/// Due date for the task
|
|
/// </summary>
|
|
public DateTime? DueDate { get; set; }
|
|
|
|
/// <summary>
|
|
/// Priority level
|
|
/// </summary>
|
|
public KanbanTaskPriority Priority { get; set; } = KanbanTaskPriority.Medium;
|
|
|
|
/// <summary>
|
|
/// Estimated time in minutes
|
|
/// </summary>
|
|
public int? EstimatedMinutes { get; set; }
|
|
|
|
/// <summary>
|
|
/// User who created the task
|
|
/// </summary>
|
|
public Guid? CreatedByUserId { get; set; }
|
|
|
|
/// <summary>
|
|
/// Whether the task is archived
|
|
/// </summary>
|
|
public bool IsArchived { get; set; }
|
|
|
|
/// <summary>
|
|
/// When the task was moved to a completed column
|
|
/// </summary>
|
|
public DateTime? CompletedAt { get; set; }
|
|
|
|
/// <summary>
|
|
/// When the task was archived
|
|
/// </summary>
|
|
public DateTime? ArchivedAt { get; set; }
|
|
|
|
/// <summary>
|
|
/// Simple notes/memo field for the task
|
|
/// </summary>
|
|
public string? NotesText { get; set; }
|
|
|
|
/// <summary>
|
|
/// Free text field for tire size notes (Reifengröße)
|
|
/// </summary>
|
|
public string? TireSizeNote { get; set; }
|
|
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
|
|
|
// Navigation properties
|
|
public virtual KanbanColumn? Column { get; set; }
|
|
public virtual AppUser? CreatedByUser { get; set; }
|
|
|
|
public virtual ICollection<KanbanTaskTodo> Todos { get; set; } = new List<KanbanTaskTodo>();
|
|
public virtual ICollection<KanbanTaskLabel> TaskLabels { get; set; } = new List<KanbanTaskLabel>();
|
|
public virtual ICollection<KanbanTaskComment> Comments { get; set; } = new List<KanbanTaskComment>();
|
|
public virtual ICollection<KanbanTaskNote> Notes { get; set; } = new List<KanbanTaskNote>();
|
|
public virtual ICollection<KanbanTaskAttachment> Attachments { get; set; } = new List<KanbanTaskAttachment>();
|
|
public virtual ICollection<KanbanTaskAssignee> Assignees { get; set; } = new List<KanbanTaskAssignee>();
|
|
public virtual ICollection<KanbanTaskCustomer> TaskCustomers { get; set; } = new List<KanbanTaskCustomer>();
|
|
public virtual ICollection<KanbanTaskTireStack> TaskTireStacks { get; set; } = new List<KanbanTaskTireStack>();
|
|
|
|
// Computed properties
|
|
public bool IsDueToday => DueDate.HasValue && DueDate.Value.Date == DateTime.UtcNow.Date && !CompletedAt.HasValue;
|
|
public bool IsOverdue => DueDate.HasValue && DueDate.Value.Date < DateTime.UtcNow.Date && !IsArchived && !CompletedAt.HasValue;
|
|
|
|
public int TodosCompleted => Todos.Count(t => t.IsCompleted);
|
|
public int TodosTotal => Todos.Count;
|
|
public string TodoProgress => TodosTotal > 0 ? $"{TodosCompleted}/{TodosTotal}" : "";
|
|
|
|
public string PriorityText => Priority switch
|
|
{
|
|
KanbanTaskPriority.Low => "Niedrig",
|
|
KanbanTaskPriority.Medium => "Mittel",
|
|
KanbanTaskPriority.High => "Hoch",
|
|
KanbanTaskPriority.Urgent => "Dringend",
|
|
_ => "Mittel"
|
|
};
|
|
|
|
public string PriorityIcon => Priority switch
|
|
{
|
|
KanbanTaskPriority.Low => "⬇️",
|
|
KanbanTaskPriority.Medium => "➡️",
|
|
KanbanTaskPriority.High => "⬆️",
|
|
KanbanTaskPriority.Urgent => "🔥",
|
|
_ => "➡️"
|
|
};
|
|
|
|
public string EstimatedTimeDisplay
|
|
{
|
|
get
|
|
{
|
|
if (!EstimatedMinutes.HasValue) return "";
|
|
var hours = EstimatedMinutes.Value / 60;
|
|
var mins = EstimatedMinutes.Value % 60;
|
|
if (hours > 0 && mins > 0) return $"{hours}h {mins}m";
|
|
if (hours > 0) return $"{hours}h";
|
|
return $"{mins}m";
|
|
}
|
|
}
|
|
}
|