hallo
This commit is contained in:
45
Desktop/hallo/LEA/Views/Account/Login.cshtml
Normal file
45
Desktop/hallo/LEA/Views/Account/Login.cshtml
Normal file
@@ -0,0 +1,45 @@
|
||||
@model LoginViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Anmelden";
|
||||
}
|
||||
|
||||
<section class="auth-container">
|
||||
<div class="auth-card">
|
||||
<h1>Willkommen zurück</h1>
|
||||
<p class="lead">Melde dich an, um deine Bewerbungen zu verwalten.</p>
|
||||
|
||||
<form asp-action="Login" method="post" class="form-grid">
|
||||
@Html.AntiForgeryToken()
|
||||
<input type="hidden" asp-for="ReturnUrl" />
|
||||
<div asp-validation-summary="ModelOnly" class="validation-summary"></div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Email"></label>
|
||||
<input asp-for="Email" />
|
||||
<span asp-validation-for="Email" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Password"></label>
|
||||
<input asp-for="Password" />
|
||||
<span asp-validation-for="Password" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group form-check">
|
||||
<input asp-for="RememberMe" />
|
||||
<label asp-for="RememberMe"></label>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Anmelden</button>
|
||||
</form>
|
||||
|
||||
<p class="auth-switch">
|
||||
Noch kein Konto? <a asp-action="Register">Jetzt registrieren</a>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@section Scripts
|
||||
{
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
51
Desktop/hallo/LEA/Views/Account/Register.cshtml
Normal file
51
Desktop/hallo/LEA/Views/Account/Register.cshtml
Normal file
@@ -0,0 +1,51 @@
|
||||
@model RegisterViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Registrieren";
|
||||
}
|
||||
|
||||
<section class="auth-container">
|
||||
<div class="auth-card">
|
||||
<h1>Account erstellen</h1>
|
||||
<p class="lead">Lege dein persönliches Profil an und verwalte alle Bewerbungen zentral.</p>
|
||||
|
||||
<form asp-action="Register" method="post" class="form-grid">
|
||||
@Html.AntiForgeryToken()
|
||||
<div asp-validation-summary="ModelOnly" class="validation-summary"></div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="FullName"></label>
|
||||
<input asp-for="FullName" />
|
||||
<span asp-validation-for="FullName" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Email"></label>
|
||||
<input asp-for="Email" />
|
||||
<span asp-validation-for="Email" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Password"></label>
|
||||
<input asp-for="Password" />
|
||||
<span asp-validation-for="Password" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="ConfirmPassword"></label>
|
||||
<input asp-for="ConfirmPassword" />
|
||||
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Registrieren</button>
|
||||
</form>
|
||||
|
||||
<p class="auth-switch">
|
||||
Bereits ein Konto? <a asp-action="Login">Jetzt anmelden</a>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@section Scripts
|
||||
{
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
28
Desktop/hallo/LEA/Views/Applications/Create.cshtml
Normal file
28
Desktop/hallo/LEA/Views/Applications/Create.cshtml
Normal 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" />
|
||||
}
|
88
Desktop/hallo/LEA/Views/Applications/Details.cshtml
Normal file
88
Desktop/hallo/LEA/Views/Applications/Details.cshtml
Normal 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>
|
28
Desktop/hallo/LEA/Views/Applications/Edit.cshtml
Normal file
28
Desktop/hallo/LEA/Views/Applications/Edit.cshtml
Normal 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" />
|
||||
}
|
142
Desktop/hallo/LEA/Views/Applications/Index.cshtml
Normal file
142
Desktop/hallo/LEA/Views/Applications/Index.cshtml
Normal 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>
|
||||
}
|
56
Desktop/hallo/LEA/Views/Applications/_ApplicationForm.cshtml
Normal file
56
Desktop/hallo/LEA/Views/Applications/_ApplicationForm.cshtml
Normal 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>
|
210
Desktop/hallo/LEA/Views/Home/Index.cshtml
Normal file
210
Desktop/hallo/LEA/Views/Home/Index.cshtml
Normal file
@@ -0,0 +1,210 @@
|
||||
@model DashboardViewModel
|
||||
@using System.Text.Encodings.Web
|
||||
@using System.Text.Json
|
||||
@using System.Linq
|
||||
@{
|
||||
ViewData["Title"] = "Übersicht";
|
||||
|
||||
var chartSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web)
|
||||
{
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||
};
|
||||
|
||||
var monthlyStats = Model.MonthlyApplications ?? Array.Empty<MonthlyApplicationStat>();
|
||||
var recentApplications = Model.RecentApplications ?? Enumerable.Empty<Application>();
|
||||
}
|
||||
|
||||
@if (!Model.IsAuthenticated)
|
||||
{
|
||||
<section class="hero">
|
||||
<div class="hero-content">
|
||||
<p class="eyebrow">LEA Bewerbungs-Tracker</p>
|
||||
<h1>Behalte deine Bewerbungen mühelos im Blick</h1>
|
||||
<p class="lead">Erfasse Bewerbungen, aktualisiere Status und sammle Notizen an einem Ort. Mit wenigen Klicks bleibst du organisiert und bestens vorbereitet auf jedes Gespräch.</p>
|
||||
<div class="hero-actions">
|
||||
<a class="btn btn-primary" asp-controller="Account" asp-action="Register">Jetzt registrieren</a>
|
||||
<a class="btn btn-outline" asp-controller="Account" asp-action="Login">Anmelden</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hero-visual" aria-hidden="true">
|
||||
<div class="hero-card">
|
||||
<span class="status-badge status-applied">Beworben</span>
|
||||
<span class="status-badge status-interview">Interview</span>
|
||||
<span class="status-badge status-offer">Angebot</span>
|
||||
<span class="status-badge status-rejected">Abgelehnt</span>
|
||||
</div>
|
||||
<div class="hero-highlight">
|
||||
<p><strong>Smarter Überblick</strong></p>
|
||||
<p>Analysiere Trends, nutze Filter und führe strukturierte Gespräche mit deinem nächsten Arbeitgeber.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="feature-grid">
|
||||
<article class="feature-card">
|
||||
<h3>Bewerbungen speichern</h3>
|
||||
<p>Lege jede Bewerbung mit wenigen Angaben an – inklusive Ansprechpartner, Quelle und individuellen Notizen.</p>
|
||||
</article>
|
||||
<article class="feature-card">
|
||||
<h3>Status & Fortschritt</h3>
|
||||
<p>Halte Termine und Feedback fest, aktualisiere den Status und bleibe immer einen Schritt voraus.</p>
|
||||
</article>
|
||||
<article class="feature-card">
|
||||
<h3>Individuelle Statistiken</h3>
|
||||
<p>Erhalte auf einen Blick, wie viele Bewerbungen offen, im Interview oder bereits abgeschlossen sind.</p>
|
||||
</article>
|
||||
</section>
|
||||
}
|
||||
else
|
||||
{
|
||||
<section class="dashboard-header">
|
||||
<div>
|
||||
<p class="eyebrow">Willkommen zurück</p>
|
||||
<h1>@(string.IsNullOrWhiteSpace(Model.FullName) ? "Dein Bewerbungs-Dashboard" : $"Hallo, {Model.FullName}!")</h1>
|
||||
<p class="lead">Behalte deine Bewerbungen im Blick, aktualisiere den Status und bereite dich optimal auf deine nächsten Schritte vor.</p>
|
||||
<div class="action-group">
|
||||
<a class="btn btn-primary" asp-controller="Applications" asp-action="Create">Neue Bewerbung erfassen</a>
|
||||
<a class="btn btn-outline" asp-controller="Applications" asp-action="Index">Alle Bewerbungen anzeigen</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="stats-grid">
|
||||
<article class="stat-card">
|
||||
<p class="stat-label">Gesamt</p>
|
||||
<p class="stat-value">@Model.TotalApplications</p>
|
||||
<p class="stat-caption">Bewerbungen insgesamt</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">Geplante 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">Erfolgreiche Angebote</p>
|
||||
</article>
|
||||
<article class="stat-card">
|
||||
<p class="stat-label">Absagen</p>
|
||||
<p class="stat-value">@Model.RejectedCount</p>
|
||||
<p class="stat-caption">Erhaltene Rückmeldungen</p>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="visual-grid">
|
||||
<article class="chart-card">
|
||||
<div class="chart-card-header">
|
||||
<h2>Statusübersicht</h2>
|
||||
<p>Wie sich deine Bewerbungen aktuell verteilen.</p>
|
||||
</div>
|
||||
@if (Model.TotalApplications == 0)
|
||||
{
|
||||
<p class="chart-empty">Sobald du Bewerbungen erfasst, erscheint hier eine Visualisierung.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
}, chartSerializerOptions);
|
||||
|
||||
<div class="chart-wrapper">
|
||||
<canvas id="dashboard-status-chart" data-chart='@Html.Raw(statusChartConfig)'></canvas>
|
||||
</div>
|
||||
}
|
||||
</article>
|
||||
|
||||
<article class="chart-card">
|
||||
<div class="chart-card-header">
|
||||
<h2>Monatlicher Verlauf</h2>
|
||||
<p>Wie viele Bewerbungen du in den letzten Monaten versendet hast.</p>
|
||||
</div>
|
||||
@if (!monthlyStats.Any(stat => stat.Count > 0))
|
||||
{
|
||||
<p class="chart-empty">Sobald Bewerbungen vorhanden sind, zeigen wir hier deinen Verlauf.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
var monthlyLabels = monthlyStats.Select(stat => stat.Label).ToArray();
|
||||
var monthlyValues = monthlyStats.Select(stat => stat.Count).ToArray();
|
||||
var monthlyChartConfig = JsonSerializer.Serialize(new
|
||||
{
|
||||
type = "line",
|
||||
labels = monthlyLabels,
|
||||
values = monthlyValues,
|
||||
colors = new[] { "rgba(68, 96, 247, 0.20)" },
|
||||
borderColor = "#4460f7",
|
||||
datasetLabel = "Bewerbungen",
|
||||
tension = 0.35,
|
||||
fill = true,
|
||||
legend = false
|
||||
}, chartSerializerOptions);
|
||||
|
||||
<div class="chart-wrapper">
|
||||
<canvas id="dashboard-monthly-chart" data-chart='@Html.Raw(monthlyChartConfig)'></canvas>
|
||||
</div>
|
||||
}
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="recent-applications">
|
||||
<div class="section-header">
|
||||
<h2>Aktuelle Bewerbungen</h2>
|
||||
<a class="link" asp-controller="Applications" asp-action="Index">Zur Bewerbungsübersicht</a>
|
||||
</div>
|
||||
|
||||
@if (!recentApplications.Any())
|
||||
{
|
||||
<div class="empty-state">
|
||||
<p>Noch keine Bewerbungen erfasst.</p>
|
||||
<a class="btn btn-primary" asp-controller="Applications" asp-action="Create">Jetzt starten</a>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="table-responsive">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Unternehmen</th>
|
||||
<th>Rolle</th>
|
||||
<th>Status</th>
|
||||
<th>Beworben am</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var application in recentApplications)
|
||||
{
|
||||
<tr>
|
||||
<td>@application.Company</td>
|
||||
<td>@application.Role</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 class="table-actions">
|
||||
<a class="link" asp-controller="Applications" asp-action="Details" asp-route-id="@application.Id">Details</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</section>
|
||||
}
|
16
Desktop/hallo/LEA/Views/Home/Privacy.cshtml
Normal file
16
Desktop/hallo/LEA/Views/Home/Privacy.cshtml
Normal file
@@ -0,0 +1,16 @@
|
||||
@{
|
||||
ViewData["Title"] = "Datenschutz";
|
||||
}
|
||||
|
||||
<section class="content-card">
|
||||
<h1>Datenschutzhinweise</h1>
|
||||
<p>
|
||||
Der Schutz deiner persönlichen Daten ist uns wichtig. Diese Anwendung speichert ausschließlich die Angaben,
|
||||
die du selbst für deine Bewerbungsverwaltung hinterlegst. Dazu gehören unter anderem Unternehmensdaten,
|
||||
Ansprechpartner sowie deine Notizen.
|
||||
</p>
|
||||
<p>
|
||||
Du kannst deine Daten jederzeit bearbeiten oder löschen. Für Fragen oder Feedback kontaktiere uns bitte über
|
||||
die im Impressum hinterlegte E-Mail-Adresse.
|
||||
</p>
|
||||
</section>
|
25
Desktop/hallo/LEA/Views/Shared/Error.cshtml
Normal file
25
Desktop/hallo/LEA/Views/Shared/Error.cshtml
Normal file
@@ -0,0 +1,25 @@
|
||||
@model ErrorViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Error";
|
||||
}
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (Model.ShowRequestId)
|
||||
{
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||
It can result in displaying sensitive information from exceptions to end users.
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||
and restarting the app.
|
||||
</p>
|
97
Desktop/hallo/LEA/Views/Shared/_Layout.cshtml
Normal file
97
Desktop/hallo/LEA/Views/Shared/_Layout.cshtml
Normal file
@@ -0,0 +1,97 @@
|
||||
@using LEA.Models
|
||||
@inject UserManager<ApplicationUser> UserManager
|
||||
@{
|
||||
ApplicationUser? currentUser = null;
|
||||
if (User.Identity?.IsAuthenticated ?? false)
|
||||
{
|
||||
currentUser = await UserManager.GetUserAsync(User);
|
||||
}
|
||||
|
||||
var displayName = currentUser?.FullName;
|
||||
}
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>@ViewData["Title"] - LEA Bewerbungs-Tracker</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
||||
<link rel="stylesheet" href="~/LEA.styles.css" asp-append-version="true" />
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<nav class="main-nav">
|
||||
<a class="brand" asp-controller="Home" asp-action="Index">LEA Bewerbungs-Tracker</a>
|
||||
<button class="nav-toggle" type="button" aria-label="Navigation umschalten" data-target="primary-nav">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
<div class="nav-menu" id="primary-nav">
|
||||
<ul class="nav-links">
|
||||
<li><a asp-controller="Home" asp-action="Index" class="@(ViewContext.RouteData.Values["controller"]?.ToString() == "Home" ? "active" : null)">Start</a></li>
|
||||
@if (User.Identity?.IsAuthenticated ?? false)
|
||||
{
|
||||
<li><a asp-controller="Applications" asp-action="Index" class="@(ViewContext.RouteData.Values["controller"]?.ToString() == "Applications" ? "active" : null)">Bewerbungen</a></li>
|
||||
}
|
||||
<li><a asp-controller="Home" asp-action="Privacy">Datenschutz</a></li>
|
||||
</ul>
|
||||
<div class="nav-actions">
|
||||
@if (User.Identity?.IsAuthenticated ?? false)
|
||||
{
|
||||
<span class="nav-user">Hallo, @(string.IsNullOrWhiteSpace(displayName) ? User.Identity?.Name : displayName)</span>
|
||||
<form asp-controller="Account" asp-action="Logout" method="post">
|
||||
@Html.AntiForgeryToken()
|
||||
<button type="submit" class="btn btn-outline">Abmelden</button>
|
||||
</form>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a class="btn btn-link" asp-controller="Account" asp-action="Login">Anmelden</a>
|
||||
<a class="btn btn-primary" asp-controller="Account" asp-action="Register">Registrieren</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<div class="flash-container">
|
||||
@if (TempData["Success"] is string successMessage)
|
||||
{
|
||||
<div class="flash-message success" role="status">
|
||||
<span>@successMessage</span>
|
||||
<button type="button" class="flash-close" aria-label="Meldung schließen">×</button>
|
||||
</div>
|
||||
}
|
||||
@if (TempData["Error"] is string errorMessage)
|
||||
{
|
||||
<div class="flash-message error" role="status">
|
||||
<span>@errorMessage</span>
|
||||
<button type="button" class="flash-close" aria-label="Meldung schließen">×</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<main class="site-main">
|
||||
@RenderBody()
|
||||
</main>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="footer-inner">
|
||||
<p>© @DateTime.Now.Year LEA Bewerbungs-Tracker</p>
|
||||
<div class="footer-links">
|
||||
<a asp-controller="Home" asp-action="Index">Start</a>
|
||||
<a asp-controller="Home" asp-action="Privacy">Datenschutz</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js" crossorigin="anonymous"></script>
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
@await RenderSectionAsync("Scripts", required: false)
|
||||
</body>
|
||||
</html>
|
48
Desktop/hallo/LEA/Views/Shared/_Layout.cshtml.css
Normal file
48
Desktop/hallo/LEA/Views/Shared/_Layout.cshtml.css
Normal file
@@ -0,0 +1,48 @@
|
||||
/* Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
|
||||
for details on configuring this project to bundle and minify static web assets. */
|
||||
|
||||
a.navbar-brand {
|
||||
white-space: normal;
|
||||
text-align: center;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0077cc;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
}
|
||||
|
||||
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
}
|
||||
|
||||
.border-top {
|
||||
border-top: 1px solid #e5e5e5;
|
||||
}
|
||||
.border-bottom {
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.box-shadow {
|
||||
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
|
||||
}
|
||||
|
||||
button.accept-policy {
|
||||
font-size: 1rem;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
line-height: 60px;
|
||||
}
|
@@ -0,0 +1,2 @@
|
||||
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
|
||||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
|
6
Desktop/hallo/LEA/Views/_ViewImports.cshtml
Normal file
6
Desktop/hallo/LEA/Views/_ViewImports.cshtml
Normal file
@@ -0,0 +1,6 @@
|
||||
@using LEA
|
||||
@using LEA.Models
|
||||
@using LEA.ViewModels
|
||||
@using LEA.Extensions
|
||||
@using Microsoft.AspNetCore.Identity
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
3
Desktop/hallo/LEA/Views/_ViewStart.cshtml
Normal file
3
Desktop/hallo/LEA/Views/_ViewStart.cshtml
Normal file
@@ -0,0 +1,3 @@
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
Reference in New Issue
Block a user