This commit is contained in:
younes elhaddoury
2025-09-17 10:28:02 +02:00
parent 9c8fb9b205
commit bb13759af4
288 changed files with 102393 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
@model ApplicationFormViewModel
@{
ViewData["Title"] = "Bewerbung hinzufügen";
}
<section class="content-card">
<div class="section-header">
<h1>@Model.Heading</h1>
<a class="link" asp-action="Index">Zurück zur Übersicht</a>
</div>
<form asp-action="Create" method="post">
@Html.AntiForgeryToken()
<div asp-validation-summary="ModelOnly" class="validation-summary"></div>
<partial name="_ApplicationForm" />
<div class="form-actions">
<a class="btn btn-outline" asp-action="Index">Abbrechen</a>
<button type="submit" class="btn btn-primary">@Model.SubmitText</button>
</div>
</form>
</section>
@section Scripts
{
<partial name="_ValidationScriptsPartial" />
}

View File

@@ -0,0 +1,88 @@
@model Application
@{
ViewData["Title"] = "Details";
}
<section class="content-card">
<div class="section-header">
<h1>@Model.Role bei @Model.Company</h1>
<div class="action-group">
<a class="btn btn-outline" asp-action="Edit" asp-route-id="@Model.Id">Bearbeiten</a>
<a class="link" asp-action="Index">Zurück</a>
</div>
</div>
<div class="detail-grid">
<div class="detail-card">
<h2>Überblick</h2>
<dl>
<div>
<dt>Status</dt>
<dd>
<span class="status-badge status-@Model.Status.ToString().ToLowerInvariant()">
@Model.Status.GetDisplayName()
</span>
</dd>
</div>
<div>
<dt>Beworben am</dt>
<dd>@Model.AppliedOn.ToString("dd.MM.yyyy")</dd>
</div>
<div>
<dt>Quelle</dt>
<dd>@(string.IsNullOrWhiteSpace(Model.Source) ? "-" : Model.Source)</dd>
</div>
<div>
<dt>Zuletzt aktualisiert</dt>
<dd>@Model.UpdatedAt.ToLocalTime().ToString("dd.MM.yyyy HH:mm")</dd>
</div>
</dl>
</div>
<div class="detail-card">
<h2>Notizen</h2>
@if (string.IsNullOrWhiteSpace(Model.Notes))
{
<p class="muted">Keine Notizen hinterlegt.</p>
}
else
{
<p>@Model.Notes</p>
}
</div>
<div class="detail-card">
<h2>Ansprechpartner</h2>
@if (Model.Contact == null || (string.IsNullOrWhiteSpace(Model.Contact.FullName) && string.IsNullOrWhiteSpace(Model.Contact.Email) && string.IsNullOrWhiteSpace(Model.Contact.Phone)))
{
<p class="muted">Kein Ansprechpartner hinterlegt.</p>
}
else
{
<dl>
@if (!string.IsNullOrWhiteSpace(Model.Contact.FullName))
{
<div>
<dt>Name</dt>
<dd>@Model.Contact.FullName</dd>
</div>
}
@if (!string.IsNullOrWhiteSpace(Model.Contact.Email))
{
<div>
<dt>E-Mail</dt>
<dd><a href="mailto:@Model.Contact.Email">@Model.Contact.Email</a></dd>
</div>
}
@if (!string.IsNullOrWhiteSpace(Model.Contact.Phone))
{
<div>
<dt>Telefon</dt>
<dd><a href="tel:@Model.Contact.Phone">@Model.Contact.Phone</a></dd>
</div>
}
</dl>
}
</div>
</div>
</section>

View File

@@ -0,0 +1,28 @@
@model ApplicationFormViewModel
@{
ViewData["Title"] = "Bewerbung bearbeiten";
}
<section class="content-card">
<div class="section-header">
<h1>@Model.Heading</h1>
<a class="link" asp-action="Index">Zurück zur Übersicht</a>
</div>
<form asp-action="Edit" asp-route-id="@Model.Id" method="post">
@Html.AntiForgeryToken()
<div asp-validation-summary="ModelOnly" class="validation-summary"></div>
<partial name="_ApplicationForm" />
<div class="form-actions">
<a class="btn btn-outline" asp-action="Index">Abbrechen</a>
<button type="submit" class="btn btn-primary">@Model.SubmitText</button>
</div>
</form>
</section>
@section Scripts
{
<partial name="_ValidationScriptsPartial" />
}

View File

@@ -0,0 +1,142 @@
@model ApplicationListViewModel
@using System.Text.Json
@{
ViewData["Title"] = "Meine Bewerbungen";
}
<section class="page-header">
<div>
<h1>Bewerbungen</h1>
<p class="lead">Verwalte deine Bewerbungen, halte Fortschritte fest und behalte alle Termine im Blick.</p>
</div>
<a class="btn btn-primary" asp-action="Create">Neue Bewerbung</a>
</section>
<section class="stats-grid compact">
<article class="stat-card">
<p class="stat-label">Gesamt</p>
<p class="stat-value">@Model.TotalApplications</p>
<p class="stat-caption">Gespeicherte Bewerbungen</p>
</article>
<article class="stat-card">
<p class="stat-label">Beworben</p>
<p class="stat-value">@Model.AppliedCount</p>
<p class="stat-caption">Offene Bewerbungen</p>
</article>
<article class="stat-card">
<p class="stat-label">Interviews</p>
<p class="stat-value">@Model.InterviewCount</p>
<p class="stat-caption">Anstehende Gespräche</p>
</article>
<article class="stat-card">
<p class="stat-label">Angebote</p>
<p class="stat-value">@Model.OfferCount</p>
<p class="stat-caption">Positive Rückmeldungen</p>
</article>
<article class="stat-card">
<p class="stat-label">Absagen</p>
<p class="stat-value">@Model.RejectedCount</p>
<p class="stat-caption">Abgeschlossene Bewerbungen</p>
</article>
</section>
@if (Model.TotalApplications > 0)
{
var statusChartConfig = JsonSerializer.Serialize(new
{
type = "doughnut",
labels = new[] { "Beworben", "Interview", "Angebot", "Abgelehnt" },
values = new[] { Model.AppliedCount, Model.InterviewCount, Model.OfferCount, Model.RejectedCount },
colors = new[] { "#4460f7", "#3ac0a0", "#ff9f43", "#ef476f" },
borderColor = "#ffffff",
datasetLabel = "Bewerbungen",
legend = true
});
<section class="visual-grid compact">
<article class="chart-card">
<div class="chart-card-header">
<h2>Statusübersicht</h2>
<p>Verteilung deiner Bewerbungen nach aktuellem Status.</p>
</div>
<div class="chart-wrapper">
<canvas id="applications-status-chart" data-chart='@Html.Raw(statusChartConfig)'></canvas>
</div>
</article>
</section>
}
<section class="filter-card">
<form method="get" class="filter-grid">
<div class="form-group">
<label for="searchTerm">Suche</label>
<input id="searchTerm" name="searchTerm" value="@Model.SearchTerm" placeholder="Nach Unternehmen, Rolle oder Notizen suchen" />
</div>
<div class="form-group">
<label for="status">Status</label>
<select id="status" name="status">
@foreach (var option in Model.StatusOptions)
{
<option value="@option.Value" selected="@(option.Selected ? "selected" : null)">@option.Text</option>
}
</select>
</div>
<div class="filter-actions">
<button type="submit" class="btn btn-primary">Filter anwenden</button>
<a class="btn btn-outline" asp-action="Index">Zurücksetzen</a>
</div>
</form>
</section>
@if (!Model.Applications.Any())
{
<div class="empty-state">
<p>Noch keine Bewerbungen erfasst.</p>
<a class="btn btn-primary" asp-action="Create">Jetzt Bewerbung hinzufügen</a>
</div>
}
else
{
<div class="table-responsive">
<table class="data-table">
<thead>
<tr>
<th>Unternehmen</th>
<th>Rolle</th>
<th>Quelle</th>
<th>Status</th>
<th>Beworben am</th>
<th>Letzte Aktualisierung</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var application in Model.Applications)
{
<tr>
<td>@application.Company</td>
<td>@application.Role</td>
<td>@(string.IsNullOrWhiteSpace(application.Source) ? "-" : application.Source)</td>
<td>
<span class="status-badge status-@application.Status.ToString().ToLowerInvariant()">
@application.Status.GetDisplayName()
</span>
</td>
<td>@application.AppliedOn.ToString("dd.MM.yyyy")</td>
<td>@application.UpdatedAt.ToLocalTime().ToString("dd.MM.yyyy HH:mm")</td>
<td>
<div class="table-actions">
<a class="link" asp-action="Details" asp-route-id="@application.Id">Details</a>
<a class="link" asp-action="Edit" asp-route-id="@application.Id">Bearbeiten</a>
<form asp-action="Delete" asp-route-id="@application.Id" method="post" class="inline-form" onsubmit="return confirm('Möchtest du diese Bewerbung wirklich löschen?');">
@Html.AntiForgeryToken()
<button type="submit" class="btn-link">Löschen</button>
</form>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
}

View File

@@ -0,0 +1,56 @@
@model ApplicationFormViewModel
<div class="form-grid two-columns">
<div class="form-group">
<label asp-for="Company"></label>
<input asp-for="Company" />
<span asp-validation-for="Company" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Role"></label>
<input asp-for="Role" />
<span asp-validation-for="Role" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Source"></label>
<input asp-for="Source" />
<span asp-validation-for="Source" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="AppliedOn"></label>
<input asp-for="AppliedOn" type="date" />
<span asp-validation-for="AppliedOn" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Status"></label>
<select asp-for="Status" asp-items="Model.StatusOptions"></select>
<span asp-validation-for="Status" class="text-danger"></span>
</div>
<div class="form-group full-width">
<label asp-for="Notes"></label>
<textarea asp-for="Notes" rows="4"></textarea>
<span asp-validation-for="Notes" class="text-danger"></span>
</div>
</div>
<div class="form-divider">
<span>Ansprechpartner (optional)</span>
</div>
<div class="form-grid three-columns">
<div class="form-group">
<label asp-for="ContactName"></label>
<input asp-for="ContactName" />
<span asp-validation-for="ContactName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ContactEmail"></label>
<input asp-for="ContactEmail" />
<span asp-validation-for="ContactEmail" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ContactPhone"></label>
<input asp-for="ContactPhone" />
<span asp-validation-for="ContactPhone" class="text-danger"></span>
</div>
</div>