diff --git a/FoodsharingSiegen.Contracts/Entity/Prospect.cs b/FoodsharingSiegen.Contracts/Entity/Prospect.cs
index c51eb9f..2485022 100644
--- a/FoodsharingSiegen.Contracts/Entity/Prospect.cs
+++ b/FoodsharingSiegen.Contracts/Entity/Prospect.cs
@@ -42,6 +42,11 @@ namespace FoodsharingSiegen.Contracts.Entity
///
public string? Memo { get; set; }
+ ///
+ /// Gets or sets the value indicating the last modification date and time.
+ ///
+ public DateTime? Modified { get; set; }
+
///
/// Gets or sets the value of the name (ab)
///
diff --git a/FoodsharingSiegen.Server/Controls/ProspectContainer.razor b/FoodsharingSiegen.Server/Controls/ProspectContainer.razor
index 3d1e9de..6d7f263 100644
--- a/FoodsharingSiegen.Server/Controls/ProspectContainer.razor
+++ b/FoodsharingSiegen.Server/Controls/ProspectContainer.razor
@@ -45,7 +45,7 @@
}
-
+
-
-
+
+
+
+ Zuletzt geändert: @Prospect?.Modified?.ToLocalTime()
\ No newline at end of file
diff --git a/FoodsharingSiegen.Server/Controls/ProspectContainer.razor.cs b/FoodsharingSiegen.Server/Controls/ProspectContainer.razor.cs
index b591559..5d4b399 100644
--- a/FoodsharingSiegen.Server/Controls/ProspectContainer.razor.cs
+++ b/FoodsharingSiegen.Server/Controls/ProspectContainer.razor.cs
@@ -72,7 +72,7 @@ namespace FoodsharingSiegen.Server.Controls
private async Task EditProspectAsync()
{
- await EditProspectDialog.ShowAsync(ModalService, () => InvokeAsync(StateHasChanged), Prospect);
+ await EditProspectDialog.ShowAsync(ModalService, OnDataChanged ?? (async () => await Task.CompletedTask), Prospect);
}
#endregion
diff --git a/FoodsharingSiegen.Server/Controls/ProspectContainer.razor.css b/FoodsharingSiegen.Server/Controls/ProspectContainer.razor.css
index 0e089da..386d98d 100644
--- a/FoodsharingSiegen.Server/Controls/ProspectContainer.razor.css
+++ b/FoodsharingSiegen.Server/Controls/ProspectContainer.razor.css
@@ -14,13 +14,15 @@
}
.pc-main {
+ display: flex;
+ flex-direction: column;
flex-basis: 0;
flex-grow: 1;
max-width: 480px;
border: 1px solid #533a20;
border-radius: 3px;
margin: 5px;
- padding: 16px;
+ padding: .5rem .5rem 0 .5rem;
}
.pc-main.warning {
diff --git a/FoodsharingSiegen.Server/Data/Service/ProspectService.cs b/FoodsharingSiegen.Server/Data/Service/ProspectService.cs
index 79c2932..6ebd250 100644
--- a/FoodsharingSiegen.Server/Data/Service/ProspectService.cs
+++ b/FoodsharingSiegen.Server/Data/Service/ProspectService.cs
@@ -44,6 +44,7 @@ namespace FoodsharingSiegen.Server.Data.Service
interaction.Created = DateTime.UtcNow;
targetProspect.Interactions.Add(interaction);
+ targetProspect.Modified = DateTime.UtcNow;
await Context.SaveChangesAsync();
@@ -77,6 +78,7 @@ namespace FoodsharingSiegen.Server.Data.Service
if (prospect == null) return new(new Exception("Cannot be empty"));
prospect.Created = DateTime.UtcNow;
+ prospect.Modified = DateTime.UtcNow;
prospect.Id = Guid.Empty;
await Context.Prospects!.AddAsync(prospect);
@@ -142,8 +144,19 @@ namespace FoodsharingSiegen.Server.Data.Service
{
try
{
- Context.Interactions!.Remove(new() { Id = interactionId });
+ var interaction = await Context.Interactions!.AsNoTracking().FirstOrDefaultAsync(x => x.Id == interactionId);
+ if(interaction == null) return new(new Exception("Interaction not found"));
+
+ Context.Interactions!.Remove(new() { Id = interaction.Id });
await Context.SaveChangesAsync();
+
+ // Update prospect modified date
+ var prospect = await Context.Prospects!.FirstOrDefaultAsync(x => x.Id == interaction.ProspectID);
+ if (prospect != null)
+ {
+ prospect.Modified = DateTime.UtcNow;
+ await Context.SaveChangesAsync();
+ }
await AuditService.Insert(AuditType.RemoveInteraction, "?");
@@ -176,6 +189,7 @@ namespace FoodsharingSiegen.Server.Data.Service
entityProspect.FsId = prospect.FsId;
entityProspect.Warning = prospect.Warning;
entityProspect.RecordState = prospect.RecordState;
+ entityProspect.Modified = DateTime.UtcNow;
var saveR = await Context.SaveChangesAsync();
diff --git a/FoodsharingSiegen.Server/Migrations/20250330182300_Proposal-Modified.Designer.cs b/FoodsharingSiegen.Server/Migrations/20250330182300_Proposal-Modified.Designer.cs
new file mode 100644
index 0000000..027eba7
--- /dev/null
+++ b/FoodsharingSiegen.Server/Migrations/20250330182300_Proposal-Modified.Designer.cs
@@ -0,0 +1,208 @@
+//
+using System;
+using FoodsharingSiegen.Server.Data;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace FoodsharingSiegen.Server.Migrations
+{
+ [DbContext(typeof(FsContext))]
+ [Migration("20250330182300_Proposal-Modified")]
+ partial class ProposalModified
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder.HasAnnotation("ProductVersion", "9.0.3");
+
+ modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Audit", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property("Created")
+ .HasColumnType("TEXT");
+
+ b.Property("Data1")
+ .HasColumnType("TEXT");
+
+ b.Property("Data2")
+ .HasColumnType("TEXT");
+
+ b.Property("Type")
+ .HasColumnType("INTEGER");
+
+ b.Property("UserID")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserID");
+
+ b.ToTable("Audits");
+ });
+
+ modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Interaction", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property("Alert")
+ .HasColumnType("INTEGER");
+
+ b.Property("Created")
+ .HasColumnType("TEXT");
+
+ b.Property("Date")
+ .HasColumnType("TEXT");
+
+ b.Property("Info")
+ .HasColumnType("TEXT");
+
+ b.Property("NotNeeded")
+ .HasColumnType("INTEGER");
+
+ b.Property("ProspectID")
+ .HasColumnType("TEXT");
+
+ b.Property("Type")
+ .HasColumnType("INTEGER");
+
+ b.Property("UserID")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ProspectID");
+
+ b.HasIndex("UserID");
+
+ b.ToTable("Interactions");
+ });
+
+ modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Prospect", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property("Created")
+ .HasColumnType("TEXT");
+
+ b.Property("FsId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Memo")
+ .HasColumnType("TEXT");
+
+ b.Property("Modified")
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("RecordState")
+ .HasColumnType("INTEGER");
+
+ b.Property("Warning")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("Prospects");
+ });
+
+ modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.User", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property("Created")
+ .HasColumnType("TEXT");
+
+ b.Property("EncryptedPassword")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("ForceLogout")
+ .HasColumnType("INTEGER");
+
+ b.Property("Groups")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Mail")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Memo")
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Network")
+ .HasColumnType("INTEGER");
+
+ b.Property("Type")
+ .HasColumnType("INTEGER");
+
+ b.Property("Verified")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Audit", b =>
+ {
+ b.HasOne("FoodsharingSiegen.Contracts.Entity.User", "User")
+ .WithMany()
+ .HasForeignKey("UserID");
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Interaction", b =>
+ {
+ b.HasOne("FoodsharingSiegen.Contracts.Entity.Prospect", "Prospect")
+ .WithMany("Interactions")
+ .HasForeignKey("ProspectID")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("FoodsharingSiegen.Contracts.Entity.User", "User")
+ .WithMany("Interactions")
+ .HasForeignKey("UserID")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Prospect");
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Prospect", b =>
+ {
+ b.Navigation("Interactions");
+ });
+
+ modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.User", b =>
+ {
+ b.Navigation("Interactions");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/FoodsharingSiegen.Server/Migrations/20250330182300_Proposal-Modified.cs b/FoodsharingSiegen.Server/Migrations/20250330182300_Proposal-Modified.cs
new file mode 100644
index 0000000..d12a797
--- /dev/null
+++ b/FoodsharingSiegen.Server/Migrations/20250330182300_Proposal-Modified.cs
@@ -0,0 +1,40 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace FoodsharingSiegen.Server.Migrations
+{
+ ///
+ public partial class ProposalModified : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "Modified",
+ table: "Prospects",
+ type: "TEXT",
+ nullable: true);
+
+ // Fill Modified column of existing rows
+ migrationBuilder.Sql(@"
+ UPDATE Prospects
+ SET Modified = COALESCE(
+ (SELECT MAX(Created)
+ FROM Interactions
+ WHERE Interactions.ProspectID = Prospects.Id),
+ Prospects.Created
+ );
+ ");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "Modified",
+ table: "Prospects");
+ }
+ }
+}
diff --git a/FoodsharingSiegen.Server/Migrations/FsContextModelSnapshot.cs b/FoodsharingSiegen.Server/Migrations/FsContextModelSnapshot.cs
index 9cc9d2e..cf9b3a3 100644
--- a/FoodsharingSiegen.Server/Migrations/FsContextModelSnapshot.cs
+++ b/FoodsharingSiegen.Server/Migrations/FsContextModelSnapshot.cs
@@ -99,6 +99,9 @@ namespace FoodsharingSiegen.Server.Migrations
b.Property("Memo")
.HasColumnType("TEXT");
+ b.Property("Modified")
+ .HasColumnType("TEXT");
+
b.Property("Name")
.IsRequired()
.HasColumnType("TEXT");