мелкие правки, стили, оценка еще в работе
This commit is contained in:
parent
aa28aecfc1
commit
76c13d303a
@ -5,7 +5,7 @@ using CandidateReviewContracts.StoragesContracts;
|
||||
using CandidateReviewContracts.ViewModels;
|
||||
using CandidateReviewDataModels.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
{
|
||||
@ -13,43 +13,15 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IAssessmentStorage _assessmentStorage;
|
||||
public AssessmentLogic(ILogger<AssessmentLogic> logger, IAssessmentStorage assessmentStorage)
|
||||
private readonly IUserStorage _userStorage;
|
||||
private readonly ICriterionStorage _criterionStorage;
|
||||
|
||||
public AssessmentLogic(ILogger<AssessmentLogic> logger, IAssessmentStorage assessmentStorage, IUserStorage userStorage, ICriterionStorage criterionStorage)
|
||||
{
|
||||
_logger = logger;
|
||||
_assessmentStorage = assessmentStorage;
|
||||
}
|
||||
|
||||
public bool AddCriterionToAssessment(AssessmentSearchModel model, ICriterionModel criterion, int value)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (criterion == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(criterion));
|
||||
}
|
||||
|
||||
var element = _assessmentStorage.GetElement(model);
|
||||
|
||||
if (element == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
element.AssessmentCriterions[element.Id] = (criterion, value);
|
||||
|
||||
_assessmentStorage.Update(new AssessmentBindingModel
|
||||
{
|
||||
Id = element.Id,
|
||||
UserId = element.UserId,
|
||||
ResumeId = element.ResumeId,
|
||||
Comment = element.Comment,
|
||||
AssessmentCriterions = element.AssessmentCriterions
|
||||
});
|
||||
|
||||
return true;
|
||||
_userStorage = userStorage;
|
||||
_criterionStorage = criterionStorage;
|
||||
}
|
||||
|
||||
public int? Create(AssessmentBindingModel model)
|
||||
@ -95,13 +67,40 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
public List<AssessmentViewModel>? ReadList(AssessmentSearchModel? model)
|
||||
{
|
||||
var list = model == null ? _assessmentStorage.GetFullList() : _assessmentStorage.GetFilteredList(model);
|
||||
if (list == null)
|
||||
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)
|
||||
{
|
||||
_logger.LogWarning("ReadList return null list");
|
||||
return null;
|
||||
}
|
||||
_logger.LogInformation("ReadList. Count: {Count}", list.Count);
|
||||
return list;
|
||||
|
||||
_logger.LogInformation("ReadList. Count: {Count}", result.Count);
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool Update(AssessmentBindingModel model)
|
||||
|
@ -4,6 +4,7 @@ using CandidateReviewContracts.SearchModels;
|
||||
using CandidateReviewContracts.StoragesContracts;
|
||||
using CandidateReviewContracts.ViewModels;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
{
|
||||
@ -84,6 +85,7 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
Status = element.Status,
|
||||
Assessments = assessmentViewModels
|
||||
};
|
||||
|
||||
_logger.LogInformation("ReadElement find. Id: {Id}", element.Id);
|
||||
return resumeViewModel;
|
||||
}
|
||||
@ -96,8 +98,39 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
_logger.LogWarning("ReadList return null list");
|
||||
return null;
|
||||
}
|
||||
List<ResumeViewModel> result = new();
|
||||
foreach (var element in list)
|
||||
{
|
||||
var assessments = _assessmentStorage.GetFilteredList(new AssessmentSearchModel { UserId = element.Id });
|
||||
var assessmentViewModels = assessments?.Select(a => new AssessmentViewModel
|
||||
{
|
||||
Id = a.Id,
|
||||
ResumeId = a.ResumeId,
|
||||
UserId = a.UserId,
|
||||
Comment = a.Comment,
|
||||
AssessmentCriterions = a.AssessmentCriterions
|
||||
}).ToList() ?? new List<AssessmentViewModel>();
|
||||
|
||||
var resumeViewModel = new ResumeViewModel
|
||||
{
|
||||
Id = element.Id,
|
||||
VacancyId = element.VacancyId,
|
||||
VacancyName = _vacancyStorage.GetElement(new VacancySearchModel { Id = element.VacancyId }).JobTitle,
|
||||
UserId = element.UserId,
|
||||
UserName = _userStorage.GetElement(new UserSearchModel { Id = element.UserId }).Name + " " + _userStorage.GetElement(new UserSearchModel { Id = element.UserId }).Surname,
|
||||
Title = element.Title,
|
||||
Experience = element.Experience,
|
||||
Education = element.Education,
|
||||
PhotoFilePath = element.PhotoFilePath,
|
||||
Description = element.Description,
|
||||
Skills = element.Skills,
|
||||
Status = element.Status,
|
||||
Assessments = assessmentViewModels
|
||||
};
|
||||
result.Add(resumeViewModel);
|
||||
}
|
||||
_logger.LogInformation("ReadList. Count: {Count}", list.Count);
|
||||
return list;
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool Update(ResumeBindingModel model)
|
||||
|
@ -71,6 +71,7 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
{
|
||||
Id = r.Id,
|
||||
VacancyId = r.VacancyId,
|
||||
UserName = element.Name + " " + element.Surname,
|
||||
VacancyName = _vacancyStorage.GetElement(new VacancySearchModel { Id = r.VacancyId }).JobTitle,
|
||||
UserId = r.UserId,
|
||||
Title = r.Title,
|
||||
|
@ -14,13 +14,15 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
private readonly IVacancyStorage _vacancyStorage;
|
||||
private readonly IResumeStorage _resumeStorage;
|
||||
private readonly ICompanyStorage _companyStorage;
|
||||
private readonly IUserStorage _userStorage;
|
||||
|
||||
public VacancyLogic(ILogger<VacancyLogic> logger, IVacancyStorage vacancyStorage, IResumeStorage resumeStorage, ICompanyStorage companyStorage)
|
||||
public VacancyLogic(ILogger<VacancyLogic> logger, IVacancyStorage vacancyStorage, IResumeStorage resumeStorage, ICompanyStorage companyStorage, IUserStorage userStorage)
|
||||
{
|
||||
_logger = logger;
|
||||
_vacancyStorage = vacancyStorage;
|
||||
_resumeStorage = resumeStorage;
|
||||
_companyStorage = companyStorage;
|
||||
_userStorage = userStorage;
|
||||
}
|
||||
public bool Create(VacancyBindingModel model)
|
||||
{
|
||||
@ -63,7 +65,7 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
||||
Id = r.Id,
|
||||
VacancyId = r.VacancyId,
|
||||
VacancyName = _vacancyStorage.GetElement(new VacancySearchModel { Id = r.VacancyId }).JobTitle,
|
||||
UserName = r.UserName,
|
||||
UserName = _userStorage.GetElement(new UserSearchModel { Id = r.UserId}).Name + " " + _userStorage.GetElement(new UserSearchModel { Id = r.UserId }).Surname,
|
||||
UserId = r.UserId,
|
||||
Title = r.Title,
|
||||
Experience = r.Experience,
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CandidateReviewContracts\CandidateReviewContracts.csproj" />
|
||||
<ProjectReference Include="..\CandidateReviewDatabaseImplement\CandidateReviewDatabaseImplement.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -17,6 +17,8 @@ namespace CandidateReviewClientApp.Controllers
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> AddAssessmentCriterion(int resumeId, int[] criterion, int[] value, string comment)
|
||||
{
|
||||
@ -42,29 +44,12 @@ namespace CandidateReviewClientApp.Controllers
|
||||
ResumeId = resumeId,
|
||||
UserId = userId,
|
||||
Comment = comment,
|
||||
AssessmentCriterions = new Dictionary<int, (ICriterionModel, int)>()
|
||||
AssessmentCriterions = criterion.Select((t, i) => new KeyValuePair<int, (ICriterionModel, int)>
|
||||
(t, (new CriterionViewModel { Id = t }, value[i]))).ToDictionary(kv => kv.Key, kv => kv.Value)
|
||||
};
|
||||
|
||||
var assessmentId = await APIClient.PostRequestAsync("api/assessment/create", assessmentModel);
|
||||
|
||||
for (int i = 0; i < criterion.Length; i++)
|
||||
{
|
||||
if (value[i] < 1 || value[i] > 5)
|
||||
{
|
||||
throw new ArgumentException($"Оценка для критерия {criterion[i]} должна быть от 1 до 5.");
|
||||
}
|
||||
|
||||
if (assessmentData.ContainsKey(assessmentId))
|
||||
{
|
||||
assessmentData[assessmentId] = (new CriterionViewModel { Id = criterion[i] }, value[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
assessmentData.Add(assessmentId, (new CriterionViewModel { Id = criterion[i] }, value[i]));
|
||||
}
|
||||
}
|
||||
|
||||
APIClient.PostRequest("api/assessment/AddCriterionToAssessment", assessmentData);
|
||||
int assessmentId = await APIClient.PostRequestAsync("api/assessment/create", assessmentModel);
|
||||
|
||||
return Redirect($"~/Resume/ResumeDetails/{resumeId}");
|
||||
}
|
||||
|
@ -28,10 +28,14 @@ namespace CandidateReviewClientApp.Controllers
|
||||
{
|
||||
return View();
|
||||
}
|
||||
var assessments = APIClient.GetRequest<List<AssessmentViewModel>>($"api/assessment/listByResumeId?id={id}");
|
||||
|
||||
var resumeAssessments = APIClient.GetRequest<List<AssessmentViewModel>>($"api/assessment/listByResumeId?id={id}");
|
||||
var userAssessment = resumeAssessments?.FirstOrDefault(a => a.UserId == APIClient.User.Id);
|
||||
var criterions = APIClient.GetRequest<List<CriterionViewModel>>($"api/criterion/list");
|
||||
resume.Assessments = assessments;
|
||||
resume.Assessments = resumeAssessments ?? new List<AssessmentViewModel>();
|
||||
ViewBag.UserAssessment = userAssessment;
|
||||
ViewBag.Criterions = criterions;
|
||||
|
||||
return View(resume);
|
||||
}
|
||||
|
||||
|
@ -8,37 +8,47 @@
|
||||
<div class="container mt-5">
|
||||
<div class="row g-4">
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<img src="@(Model.LogoFilePath ?? "https://static.thenounproject.com/png/2504969-200.png")" style="max-width: 150px; max-height: 150px;" class="card-img-top img-fluid rounded-circle mx-auto d-block" alt="Логотип компании">
|
||||
<div class="card-body">
|
||||
<div class="card shadow-sm">
|
||||
<img src="@(Model.LogoFilePath ?? "https://static.thenounproject.com/png/2504969-200.png")"
|
||||
class="card-img-top img-fluid rounded-circle mx-auto d-block" alt="Логотип компании"
|
||||
style="max-width: 150px; max-height: 150px;">
|
||||
<div class="card-body text-center">
|
||||
<h5 class="card-title">@Model.Name</h5>
|
||||
<input type="hidden" name="id" value="@Model?.Id" />
|
||||
<p class="card-text">@(Model.Description == null ? "Описание отсутствует" : Model.Description) </p>
|
||||
<a href="@(Model.Website ?? "#")" target="_blank" class="btn btn-primary mt-2">@(Model.Website != null ? "Официальный сайт" : "Веб-сайт отсутствует") @(Model.Website != null ? "" : "disabled")</a> </a>
|
||||
<p class="card-text">@((Model.Description ?? "Описание отсутствует"))</p>
|
||||
<a href="@(Model.Website ?? "#")"
|
||||
target="_blank"
|
||||
class="btn btn-primary mt-2 @(Model.Website == null ? "disabled" : "")"
|
||||
@(Model.Website == null ? "aria-disabled=\"true\"" : "")>
|
||||
@(Model.Website != null ? "Официальный сайт" : "Веб-сайт отсутствует")
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8">
|
||||
<div class="card mb-4">
|
||||
<div class="card mb-4 shadow-sm">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h2>Информация о компании</h2>
|
||||
<a asp-action="EditCompanyProfile" asp-controller="Company" asp-route-id="@Model.Id" class="btn btn-primary">Редактировать</a>
|
||||
<a asp-action="EditCompanyProfile" asp-controller="Company" asp-route-id="@Model.Id"
|
||||
class="btn btn-warning">Редактировать</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<dl class="row">
|
||||
<dt class="col-sm-3">Адрес:</dt>
|
||||
<dd class="col-sm-9">@(Model.Address?.ToString() ?? "Адрес не указан")</dd>
|
||||
<dd class="col-sm-9">@((Model.Address?.ToString() ?? "Адрес не указан"))</dd>
|
||||
|
||||
<dt class="col-sm-3">Контакты:</dt>
|
||||
<dd class="col-sm-9">@(Model.Contacts?.ToString() ?? "Контакты не указаны")</dd>
|
||||
<dd class="col-sm-9">@((Model.Contacts?.ToString() ?? "Контакты не указаны"))</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card mb-4 shadow-sm">
|
||||
<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>
|
||||
<a asp-action="EditVacancy" asp-controller="Vacancy" asp-route-companyId="@Model.Id"
|
||||
class="btn btn-success">Добавить вакансию</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if (Model.Vacancies != null && Model.Vacancies.Any())
|
||||
@ -59,11 +69,12 @@
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="card">
|
||||
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h2>Сотрудники компании</h2>
|
||||
<a asp-action="UserProfileEdit" asp-controller="User" asp-route-companyId="@Model.Id" class="btn btn-success">Добавить сотрудника</a>
|
||||
<a asp-action="UserProfileEdit" asp-controller="User" asp-route-companyId="@Model.Id"
|
||||
class="btn btn-success">Добавить сотрудника</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if (Model.Employees != null && Model.Employees.Any())
|
||||
@ -83,16 +94,17 @@
|
||||
<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="text-info" 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 rounded-pill" title="Просмотр">
|
||||
<i class="bi bi-eye"></i> Просмотр
|
||||
</a>
|
||||
<a asp-action="UserProfileEdit" asp-controller="User" asp-route-id="@employee.Id" class="text-warning" 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 rounded-pill" title="Редактировать">
|
||||
<i class="bi bi-pencil"></i> Редактировать
|
||||
</a>
|
||||
<a asp-action="DeleteEmployee" asp-controller="User" asp-route-id="@employee.Id" class="text-danger" 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 rounded-pill" title="Удалить" onclick="return confirm('Вы уверены, что хотите удалить сотрудника?');">
|
||||
<i class="bi bi-trash"></i> Удалить
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@ -107,6 +119,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
|
@ -8,38 +8,33 @@
|
||||
|
||||
<div class="d-flex justify-content-center mt-4">
|
||||
<div class="box">
|
||||
<h3>Создать профиль своей компании</h3>
|
||||
<p>Здесь вы можете создать и настроить профиль вашей компании, указать основные данные. Профиль вашей компании будет виден кандидатам, что поможет вам привлечь их внимание к вакансиям, которые вы предлагаете.</p>
|
||||
<h3>Создать профиль компании</h3>
|
||||
</div>
|
||||
<div class="box">
|
||||
<h3>Подобрать кандидатов на вакансию</h3>
|
||||
<p>Используйте наш удобный инструмент для подбора кандидатов на вакансию. Вы можете просмотреть параметры возможных кандидатов. Это упростит процесс поиска подходящих кандидатов для ваших вакансий и даст вам больше шансов найти именно того, кто вам нужен.</p>
|
||||
</div>
|
||||
<div class="box">
|
||||
<h3>Найти подходящую вакансию</h3>
|
||||
<p>Если вы ищете работу, здесь вы можете просмотреть все доступные вакансии. Мы стремимся помочь вам найти именно то рабочее место, которое соответствует вашим ожиданиям и интересам.</p>
|
||||
</div>
|
||||
<div class="box">
|
||||
<h3>Оценить кандидатов на вакансию</h3>
|
||||
<p>После просмотра резюме у вас есть возможность оценить кандидатов и оставить свои комментарии. Вы можете выставить оценки по различным критериям и добавить свои заметки. Это поможет в дальнейшем процессе выбора и предоставляет общую картину по каждому кандидату, что значительно упрощает принятие решения.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.d-flex {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.box {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 8px;
|
||||
margin: 10px;
|
||||
padding: 20px;
|
||||
width: 200px;
|
||||
width: 45%;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
transition: transform 0.2s;
|
||||
|
@ -1,6 +1,7 @@
|
||||
@using CandidateReviewDataModels.Models
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using CandidateReviewContracts.ViewModels
|
||||
@using Newtonsoft.Json
|
||||
@model ResumeViewModel
|
||||
|
||||
@{
|
||||
@ -64,29 +65,91 @@
|
||||
<h2 class="mb-4">Оценка резюме</h2>
|
||||
|
||||
<form method="post" asp-controller="Assessment" asp-action="AddAssessmentCriterion">
|
||||
<input type="hidden" name="ResumeId" value="@Model.Id" />
|
||||
<input type="hidden" name="resumeId" value="@Model.Id" />
|
||||
|
||||
@if (ViewBag.Criterions != null)
|
||||
<div id="criteria-container">
|
||||
<div id="existing-criteria-container">
|
||||
@if (Model.Assessments.Any())
|
||||
{
|
||||
foreach (var criterion in ViewBag.Criterions)
|
||||
foreach (var assessment in Model.Assessments)
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" value="@criterion.Name" readonly />
|
||||
// Если это пользовательская оценка, пропускаем её, так как она будет отображена отдельно.
|
||||
if (ViewBag.UserAssessment is AssessmentViewModel currentUserAssessment && assessment.UserId == currentUserAssessment.UserId)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
<h4>Оценка пользователя: @assessment.UserName</h4>
|
||||
@foreach (var criterion in assessment.AssessmentCriterions)
|
||||
{
|
||||
<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>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<input type="number" class="form-control" name="value[]" min="1" max="5" placeholder="Введите значение от 1 до 5" required />
|
||||
<input type="hidden" name="criterion[]" value="@criterion.Id" />
|
||||
<div class="col-md-4">
|
||||
<input type="number" name="value" class="form-control" value="@criterion.Value" readonly />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<p>Комментарий: @assessment.Comment</p>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>Нет доступных критериев.</p>
|
||||
<p>Это резюме еще никто не оценивал. Станьте первыми!</p>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
@if (ViewBag.UserAssessment is AssessmentViewModel userAssessment)
|
||||
{
|
||||
<div id="user-assessment-container">
|
||||
<h4>Ваша оценка</h4>
|
||||
@foreach (var criterion in userAssessment.AssessmentCriterions)
|
||||
{
|
||||
<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>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="number" name="value" class="form-control" value="@criterion.Value" readonly />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<p>Комментарий: @userAssessment.Comment</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div id="new-criteria-container">
|
||||
<div class="row mb-3 criterion-row">
|
||||
<div class="col-8">
|
||||
<select name="criterion" class="form-control">
|
||||
<option value="">Выберите критерий</option>
|
||||
@if (ViewBag.Criterions is List<CriterionViewModel> criterions)
|
||||
{
|
||||
foreach (var criterion in criterions)
|
||||
{
|
||||
<option value="@criterion.Id">@criterion.Name</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="number" name="value" class="form-control" min="1" max="5" placeholder="Введите значение от 1 до 5" required />
|
||||
</div>
|
||||
<div class="col-md-1 d-flex align-items-center">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-criterion">Х</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-outline-secondary mt-2" id="add-criterion">Добавить критерий</button>
|
||||
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-12">
|
||||
<label for="comment" class="form-label">Комментарий</label>
|
||||
<textarea id="comment" name="comment" class="form-control" rows="4" placeholder="Оставьте ваш комментарий..."></textarea>
|
||||
@ -94,6 +157,8 @@
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success mt-3">Сохранить</button>
|
||||
}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="mt-4">
|
||||
@ -103,7 +168,49 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var criterions = @Html.Raw(Json.Serialize(ViewBag.Criterions));
|
||||
const criterions = @Html.Raw(JsonConvert.SerializeObject(ViewBag.Criterions));
|
||||
|
||||
document.getElementById('add-criterion').addEventListener('click', function () {
|
||||
const container = document.getElementById('new-criteria-container');
|
||||
const existingCriteria = Array.from(container.querySelectorAll('select[name="criterion"]')).map(select => select.value);
|
||||
|
||||
const newRow = document.createElement('div');
|
||||
newRow.className = 'row mb-3 criterion-row';
|
||||
|
||||
let selectOptions = '<option value="">Выберите критерий</option>';
|
||||
criterions.forEach(criterion => {
|
||||
if (!existingCriteria.includes(criterion.Id.toString())) {
|
||||
selectOptions += `<option value="${criterion.Id}">${criterion.Name}</option>`;
|
||||
}
|
||||
});
|
||||
|
||||
newRow.innerHTML = `
|
||||
<div class="col-8">
|
||||
<select name="criterion" class="form-control">${selectOptions}</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="number" name="value" class="form-control" min="1" max="5" placeholder="Введите значение от 1 до 5" required />
|
||||
</div>
|
||||
<div class="col-md-1 d-flex align-items-center">
|
||||
<button type="button" class="btn btn-danger btn-sm remove-criterion">✕</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
container.appendChild(newRow);
|
||||
attachRemoveEvent(newRow.querySelector('.remove-criterion'));
|
||||
});
|
||||
|
||||
function attachRemoveEvent(button) {
|
||||
button.addEventListener('click', function () {
|
||||
const container = document.getElementById('new-criteria-container');
|
||||
const rows = container.querySelectorAll('.criterion-row');
|
||||
if (rows.length > 1) {
|
||||
button.closest('.criterion-row').remove();
|
||||
} else {
|
||||
alert('Нельзя удалить последний критерий. Должен быть хотя бы один критерий оценки.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll('.remove-criterion').forEach(button => attachRemoveEvent(button));
|
||||
</script>
|
||||
|
@ -17,13 +17,13 @@
|
||||
<td>@vacancy.JobType</td>
|
||||
<td>@vacancy.Status</td>
|
||||
<td>
|
||||
<a asp-action="VacancyDetails" asp-controller="Vacancy" asp-route-id="@vacancy.Id" class="text-info" title="Просмотр">
|
||||
<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="text-warning" title="Редактировать">
|
||||
<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="text-danger" title="Удалить" onclick="return confirm('Вы уверены, что хотите удалить вакансию?');">
|
||||
<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>
|
||||
|
@ -9,8 +9,9 @@
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card">
|
||||
<img src="@(Model.AvatarFilePath ?? "https://cdn-icons-png.flaticon.com/512/18/18601.png")" style="max-width: 150px; max-height: 150px;" class="card-img-top img-fluid rounded-circle mx-auto d-block" alt="Аватар пользователя">
|
||||
<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="card-body text-center">
|
||||
<h5 class="card-title mb-0">
|
||||
@(string.IsNullOrEmpty(@Model?.Surname) ? "" : @Model?.Surname) @Model?.Name @(string.IsNullOrEmpty(@Model?.LastName) ? "" : @Model?.LastName)
|
||||
@ -41,9 +42,10 @@
|
||||
@if (userRole)
|
||||
{
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<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())
|
||||
@ -91,3 +93,77 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.table {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.table th, .table td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
</style>
|
||||
|
||||
@section Scripts {
|
||||
<script>
|
||||
document.querySelectorAll('form[onsubmit]').forEach(function (form) {
|
||||
form.addEventListener('submit', function (event) {
|
||||
if (!confirm('Вы уверены, что хотите удалить?')) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
}
|
||||
|
@ -8,21 +8,23 @@
|
||||
<div class="container mt-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<h1>Поиск вакансий</h1>
|
||||
<h1 class="mb-4 text-center">Поиск вакансий</h1>
|
||||
|
||||
<form asp-action="SearchVacancies" asp-controller="Vacancy" asp-route-tags="tags" method="get">
|
||||
<div class="input-group mb-3">
|
||||
<input type="text" class="form-control" name="tags" id="tags" placeholder="Введите поисковый запрос">
|
||||
<button class="btn btn-primary" type="submit">Поиск</button>
|
||||
<div class="input-group mb-4">
|
||||
<input type="text" class="form-control form-control-lg" name="tags" id="tags" placeholder="Введите поисковый запрос" required>
|
||||
<button class="btn btn-primary btn-lg" type="submit">Поиск</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@if (Model != null)
|
||||
{
|
||||
<h2>Результаты поиска:</h2>
|
||||
<h2 class="mb-3">Результаты поиска:</h2>
|
||||
|
||||
@if (Model.Any(v => v != null))
|
||||
{
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Название вакансии</th>
|
||||
<th>Тип работы</th>
|
||||
@ -40,8 +42,8 @@
|
||||
<td>@vacancy.Salary</td>
|
||||
<td>@vacancy.Tags</td>
|
||||
<td>
|
||||
<a asp-action="VacancyDetails" asp-controller="Vacancy" asp-route-id="@vacancy.Id" class="btn btn-primary">Просмотр</a>
|
||||
<a asp-controller="Resume" asp-action="EditResume" asp-route-vacancyId="@vacancy.Id" class="btn btn-primary">Составить резюме</a>
|
||||
<a asp-action="VacancyDetails" asp-controller="Vacancy" asp-route-id="@vacancy.Id" class="btn btn-info btn-sm btn-block mr-2">Просмотр</a>
|
||||
<a asp-controller="Resume" asp-action="EditResume" asp-route-vacancyId="@vacancy.Id" class="btn btn-success btn-sm btn-block">Составить резюме</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@ -50,17 +52,80 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>Вакансий не найдено.</p>
|
||||
<p class="text-center text-muted">Вакансий не найдено.</p>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>Произошла ошибка при получении данных.</p>
|
||||
<p class="text-center text-danger">Произошла ошибка при получении данных.</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.table {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.table th, .table td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
document.querySelector('form').addEventListener('submit', function (event) {
|
||||
const tagsInput = document.getElementById('tags');
|
||||
@ -70,4 +135,3 @@
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
using CandidateReviewContracts.BindingModels;
|
||||
using CandidateReviewContracts.SearchModels;
|
||||
using CandidateReviewContracts.ViewModels;
|
||||
using CandidateReviewDataModels.Models;
|
||||
|
||||
namespace CandidateReviewContracts.BusinessLogicsContracts
|
||||
{
|
||||
@ -10,7 +9,6 @@ namespace CandidateReviewContracts.BusinessLogicsContracts
|
||||
List<AssessmentViewModel>? ReadList(AssessmentSearchModel? model);
|
||||
AssessmentViewModel? ReadElement(AssessmentSearchModel model);
|
||||
int? Create(AssessmentBindingModel model);
|
||||
bool AddCriterionToAssessment(AssessmentSearchModel model, ICriterionModel criterion, int value);
|
||||
bool Update(AssessmentBindingModel model);
|
||||
bool Delete(AssessmentBindingModel model);
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace CandidateReviewContracts.SearchModels
|
||||
using CandidateReviewDataModels.Models;
|
||||
|
||||
namespace CandidateReviewContracts.SearchModels
|
||||
{
|
||||
public class AssessmentSearchModel
|
||||
{
|
||||
@ -8,5 +10,7 @@
|
||||
public int? ResumeId { get; set; }
|
||||
|
||||
public int? Id { get; set; }
|
||||
|
||||
public Dictionary<int, (ICriterionModel, int)> AssessmentCriterions = new();
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ 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);
|
||||
|
@ -0,0 +1,17 @@
|
||||
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; }
|
||||
}
|
||||
}
|
@ -6,12 +6,14 @@ namespace CandidateReviewContracts.ViewModels
|
||||
{
|
||||
public int? UserId { get; set; }
|
||||
|
||||
public string? UserName { get; set; }
|
||||
|
||||
public string? Comment { get; set; }
|
||||
|
||||
public int Id { get; set; }
|
||||
|
||||
public int? ResumeId { get; set; }
|
||||
|
||||
public Dictionary<int, (ICriterionModel, int)> AssessmentCriterions { get; set; } = new();
|
||||
public List<AssessmentCriterionViewModel> AssessmentCriterions { get; set; } = new();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
namespace CandidateReviewDataModels.Models
|
||||
{
|
||||
public interface IAssessmentCriterionModel : IId
|
||||
{
|
||||
int AssessmentId { get; }
|
||||
int CriterionId { get; }
|
||||
int Value { get; }
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ using CandidateReviewContracts.SearchModels;
|
||||
using CandidateReviewContracts.StoragesContracts;
|
||||
using CandidateReviewContracts.ViewModels;
|
||||
using CandidateReviewDatabaseImplement.Models;
|
||||
using CandidateReviewDataModels.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace CandidateReviewDatabaseImplement.Implements
|
||||
@ -38,25 +39,44 @@ namespace CandidateReviewDatabaseImplement.Implements
|
||||
return null;
|
||||
}
|
||||
using var context = new CandidateReviewDatabase();
|
||||
if (model.ResumeId.HasValue)
|
||||
if (model.ResumeId.HasValue && model.UserId.HasValue)
|
||||
{
|
||||
return context.Assessments
|
||||
.FirstOrDefault(x => x.ResumeId == model.ResumeId && x.UserId == model.UserId)
|
||||
?.GetViewModel;
|
||||
}
|
||||
else if (model.ResumeId.HasValue)
|
||||
{
|
||||
return context.Assessments
|
||||
.FirstOrDefault(x => x.ResumeId == model.ResumeId)
|
||||
?.GetViewModel;
|
||||
}
|
||||
|
||||
if (model.UserId.HasValue)
|
||||
else if (model.UserId.HasValue)
|
||||
{
|
||||
return context.Assessments
|
||||
.FirstOrDefault(x => x.UserId == model.UserId)
|
||||
?.GetViewModel;
|
||||
}
|
||||
|
||||
return context.Assessments
|
||||
.FirstOrDefault(x => model.Id.HasValue && x.Id == model.Id)
|
||||
?.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)
|
||||
@ -102,16 +122,27 @@ namespace CandidateReviewDatabaseImplement.Implements
|
||||
public int? Insert(AssessmentBindingModel model)
|
||||
{
|
||||
using var context = new CandidateReviewDatabase();
|
||||
var newAssessment = Assessment.Create(context, model);
|
||||
|
||||
if (newAssessment == null)
|
||||
var newAssessment = new Assessment
|
||||
{
|
||||
return null;
|
||||
}
|
||||
ResumeId = model.ResumeId,
|
||||
UserId = model.UserId,
|
||||
Comment = model.Comment
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -43,19 +43,18 @@ namespace CandidateReviewDatabaseImplement.Models
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new Assessment()
|
||||
|
||||
var assessment = new Assessment
|
||||
{
|
||||
Id = model.Id,
|
||||
ResumeId = model.ResumeId,
|
||||
UserId = model.UserId,
|
||||
Comment = model.Comment,
|
||||
Criterions = model.AssessmentCriterions.Select(x => new AssessmentCriterion()
|
||||
{
|
||||
Criterion = context.Criterions.First(y => y.Id == x.Key),
|
||||
Value = x.Value.Item2
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
return assessment;
|
||||
}
|
||||
|
||||
public void Update(AssessmentBindingModel model)
|
||||
{
|
||||
if (model == null)
|
||||
@ -66,12 +65,24 @@ namespace CandidateReviewDatabaseImplement.Models
|
||||
UserId = model.UserId;
|
||||
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()
|
||||
{
|
||||
Id = Id,
|
||||
ResumeId = ResumeId,
|
||||
UserId = UserId,
|
||||
Comment = Comment
|
||||
Comment = Comment,
|
||||
AssessmentCriterions = GetAssessmentCriterionsAsViewModel()
|
||||
};
|
||||
|
||||
public void UpdateCriterions(CandidateReviewDatabase context, AssessmentBindingModel model)
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using CandidateReviewContracts.ViewModels;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace CandidateReviewDatabaseImplement.Models
|
||||
{
|
||||
@ -13,5 +14,13 @@ 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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -25,30 +25,13 @@ namespace CandidateReviewRestApi.Controllers
|
||||
try
|
||||
{
|
||||
return _logic.ReadElement(new AssessmentSearchModel
|
||||
{
|
||||
Id = id
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Ошибка получения оценки");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public List<AssessmentViewModel>? ListByUserId(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _logic.ReadList(new AssessmentSearchModel
|
||||
{
|
||||
UserId = id
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Ошибка получения оценок");
|
||||
_logger.LogError(ex, "Ошибка получения оценки");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@ -71,12 +54,12 @@ namespace CandidateReviewRestApi.Controllers
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public int? Create(AssessmentBindingModel model)
|
||||
public IActionResult Create(AssessmentBindingModel model)
|
||||
{
|
||||
try
|
||||
{
|
||||
int? id = _logic.Create(model);
|
||||
return id;
|
||||
return Ok(new AssessmentBindingModel { Id = (int)id });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -84,53 +67,6 @@ namespace CandidateReviewRestApi.Controllers
|
||||
throw;
|
||||
}
|
||||
}
|
||||
[HttpPost]
|
||||
public void AddCriterionToAssessment(Dictionary<int, (ICriterionModel, int)> model)
|
||||
{
|
||||
if (model == null || model.Count == 0)
|
||||
{
|
||||
throw new ArgumentException("Модель данных не должна быть пустой.", nameof(model));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var kvp in model)
|
||||
{
|
||||
var id = kvp.Key;
|
||||
var (criterion, value) = kvp.Value;
|
||||
|
||||
if (criterion == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!model.ContainsKey(id))
|
||||
{
|
||||
model.Add(id, (criterion, value));
|
||||
}
|
||||
else
|
||||
{
|
||||
model[id] = (criterion, value);
|
||||
}
|
||||
|
||||
var success = _logic.AddCriterionToAssessment(
|
||||
new AssessmentSearchModel { Id = id },
|
||||
criterion,
|
||||
value
|
||||
);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
throw new Exception("Ошибка добавления критерия.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Ошибка добавления критериев.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public void Update(AssessmentBindingModel model)
|
||||
|
Loading…
Reference in New Issue
Block a user