feat(halloffame): implement image upload and enhance module functionality

- Added image upload system (JPG/PNG, max 5MB) with live preview and removal option
- Fixed Concurrency Exception during deletion (split transactions for reports and entries)
- Optimized card layout: consistent height and height-based truncation for descriptions
- Added sort direction toggle (Ascending/Descending) with arrow icons for Date, Name, and Year
- Refactored HallOfFameService to use streams for Server/Wasm compatibility
- Improved error handling and UI feedback for upload and delete operations
This commit is contained in:
Adam Gaiswinkler
2026-02-10 17:45:48 +01:00
parent 2d8c6736a7
commit 1bff5ebbbd
18 changed files with 956 additions and 127 deletions

View File

@@ -13,6 +13,11 @@ namespace SZUAbsolventenverein.Module.HallOfFame.Repository
Models.HallOfFame AddHallOfFame(Models.HallOfFame HallOfFame);
Models.HallOfFame UpdateHallOfFame(Models.HallOfFame HallOfFame);
void DeleteHallOfFame(int HallOfFameId);
IEnumerable<Models.HallOfFameReport> GetHallOfFameReports(int HallOfFameId);
Models.HallOfFameReport GetHallOfFameReport(int HallOfFameReportId);
Models.HallOfFameReport AddHallOfFameReport(Models.HallOfFameReport HallOfFameReport);
void DeleteHallOfFameReport(int HallOfFameReportId);
}
public class HallOfFameRepository : IHallOfFameRepository, ITransientService
@@ -27,7 +32,14 @@ namespace SZUAbsolventenverein.Module.HallOfFame.Repository
public IEnumerable<Models.HallOfFame> GetHallOfFames(int ModuleId)
{
using var db = _factory.CreateDbContext();
return db.HallOfFame.Where(item => item.ModuleId == ModuleId).ToList();
var items = db.HallOfFame.Where(item => item.ModuleId == ModuleId)
.OrderByDescending(item => item.CreatedOn)
.ToList();
foreach (var item in items)
{
item.Description = item.Description?.Replace("\t", " ");
}
return items;
}
public Models.HallOfFame GetHallOfFame(int HallOfFameId)
@@ -38,19 +50,26 @@ namespace SZUAbsolventenverein.Module.HallOfFame.Repository
public Models.HallOfFame GetHallOfFame(int HallOfFameId, bool tracking)
{
using var db = _factory.CreateDbContext();
Models.HallOfFame item;
if (tracking)
{
return db.HallOfFame.Find(HallOfFameId);
item = db.HallOfFame.Find(HallOfFameId);
}
else
{
return db.HallOfFame.AsNoTracking().FirstOrDefault(item => item.HallOfFameId == HallOfFameId);
item = db.HallOfFame.AsNoTracking().FirstOrDefault(i => i.HallOfFameId == HallOfFameId);
}
if (item != null)
{
item.Description = item.Description?.Replace("\t", " ");
}
return item;
}
public Models.HallOfFame AddHallOfFame(Models.HallOfFame HallOfFame)
{
using var db = _factory.CreateDbContext();
HallOfFame.Description = HallOfFame.Description?.Replace("\t", " ");
db.HallOfFame.Add(HallOfFame);
db.SaveChanges();
return HallOfFame;
@@ -59,17 +78,72 @@ namespace SZUAbsolventenverein.Module.HallOfFame.Repository
public Models.HallOfFame UpdateHallOfFame(Models.HallOfFame HallOfFame)
{
using var db = _factory.CreateDbContext();
HallOfFame.Description = HallOfFame.Description?.Replace("\t", " ");
db.Entry(HallOfFame).State = EntityState.Modified;
db.SaveChanges();
return HallOfFame;
}
public void DeleteHallOfFame(int HallOfFameId)
{
// First transaction: Delete all associated reports
using (var db = _factory.CreateDbContext())
{
var reports = db.HallOfFameReport.Where(item => item.HallOfFameId == HallOfFameId).ToList();
if (reports.Any())
{
db.HallOfFameReport.RemoveRange(reports);
db.SaveChanges();
}
}
// Second transaction: Delete the HallOfFame entry itself
using (var db = _factory.CreateDbContext())
{
var hallOfFame = db.HallOfFame.Find(HallOfFameId);
if (hallOfFame != null)
{
db.HallOfFame.Remove(hallOfFame);
db.SaveChanges();
}
}
}
public IEnumerable<Models.HallOfFameReport> GetHallOfFameReports(int HallOfFameId)
{
using var db = _factory.CreateDbContext();
Models.HallOfFame HallOfFame = db.HallOfFame.Find(HallOfFameId);
db.HallOfFame.Remove(HallOfFame);
return db.HallOfFameReport.Where(item => item.HallOfFameId == HallOfFameId)
.OrderByDescending(item => item.CreatedOn)
.ToList();
}
public Models.HallOfFameReport GetHallOfFameReport(int HallOfFameReportId)
{
using var db = _factory.CreateDbContext();
return db.HallOfFameReport.Find(HallOfFameReportId);
}
public Models.HallOfFameReport AddHallOfFameReport(Models.HallOfFameReport HallOfFameReport)
{
using var db = _factory.CreateDbContext();
db.HallOfFameReport.Add(HallOfFameReport);
db.SaveChanges();
return HallOfFameReport;
}
public void DeleteHallOfFameReport(int HallOfFameReportId)
{
using var db = _factory.CreateDbContext();
// Clear any tracked entities to avoid conflicts
db.ChangeTracker.Clear();
Models.HallOfFameReport HallOfFameReport = db.HallOfFameReport.Find(HallOfFameReportId);
if (HallOfFameReport != null)
{
db.HallOfFameReport.Remove(HallOfFameReport);
db.SaveChanges();
}
}
}
}