using LEA.Data; using LEA.Extensions; using LEA.Models; using LEA.ViewModels; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.EntityFrameworkCore; namespace LEA.Controllers; [Authorize] public class ApplicationsController : Controller { private readonly AppDbContext _context; private readonly UserManager _userManager; public ApplicationsController(AppDbContext context, UserManager userManager) { _context = context; _userManager = userManager; } public async Task Index(string? searchTerm, ApplicationStatus? status) { var userId = GetCurrentUserId(); var query = _context.Applications .Include(a => a.Contact) .Where(a => a.UserId == userId); if (!string.IsNullOrWhiteSpace(searchTerm)) { var term = $"%{searchTerm.Trim()}%"; query = query.Where(a => EF.Functions.Like(a.Company, term) || EF.Functions.Like(a.Role, term) || EF.Functions.Like(a.Source ?? string.Empty, term) || EF.Functions.Like(a.Notes ?? string.Empty, term) || (a.Contact != null && ( EF.Functions.Like(a.Contact.FullName ?? string.Empty, term) || EF.Functions.Like(a.Contact.Email ?? string.Empty, term)))); } if (status.HasValue) { query = query.Where(a => a.Status == status.Value); } var applications = await query .OrderByDescending(a => a.UpdatedAt) .ThenByDescending(a => a.AppliedOn) .ToListAsync(); var statsQuery = _context.Applications.Where(a => a.UserId == userId); var statusCounts = await statsQuery .GroupBy(a => a.Status) .Select(g => new { g.Key, Count = g.Count() }) .ToListAsync(); var statusDictionary = Enum.GetValues() .ToDictionary(s => s, s => statusCounts.FirstOrDefault(sc => sc.Key == s)?.Count ?? 0); var model = new ApplicationListViewModel { Applications = applications, SearchTerm = searchTerm, StatusFilter = status, StatusOptions = GetStatusSelectList(status, includeAllOption: true), StatusCounts = statusDictionary, TotalApplications = await statsQuery.CountAsync() }; return View(model); } [HttpGet] public IActionResult Create() { var model = new ApplicationFormViewModel { AppliedOn = DateTime.Today, Status = ApplicationStatus.Applied, StatusOptions = GetStatusSelectList(ApplicationStatus.Applied), Heading = "Bewerbung hinzufügen", SubmitText = "Speichern" }; return View(model); } [HttpPost] [ValidateAntiForgeryToken] public async Task Create(ApplicationFormViewModel model) { if (!ModelState.IsValid) { model.StatusOptions = GetStatusSelectList(model.Status); model.Heading = "Bewerbung hinzufügen"; model.SubmitText = "Speichern"; return View(model); } var application = new Application { Role = model.Role.Trim(), Company = model.Company.Trim(), Source = string.IsNullOrWhiteSpace(model.Source) ? null : model.Source.Trim(), Status = model.Status, AppliedOn = model.AppliedOn, Notes = string.IsNullOrWhiteSpace(model.Notes) ? null : model.Notes.Trim(), UserId = GetCurrentUserId(), UpdatedAt = DateTime.UtcNow }; if (HasContactInformation(model)) { application.Contact = new Contact { FullName = string.IsNullOrWhiteSpace(model.ContactName) ? null : model.ContactName.Trim(), Email = string.IsNullOrWhiteSpace(model.ContactEmail) ? null : model.ContactEmail.Trim(), Phone = string.IsNullOrWhiteSpace(model.ContactPhone) ? null : model.ContactPhone.Trim() }; } _context.Applications.Add(application); await _context.SaveChangesAsync(); TempData["Success"] = "Die Bewerbung wurde gespeichert."; return RedirectToAction(nameof(Index)); } [HttpGet] public async Task Edit(int id) { var application = await FindApplicationForCurrentUserAsync(id); if (application == null) { return NotFound(); } var model = new ApplicationFormViewModel { Id = application.Id, Role = application.Role, Company = application.Company, Source = application.Source, Status = application.Status, AppliedOn = application.AppliedOn, Notes = application.Notes, ContactName = application.Contact?.FullName, ContactEmail = application.Contact?.Email, ContactPhone = application.Contact?.Phone, StatusOptions = GetStatusSelectList(application.Status), Heading = "Bewerbung bearbeiten", SubmitText = "Änderungen speichern" }; return View(model); } [HttpPost] [ValidateAntiForgeryToken] public async Task Edit(int id, ApplicationFormViewModel model) { if (id != model.Id) { return NotFound(); } if (!ModelState.IsValid) { model.StatusOptions = GetStatusSelectList(model.Status); model.Heading = "Bewerbung bearbeiten"; model.SubmitText = "Änderungen speichern"; return View(model); } var application = await FindApplicationForCurrentUserAsync(id); if (application == null) { return NotFound(); } application.Role = model.Role.Trim(); application.Company = model.Company.Trim(); application.Source = string.IsNullOrWhiteSpace(model.Source) ? null : model.Source.Trim(); application.Status = model.Status; application.AppliedOn = model.AppliedOn; application.Notes = string.IsNullOrWhiteSpace(model.Notes) ? null : model.Notes.Trim(); application.UpdatedAt = DateTime.UtcNow; if (HasContactInformation(model)) { if (application.Contact == null) { application.Contact = new Contact(); } application.Contact.FullName = string.IsNullOrWhiteSpace(model.ContactName) ? null : model.ContactName.Trim(); application.Contact.Email = string.IsNullOrWhiteSpace(model.ContactEmail) ? null : model.ContactEmail.Trim(); application.Contact.Phone = string.IsNullOrWhiteSpace(model.ContactPhone) ? null : model.ContactPhone.Trim(); } else if (application.Contact != null) { _context.Contacts.Remove(application.Contact); } await _context.SaveChangesAsync(); TempData["Success"] = "Die Bewerbung wurde aktualisiert."; return RedirectToAction(nameof(Index)); } [HttpGet] public async Task Details(int id) { var application = await FindApplicationForCurrentUserAsync(id); if (application == null) { return NotFound(); } return View(application); } [HttpPost] [ValidateAntiForgeryToken] public async Task Delete(int id) { var application = await FindApplicationForCurrentUserAsync(id); if (application == null) { return NotFound(); } _context.Applications.Remove(application); await _context.SaveChangesAsync(); TempData["Success"] = "Die Bewerbung wurde gelöscht."; return RedirectToAction(nameof(Index)); } private async Task FindApplicationForCurrentUserAsync(int id) { var userId = GetCurrentUserId(); return await _context.Applications .Include(a => a.Contact) .Where(a => a.UserId == userId) .FirstOrDefaultAsync(a => a.Id == id); } private IEnumerable GetStatusSelectList(ApplicationStatus? selectedStatus, bool includeAllOption = false) { var options = Enum.GetValues() .Select(status => new SelectListItem { Text = status.GetDisplayName(), Value = status.ToString(), Selected = selectedStatus.HasValue && selectedStatus.Value == status }) .ToList(); if (includeAllOption) { options.Insert(0, new SelectListItem { Text = "Alle Status", Value = string.Empty, Selected = !selectedStatus.HasValue }); } return options; } private bool HasContactInformation(ApplicationFormViewModel model) { return !string.IsNullOrWhiteSpace(model.ContactName) || !string.IsNullOrWhiteSpace(model.ContactEmail) || !string.IsNullOrWhiteSpace(model.ContactPhone); } private string GetCurrentUserId() { return _userManager.GetUserId(User) ?? throw new InvalidOperationException("Benutzer ist nicht angemeldet."); } }