diff --git a/Components/Pages/Home.razor b/Components/Pages/Home.razor index ed5f309..b16758b 100644 --- a/Components/Pages/Home.razor +++ b/Components/Pages/Home.razor @@ -16,9 +16,23 @@
+ @{ + bool dividerShown = false; + } @foreach (var ticket in TicketService.GetPendingTickets()) { -
+ // Sobald das erste wartende Ticket auftaucht und der Trenner noch nicht da ist: + @if (ticket.IsWaitingForFeedback && !dividerShown) + { +
+
+ Wartende Tickets +
+
+ dividerShown = true; // Trenner wurde gezeichnet, nicht nochmal anzeigen + } + +
@ticket.Priority
@ticket.Title
@@ -33,9 +47,18 @@ @ticket.Comments.Count Kommentare - +
+ + +
} @@ -57,7 +80,23 @@ } } - private void Complete(Guid id) => TicketService.CompleteTicket(id); + private void ToggleWaitingStatus(Ticket ticket) + { + // Status umkehren + ticket.IsWaitingForFeedback = !ticket.IsWaitingForFeedback; + + // In der Datenbank speichern + TicketService.UpdateTicket(ticket); + + // UI explizit anweisen, sich neu zu sortieren + StateHasChanged(); + } + + private void Complete(Guid id) + { + TicketService.CompleteTicket(id); + StateHasChanged(); + } private void GoToDetails(Guid id) => Nav.NavigateTo($"/ticket/edit/{id}"); } @@ -68,10 +107,38 @@ background: #f8f9fa; border-radius: 8px; padding: 1rem; margin-bottom: 1rem; border-left: 5px solid #ccc; cursor: pointer; transition: transform 0.1s; } + .is-waiting { + opacity: 0.6; + background-color: #e9ecef; + border-left-color: #6c757d !important; /* Überschreibt die Prio-Farbe mit Grau */ + } + .ticket-actions { + display: flex; + gap: 0.5rem; + } .ticket-card:hover { transform: scale(1.01); } .priority-critical { border-left-color: #dc3545; } .priority-high { border-left-color: #fd7e14; } .ticket-header { display: flex; justify-content: space-between; align-items: center; } .prio-tag { font-size: 0.7rem; font-weight: bold; text-transform: uppercase; } .ticket-footer { display: flex; justify-content: space-between; align-items: center; margin-top: 1rem; } + .waiting-separator { + display: flex; + align-items: center; + text-align: center; + margin: 2.5rem 0 1.5rem 0; + color: #6c757d; + font-size: 0.85rem; + font-weight: bold; + text-transform: uppercase; + letter-spacing: 1px; + } + + .waiting-separator hr { + flex-grow: 1; + border: none; + border-top: 2px dashed #dee2e6; + margin: 0 1rem; + opacity: 1; + } diff --git a/Components/Pages/TicketDetail.razor b/Components/Pages/TicketDetail.razor index aa8f8e7..077ada1 100644 --- a/Components/Pages/TicketDetail.razor +++ b/Components/Pages/TicketDetail.razor @@ -35,10 +35,14 @@ }
-
-
+
+
+ + +
+
- +
diff --git a/Migrations/20260527090007_AddWaitingStatus.Designer.cs b/Migrations/20260527090007_AddWaitingStatus.Designer.cs new file mode 100644 index 0000000..7fe0da9 --- /dev/null +++ b/Migrations/20260527090007_AddWaitingStatus.Designer.cs @@ -0,0 +1,97 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using TodoTicketApp.Data; + +#nullable disable + +namespace TodoTicketApp.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20260527090007_AddWaitingStatus")] + partial class AddWaitingStatus + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.8"); + + modelBuilder.Entity("TodoTicketApp.Models.Ticket", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.PrimitiveCollection("AttachmentNames") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("Description") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("IsCompleted") + .HasColumnType("INTEGER"); + + b.Property("IsWaitingForFeedback") + .HasColumnType("INTEGER"); + + b.Property("Priority") + .HasColumnType("INTEGER"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Tickets"); + }); + + modelBuilder.Entity("TodoTicketApp.Models.TicketComment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("Text") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TicketId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("TicketId"); + + b.ToTable("Comments"); + }); + + modelBuilder.Entity("TodoTicketApp.Models.TicketComment", b => + { + b.HasOne("TodoTicketApp.Models.Ticket", null) + .WithMany("Comments") + .HasForeignKey("TicketId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("TodoTicketApp.Models.Ticket", b => + { + b.Navigation("Comments"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20260527090007_AddWaitingStatus.cs b/Migrations/20260527090007_AddWaitingStatus.cs new file mode 100644 index 0000000..739af07 --- /dev/null +++ b/Migrations/20260527090007_AddWaitingStatus.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace TodoTicketApp.Migrations +{ + /// + public partial class AddWaitingStatus : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IsWaitingForFeedback", + table: "Tickets", + type: "INTEGER", + nullable: false, + defaultValue: false); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsWaitingForFeedback", + table: "Tickets"); + } + } +} diff --git a/Migrations/AppDbContextModelSnapshot.cs b/Migrations/AppDbContextModelSnapshot.cs index 7c68e90..fb5a458 100644 --- a/Migrations/AppDbContextModelSnapshot.cs +++ b/Migrations/AppDbContextModelSnapshot.cs @@ -37,6 +37,9 @@ namespace TodoTicketApp.Migrations b.Property("IsCompleted") .HasColumnType("INTEGER"); + b.Property("IsWaitingForFeedback") + .HasColumnType("INTEGER"); + b.Property("Priority") .HasColumnType("INTEGER"); diff --git a/Models/Ticket.cs b/Models/Ticket.cs index a167a96..c2bd74b 100644 --- a/Models/Ticket.cs +++ b/Models/Ticket.cs @@ -16,6 +16,7 @@ public class Ticket public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public TicketPriority Priority { get; set; } = TicketPriority.Medium; public bool IsCompleted { get; set; } = false; + public bool IsWaitingForFeedback { get; set; } = false; // Relationen public List Comments { get; set; } = new(); diff --git a/Services/SqliteTicketService.cs b/Services/SqliteTicketService.cs index d5b37fd..5359794 100644 --- a/Services/SqliteTicketService.cs +++ b/Services/SqliteTicketService.cs @@ -25,7 +25,8 @@ public class SqliteTicketService : ITicketService return _context.Tickets .Include(t => t.Comments) .Where(t => !t.IsCompleted) - .OrderByDescending(t => t.Priority) + .OrderBy(t => t.IsWaitingForFeedback) + .ThenByDescending(t => t.Priority) .ThenBy(t => t.CreatedAt) .ToList(); }