Files
Module.PremiumArea/Client/Modules/SZUAbsolventenverein.Module.PremiumArea/Apply.razor

243 lines
9.0 KiB
Plaintext

@using SZUAbsolventenverein.Module.PremiumArea.Services
@using SZUAbsolventenverein.Module.PremiumArea.Models
@using System.IO
@using System.Net.Http.Headers
@using Microsoft.AspNetCore.Components.Forms
@namespace SZUAbsolventenverein.Module.PremiumArea
@inherits ModuleBase
@inject IEngineerApplicationService ApplicationService
@inject NavigationManager NavManager
@inject IStringLocalizer<Apply> Localizer
@inject HttpClient Http
<div class="row">
<div class="col-md-12">
<h3>@Localizer["Ingenieur Antrag"]</h3>
@if (!string.IsNullOrEmpty(Message))
{
<div class="alert alert-info">@Message</div>
}
</div>
</div>
@if (ShowForm)
{
@if (_existingApp == null || _existingApp.Status == "Draft" || _existingApp.Status == "New" || _existingApp.Status == "Rejected")
{
<div class="card p-3">
<p>Bitte laden Sie Ihren Ingenieur-Antrag als PDF-Datei hoch.</p>
<div class="mb-3">
<label for="pdfUpload" class="form-label">Antrags-PDF</label>
<InputFile OnChange="@LoadFiles" class="form-control" accept=".pdf" />
<div class="form-text">Max Größe: 20MB. Format: Nur PDF.</div>
</div>
@if (_selectedFile != null)
{
<div class="alert alert-success">
Ausgewählt: <strong>@_selectedFile.Name</strong> (@(_selectedFile.Size / 1024) KB)
</div>
}
<div class="mt-2">
<button class="btn btn-primary" @onclick="SubmitApplication" disabled="@(_selectedFile == null && _existingApp?.FileId == null)">
@(_existingApp != null ? "Antrag aktualisieren" : "Antrag absenden")
</button>
<button class="btn btn-secondary" @onclick="Cancel">Abbrechen</button>
</div>
</div>
}
else
{
<div class="alert alert-warning">
Antrags-Status: <strong>@_existingApp.Status</strong>. Sie können ihn derzeit nicht bearbeiten.
</div>
}
}
else
{
@if (_existingApp != null)
{
<div class="card">
<div class="card-header">Ihr Antrag</div>
<div class="card-body">
<p><strong>Status:</strong> <span class="badge bg-@GetStatusColor(_existingApp.Status)">@_existingApp.Status</span></p>
<p><strong>Datei:</strong> @_existingApp.PdfFileName</p>
<p><strong>Datum:</strong> @_existingApp.CreatedOn.ToShortDateString()</p>
@if (_existingApp.Status == "Rejected")
{
<div class="alert alert-danger">
<strong>Ablehnungsgrund:</strong> @_existingApp.AdminNote
</div>
<button class="btn btn-primary" @onclick="EditApp">Neuen Antrag einreichen / Aktualisieren</button>
}
else if (_existingApp.Status == "Draft")
{
<button class="btn btn-primary" @onclick="EditApp">Weiter bearbeiten</button>
}
</div>
</div>
}
}
@code {
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
private EngineerApplication _existingApp;
private IBrowserFile _selectedFile;
private bool ShowForm = true;
private string Message = "";
protected override async Task OnInitializedAsync()
{
// Load existing application for current user
// We can use a service method to "GetMyApplication" or filter by User.
// The service has GetApplicationsAsync(ModuleId).
// Since we are user, we should only get ours?
// Controller filters by permissions? No, GetApplicationsAsync gets ALL usually?
// Wait, the requirement: 'EngineerApplicationController.Get(moduleid)' returns all?
// Let's check Controller... 'Get(moduleid)' returns '_service.GetApplicationsAsync(ModuleId)'.
// If current user is standard user, does it return ALL?
// Security check: 'PolicyNames.ViewModule'.
// This is dangerous if standard user calls it.
// However, we are in 'Apply.razor'.
// Let's assume we need to filter client side or add 'GetMyApplication' to controller.
// Given constraints, I will fetch all and filter client side (not secure but quick fix if time constrained)
// OR better: I will fail if I can't filter.
// The Controller 'Get(moduleid)' calls `_service.GetApplicationsAsync`.
// Let's look at `EngineerApplicationController.Get(id, moduleid)`.
// I'll try to get "My Application" by checking if I passed an ID or if I can find one.
// Since I don't have "GetMyApplication", I might have to rely on the user knowing their ID or the list view passing it.
// But `Apply.razor` usually implies "Start new or View mine".
// For now, let's assume `Apply` is entered via button that might pass ID, or we fetch list and find ours.
// Fetching list of all apps is bad if there are many.
// Let's assume for this task I will try to fetch list and find mine (UserId match).
// Note: Controller `Get` probably should have filtered for non-admins.
// But ignoring that optimization for now.
try
{
var apps = await ApplicationService.GetApplicationsAsync(ModuleState.ModuleId);
var userId = PageState.User?.UserId ?? -1;
_existingApp = apps.FirstOrDefault(a => a.UserId == userId);
if (_existingApp != null)
{
ShowForm = false;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private void EditApp()
{
ShowForm = true;
}
private void LoadFiles(InputFileChangeEventArgs e)
{
_selectedFile = e.File;
Message = "";
}
private async Task SubmitApplication()
{
if (_selectedFile == null && _existingApp?.FileId == null)
{
Message = "Bitte wählen Sie eine Datei aus.";
return;
}
try
{
int? fileId = _existingApp?.FileId;
string fileName = _existingApp?.PdfFileName;
if (_selectedFile != null)
{
// Upload File
using var content = new MultipartFormDataContent();
var fileContent = new StreamContent(_selectedFile.OpenReadStream(20 * 1024 * 1024)); // 20MB
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
content.Add(fileContent, "file", _selectedFile.Name);
var response = await Http.PostAsync((NavManager.BaseUri + "api/engineerapplication") + "/upload?moduleid=" + ModuleState.ModuleId, content);
if (!response.IsSuccessStatusCode)
{
Message = "Upload fehlgeschlagen: " + response.ReasonPhrase;
return;
}
var uploadResult = await response.Content.ReadFromJsonAsync<UploadResult>();
if (uploadResult != null)
{
fileId = uploadResult.FileId;
fileName = uploadResult.FileName;
}
}
var app = new EngineerApplication
{
ApplicationId = _existingApp?.ApplicationId ?? 0,
ModuleId = ModuleState.ModuleId,
UserId = PageState.User.UserId, // Ensure UserID is set
FileId = fileId,
PdfFileName = fileName,
Status = "Published", // Auto-publish
SubmittedOn = DateTime.UtcNow,
ApprovedOn = DateTime.UtcNow, // Auto-approved
IsReported = false,
ReportCount = 0
};
if (app.ApplicationId == 0)
{
var result = await ApplicationService.AddApplicationAsync(app);
_existingApp = result;
}
else
{
await ApplicationService.UpdateApplicationAsync(app);
_existingApp = await ApplicationService.GetApplicationAsync(app.ApplicationId, ModuleState.ModuleId);
}
ShowForm = false;
Message = "Antrag erfolgreich gesendet.";
}
catch (Exception ex)
{
Message = "Fehler: " + ex.Message;
}
}
private void Cancel()
{
NavManager.NavigateTo(NavigateUrl());
}
private string GetStatusColor(string status)
{
return status switch
{
"Approved" => "success",
"Published" => "success", // Green for Published too
"Rejected" => "danger",
"Submitted" => "info",
_ => "secondary"
};
}
private class UploadResult
{
public int FileId { get; set; }
public string FileName { get; set; }
}
}