поиск вакансий, вывод сотрудников и добавление сотрудников, новая роль Администратор, мелкие правки
This commit is contained in:
parent
525668cb62
commit
be517e47e4
@ -13,11 +13,13 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
|||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly ICompanyStorage _сompanyStorage;
|
private readonly ICompanyStorage _сompanyStorage;
|
||||||
private readonly IVacancyStorage _vacancyStorage;
|
private readonly IVacancyStorage _vacancyStorage;
|
||||||
public CompanyLogic(ILogger<CompanyLogic> logger, ICompanyStorage сompanyStorage, IVacancyStorage vacancyStorage)
|
private readonly IUserStorage _userStorage;
|
||||||
|
public CompanyLogic(ILogger<CompanyLogic> logger, ICompanyStorage сompanyStorage, IVacancyStorage vacancyStorage, IUserStorage userStorage)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_сompanyStorage = сompanyStorage;
|
_сompanyStorage = сompanyStorage;
|
||||||
_vacancyStorage = vacancyStorage;
|
_vacancyStorage = vacancyStorage;
|
||||||
|
_userStorage = userStorage;
|
||||||
}
|
}
|
||||||
public int Create(CompanyBindingModel model)
|
public int Create(CompanyBindingModel model)
|
||||||
{
|
{
|
||||||
@ -87,6 +89,23 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
|||||||
Tags = v.Tags
|
Tags = v.Tags
|
||||||
}).ToList() ?? new List<VacancyViewModel>();
|
}).ToList() ?? new List<VacancyViewModel>();
|
||||||
|
|
||||||
|
var employees = _userStorage.GetFilteredList(new UserSearchModel { CompanyId = company.Id, Role = CandidateReviewDataModels.Enums.RoleEnum.Сотрудник });
|
||||||
|
|
||||||
|
var employeeViewModels = employees?.Select(u => new UserViewModel
|
||||||
|
{
|
||||||
|
Id = u.Id,
|
||||||
|
CompanyId = u.CompanyId,
|
||||||
|
Surname = u.Surname,
|
||||||
|
Name = u.Name,
|
||||||
|
LastName = u.LastName,
|
||||||
|
Email = u.Email,
|
||||||
|
EmailConfirmed = u.EmailConfirmed,
|
||||||
|
AvatarFilePath = u.AvatarFilePath,
|
||||||
|
Password = u.Password,
|
||||||
|
PhoneNumber = u.PhoneNumber,
|
||||||
|
Role = u.Role
|
||||||
|
}).ToList() ?? new List<UserViewModel>();
|
||||||
|
|
||||||
var companyViewModel = new CompanyViewModel
|
var companyViewModel = new CompanyViewModel
|
||||||
{
|
{
|
||||||
Id = company.Id,
|
Id = company.Id,
|
||||||
@ -96,15 +115,14 @@ namespace CandidateReviewBusinessLogic.BusinessLogic
|
|||||||
Address = company.Address,
|
Address = company.Address,
|
||||||
Website = company.Website,
|
Website = company.Website,
|
||||||
LogoFilePath = company.LogoFilePath,
|
LogoFilePath = company.LogoFilePath,
|
||||||
Vacancies = vacancyViewModels
|
Vacancies = vacancyViewModels,
|
||||||
|
Employees = employeeViewModels
|
||||||
};
|
};
|
||||||
|
|
||||||
_logger.LogInformation("ReadElement: Company found. Id: {Id}", company.Id);
|
_logger.LogInformation("ReadElement: Company found. Id: {Id}", company.Id);
|
||||||
return companyViewModel;
|
return companyViewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public List<CompanyViewModel>? ReadList(CompanySearchModel? model)
|
public List<CompanyViewModel>? ReadList(CompanySearchModel? model)
|
||||||
{
|
{
|
||||||
var list = model == null ? _сompanyStorage.GetFullList() : _сompanyStorage.GetFilteredList(model);
|
var list = model == null ? _сompanyStorage.GetFullList() : _сompanyStorage.GetFilteredList(model);
|
||||||
|
@ -22,11 +22,6 @@ namespace CandidateReviewUserApp.Controllers
|
|||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IActionResult Privacy()
|
|
||||||
{
|
|
||||||
return View();
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult Enter()
|
public IActionResult Enter()
|
||||||
{
|
{
|
||||||
@ -41,14 +36,15 @@ namespace CandidateReviewUserApp.Controllers
|
|||||||
throw new Exception("Ââåäèòå ëîãèí è ïàðîëü");
|
throw new Exception("Ââåäèòå ëîãèí è ïàðîëü");
|
||||||
}
|
}
|
||||||
APIClient.User = APIClient.GetRequest<UserViewModel>($"api/user/login?login={login}&password={password}");
|
APIClient.User = APIClient.GetRequest<UserViewModel>($"api/user/login?login={login}&password={password}");
|
||||||
if (APIClient.User.CompanyId != null)
|
|
||||||
{
|
|
||||||
APIClient.Company = APIClient.GetRequest<CompanyViewModel>($"api/company/profile?id={APIClient.User?.CompanyId}");
|
|
||||||
}
|
|
||||||
if (APIClient.User == null)
|
if (APIClient.User == null)
|
||||||
{
|
{
|
||||||
throw new Exception("Íåâåðíûé ëîãèí/ïàðîëü");
|
throw new Exception("Íåâåðíûé ëîãèí/ïàðîëü");
|
||||||
}
|
}
|
||||||
|
if (APIClient.User?.CompanyId != null)
|
||||||
|
{
|
||||||
|
APIClient.Company = APIClient.GetRequest<CompanyViewModel>($"api/company/profile?id={APIClient.User?.CompanyId}");
|
||||||
|
}
|
||||||
|
|
||||||
Response.Redirect("/Home/Index");
|
Response.Redirect("/Home/Index");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +66,7 @@ namespace CandidateReviewUserApp.Controllers
|
|||||||
|
|
||||||
if (login.Equals("tania.art03@gmail.com", StringComparison.OrdinalIgnoreCase))
|
if (login.Equals("tania.art03@gmail.com", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
role = RoleEnum.Ñîòðóäíèê;
|
role = RoleEnum.Àäìèíèñòðàòîð;
|
||||||
}
|
}
|
||||||
else if (login.Equals("t.artamonova73@icloud.com", StringComparison.OrdinalIgnoreCase))
|
else if (login.Equals("t.artamonova73@icloud.com", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,7 @@ namespace CandidateReviewClientApp.Controllers
|
|||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult UserProfile(int? id)
|
public IActionResult UserProfile(int? id)
|
||||||
{
|
{
|
||||||
var userId = id ?? APIClient.User.Id;
|
var userId = id ?? APIClient.User?.Id;
|
||||||
|
|
||||||
var model = APIClient.GetRequest<UserViewModel>($"api/user/profile?id={userId}");
|
var model = APIClient.GetRequest<UserViewModel>($"api/user/profile?id={userId}");
|
||||||
|
|
||||||
@ -31,41 +31,79 @@ namespace CandidateReviewClientApp.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult UserProfileEdit()
|
public IActionResult UserProfileEdit(int? id)
|
||||||
{
|
{
|
||||||
if (APIClient.User == null)
|
if (APIClient.User == null)
|
||||||
{
|
{
|
||||||
return Redirect("/Home/Enter");
|
return Redirect("/Home/Enter");
|
||||||
}
|
}
|
||||||
var model = APIClient.GetRequest<UserViewModel?>($"api/user/profile?id={APIClient.User.Id}");
|
|
||||||
if (model == null)
|
if (APIClient.Company == null)
|
||||||
{
|
{
|
||||||
return RedirectToAction("/Home/Index");
|
return Redirect("/Home/Index");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!id.HasValue)
|
||||||
|
{
|
||||||
|
return View(new UserViewModel());
|
||||||
|
}
|
||||||
|
else if (id.HasValue)
|
||||||
|
{
|
||||||
|
var employee = APIClient.GetRequest<UserViewModel?>($"api/user/profile?id={id}");
|
||||||
|
return View(employee);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var model = APIClient.GetRequest<UserViewModel?>($"api/user/profile?id={APIClient.User.Id}");
|
||||||
|
return View(model);
|
||||||
}
|
}
|
||||||
return View(model);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public void UserProfileEdit(UserBindingModel model)
|
public void UserProfileEdit(UserBindingModel model)
|
||||||
{
|
{
|
||||||
APIClient.PostRequest("api/user/update", new UserBindingModel
|
if (model.Id != 0)
|
||||||
{
|
{
|
||||||
Id = model.Id,
|
APIClient.PostRequest("api/user/update", model);
|
||||||
Surname = model.Surname,
|
}
|
||||||
Name = model.Name,
|
else
|
||||||
LastName = model.LastName,
|
{
|
||||||
CompanyId = model.CompanyId,
|
APIClient.PostRequest("api/user/register", model);
|
||||||
Email = model.Email,
|
if (APIClient.Company != null)
|
||||||
Password = model.Password,
|
{
|
||||||
EmailConfirmed = model.EmailConfirmed,
|
APIClient.Company?.Employees.Add(new UserViewModel
|
||||||
Role = model.Role,
|
{
|
||||||
AvatarFilePath = model.AvatarFilePath,
|
Id = model.Id,
|
||||||
PhoneNumber = model.PhoneNumber
|
Surname = model.Surname,
|
||||||
});
|
Name = model.Name,
|
||||||
|
LastName = model.LastName,
|
||||||
|
CompanyId = model.CompanyId,
|
||||||
|
Email = model.Email,
|
||||||
|
Password = model.Password,
|
||||||
|
EmailConfirmed = model.EmailConfirmed,
|
||||||
|
Role = CandidateReviewDataModels.Enums.RoleEnum.Сотрудник,
|
||||||
|
AvatarFilePath = model.AvatarFilePath,
|
||||||
|
PhoneNumber = model.PhoneNumber
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Response.Redirect($"/Company/CompanyProfile/{model.CompanyId}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Response.Redirect($"/User/UserProfile/{model.Id}");
|
Response.Redirect($"/User/UserProfile/{model.Id}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IActionResult DeleteEmployee(int id)
|
||||||
|
{
|
||||||
|
APIClient.PostRequest("api/user/delete", new UserBindingModel
|
||||||
|
{
|
||||||
|
Id = id
|
||||||
|
});
|
||||||
|
APIClient.Company = APIClient.GetRequest<CompanyViewModel?>($"api/company/profile?id={APIClient.User?.CompanyId}");
|
||||||
|
|
||||||
|
return Redirect($"~/Company/CompanyProfile");
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public void Logout()
|
public void Logout()
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using CandidateReviewContracts.BindingModels;
|
using CandidateReviewContracts.BindingModels;
|
||||||
using CandidateReviewContracts.ViewModels;
|
using CandidateReviewContracts.ViewModels;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace CandidateReviewClientApp.Controllers
|
namespace CandidateReviewClientApp.Controllers
|
||||||
{
|
{
|
||||||
@ -13,7 +14,7 @@ namespace CandidateReviewClientApp.Controllers
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult Vacancy(int? id)
|
public IActionResult VacancyDetails(int? id)
|
||||||
{
|
{
|
||||||
if (APIClient.User == null)
|
if (APIClient.User == null)
|
||||||
{
|
{
|
||||||
@ -42,6 +43,7 @@ namespace CandidateReviewClientApp.Controllers
|
|||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public void EditVacancy(VacancyBindingModel model)
|
public void EditVacancy(VacancyBindingModel model)
|
||||||
{
|
{
|
||||||
@ -49,6 +51,12 @@ namespace CandidateReviewClientApp.Controllers
|
|||||||
{
|
{
|
||||||
throw new Exception("Доступно только авторизованным пользователям");
|
throw new Exception("Доступно только авторизованным пользователям");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(model.Tags))
|
||||||
|
{
|
||||||
|
model.Tags = model.Tags.ToLowerInvariant();
|
||||||
|
}
|
||||||
|
|
||||||
if (model.Id != 0)
|
if (model.Id != 0)
|
||||||
{
|
{
|
||||||
APIClient.PostRequest("api/vacancy/update", model);
|
APIClient.PostRequest("api/vacancy/update", model);
|
||||||
@ -58,11 +66,16 @@ namespace CandidateReviewClientApp.Controllers
|
|||||||
APIClient.PostRequest("api/vacancy/create", model);
|
APIClient.PostRequest("api/vacancy/create", model);
|
||||||
if (APIClient.Company != null)
|
if (APIClient.Company != null)
|
||||||
{
|
{
|
||||||
|
if (!string.IsNullOrEmpty(model.Tags))
|
||||||
|
{
|
||||||
|
model.Tags = model.Tags.ToLowerInvariant();
|
||||||
|
}
|
||||||
|
|
||||||
APIClient.Company?.Vacancies.Add(new VacancyViewModel
|
APIClient.Company?.Vacancies.Add(new VacancyViewModel
|
||||||
{
|
{
|
||||||
Id = model.Id,
|
Id = model.Id,
|
||||||
CompanyId = model.CompanyId,
|
CompanyId = model.CompanyId,
|
||||||
CreatedAt = model.CreatedAt,
|
CreatedAt = DateTime.Now.ToUniversalTime(),
|
||||||
Description = model.Description,
|
Description = model.Description,
|
||||||
JobTitle = model.JobTitle,
|
JobTitle = model.JobTitle,
|
||||||
JobType = model.JobType,
|
JobType = model.JobType,
|
||||||
@ -77,16 +90,34 @@ namespace CandidateReviewClientApp.Controllers
|
|||||||
Response.Redirect($"/Company/CompanyProfile/{model.CompanyId}");
|
Response.Redirect($"/Company/CompanyProfile/{model.CompanyId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
public IActionResult Delete(int id)
|
||||||
public void Delete(int id)
|
{
|
||||||
|
if (APIClient.Company == null)
|
||||||
|
{
|
||||||
|
throw new Exception("Компания не определена");
|
||||||
|
}
|
||||||
|
|
||||||
|
APIClient.PostRequest($"api/vacancy/delete", new VacancyBindingModel { Id = id });
|
||||||
|
APIClient.Company = APIClient.GetRequest<CompanyViewModel?>($"api/company/profile?id={APIClient.User?.CompanyId}");
|
||||||
|
|
||||||
|
return Redirect("~/Company/CompanyProfile");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IActionResult SearchVacancies(string? tags)
|
||||||
{
|
{
|
||||||
if (APIClient.User == null)
|
if (APIClient.User == null)
|
||||||
{
|
{
|
||||||
throw new Exception("Доступно только авторизованным пользователям");
|
throw new Exception("Доступно только авторизованным пользователям");
|
||||||
}
|
}
|
||||||
|
|
||||||
APIClient.PostRequest($"api/vacancy/delete", new VacancyBindingModel { Id = id });
|
if (string.IsNullOrEmpty(tags))
|
||||||
Response.Redirect("/Home/Index");
|
{
|
||||||
|
ViewBag.Message = "Пожалуйста, введите поисковый запрос.";
|
||||||
|
return View(new List<VacancyViewModel?>());
|
||||||
|
}
|
||||||
|
|
||||||
|
var results = APIClient.GetRequest<List<VacancyViewModel?>>($"api/vacancy/search?tags={tags}");
|
||||||
|
return View(results);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,19 +3,18 @@
|
|||||||
|
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Профиль компании";
|
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="container mt-5">
|
||||||
<div class="row g-4">
|
<div class="row g-4">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<img src="@(Model.LogoFilePath ?? "https://static.thenounproject.com/png/2504969-200.png")"
|
<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="Логотип компании">
|
||||||
class="card-img-top img-fluid rounded" alt="Логотип компании">
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">@Model.Name</h5>
|
<h5 class="card-title">@Model.Name</h5>
|
||||||
<p class="card-text">@(Model.Description == null ? "Описание отсутствует" : Model.Description) </p>
|
<p class="card-text">@(Model.Description == null ? "Описание отсутствует" : Model.Description) </p>
|
||||||
<a href="@(Model.Website ?? "#")" target="_blank" class="btn btn-primary mt-2">@(Model.Website ?? "Веб-сайт отсутствует")</a> </a>
|
<a href="@(Model.Website ?? "#")" target="_blank" class="btn btn-primary mt-2">@(Model.Website != null ? "Официальный сайт" : "Веб-сайт отсутствует")</a> </a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -48,30 +47,36 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@if (@Model.Vacancies != null && @Model.Vacancies.Any())
|
@if (Model.Vacancies != null && Model.Vacancies.Any())
|
||||||
{
|
{
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Название</th>
|
<th>Название</th>
|
||||||
<th>Тип занятости</th>
|
<th>Тип занятости</th>
|
||||||
<th>Зарплата</th>
|
<th>Статус</th>
|
||||||
<th>Действия</th>
|
<th>Действия</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach (var vacancy in @Model.Vacancies)
|
@foreach (var vacancy in Model.Vacancies)
|
||||||
{
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td>@vacancy.JobTitle</td>
|
<td>@vacancy.JobTitle</td>
|
||||||
<td>@vacancy.JobType</td>
|
<td>@vacancy.JobType</td>
|
||||||
<td>@vacancy.Salary</td>
|
<td>@vacancy.Status</td>
|
||||||
<td>
|
<td>
|
||||||
<a asp-action="VacancyDetails" asp-controller="Vacancy" asp-route-id="@vacancy.Id" class="btn btn-sm btn-info">Просмотр</a>
|
<a asp-action="VacancyDetails" asp-controller="Vacancy" asp-route-id="@vacancy.Id" class="text-info" title="Просмотр">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</a>
|
||||||
@if (userRole)
|
@if (userRole)
|
||||||
{
|
{
|
||||||
<a asp-action="EditVacancy" asp-controller="Vacancy" asp-route-id="@vacancy.Id" class="btn btn-sm btn-warning">Редактировать</a>
|
<a asp-action="EditVacancy" asp-controller="Vacancy" asp-route-id="@vacancy.Id" class="text-warning" title="Редактировать">
|
||||||
<a asp-action="DeleteVacancy" asp-controller="Vacancy" asp-route-id="@vacancy.Id" class="btn btn-sm btn-danger" onclick="return confirm('Вы уверены, что хотите удалить вакансию?');">Удалить</a>
|
<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('Вы уверены, что хотите удалить вакансию?');">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</a>
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -85,6 +90,70 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<br />
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header d-flex justify-content-between align-items-center">
|
||||||
|
<h2>Сотрудники компании</h2>
|
||||||
|
@if (userRole)
|
||||||
|
{
|
||||||
|
<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())
|
||||||
|
{
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Фамилия</th>
|
||||||
|
<th>Имя</th>
|
||||||
|
<th>Эл. почта</th>
|
||||||
|
<th>Действия</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach (var employee in Model.Employees)
|
||||||
|
{
|
||||||
|
<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>
|
||||||
|
@if (userRole)
|
||||||
|
{
|
||||||
|
<a asp-action="UserProfileEdit" asp-controller="User" asp-route-id="@employee.Id" class="text-warning" 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>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
@* <nav>
|
||||||
|
<ul class="pagination justify-content-center">
|
||||||
|
@for (int i = 1; i <= pageCount; i++)
|
||||||
|
{
|
||||||
|
<li class="page-item @(i == pageNumber ? "active" : "")">
|
||||||
|
<a class="page-link" asp-action="CompanyProfile" asp-controller="Company" asp-route-id="@Model.Id" asp-route-pageNumber="@i">
|
||||||
|
@i
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</nav> *@
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<p>Сотрудников нет.</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
<title>@ViewData["Title"] - CandidateReviewClientApp</title>
|
<title>@ViewData["Title"] - CandidateReviewClientApp</title>
|
||||||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
|
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
|
||||||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" asp-append-version="true">
|
||||||
<link rel="stylesheet" href="~/CandidateReviewClientApp.styles.css" asp-append-version="true" />
|
<link rel="stylesheet" href="~/CandidateReviewClientApp.styles.css" asp-append-version="true" />
|
||||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||||
@ -21,10 +22,10 @@
|
|||||||
</button>
|
</button>
|
||||||
<div class="collapse navbar-collapse" id="mainNav">
|
<div class="collapse navbar-collapse" id="mainNav">
|
||||||
<ul class="navbar-nav ml-auto">
|
<ul class="navbar-nav ml-auto">
|
||||||
@if (APIClient.User?.Role == RoleEnum.Сотрудник)
|
@if (APIClient.User?.Role == RoleEnum.Сотрудник || APIClient.User?.Role == RoleEnum.Администратор)
|
||||||
{
|
{
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link text-dark" asp-area="" asp-controller="Company" asp-action="@(APIClient.User?.CompanyId == null ? "EditCompanyProfile" : "CompanyProfile")">Профиль компании</a>
|
<a class="nav-link text-dark" asp-area="" asp-controller="Company" asp-route-id="@(APIClient.Company?.Id)" asp-action="@(APIClient.User?.CompanyId == null ? "EditCompanyProfile" : "CompanyProfile")">Профиль компании</a>
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
|
@ -9,10 +9,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-4 mb-4">
|
<div class="col-md-4 mb-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@if (!string.IsNullOrEmpty(@Model?.AvatarFilePath))
|
<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="Аватар пользователя">
|
||||||
{
|
|
||||||
<img src="@Model?.AvatarFilePath" 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">
|
<div class="card-body text-center">
|
||||||
<h5 class="card-title mb-0">
|
<h5 class="card-title mb-0">
|
||||||
@Model?.Name @(string.IsNullOrEmpty(@Model?.Surname) ? "" : @Model?.Surname) @(string.IsNullOrEmpty(@Model?.LastName) ? "" : @Model?.LastName)
|
@Model?.Name @(string.IsNullOrEmpty(@Model?.Surname) ? "" : @Model?.Surname) @(string.IsNullOrEmpty(@Model?.LastName) ? "" : @Model?.LastName)
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Редактирование профиля";
|
ViewData["Title"] = "Редактирование профиля";
|
||||||
|
var userRole = APIClient.User?.Role == CandidateReviewDataModels.Enums.RoleEnum.Администратор ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="container mt-5">
|
<div class="container mt-5">
|
||||||
@ -12,45 +13,67 @@
|
|||||||
<form method="post" class="needs-validation" novalidate>
|
<form method="post" class="needs-validation" novalidate>
|
||||||
<input type="hidden" name="id" value="@Model?.Id" />
|
<input type="hidden" name="id" value="@Model?.Id" />
|
||||||
|
|
||||||
<div class="mb-3">
|
@if (userRole)
|
||||||
<label for="Name" class="form-label">Имя <span class="text-danger">*</span></label>
|
{
|
||||||
<input type="text" class="form-control" id="Name" name="Name" value="@Model?.Name" required />
|
<input type="hidden" name="companyId" value="@(APIClient.User?.CompanyId)" />
|
||||||
<div class="invalid-feedback">Пожалуйста, введите имя.</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="Surname" class="form-label">Фамилия <span class="text-danger">*</span></label>
|
<label for="Name" class="form-label">Имя <span class="text-danger">*</span></label>
|
||||||
<input type="text" class="form-control" id="Surname" name="Surname" value="@Model?.Surname" required />
|
<input type="text" class="form-control" id="Name" name="Name" value="@Model?.Name" required />
|
||||||
<div class="invalid-feedback">Пожалуйста, введите фамилию.</div>
|
<div class="invalid-feedback">Пожалуйста, введите имя.</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="LastName" class="form-label">Отчество</label>
|
<label for="Surname" class="form-label">Фамилия <span class="text-danger">*</span></label>
|
||||||
<input type="text" class="form-control" id="LastName" name="LastName" value="@Model?.LastName" />
|
<input type="text" class="form-control" id="Surname" name="Surname" value="@Model?.Surname" required />
|
||||||
<div class="invalid-feedback">Пожалуйста, введите отчество.</div>
|
<div class="invalid-feedback">Пожалуйста, введите фамилию.</div>
|
||||||
</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" />
|
||||||
|
<div class="invalid-feedback">Пожалуйста, введите электронную почту.</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="PhoneNumber" class="form-label">Телефон</label>
|
<label for="Password" class="form-label">Пароль <span class="text-danger">*</span></label>
|
||||||
<input type="tel" class="form-control" id="PhoneNumber" name="PhoneNumber" value="@Model?.PhoneNumber" />
|
<input type="text" class="form-control" id="Password" name="Password" value="@Model?.Password" />
|
||||||
<div class="invalid-feedback">Пожалуйста, введите телефон.</div>
|
<div class="invalid-feedback">Пожалуйста, введите пароль.</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="hidden" name="Email" value="@Model?.Email" />
|
<div class="d-flex justify-content-between">
|
||||||
<input type="hidden" name="Password" value="@Model?.Password" />
|
<button type="submit" class="btn btn-primary">Сохранить</button>
|
||||||
<input type="hidden" name="Role" value="@Model?.Role" />
|
<a asp-controller="Company" asp-action="CompanyProfile" class="btn btn-secondary">Отмена</a>
|
||||||
<input type="hidden" name="CompanyId" value="@Model?.CompanyId" />
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<input type="hidden" name="Email" value="@Model?.Email" />
|
||||||
|
<input type="hidden" name="Password" value="@Model?.Password" />
|
||||||
|
<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">
|
<div class="mb-3">
|
||||||
<label for="AvatarFilePath" class="form-label">Аватар</label>
|
<label for="PhoneNumber" class="form-label">Телефон</label>
|
||||||
<input type="file" class="form-control" id="AvatarFilePath" name="AvatarFilePath" value="@Model?.AvatarFilePath" accept=".jpg,.jpeg,.png" />
|
<input type="tel" class="form-control" id="PhoneNumber" name="PhoneNumber" value="@Model?.PhoneNumber" />
|
||||||
<div class="invalid-feedback">Выберите файл изображения.</div>
|
<div class="invalid-feedback">Пожалуйста, введите телефон.</div>
|
||||||
</div>
|
</div>
|
||||||
|
<input type="hidden" name="Role" value="@Model?.Role" />
|
||||||
|
<input type="hidden" name="CompanyId" value="@Model?.CompanyId" />
|
||||||
|
|
||||||
<div class="d-flex justify-content-between">
|
<div class="mb-3">
|
||||||
<button type="submit" class="btn btn-primary">Сохранить</button>
|
<label for="AvatarFilePath" class="form-label">Аватар</label>
|
||||||
<a asp-controller="User" asp-action="UserProfile" class="btn btn-secondary">Отмена</a>
|
<input type="file" class="form-control" id="AvatarFilePath" name="AvatarFilePath" accept=".jpg,.jpeg,.png" />
|
||||||
</div>
|
<img id="avatarPreview" src="@Model?.AvatarFilePath" alt="Предварительный просмотр аватара" style="max-width: 100px; max-height: 100px;" />
|
||||||
|
<div class="invalid-feedback">Выберите файл изображения.</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<button type="submit" class="btn btn-primary">Сохранить</button>
|
||||||
|
<a asp-controller="User" asp-action="UserProfile" class="btn btn-secondary">Отмена</a>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -62,7 +85,7 @@
|
|||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$('#PhoneNumber').inputmask({
|
$('#PhoneNumber').inputmask({
|
||||||
mask: '+7 (999) 999-99-99', // Adjust mask as needed
|
mask: '+7 (999) 999-99-99',
|
||||||
showMaskOnHover: false,
|
showMaskOnHover: false,
|
||||||
onincomplete: function () {
|
onincomplete: function () {
|
||||||
$(this).removeClass('is-valid').addClass('is-invalid');
|
$(this).removeClass('is-valid').addClass('is-invalid');
|
||||||
@ -91,6 +114,23 @@
|
|||||||
})
|
})
|
||||||
})()
|
})()
|
||||||
</script>
|
</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");
|
await Html.RenderPartialAsync("_ValidationScriptsPartial");
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="JobType" class="form-label">Тип занятости</label>
|
<label asp-for="JobType" class="form-label">Тип занятости</label>
|
||||||
<select id="JobType" name="JobType" class="form-control" asp-items="@(new SelectList(Enum.GetValues(typeof(JobTypeEnum)).Cast<JobTypeEnum>()))"></select>
|
<select asp-for="JobType" class="form-control" asp-items="@GetJobTypeSelectList()"></select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
@ -44,30 +44,32 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="Status" class="form-label">Статус вакансии</label>
|
<label asp-for="Status" class="form-label">Статус вакансии</label>
|
||||||
<select id="Status" name="Status" class="form-control" asp-items="@(new SelectList(Enum.GetValues(typeof(VacancyStatusEnum)).Cast<VacancyStatusEnum>()))"></select>
|
<select asp-for="Status" class="form-control" asp-items="@GetStatusSelectList()"></select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="hidden" name="createdAt" value="@Model?.CreatedAt" />
|
|
||||||
|
|
||||||
@{
|
|
||||||
var tagsString = @Model?.Tags;
|
|
||||||
var displayedTags = string.IsNullOrEmpty(tagsString) ? "" : string.Join(", ", tagsString.Split(',').Select(t => t.Trim()));
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="tags" class="form-label">Тэги</label>
|
<label for="tags" class="form-label">Тэги</label>
|
||||||
<input type="text" class="form-control" id="tags" name="tags" value="@displayedTags" placeholder="Введите тэги через запятую">
|
<input type="text" class="form-control" id="tags" name="tags" value="@Model?.Tags" placeholder="Введите тэги через пробел">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@* <input type="hidden" name="createdAt" value="@(APIClient.Company?.Vacancies.Add(Model))" />
|
|
||||||
*@
|
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<button type="submit" class="btn btn-primary">Сохранить</button>
|
<button type="submit" class="btn btn-primary">Сохранить</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@functions {
|
||||||
|
public SelectList GetJobTypeSelectList()
|
||||||
|
{
|
||||||
|
return new SelectList(Enum.GetValues(typeof(JobTypeEnum)).Cast<JobTypeEnum>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public SelectList GetStatusSelectList()
|
||||||
|
{
|
||||||
|
return new SelectList(Enum.GetValues(typeof(VacancyStatusEnum)).Cast<VacancyStatusEnum>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
'use strict'
|
'use strict'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
@* @using CandidateReviewContracts.ViewModels
|
@using CandidateReviewContracts.ViewModels
|
||||||
@model VacancyViewModel
|
@model List<VacancyViewModel?>
|
||||||
|
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Поиск вакансий";
|
ViewData["Title"] = "Поиск вакансий";
|
||||||
@ -7,34 +7,66 @@
|
|||||||
|
|
||||||
<div class="container mt-5">
|
<div class="container mt-5">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-6">
|
<div class="col-md-8">
|
||||||
<h1>Поиск вакансий</h1>
|
<h1>Поиск вакансий</h1>
|
||||||
<form asp-action="Search" asp-controller="Vacancy" method="get">
|
<form asp-action="SearchVacancies" asp-controller="Vacancy" asp-route-tags="tags" method="get">
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
<input type="text" class="form-control" name="searchTerm" placeholder="Введите поисковый запрос" value="@Model?.SearchTerm">
|
<input type="text" class="form-control" name="tags" id="tags" placeholder="Введите поисковый запрос">
|
||||||
<button class="btn btn-primary" type="submit">Поиск</button>
|
<button class="btn btn-primary" type="submit">Поиск</button>
|
||||||
</div>
|
</div>
|
||||||
|
@if (ViewBag.Message != null)
|
||||||
|
{
|
||||||
|
<p class="alert alert-warning">@ViewBag.Message</p>
|
||||||
|
}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@if (@Model != null && @Model.Vacancies != null)
|
@if (Model != null)
|
||||||
{
|
{
|
||||||
<h2>Результаты поиска:</h2>
|
<h2>Результаты поиска:</h2>
|
||||||
@if (Model.Vacancies.Count > 0)
|
@if (Model.Any(v => v != null))
|
||||||
{
|
{
|
||||||
<ul>
|
<table class="table table-striped">
|
||||||
@foreach (var vacancy in Model.Vacancies)
|
<thead>
|
||||||
{
|
<tr>
|
||||||
<li>@vacancy.JobTitle</li>
|
<th>Название вакансии</th>
|
||||||
}
|
<th>Тип работы</th>
|
||||||
</ul>
|
<th>Зарплата</th>
|
||||||
|
<th>Тэги</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach (var vacancy in Model.Where(v => v != null))
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>@vacancy.JobTitle</td>
|
||||||
|
<td>@vacancy.JobType</td>
|
||||||
|
<td>@vacancy.Salary</td>
|
||||||
|
<td>@vacancy.Tags</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<p>Вакансий не найдено.</p>
|
<p>Вакансий не найдено.</p>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<p>Произошла ошибка при получении данных.</p>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
*@
|
<script>
|
||||||
|
document.querySelector('form').addEventListener('submit', function (event) {
|
||||||
|
const tagsInput = document.getElementById('tags');
|
||||||
|
if (tagsInput.value.trim() === "") {
|
||||||
|
alert("Пожалуйста, введите поисковый запрос.");
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
@ -4,20 +4,25 @@
|
|||||||
|
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Информация о вакансии";
|
ViewData["Title"] = "Информация о вакансии";
|
||||||
|
var companyName = APIClient.Company?.Name ?? "Компания не определена";
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="container mt-5">
|
<div class="container mt-5">
|
||||||
<div class="card">
|
<div class="d-flex justify-content-between mb-3">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h2>@Model.JobTitle</h2>
|
<h2>@Model.JobTitle</h2>
|
||||||
<input type="hidden" name="id" value="@Model?.Id" />
|
<input type="hidden" name="id" value="@Model?.Id" />
|
||||||
</div>
|
</div>
|
||||||
|
<a asp-action="CompanyProfile" asp-controller="Company" class="btn btn-secondary">Назад</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<dl class="row">
|
<dl class="row">
|
||||||
<dt class="col-sm-4">Компания:</dt>
|
<dt class="col-sm-4">Компания:</dt>
|
||||||
<dd class="col-sm-8">@Model.CompanyId</dd>
|
<dd class="col-sm-8">@companyName</dd>
|
||||||
|
|
||||||
<dt class="col-sm-4">Тип занятости:</dt>
|
<dt class="col-sm-4">Тип занятости:</dt>
|
||||||
<dd class="col-sm-8">@Model.JobType</dd>
|
<dd class="col-sm-8">@Model.JobType</dd>
|
||||||
@ -51,4 +56,3 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
using CandidateReviewContracts.ViewModels;
|
using CandidateReviewDataModels.Models;
|
||||||
using CandidateReviewDataModels.Models;
|
|
||||||
|
|
||||||
namespace CandidateReviewContracts.BindingModels
|
namespace CandidateReviewContracts.BindingModels
|
||||||
{
|
{
|
||||||
public class CompanyBindingModel : ICompanyModel
|
public class CompanyBindingModel : ICompanyModel
|
||||||
{
|
{
|
||||||
public string Name { get; set; } = string.Empty;
|
public string Name { get; set; } = string.Empty;
|
||||||
|
|
||||||
public string? LogoFilePath { get; set; }
|
public string? LogoFilePath { get; set; }
|
||||||
|
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
@ -17,7 +17,5 @@ namespace CandidateReviewContracts.BindingModels
|
|||||||
public string? Contacts { get; set; }
|
public string? Contacts { get; set; }
|
||||||
|
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
public List<IVacancyModel> Vacancies { get; set; } = new();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
namespace CandidateReviewContracts.SearchModels
|
using CandidateReviewDataModels.Enums;
|
||||||
|
|
||||||
|
namespace CandidateReviewContracts.SearchModels
|
||||||
{
|
{
|
||||||
public class UserSearchModel
|
public class UserSearchModel
|
||||||
{
|
{
|
||||||
@ -10,6 +12,8 @@
|
|||||||
|
|
||||||
public string? Email { get; set; }
|
public string? Email { get; set; }
|
||||||
|
|
||||||
|
public RoleEnum? Role { get; set; }
|
||||||
|
|
||||||
public string? Password { get; set; }
|
public string? Password { get; set; }
|
||||||
|
|
||||||
public int? Id { get; set; }
|
public int? Id { get; set; }
|
||||||
|
@ -18,5 +18,7 @@ namespace CandidateReviewContracts.ViewModels
|
|||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
public List<VacancyViewModel> Vacancies { get; set; } = new();
|
public List<VacancyViewModel> Vacancies { get; set; } = new();
|
||||||
|
|
||||||
|
public List<UserViewModel> Employees { get; set; } = new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
{
|
{
|
||||||
Неизвестен = -1,
|
Неизвестен = -1,
|
||||||
Сотрудник = 0,
|
Сотрудник = 0,
|
||||||
Пользователь = 1
|
Пользователь = 1,
|
||||||
|
Администратор = 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ using CandidateReviewContracts.SearchModels;
|
|||||||
using CandidateReviewContracts.StoragesContracts;
|
using CandidateReviewContracts.StoragesContracts;
|
||||||
using CandidateReviewContracts.ViewModels;
|
using CandidateReviewContracts.ViewModels;
|
||||||
using CandidateReviewDatabaseImplement.Models;
|
using CandidateReviewDatabaseImplement.Models;
|
||||||
|
using CandidateReviewDataModels.Enums;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace CandidateReviewDatabaseImplement.Implements
|
namespace CandidateReviewDatabaseImplement.Implements
|
||||||
@ -39,11 +40,23 @@ namespace CandidateReviewDatabaseImplement.Implements
|
|||||||
|
|
||||||
public List<UserViewModel> GetFilteredList(UserSearchModel model)
|
public List<UserViewModel> GetFilteredList(UserSearchModel model)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(model.Email) || string.IsNullOrEmpty(model.Password))
|
using var context = new CandidateReviewDatabase();
|
||||||
|
|
||||||
|
if (model.CompanyId.HasValue && model.Role != null)
|
||||||
|
{
|
||||||
|
return context.Users
|
||||||
|
.Include(x => x.Company)
|
||||||
|
.Include(x => x.Resumes)
|
||||||
|
.Include(x => x.Assessments)
|
||||||
|
.Where(x => x.CompanyId.Equals(model.CompanyId) && x.Role.Equals(model.Role))
|
||||||
|
.Select(x => x.GetViewModel)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
else if (string.IsNullOrEmpty(model.Email) || string.IsNullOrEmpty(model.Password))
|
||||||
{
|
{
|
||||||
return new();
|
return new();
|
||||||
}
|
}
|
||||||
using var context = new CandidateReviewDatabase();
|
|
||||||
return context.Users
|
return context.Users
|
||||||
.Include(x => x.Company)
|
.Include(x => x.Company)
|
||||||
.Include(x => x.Resumes)
|
.Include(x => x.Resumes)
|
||||||
|
@ -78,13 +78,14 @@ namespace CandidateReviewDatabaseImplement.Implements
|
|||||||
}
|
}
|
||||||
if (!string.IsNullOrEmpty(model.Tags))
|
if (!string.IsNullOrEmpty(model.Tags))
|
||||||
{
|
{
|
||||||
|
var tags = model.Tags.Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(t => t.ToLowerInvariant()).ToArray();
|
||||||
return context.Vacancies
|
return context.Vacancies
|
||||||
.Include(x => x.Company)
|
.Include(x => x.Company)
|
||||||
.Include(x => x.Resumes)
|
.Include(x => x.Resumes)
|
||||||
.Where(x => x.Tags.Contains(model.Tags))
|
.Where(x => tags.Any(tag => x.Tags.Contains(tag)))
|
||||||
.ToList()
|
.ToList()
|
||||||
.Select(x => x.GetViewModel)
|
.Select(x => x.GetViewModel)
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
return context.Vacancies
|
return context.Vacancies
|
||||||
.Include(x => x.Company)
|
.Include(x => x.Company)
|
||||||
|
@ -70,7 +70,7 @@ namespace CandidateReviewDatabaseImplement.Models
|
|||||||
Salary = model.Salary,
|
Salary = model.Salary,
|
||||||
Description = model.Description,
|
Description = model.Description,
|
||||||
Status = model.Status,
|
Status = model.Status,
|
||||||
CreatedAt = model.CreatedAt,
|
CreatedAt = DateTime.Now.ToUniversalTime(),
|
||||||
Tags = model.Tags
|
Tags = model.Tags
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -88,7 +88,6 @@ namespace CandidateReviewDatabaseImplement.Models
|
|||||||
Salary = model.Salary;
|
Salary = model.Salary;
|
||||||
Description = model.Description;
|
Description = model.Description;
|
||||||
Status = model.Status;
|
Status = model.Status;
|
||||||
CreatedAt = model.CreatedAt;
|
|
||||||
Tags = model.Tags;
|
Tags = model.Tags;
|
||||||
}
|
}
|
||||||
public VacancyViewModel GetViewModel => new()
|
public VacancyViewModel GetViewModel => new()
|
||||||
|
@ -81,17 +81,5 @@ namespace CandidateReviewRestApi.Controllers
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*private CompanyBindingModel GetCompanyWithVacancies(CompanyBindingModel model)
|
|
||||||
{
|
|
||||||
var vacancies = _vacancyLogic.ReadList(new VacancySearchModel { CompanyId = model.Id });
|
|
||||||
if (vacancies != null)
|
|
||||||
{
|
|
||||||
model.Vacancies = vacancies.Where(v => v.CompanyId == model.Id)
|
|
||||||
.Select(v => (IVacancyModel)v)
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
return model;
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,27 @@ namespace CandidateReviewRestApi.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public List<VacancyViewModel>? Search(string? tags)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(tags))
|
||||||
|
{
|
||||||
|
return _logic.ReadList(new VacancySearchModel
|
||||||
|
{
|
||||||
|
Tags = tags
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new List<VacancyViewModel>();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Ошибка получения вакансий");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public void Create(VacancyBindingModel model)
|
public void Create(VacancyBindingModel model)
|
||||||
{
|
{
|
||||||
@ -63,7 +84,7 @@ namespace CandidateReviewRestApi.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete]
|
[HttpPost]
|
||||||
public void Delete(VacancyBindingModel model)
|
public void Delete(VacancyBindingModel model)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
Loading…
Reference in New Issue
Block a user