добавлены стили, мелкие правки
оценка почти но никак
This commit is contained in:
parent
76c13d303a
commit
fd31ade855
@ -67,40 +67,15 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
public List<AssessmentViewModel>? ReadList(AssessmentSearchModel? model)
|
||||
{
|
||||
var list = model == null ? _assessmentStorage.GetFullList() : _assessmentStorage.GetFilteredList(model);
|
||||
List<AssessmentViewModel> result = new();
|
||||
|
||||
foreach (var elem in list)
|
||||
{
|
||||
var user = _userStorage.GetElement(new UserSearchModel { Id = elem.UserId });
|
||||
var assessmentCriterions = _assessmentStorage.GetAssessmentCriterions(elem.Id);
|
||||
|
||||
var assessmentViewModel = new AssessmentViewModel
|
||||
{
|
||||
Id = elem.Id,
|
||||
ResumeId = elem.ResumeId,
|
||||
UserId = elem.UserId,
|
||||
UserName = user.Name + " " + user.Name,
|
||||
Comment = elem.Comment,
|
||||
AssessmentCriterions = assessmentCriterions.Select(ac => new AssessmentCriterionViewModel
|
||||
{
|
||||
AssessmentId = ac.AssessmentId,
|
||||
CriterionId = ac.CriterionId,
|
||||
Value = ac.Value,
|
||||
CriterionName = _criterionStorage.GetElement(new CriterionSearchModel { Id = ac.CriterionId })?.Name
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
result.Add(assessmentViewModel);
|
||||
}
|
||||
|
||||
if (result == null)
|
||||
if (list == null)
|
||||
{
|
||||
_logger.LogWarning("ReadList return null list");
|
||||
return null;
|
||||
}
|
||||
|
||||
_logger.LogInformation("ReadList. Count: {Count}", result.Count);
|
||||
return result;
|
||||
_logger.LogInformation("ReadList. Count: {Count}", list.Count);
|
||||
return list;
|
||||
}
|
||||
|
||||
public bool Update(AssessmentBindingModel model)
|
||||
|
@ -64,6 +64,7 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
{
|
||||
Id = a.Id,
|
||||
ResumeId = a.ResumeId,
|
||||
UserName = a.UserName,
|
||||
UserId = a.UserId,
|
||||
Comment = a.Comment,
|
||||
AssessmentCriterions = a.AssessmentCriterions
|
||||
@ -107,6 +108,7 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
Id = a.Id,
|
||||
ResumeId = a.ResumeId,
|
||||
UserId = a.UserId,
|
||||
UserName = a.UserName,
|
||||
Comment = a.Comment,
|
||||
AssessmentCriterions = a.AssessmentCriterions
|
||||
}).ToList() ?? new List<AssessmentViewModel>();
|
||||
|
@ -104,6 +104,12 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
_logger.LogWarning("ReadList return null list");
|
||||
return null;
|
||||
}
|
||||
foreach (var item in list)
|
||||
{
|
||||
var companyName = _companyStorage.GetElement(new CompanySearchModel { Id = item.CompanyId }).Name;
|
||||
item.CompanyName = companyName;
|
||||
}
|
||||
|
||||
_logger.LogInformation("ReadList. Count: {Count}", list.Count);
|
||||
return list;
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ using CandidateReviewContracts.ViewModels;
|
||||
using CandidateReviewDataModels.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography.Xml;
|
||||
|
||||
namespace CandidateReviewClientApp.Controllers
|
||||
{
|
||||
@ -22,7 +24,7 @@ namespace CandidateReviewClientApp.Controllers
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> AddAssessmentCriterion(int resumeId, int[] criterion, int[] value, string comment)
|
||||
{
|
||||
string returnUrl = HttpContext.Request.Headers["Referer"].ToString();
|
||||
string returnUrl = HttpContext.Request.Headers.Referer.ToString();
|
||||
|
||||
try
|
||||
{
|
||||
@ -35,22 +37,54 @@ namespace CandidateReviewClientApp.Controllers
|
||||
{
|
||||
throw new ArgumentException("Массивы критериев и оценок должны быть не null и одинаковой длины.");
|
||||
}
|
||||
Dictionary<int, (CriterionModel, int)> assCriterions = new();
|
||||
|
||||
|
||||
var userId = APIClient.User?.Id;
|
||||
var assessmentData = new Dictionary<int, (ICriterionModel, int)>();
|
||||
|
||||
var assessmentModel = new AssessmentBindingModel
|
||||
{
|
||||
ResumeId = resumeId,
|
||||
UserId = userId,
|
||||
Comment = comment,
|
||||
AssessmentCriterions = criterion.Select((t, i) => new KeyValuePair<int, (ICriterionModel, int)>
|
||||
(t, (new CriterionViewModel { Id = t }, value[i]))).ToDictionary(kv => kv.Key, kv => kv.Value)
|
||||
AssessmentCriterions = assCriterions
|
||||
};
|
||||
|
||||
|
||||
int assessmentId = await APIClient.PostRequestAsync("api/assessment/create", assessmentModel);
|
||||
|
||||
for (int i = 0; i < criterion.Length; i++)
|
||||
{
|
||||
var crit = APIClient.GetRequest<CriterionViewModel>($"api/criterion/details?id={criterion[i]}");
|
||||
assCriterions.Add(assessmentId, (new CriterionModel { Id = crit.Id, Name = crit.Name }, value[i]));
|
||||
}
|
||||
|
||||
assessmentModel.AssessmentCriterions = assCriterions;
|
||||
assessmentModel.Id = assessmentId;
|
||||
APIClient.PostRequest("api/assessment/update", assessmentModel);
|
||||
|
||||
var user = APIClient.GetRequest<UserViewModel>($"api/user/profile?id={APIClient.User?.Id}");
|
||||
|
||||
APIClient.User?.Assessments.Add(new AssessmentViewModel
|
||||
{
|
||||
ResumeId = assessmentModel.ResumeId,
|
||||
UserId = assessmentModel.UserId,
|
||||
Comment = assessmentModel.Comment,
|
||||
AssessmentCriterions = assessmentModel.AssessmentCriterions
|
||||
});
|
||||
var resume = APIClient.GetRequest<ResumeViewModel>($"api/resume/details?id={resumeId}");
|
||||
if (resume != null)
|
||||
{
|
||||
resume?.Assessments.Add(new AssessmentViewModel
|
||||
{
|
||||
ResumeId = assessmentModel.ResumeId,
|
||||
UserId = assessmentModel.UserId,
|
||||
Comment = assessmentModel.Comment,
|
||||
AssessmentCriterions = assessmentModel.AssessmentCriterions
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Пользователь не найден");
|
||||
}
|
||||
return Redirect($"~/Resume/ResumeDetails/{resumeId}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -59,6 +93,22 @@ namespace CandidateReviewClientApp.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
public IActionResult Delete(int id, int resumeId)
|
||||
{
|
||||
string returnUrl = HttpContext.Request.Headers["Referer"].ToString();
|
||||
|
||||
try
|
||||
{
|
||||
APIClient.PostRequest($"api/assessment/delete", new AssessmentBindingModel { Id = id });
|
||||
|
||||
return Redirect($"~/Resume/ResumeDetails/{resumeId}") ;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return RedirectToAction("Error", new { errorMessage = $"{ex.Message}", returnUrl });
|
||||
}
|
||||
}
|
||||
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public IActionResult Error(string errorMessage, string returnUrl)
|
||||
{
|
||||
|
@ -105,7 +105,15 @@ namespace CandidateReviewClientApp.Controllers
|
||||
{
|
||||
APIClient.User?.Resumes.Add(new ResumeViewModel
|
||||
{
|
||||
Id = model.Id
|
||||
Id = model.Id,
|
||||
Description = model.Description,
|
||||
Education = model.Education,
|
||||
Experience = model.Experience,
|
||||
Skills = model.Skills,
|
||||
Status = model.Status,
|
||||
Title = model.Title,
|
||||
UserId = model.UserId,
|
||||
VacancyId = model.VacancyId
|
||||
});
|
||||
}
|
||||
else
|
||||
@ -116,7 +124,15 @@ namespace CandidateReviewClientApp.Controllers
|
||||
{
|
||||
vacancy.Resumes.Add(new ResumeViewModel
|
||||
{
|
||||
Id = model.Id
|
||||
Id = model.Id,
|
||||
Description = model.Description,
|
||||
Education = model.Education,
|
||||
Experience = model.Experience,
|
||||
Skills = model.Skills,
|
||||
Status = model.Status,
|
||||
Title = model.Title,
|
||||
UserId = model.UserId,
|
||||
VacancyId = model.VacancyId
|
||||
});
|
||||
}
|
||||
else
|
||||
|
@ -43,7 +43,11 @@ namespace CandidateReviewClientApp.Controllers
|
||||
|
||||
if (!id.HasValue)
|
||||
{
|
||||
return View(new UserViewModel());
|
||||
var model = new UserViewModel
|
||||
{
|
||||
CompanyId = APIClient.Company.Id
|
||||
};
|
||||
return View(model);
|
||||
}
|
||||
else if (id.HasValue)
|
||||
{
|
||||
@ -68,7 +72,7 @@ namespace CandidateReviewClientApp.Controllers
|
||||
APIClient.PostRequest("api/user/update", model);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
APIClient.PostRequest("api/user/register", model);
|
||||
if (APIClient.Company != null)
|
||||
{
|
||||
|
@ -30,6 +30,17 @@ namespace CandidateReviewClientApp.Controllers
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult Vacancies(int? companyId)
|
||||
{
|
||||
if (APIClient.User == null)
|
||||
{
|
||||
return Redirect("~/Home/Enter");
|
||||
}
|
||||
var vacancies = APIClient.GetRequest<List<VacancyViewModel>?>($"api/vacancy/list?companyId={companyId}");
|
||||
return View(vacancies);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult EditVacancy(int? id)
|
||||
{
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Профиль компании";
|
||||
var isAdmin = APIClient.User.Role == CandidateReviewDataModels.Enums.RoleEnum.Администратор ? true : false;
|
||||
}
|
||||
|
||||
<div class="container mt-5">
|
||||
@ -48,20 +49,54 @@
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h2>Вакансии компании</h2>
|
||||
<a asp-action="EditVacancy" asp-controller="Vacancy" asp-route-companyId="@Model.Id"
|
||||
class="btn btn-success">Добавить вакансию</a>
|
||||
class="btn btn-success"> <i class="bi bi-plus-circle me-2"></i> Добавить вакансию</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if (Model.Vacancies != null && Model.Vacancies.Any())
|
||||
{
|
||||
@await Html.PartialAsync("_VacanciesTable", Model.Vacancies.Take(5))
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Название вакансии</th>
|
||||
<th>Статус</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var vacancy in Model.Vacancies.Take(5))
|
||||
{
|
||||
<tr>
|
||||
<td>@vacancy.JobTitle</td>
|
||||
<td>@vacancy.Status</td>
|
||||
<td>
|
||||
<div class="d-flex justify-content-center">
|
||||
<a asp-action="VacancyDetails" asp-controller="Vacancy" asp-route-id="@vacancy.Id"
|
||||
class="btn btn-info btn-sm me-2" title="Просмотр">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
<a asp-action="EditVacancy" asp-controller="Vacancy" asp-route-id="@vacancy.Id"
|
||||
class="btn btn-warning btn-sm me-2" title="Редактировать">
|
||||
<i class="bi bi-pencil-square"></i>
|
||||
</a>
|
||||
<a asp-action="Delete" asp-controller="Vacancy" asp-route-id="@vacancy.Id"
|
||||
class="btn btn-danger btn-sm" title="Удалить"
|
||||
onclick="return confirm('Вы уверены, что хотите удалить вакансию?');">
|
||||
<i class="bi bi-trash"></i>
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@if (Model.Vacancies.Count() > 5)
|
||||
{
|
||||
<button id="showAllVacanciesBtn" class="btn btn-primary" onclick="toggleVacancies()">Показать все</button>
|
||||
<a asp-action="Vacancies" asp-controller="Vacancy" asp-route-companyId="@Model.Id"
|
||||
class="btn btn-primary mt-3">Посмотреть все</a>
|
||||
}
|
||||
|
||||
<div id="allVacancies" style="display:none;">
|
||||
@await Html.PartialAsync("_VacanciesTable", Model.Vacancies)
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -73,44 +108,50 @@
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h2>Сотрудники компании</h2>
|
||||
@if (@isAdmin) {
|
||||
<a asp-action="UserProfileEdit" asp-controller="User" asp-route-companyId="@Model.Id"
|
||||
class="btn btn-success">Добавить сотрудника</a>
|
||||
class="btn btn-success"> <i class="bi bi-plus-circle me-2"></i> Добавить сотрудника</a>
|
||||
}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if (Model.Employees != null && Model.Employees.Any())
|
||||
{
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Фамилия</th>
|
||||
<th>Имя</th>
|
||||
<th>Эл. почта</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var employee in Model.Employees)
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Фамилия</th>
|
||||
<th>Имя</th>
|
||||
<th>Эл. почта</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var employee in Model.Employees.Take(5))
|
||||
{
|
||||
<tr>
|
||||
<td>@employee.Surname</td>
|
||||
<td>@employee.Name</td>
|
||||
<td>@employee.Email</td>
|
||||
<td>
|
||||
<a asp-action="UserProfile" asp-controller="User" asp-route-id="@employee.Id" class="btn btn-info btn-sm rounded-pill" title="Просмотр">
|
||||
<i class="bi bi-eye"></i> Просмотр
|
||||
<a asp-action="UserProfile" asp-controller="User" asp-route-id="@employee.Id" class="btn btn-info btn-sm me-2" title="Просмотр">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
|
||||
<a asp-action="UserProfileEdit" asp-controller="User" asp-route-id="@employee.Id" class="btn btn-warning btn-sm rounded-pill" title="Редактировать">
|
||||
<i class="bi bi-pencil"></i> Редактировать
|
||||
<a asp-action="UserProfileEdit" asp-controller="User" asp-route-id="@employee.Id" class="btn btn-warning btn-sm me-2" title="Редактировать">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
|
||||
<a asp-action="DeleteEmployee" asp-controller="User" asp-route-id="@employee.Id" class="btn btn-danger btn-sm rounded-pill" title="Удалить" onclick="return confirm('Вы уверены, что хотите удалить сотрудника?');">
|
||||
<i class="bi bi-trash"></i> Удалить
|
||||
<a asp-action="DeleteEmployee" asp-controller="User" asp-route-id="@employee.Id" class="btn btn-danger btn-sm me-2" title="Удалить" onclick="return confirm('Вы уверены, что хотите удалить сотрудника?');">
|
||||
<i class="bi bi-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -121,20 +162,19 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
.btn {
|
||||
background-color: #0A1128;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
@section Scripts {
|
||||
<script>
|
||||
function toggleVacancies() {
|
||||
var allVacancies = document.getElementById('allVacancies');
|
||||
var button = document.getElementById('showAllVacanciesBtn');
|
||||
|
||||
if (allVacancies.style.display === 'none') {
|
||||
allVacancies.style.display = 'block';
|
||||
button.innerText = 'Скрыть';
|
||||
} else {
|
||||
allVacancies.style.display = 'none';
|
||||
button.innerText = 'Показать все';
|
||||
}
|
||||
.btn:hover {
|
||||
background-color: #1C3273;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
</script>
|
||||
}
|
||||
</style>
|
||||
|
@ -78,4 +78,20 @@
|
||||
})
|
||||
})()
|
||||
</script>
|
||||
<style>
|
||||
.btn {
|
||||
background-color: #0A1128;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #1C3273;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -70,4 +70,20 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
.btn {
|
||||
background-color: #0A1128;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #1C3273;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
</style>
|
@ -3,40 +3,28 @@
|
||||
Layout = "_LoginLayout";
|
||||
}
|
||||
|
||||
@if (!ViewData.ModelState.IsValid)
|
||||
{
|
||||
<div class="alert alert-danger">
|
||||
<ul>
|
||||
@foreach (var error in ViewData.ModelState.Values.SelectMany(v => v.Errors))
|
||||
{
|
||||
<li>@error.ErrorMessage</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header">
|
||||
<h3 class="text-center">Вход в приложение</h3>
|
||||
<div class="card shadow-lg rounded">
|
||||
<div class="card-header bg-primary text-white text-center rounded-top">
|
||||
<h3 class="mb-0">Вход в приложение</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-body p-4">
|
||||
<form method="post">
|
||||
<div class="form-group">
|
||||
<label for="login">Логин:</label>
|
||||
<div class="form-group mb-3">
|
||||
<label for="login" class="form-label">Логин:</label>
|
||||
<input type="text" class="form-control" id="login" name="login" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Пароль:</label>
|
||||
<div class="form-group mb-3">
|
||||
<label for="password" class="form-label">Пароль:</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
<div class="form-group text-center mt-3">
|
||||
<button type="submit" class="btn btn-primary">Войти</button>
|
||||
<div class="form-group text-center mt-4">
|
||||
<button type="submit" class="btn btn-primary w-100 py-2">Войти</button>
|
||||
</div>
|
||||
<div class="form-group text-center mt-2">
|
||||
<a asp-area="" asp-controller="Home" asp-action="Register" class="text-muted">Ещё не зарегистрированы? Регистрация</a>
|
||||
<div class="form-group text-center mt-3">
|
||||
<a asp-area="" asp-controller="Home" asp-action="Register" class="text-muted text-decoration-none">Ещё не зарегистрированы? Регистрация</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -44,4 +32,54 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background-color: #f0f4f7;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
background-color: #f0f4f7; /* Цвет фона формы */
|
||||
border-top-left-radius: 15px;
|
||||
border-top-right-radius: 15px;
|
||||
border-bottom: 1px solid #ddd; /* Тонкая линия, чтобы отделить заголовок от содержимого */
|
||||
}
|
||||
|
||||
.form-control {
|
||||
border-radius: 10px;
|
||||
box-shadow: none;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
border-color: #0A1128;
|
||||
box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #0A1128;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #1C3273;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.text-muted:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
@ -7,18 +7,21 @@
|
||||
<p>Здесь вы можете:</p>
|
||||
|
||||
<div class="d-flex justify-content-center mt-4">
|
||||
<div class="box">
|
||||
<h3>Создать профиль компании</h3>
|
||||
</div>
|
||||
<div class="box">
|
||||
<h3>Подобрать кандидатов на вакансию</h3>
|
||||
</div>
|
||||
<div class="box">
|
||||
<h3>Найти подходящую вакансию</h3>
|
||||
</div>
|
||||
<div class="box">
|
||||
<h3>Оценить кандидатов на вакансию</h3>
|
||||
</div>
|
||||
<div class="box">
|
||||
<i class="bi bi-building" style="font-size: 2rem; color: #007bff;"></i>
|
||||
<h3 class="mt-3">Создать профиль компании</h3>
|
||||
</div>
|
||||
<div class="box">
|
||||
<i class="bi bi-search" style="font-size: 2rem; color: #007bff;"></i>
|
||||
<h3 class="mt-3">Подобрать кандидатов на вакансию</h3>
|
||||
</div>
|
||||
<div class="box">
|
||||
<i class="bi bi-briefcase" style="font-size: 2rem; color: #007bff;"></i>
|
||||
<h3 class="mt-3">Найти подходящую вакансию</h3>
|
||||
</div>
|
||||
<div class="box">
|
||||
<i class="bi bi-people" style="font-size: 2rem; color: #007bff;"></i>
|
||||
<h3 class="mt-3">Оценить кандидатов на вакансию</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -30,6 +33,10 @@
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.box i {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.box {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 8px;
|
||||
|
@ -6,8 +6,8 @@
|
||||
<div class="container mt-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header">
|
||||
<div class="card shadow-lg rounded">
|
||||
<div class="card-header bg-primary text-white text-center rounded-top">
|
||||
<h3 class="text-center">Регистрация</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@ -36,11 +36,62 @@
|
||||
<button type="submit" class="btn btn-primary">Зарегистрироваться</button>
|
||||
</div>
|
||||
<div class="form-group text-center mt-2">
|
||||
<a asp-area="" asp-controller="Home" asp-action="Enter" class="text-muted">Уже зарегистрированы? Войти</a>
|
||||
<a asp-area="" asp-controller="Home" asp-action="Enter" class="text-muted text-decoration-none">Уже зарегистрированы? Войти</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background-color: #f0f4f7;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
border-top-left-radius: 15px;
|
||||
border-top-right-radius: 15px;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
border-radius: 10px;
|
||||
box-shadow: none;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
border-color: #0A1128;
|
||||
box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #0A1128;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #1C3273;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.text-muted:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
@ -40,12 +40,6 @@
|
||||
<input type="text" class="form-control" id="description" name="description" value="@Model?.Description" placeholder="Введите описание резюме">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="PhotoFilePath" class="form-label">Ваше фото для текущего резюме</label>
|
||||
<input type="file" class="form-control" id="PhotoFilePath" name="PhotoFilePath" accept=".jpg,.jpeg,.png" />
|
||||
<img id="avatarPreview" src="@Model?.PhotoFilePath" alt="Предварительный просмотр фото" style="max-width: 100px; max-height: 100px;" />
|
||||
<div class="invalid-feedback">Выберите файл изображения.</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
@if (Model.Status == ResumeStatusEnum.Черновик)
|
||||
{
|
||||
@ -54,6 +48,10 @@
|
||||
@if (Model.Id <= 0)
|
||||
{
|
||||
<button type="submit" formmethod="post" class="btn btn-secondary" name="isDraft" value="true">Сохранить черновик</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="submit" class="btn btn-primary">Сохранить</button>
|
||||
}
|
||||
<button class="btn btn-secondary" onclick="window.history.back();">Назад</button>
|
||||
</div>
|
||||
@ -78,4 +76,20 @@
|
||||
}, false)
|
||||
})
|
||||
})()
|
||||
</script>
|
||||
</script>
|
||||
<style>
|
||||
.btn {
|
||||
background-color: #0A1128;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #1C3273;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
</style>
|
@ -7,16 +7,14 @@
|
||||
@{
|
||||
ViewData["Title"] = "Резюме";
|
||||
bool userRole = APIClient.User?.Role == CandidateReviewDataModels.Enums.RoleEnum.Сотрудник || APIClient.User.Role == CandidateReviewDataModels.Enums.RoleEnum.Администратор;
|
||||
bool isAdmin = APIClient.User.Role == CandidateReviewDataModels.Enums.RoleEnum.Администратор ? true : false;
|
||||
var assessmentCriterions = new Dictionary<int, (ICriterionModel, int)>();
|
||||
}
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="d-flex justify-content-between mb-4">
|
||||
<div class="card-header">
|
||||
<h2>@Model.Title</h2>
|
||||
<img src="@(Model.PhotoFilePath ?? "https://cdn-icons-png.flaticon.com/512/18/18601.png")"
|
||||
style="max-width: 150px; max-height: 150px; object-fit: cover; "
|
||||
class="card-img-top img-fluid rounded-circle mx-auto d-block"
|
||||
alt="Аватар пользователя" />
|
||||
<input type="hidden" name="id" value="@Model?.Id" />
|
||||
</div>
|
||||
<button class="btn btn-secondary" onclick="window.history.back();">Назад</button>
|
||||
@ -64,6 +62,14 @@
|
||||
{
|
||||
<h2 class="mb-4">Оценка резюме</h2>
|
||||
|
||||
@if (isAdmin)
|
||||
{
|
||||
<div class="mt-4">
|
||||
<a asp-action="ManageCriterions" asp-controller="Criterion" class="btn btn-outline-secondary">Управление критериями</a>
|
||||
</div>
|
||||
<br></br>
|
||||
}
|
||||
|
||||
<form method="post" asp-controller="Assessment" asp-action="AddAssessmentCriterion">
|
||||
<input type="hidden" name="resumeId" value="@Model.Id" />
|
||||
|
||||
@ -85,11 +91,11 @@
|
||||
<div class="row mb-3 criterion-row">
|
||||
<div class="col-8">
|
||||
<select name="criterion" class="form-control" disabled>
|
||||
<option value="@criterion.CriterionId" selected>@criterion.CriterionName</option>
|
||||
<option value="@criterion.Value.Item1.Id" selected>@criterion.Value.Item1.Name</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="number" name="value" class="form-control" value="@criterion.Value" readonly />
|
||||
<input type="number" name="value" class="form-control" value="@criterion.Value.Item2" readonly />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@ -111,15 +117,20 @@
|
||||
<div class="row mb-3 criterion-row">
|
||||
<div class="col-8">
|
||||
<select name="criterion" class="form-control" disabled>
|
||||
<option value="@criterion.CriterionId" selected>@criterion.CriterionName</option>
|
||||
<option value="@criterion.Value.Item1.Id" selected>@criterion.Value.Item1.Name</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="number" name="value" class="form-control" value="@criterion.Value" readonly />
|
||||
<input type="number" name="value" class="form-control" value="@criterion.Value.Item2" readonly />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<p>Комментарий: @userAssessment.Comment</p>
|
||||
|
||||
<a asp-controller="Assessment" asp-action="Delete" asp-route-id="@userAssessment.Id" asp-route-resumeId="@Model.Id" onclick="return confirm('Вы уверены, что хотите удалить оценку?');"
|
||||
class="btn btn-info btn-sm me-2" title="Просмотр">
|
||||
Удалить оценку
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
@ -160,11 +171,8 @@
|
||||
}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="mt-4">
|
||||
<a asp-action="ManageCriterions" asp-controller="Criterion" class="btn btn-outline-secondary">Управление критериями</a>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@ -214,3 +222,20 @@
|
||||
|
||||
document.querySelectorAll('.remove-criterion').forEach(button => attachRemoveEvent(button));
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.btn {
|
||||
background-color: #0A1128;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #1C3273;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
</style>
|
||||
|
@ -14,25 +14,25 @@
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<nav class="navbar navbar-expand-lg navbar-dark shadow-md">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Candidate Review</a>
|
||||
<button class="navbar-toggler" type="button" onclick="toggleNavbar()" aria-controls="mainNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="mainNav">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
@if (APIClient.User?.Role == RoleEnum.Сотрудник || APIClient.User?.Role == RoleEnum.Администратор)
|
||||
{
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-controller="Company" asp-route-id="@(APIClient.Company?.Id)" asp-action="@(APIClient.Company == null ? "EditCompanyProfile" : "CompanyProfile")">Профиль компании</a>
|
||||
<a class="nav-link" asp-area="" asp-controller="Company" asp-route-id="@(APIClient.Company?.Id)" asp-action="@(APIClient.Company == null ? "EditCompanyProfile" : "CompanyProfile")">Профиль компании</a>
|
||||
</li>
|
||||
}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-controller="User" asp-action="UserProfile" asp-route-id="@(APIClient.User?.Id)">Профиль</a>
|
||||
<a class="nav-link" asp-area="" asp-controller="User" asp-action="UserProfile" asp-route-id="@(APIClient.User?.Id)">Профиль</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-controller="Vacancy" asp-action="SearchVacancies">Поиск вакансий</a>
|
||||
<a class="nav-link" asp-area="" asp-controller="Vacancy" asp-action="SearchVacancies">Поиск вакансий</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -58,5 +58,25 @@
|
||||
navbar.classList.toggle('show');
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.navbar {
|
||||
background-color: #0A1128;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.navbar .nav-link {
|
||||
font-size: 1rem;
|
||||
transition: color 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.navbar .nav-link:hover {
|
||||
color: #D9D9D9;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,33 +0,0 @@
|
||||
@model IEnumerable<CandidateReviewContracts.ViewModels.VacancyViewModel>
|
||||
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Название</th>
|
||||
<th>Тип занятости</th>
|
||||
<th>Статус</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var vacancy in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>@vacancy.JobTitle</td>
|
||||
<td>@vacancy.JobType</td>
|
||||
<td>@vacancy.Status</td>
|
||||
<td>
|
||||
<a asp-action="VacancyDetails" asp-controller="Vacancy" asp-route-id="@vacancy.Id" class="btn btn-info btn-sm rounded-pill" title="Просмотр">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
<a asp-action="EditVacancy" asp-controller="Vacancy" asp-route-id="@vacancy.Id" class="btn btn-warning btn-sm rounded-pill" title="Редактировать">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
<a asp-action="Delete" asp-controller="Vacancy" asp-route-id="@vacancy.Id" class="btn btn-danger btn-sm rounded-pill" title="Удалить" onclick="return confirm('Вы уверены, что хотите удалить вакансию?');">
|
||||
<i class="bi bi-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
101
CandidateReviewClientApp/Views/User/Employees.cshtml
Normal file
101
CandidateReviewClientApp/Views/User/Employees.cshtml
Normal file
@ -0,0 +1,101 @@
|
||||
@using CandidateReviewContracts.ViewModels
|
||||
@model List<UserViewModel>
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Сотрудники компании";
|
||||
}
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-12">
|
||||
<h1 class="mb-4 text-center">Сотрудники</h1>
|
||||
<div class="mb-4 text-end">
|
||||
<a asp-action="UserProfileEdit" asp-controller="User" asp-route-companyId="@APIClient.Company.Id" class="btn btn-success">
|
||||
<i class="bi bi-plus-circle me-2"></i> Добавить сотрудника
|
||||
</a>
|
||||
</div>
|
||||
@if (Model != null)
|
||||
{
|
||||
@if (Model.Any())
|
||||
{
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Фамилия</th>
|
||||
<th>Имя</th>
|
||||
<th>Эл. почта</th>
|
||||
<th>Номер телефона</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var employee in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>@employee.Surname</td>
|
||||
<td>@employee.Name</td>
|
||||
<td>@employee.Email</td>
|
||||
<td>@employee.PhoneNumber</td>
|
||||
<td>
|
||||
<a asp-action="UserProfile" asp-controller="User" asp-route-id="@employee.Id" class="btn btn-info btn-sm me-2" title="Просмотр">
|
||||
<i class="bi bi-eye"></i> Просмотр
|
||||
</a>
|
||||
|
||||
<a asp-action="UserProfileEdit" asp-controller="User" asp-route-id="@employee.Id" class="btn btn-warning btn-sm me-2" title="Редактировать">
|
||||
<i class="bi bi-pencil"></i> Редактировать
|
||||
</a>
|
||||
|
||||
<a asp-action="Delete" asp-controller="User" asp-route-id="@employee.Id" class="btn btn-danger btn-sm me-2" title="Удалить" onclick="return confirm('Вы уверены, что хотите удалить сотрудника?');">
|
||||
<i class="bi bi-trash"></i> Удалить
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="text-center text-muted">Сотрудников нет.</p>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="text-center text-danger">Произошла ошибка при получении данных.</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.table-hover tbody tr:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.btn-info, .btn-warning, .btn-danger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-info i, .btn-warning i, .btn-danger i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #0A1128;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #1C3273;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
</style>
|
@ -3,54 +3,68 @@
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Профиль пользователя";
|
||||
var userRole = APIClient.User?.Role == CandidateReviewDataModels.Enums.RoleEnum.Пользователь ? true : false;
|
||||
var userRole = APIClient.User?.Role == CandidateReviewDataModels.Enums.RoleEnum.Пользователь || APIClient.User?.Role == CandidateReviewDataModels.Enums.RoleEnum.Администратор ? true : false;
|
||||
}
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card shadow-sm">
|
||||
<img src="@(Model.AvatarFilePath ?? "https://cdn-icons-png.flaticon.com/512/18/18601.png")"
|
||||
class="card-img-top img-fluid rounded-circle mx-auto d-block" style="max-width: 150px; max-height: 150px;" alt="Аватар пользователя">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-lg p-4 rounded">
|
||||
<div class="text-center">
|
||||
<img src="https://cdn-icons-png.flaticon.com/512/18/18601.png"
|
||||
class="card-img-top img-fluid rounded-circle mx-auto d-block"
|
||||
style="max-width: 150px; max-height: 150px;" alt="Аватар пользователя">
|
||||
</div>
|
||||
<div class="card-body text-center">
|
||||
<h5 class="card-title mb-0">
|
||||
@(string.IsNullOrEmpty(@Model?.Surname) ? "" : @Model?.Surname) @Model?.Name @(string.IsNullOrEmpty(@Model?.LastName) ? "" : @Model?.LastName)
|
||||
</h5>
|
||||
<h3 class="card-title mb-2">
|
||||
@(string.IsNullOrEmpty(@Model?.Surname) ? "" : @Model?.Surname)
|
||||
@Model?.Name
|
||||
@(string.IsNullOrEmpty(@Model?.LastName) ? "" : @Model?.LastName)
|
||||
</h3>
|
||||
<dl class="row mt-3">
|
||||
<dt class="col-sm-4">Email:</dt>
|
||||
<dt class="col-sm-4 text-muted">Email:</dt>
|
||||
<dd class="col-sm-8">@Model?.Email</dd>
|
||||
@if (!string.IsNullOrEmpty(@Model?.PhoneNumber))
|
||||
{
|
||||
<dt class="col-sm-4">Телефон:</dt>
|
||||
<dt class="col-sm-4 text-muted">Телефон:</dt>
|
||||
<dd class="col-sm-8">@Model?.PhoneNumber</dd>
|
||||
}
|
||||
<dt class="col-sm-4">Роль:</dt>
|
||||
<dt class="col-sm-4 text-muted">Роль:</dt>
|
||||
<dd class="col-sm-8">@Model?.Role</dd>
|
||||
</dl>
|
||||
<div class="btn-group mt-3" role="group" aria-label="Действия">
|
||||
<a asp-action="UserProfileEdit" asp-controller="User" asp-route-id="@Model?.Id" class="btn btn-primary">Редактировать профиль</a>
|
||||
<form asp-action="Delete" asp-controller="User" method="post" onsubmit="return confirm('Вы уверены, что хотите удалить профиль?');">
|
||||
|
||||
<div class="btn-group mt-4" role="group" aria-label="Действия">
|
||||
<a asp-action="UserProfileEdit" asp-controller="User" asp-route-id="@Model?.Id"
|
||||
class="btn btn-outline-primary px-4 py-2 me-2">
|
||||
<i class="bi bi-pencil me-2"></i>Редактировать профиль
|
||||
</a>
|
||||
<form asp-action="Delete" asp-controller="User" method="post"
|
||||
onsubmit="return confirm('Вы уверены, что хотите удалить профиль?');" class="d-inline me-2">
|
||||
<input type="hidden" name="id" value="@Model?.Id" />
|
||||
<button type="submit" class="btn btn-danger">Удалить профиль</button>
|
||||
<button type="submit" class="btn btn-outline-danger px-4 py-2">
|
||||
<i class="bi bi-trash me-2"></i>Удалить профиль
|
||||
</button>
|
||||
</form>
|
||||
<a asp-action="Logout" asp-controller="User" class="btn btn-secondary">Выйти</a>
|
||||
<a asp-action="Logout" asp-controller="User" class="btn btn-outline-secondary px-4 py-2">
|
||||
<i class="bi bi-box-arrow-right me-2"></i>Выйти
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (userRole)
|
||||
{
|
||||
<div class="col-md-8">
|
||||
<div class="col-md-8 mt-4">
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h2>Мои резюме</h2>
|
||||
<a asp-action="CreateResume" asp-controller="Resume" class="btn btn-success">Создать резюме</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if (Model.Resumes != null && Model.Resumes.Any())
|
||||
{
|
||||
<table class="table table-striped">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Название</th>
|
||||
@ -67,13 +81,13 @@
|
||||
<td>@resume.VacancyName</td>
|
||||
<td>@resume.Status</td>
|
||||
<td>
|
||||
<a asp-action="ResumeDetails" asp-controller="Resume" asp-route-id="@resume.Id" class="text-info" title="Просмотр">
|
||||
<a asp-action="ResumeDetails" asp-controller="Resume" asp-route-id="@resume.Id" class="btn btn-info btn-sm me-2" title="Просмотр">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
<a asp-action="EditResume" asp-controller="Resume" asp-route-id="@resume.Id" class="text-warning" title="Редактировать">
|
||||
<a asp-action="EditResume" asp-controller="Resume" asp-route-id="@resume.Id" class="btn btn-warning btn-sm me-2" title="Редактировать">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
<a asp-action="Delete" asp-controller="Resume" asp-route-id="@resume.Id" class="text-danger" title="Удалить" onclick="return confirm('Вы уверены, что хотите удалить резюме?');">
|
||||
<a asp-action="Delete" asp-controller="Resume" asp-route-id="@resume.Id" class="btn btn-danger btn-sm me-2" title="Удалить" onclick="return confirm('Вы уверены, что хотите удалить резюме?');">
|
||||
<i class="bi bi-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
@ -84,7 +98,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>Нет резюме.</p>
|
||||
<p class="text-muted">У вас нет резюме.</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@ -106,53 +120,36 @@
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.table th, .table td {
|
||||
vertical-align: middle;
|
||||
.table th, .table td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #0A1128;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #1C3273;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
font-size: 0.875rem;
|
||||
padding: 0.375rem 0.75rem;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.btn-info, .btn-success {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.form-control {
|
||||
border-radius: 5px;
|
||||
.btn-group .btn {
|
||||
border-radius: 15px; /* скругление кнопок внутри группы */
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
border-color: #80bdff;
|
||||
box-shadow: 0 0 0 0.25rem rgba(0, 123, 255, 0.25);
|
||||
}
|
||||
|
||||
.table-striped tbody tr:nth-of-type(odd) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.table-light {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
.btn-group button, .btn-group a {
|
||||
border-radius: 15px; /* добавлено для кнопок внутри .btn-group */
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -2,68 +2,60 @@
|
||||
@model UserViewModel
|
||||
|
||||
@{
|
||||
var title = @Model.Id <= 0 ? "Добавить сотрудника" : "Редактировать профиль";
|
||||
var title = @Model?.Id <= 0 ? "Добавить сотрудника" : "Редактировать профиль";
|
||||
var userRole = APIClient.User?.Role == CandidateReviewDataModels.Enums.RoleEnum.Администратор ? true : false;
|
||||
}
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<h2 class="mb-4">Редактирование профиля</h2>
|
||||
<h2 class="mb-4">@title</h2>
|
||||
<form method="post" class="needs-validation" novalidate>
|
||||
<input type="hidden" name="id" value="@Model?.Id" />
|
||||
<input type="hidden" name="password" value="@Model?.Password" />
|
||||
<input type="hidden" name="CompanyId" value="@Model?.CompanyId" />
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="Surname" class="form-label">Фамилия <span class="text-danger">*</span></label>
|
||||
<label for="Surname" class="form-label">Фамилия *</label>
|
||||
<input type="text" class="form-control" id="Surname" name="Surname" value="@Model?.Surname" required />
|
||||
<div class="invalid-feedback">Пожалуйста, введите фамилию.</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="Name" class="form-label">Имя <span class="text-danger">*</span></label>
|
||||
<label for="Name" class="form-label">Имя *</label>
|
||||
<input type="text" class="form-control" id="Name" name="Name" value="@Model?.Name" required />
|
||||
<div class="invalid-feedback">Пожалуйста, введите имя.</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="LastName" class="form-label">Отчество</label>
|
||||
<input type="text" class="form-control" id="LastName" name="LastName" value="@Model?.LastName" />
|
||||
<div class="invalid-feedback">Пожалуйста, введите отчество.</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="Email" class="form-label">Электронная почта <span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="Email" name="Email" value="@Model?.Email" readonly/>
|
||||
<div class="invalid-feedback">Пожалуйста, введите электронную почту.</div>
|
||||
<label for="Email" class="form-label">Электронная почта *</label>
|
||||
<input type="email" class="form-control" id="Email" name="Email" value="@Model?.Email" @(Model?.Id < 0 ? "readonly" : "") required />
|
||||
</div>
|
||||
|
||||
@if (Model.Id <= 0)
|
||||
@if (Model?.Id <= 0)
|
||||
{
|
||||
<div class="mb-3">
|
||||
<label for="Password" class="form-label">Пароль <span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="Password" name="Password" value="@Model?.Password" />
|
||||
<div class="invalid-feedback">Пожалуйста, введите пароль.</div>
|
||||
<label for="Password" class="form-label">Пароль *</label>
|
||||
<input type="password" class="form-control" id="Password" name="Password" required />
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<input type="hidden" name="password" value="@Model?.Password" />
|
||||
}
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="PhoneNumber" class="form-label">Телефон</label>
|
||||
<input type="tel" class="form-control" id="PhoneNumber" name="PhoneNumber" value="@Model?.PhoneNumber" />
|
||||
<div class="invalid-feedback">Пожалуйста, введите телефон.</div>
|
||||
</div>
|
||||
<input type="hidden" name="Role" value="@Model?.Role" />
|
||||
<input type="hidden" name="CompanyId" value="@Model?.CompanyId" />
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="AvatarFilePath" class="form-label">Аватар</label>
|
||||
<input type="file" class="form-control" id="AvatarFilePath" name="AvatarFilePath" accept=".jpg,.jpeg,.png" />
|
||||
<img id="avatarPreview" src="@Model?.AvatarFilePath" alt="Предварительный просмотр аватара" style="max-width: 100px; max-height: 100px;" />
|
||||
<div class="invalid-feedback">Выберите файл изображения.</div>
|
||||
</div>
|
||||
<input type="hidden" name="Role" value="@Model?.Role" />
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
<button type="submit" class="btn btn-primary">Сохранить</button>
|
||||
<button class="btn btn-secondary" onclick="window.history.back();">Назад</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="window.history.back();">Назад</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -105,26 +97,26 @@
|
||||
})
|
||||
})()
|
||||
</script>
|
||||
<script>
|
||||
const avatarInput = document.getElementById('AvatarFilePath');
|
||||
const avatarPreview = document.getElementById('avatarPreview');
|
||||
|
||||
avatarInput.addEventListener('change', function (event) {
|
||||
const file = event.target.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
avatarPreview.src = e.target.result;
|
||||
}
|
||||
reader.readAsDataURL(file);
|
||||
} else {
|
||||
avatarPreview.src = "@Model?.AvatarFilePath";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@{
|
||||
await Html.RenderPartialAsync("_ValidationScriptsPartial");
|
||||
}
|
||||
}
|
||||
|
||||
<style>
|
||||
.btn {
|
||||
background-color: #0A1128;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #1C3273;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
@ -91,3 +91,20 @@
|
||||
})()
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.btn {
|
||||
background-color: #0A1128;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #1C3273;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Компания</th>
|
||||
<th>Название вакансии</th>
|
||||
<th>Тип работы</th>
|
||||
<th>Зарплата</th>
|
||||
@ -37,6 +38,7 @@
|
||||
@foreach (var vacancy in Model.Where(v => v != null))
|
||||
{
|
||||
<tr>
|
||||
<td>@vacancy.CompanyName</td>
|
||||
<td>@vacancy.JobTitle</td>
|
||||
<td>@vacancy.JobType</td>
|
||||
<td>@vacancy.Salary</td>
|
||||
@ -87,10 +89,6 @@
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.btn-info, .btn-success {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
@ -109,17 +107,20 @@
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.table-light {
|
||||
background-color: #f8f9fa;
|
||||
.btn {
|
||||
background-color: #0A1128;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #dc3545;
|
||||
}
|
||||
.btn:hover {
|
||||
background-color: #1C3273;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
|
107
CandidateReviewClientApp/Views/Vacancy/Vacancies.cshtml
Normal file
107
CandidateReviewClientApp/Views/Vacancy/Vacancies.cshtml
Normal file
@ -0,0 +1,107 @@
|
||||
@using CandidateReviewContracts.ViewModels
|
||||
@model List<VacancyViewModel>
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Вакансии";
|
||||
}
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-12">
|
||||
<h1 class="mb-4 text-center">Вакансии</h1>
|
||||
<div class="mb-4 text-end">
|
||||
<a asp-action="EditVacancy" asp-controller="Vacancy" asp-route-companyId="@APIClient.Company?.Id" class="btn btn-success">
|
||||
<i class="bi bi-plus-circle me-2"></i> Добавить вакансию
|
||||
</a>
|
||||
</div>
|
||||
@if (Model != null)
|
||||
{
|
||||
@if (Model.Any())
|
||||
{
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Название вакансии</th>
|
||||
<th>Тип занятости</th>
|
||||
<th>Зарплата</th>
|
||||
<th>Статус</th>
|
||||
<th>Тэги</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var vacancy in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>@vacancy.JobTitle</td>
|
||||
<td>@vacancy.JobType</td>
|
||||
<td>@vacancy.Salary</td>
|
||||
<td>@vacancy.Tags</td>
|
||||
<td>@vacancy.Status</td>
|
||||
<td>
|
||||
<div class="d-flex justify-content-center">
|
||||
<a asp-action="VacancyDetails" asp-controller="Vacancy" asp-route-id="@vacancy.Id"
|
||||
class="btn btn-info btn-sm me-2" title="Просмотр">
|
||||
<i class="bi bi-eye"></i> Просмотр
|
||||
</a>
|
||||
<a asp-action="EditVacancy" asp-controller="Vacancy" asp-route-id="@vacancy.Id"
|
||||
class="btn btn-warning btn-sm me-2" title="Редактировать">
|
||||
<i class="bi bi-pencil-square"></i> Редактировать
|
||||
</a>
|
||||
<a asp-action="Delete" asp-controller="Vacancy" asp-route-id="@vacancy.Id"
|
||||
class="btn btn-danger btn-sm" title="Удалить"
|
||||
onclick="return confirm('Вы уверены, что хотите удалить вакансию?');">
|
||||
<i class="bi bi-trash"></i> Удалить
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="text-center text-muted">Вакансий нет.</p>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="text-center text-danger">Произошла ошибка при получении данных.</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.table-hover tbody tr:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.btn-info, .btn-warning, .btn-danger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-info i, .btn-warning i, .btn-danger i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #0A1128;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #1C3273;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
</style>
|
@ -104,3 +104,20 @@
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.min.js"></script>
|
||||
|
||||
<style>
|
||||
.btn {
|
||||
background-color: #0A1128;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
font-size: 16px;
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #1C3273;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
</style>
|
||||
|
@ -10,7 +10,7 @@ namespace CandidateReviewContracts.BindingModels
|
||||
public string? Comment { get; set; }
|
||||
|
||||
public int Id { get; set; }
|
||||
public Dictionary<int, (ICriterionModel, int)> AssessmentCriterions { get; set; } = new();
|
||||
public Dictionary<int, (CriterionModel, int)> AssessmentCriterions { get; set; } = new();
|
||||
|
||||
public int? ResumeId { get; set; }
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ namespace CandidateReviewContracts.StoragesContracts
|
||||
{
|
||||
List<AssessmentViewModel> GetFullList();
|
||||
List<AssessmentViewModel> GetFilteredList(AssessmentSearchModel model);
|
||||
List<AssessmentCriterionViewModel>? GetAssessmentCriterions(int? assessmentId);
|
||||
AssessmentViewModel? GetElement(AssessmentSearchModel model);
|
||||
int? Insert(AssessmentBindingModel model);
|
||||
AssessmentViewModel? Update(AssessmentBindingModel model);
|
||||
|
@ -1,17 +0,0 @@
|
||||
using CandidateReviewDataModels.Models;
|
||||
|
||||
namespace CandidateReviewContracts.ViewModels
|
||||
{
|
||||
public class AssessmentCriterionViewModel : IAssessmentCriterionModel
|
||||
{
|
||||
public int AssessmentId { get; set; }
|
||||
|
||||
public int CriterionId { get; set; }
|
||||
|
||||
public string CriterionName { get; set; } = string.Empty;
|
||||
|
||||
public int Value { get; set; }
|
||||
|
||||
public int Id { get; set; }
|
||||
}
|
||||
}
|
@ -14,6 +14,6 @@ namespace CandidateReviewContracts.ViewModels
|
||||
|
||||
public int? ResumeId { get; set; }
|
||||
|
||||
public List<AssessmentCriterionViewModel> AssessmentCriterions { get; set; } = new();
|
||||
public Dictionary<int, (CriterionModel, int)> AssessmentCriterions { get; set; } = new();
|
||||
}
|
||||
}
|
||||
|
@ -28,5 +28,6 @@ namespace CandidateReviewContracts.ViewModels
|
||||
public int Id { get; set; }
|
||||
|
||||
public List<ResumeViewModel> Resumes { get; set; } = new();
|
||||
public List<AssessmentViewModel> Assessments { get; set; } = new();
|
||||
}
|
||||
}
|
||||
|
15
CandidateReviewDataModels/Models/CriterionModel.cs
Normal file
15
CandidateReviewDataModels/Models/CriterionModel.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CandidateReviewDataModels.Models
|
||||
{
|
||||
public class CriterionModel : ICriterionModel
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
public int Id { get; set; }
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace CandidateReviewDataModels.Models
|
||||
{
|
||||
public interface IAssessmentCriterionModel : IId
|
||||
{
|
||||
int AssessmentId { get; }
|
||||
int CriterionId { get; }
|
||||
int Value { get; }
|
||||
}
|
||||
}
|
@ -15,10 +15,10 @@ namespace CandidateReviewDatabaseImplement.Implements
|
||||
using var context = new CandidateReviewDatabase();
|
||||
|
||||
var element = context.Assessments
|
||||
.Include(x => x.User)
|
||||
.Include(x => x.Resume)
|
||||
.Include(x => x.Criterions)
|
||||
.ThenInclude(x => x.Criterion)
|
||||
.Include(x => x.Criterions)
|
||||
.ThenInclude(x => x.Criterion)
|
||||
.Include(x => x.User)
|
||||
.Include(x => x.Resume)
|
||||
.FirstOrDefault(rec => rec.Id == model.Id);
|
||||
|
||||
if (element != null)
|
||||
@ -62,21 +62,6 @@ namespace CandidateReviewDatabaseImplement.Implements
|
||||
?.GetViewModel;
|
||||
}
|
||||
|
||||
public List<AssessmentCriterionViewModel>? GetAssessmentCriterions(int? assessmentId)
|
||||
{
|
||||
if (!assessmentId.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
using var context = new CandidateReviewDatabase();
|
||||
|
||||
return context.AssessmentCriterions
|
||||
.Where(x => x.AssessmentId == assessmentId)
|
||||
.ToList()
|
||||
.Select(x => x.GetViewModel)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public List<AssessmentViewModel> GetFilteredList(AssessmentSearchModel model)
|
||||
{
|
||||
if (model is null)
|
||||
@ -123,26 +108,15 @@ namespace CandidateReviewDatabaseImplement.Implements
|
||||
{
|
||||
using var context = new CandidateReviewDatabase();
|
||||
|
||||
var newAssessment = new Assessment
|
||||
var newAssessment = Assessment.Create(context, model);
|
||||
if (newAssessment == null)
|
||||
{
|
||||
ResumeId = model.ResumeId,
|
||||
UserId = model.UserId,
|
||||
Comment = model.Comment
|
||||
};
|
||||
return null;
|
||||
}
|
||||
|
||||
context.Assessments.Add(newAssessment);
|
||||
context.SaveChanges();
|
||||
|
||||
/*var criterionsToAdd = model.AssessmentCriterions.Select(x => new AssessmentCriterion
|
||||
{
|
||||
AssessmentId = newAssessment.Id,
|
||||
Criterion = context.Criterions.First(y => y.Id == x.Key),
|
||||
Value = x.Value.Item2
|
||||
}).ToList();
|
||||
|
||||
context.AssessmentCriterions.AddRange(criterionsToAdd);
|
||||
context.SaveChanges();*/
|
||||
|
||||
return newAssessment.Id;
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,15 @@ namespace CandidateReviewDatabaseImplement.Implements
|
||||
.Select(x => x.GetViewModel)
|
||||
.ToList();
|
||||
}
|
||||
if (model.CompanyId.HasValue)
|
||||
{
|
||||
return context.Vacancies
|
||||
.Include(x => x.Company)
|
||||
.Where(x => x.CompanyId == model.CompanyId)
|
||||
.ToList()
|
||||
.Select(x => x.GetViewModel)
|
||||
.ToList();
|
||||
}
|
||||
if (!string.IsNullOrEmpty(model.Tags) && model.Status.HasValue)
|
||||
{
|
||||
var tags = model.Tags.Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(t => t.ToLowerInvariant()).ToArray();
|
||||
|
@ -18,9 +18,9 @@ namespace CandidateReviewDatabaseImplement.Models
|
||||
public virtual User User { get; set; }
|
||||
public virtual Resume Resume { get; set; }
|
||||
|
||||
private Dictionary<int, (ICriterionModel, int)>? _assessmentCriterions = null;
|
||||
private Dictionary<int, (CriterionModel, int)>? _assessmentCriterions = null;
|
||||
|
||||
public Dictionary<int, (ICriterionModel, int)> AssessmentCriterions
|
||||
public Dictionary<int, (CriterionModel, int)> AssessmentCriterions
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -28,7 +28,7 @@ namespace CandidateReviewDatabaseImplement.Models
|
||||
{
|
||||
_assessmentCriterions = Criterions
|
||||
.ToDictionary(recAC => recAC.CriterionId, recAC =>
|
||||
(recAC.Criterion as ICriterionModel, recAC.Value));
|
||||
(new CriterionModel { Id = recAC.Criterion.Id, Name = recAC.Criterion.Name }, recAC.Value));
|
||||
}
|
||||
return _assessmentCriterions;
|
||||
}
|
||||
@ -37,22 +37,20 @@ namespace CandidateReviewDatabaseImplement.Models
|
||||
[ForeignKey("AssessmentId")]
|
||||
public virtual List<AssessmentCriterion> Criterions { get; set; } = new();
|
||||
|
||||
public static Assessment? Create(CandidateReviewDatabase context, AssessmentBindingModel model)
|
||||
public static Assessment Create(CandidateReviewDatabase context, AssessmentBindingModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var assessment = new Assessment
|
||||
return new Assessment()
|
||||
{
|
||||
Id = model.Id,
|
||||
ResumeId = model.ResumeId,
|
||||
UserId = model.UserId,
|
||||
Comment = model.Comment,
|
||||
Criterions = model.AssessmentCriterions.Select(x => new AssessmentCriterion
|
||||
{
|
||||
Assessment = context.Assessments.First(y => y.Id == x.Key),
|
||||
Value = x.Value.Item2
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
return assessment;
|
||||
}
|
||||
|
||||
public void Update(AssessmentBindingModel model)
|
||||
@ -66,15 +64,6 @@ namespace CandidateReviewDatabaseImplement.Models
|
||||
Comment = model.Comment;
|
||||
}
|
||||
|
||||
private List<AssessmentCriterionViewModel> GetAssessmentCriterionsAsViewModel()
|
||||
{
|
||||
return AssessmentCriterions.Select(ac => new AssessmentCriterionViewModel
|
||||
{
|
||||
CriterionId = ac.Key,
|
||||
Value = ac.Value.Item2,
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
|
||||
public AssessmentViewModel GetViewModel => new()
|
||||
{
|
||||
@ -82,7 +71,7 @@ namespace CandidateReviewDatabaseImplement.Models
|
||||
ResumeId = ResumeId,
|
||||
UserId = UserId,
|
||||
Comment = Comment,
|
||||
AssessmentCriterions = GetAssessmentCriterionsAsViewModel()
|
||||
AssessmentCriterions = AssessmentCriterions
|
||||
};
|
||||
|
||||
public void UpdateCriterions(CandidateReviewDatabase context, AssessmentBindingModel model)
|
||||
@ -102,14 +91,20 @@ namespace CandidateReviewDatabaseImplement.Models
|
||||
var assessment = context.Assessments.First(x => x.Id == Id);
|
||||
foreach (var ac in model.AssessmentCriterions)
|
||||
{
|
||||
var criterion = context.Criterions.First(x => x.Id == ac.Value.Item1.Id);
|
||||
if (criterion == null)
|
||||
{
|
||||
throw new Exception($"Критерий с ID {ac.Key} не найден.");
|
||||
}
|
||||
|
||||
context.AssessmentCriterions.Add(new AssessmentCriterion
|
||||
{
|
||||
Assessment = assessment,
|
||||
Criterion = context.Criterions.First(x => x.Id == ac.Key),
|
||||
Criterion = criterion,
|
||||
Value = ac.Value.Item2
|
||||
});
|
||||
context.SaveChanges();
|
||||
}
|
||||
context.SaveChanges();
|
||||
_assessmentCriterions = null;
|
||||
}
|
||||
}
|
||||
|
@ -14,13 +14,5 @@ namespace CandidateReviewDatabaseImplement.Models
|
||||
public int Value { get; set; }
|
||||
public virtual Assessment Assessment { get; set; } = new();
|
||||
public virtual Criterion Criterion { get; set; } = new();
|
||||
|
||||
public AssessmentCriterionViewModel GetViewModel => new()
|
||||
{
|
||||
Id = Id,
|
||||
AssessmentId = AssessmentId,
|
||||
CriterionId = CriterionId,
|
||||
Value = Value
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +57,27 @@ namespace CandidateReviewRestApi.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public List<VacancyViewModel>? List(int? companyId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (companyId.HasValue)
|
||||
{
|
||||
return _logic.ReadList(new VacancySearchModel
|
||||
{
|
||||
CompanyId = companyId
|
||||
});
|
||||
}
|
||||
else return new List<VacancyViewModel>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Ошибка получения вакансий");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void Create(VacancyBindingModel model)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user