From be517e47e4e02dc1b8656bced17f685f32cbe67c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A2=D0=B0=D1=82=D1=8C=D1=8F=D0=BD=D0=B0=20=D0=90=D1=80?= =?UTF-8?q?=D1=82=D0=B0=D0=BC=D0=BE=D0=BD=D0=BE=D0=B2=D0=B0?= Date: Sat, 23 Nov 2024 21:39:18 +0400 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=BE=D0=B8=D1=81=D0=BA=20=D0=B2=D0=B0?= =?UTF-8?q?=D0=BA=D0=B0=D0=BD=D1=81=D0=B8=D0=B9,=20=D0=B2=D1=8B=D0=B2?= =?UTF-8?q?=D0=BE=D0=B4=20=D1=81=D0=BE=D1=82=D1=80=D1=83=D0=B4=D0=BD=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=B2=20=D0=B8=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D0=BE=D1=82=D1=80=D1=83?= =?UTF-8?q?=D0=B4=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2,=20=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D1=8F=20=D1=80=D0=BE=D0=BB=D1=8C=20=D0=90=D0=B4=D0=BC?= =?UTF-8?q?=D0=B8=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=82=D0=BE=D1=80,?= =?UTF-8?q?=20=D0=BC=D0=B5=D0=BB=D0=BA=D0=B8=D0=B5=20=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BusinessLogic/CompanyLogic.cs | 28 ++++- .../Controllers/HomeController.cs | 16 +-- .../Controllers/UserController.cs | 76 +++++++++--- .../Controllers/VacancyController.cs | 45 +++++-- .../Views/Company/CompanyProfile.cshtml | 93 +++++++++++++-- .../Views/Shared/_Layout.cshtml | 5 +- .../Views/User/UserProfile.cshtml | 5 +- .../Views/User/UserProfileEdit.cshtml | 112 ++++++++++++------ .../Views/Vacancy/EditVacancy.cshtml | 32 ++--- .../Views/Vacancy/SearchVacancies.cshtml | 62 +++++++--- .../Views/Vacancy/VacancyDetails.cshtml | 16 ++- .../BindingModels/CompanyBindingModel.cs | 6 +- .../SearchModels/UserSearchModel.cs | 6 +- .../ViewModels/CompanyViewModel.cs | 2 + CandidateReviewDataModels/Enums/RoleEnum.cs | 3 +- .../Implements/UserStorage.cs | 17 ++- .../Implements/VacancyStorage.cs | 13 +- .../Models/Vacancy.cs | 3 +- .../Controllers/CompanyController.cs | 12 -- .../Controllers/VacancyController.cs | 23 +++- 20 files changed, 415 insertions(+), 160 deletions(-) diff --git a/CandidateReviewBusinessLogic/BusinessLogic/CompanyLogic.cs b/CandidateReviewBusinessLogic/BusinessLogic/CompanyLogic.cs index ba782e5..9038cf2 100644 --- a/CandidateReviewBusinessLogic/BusinessLogic/CompanyLogic.cs +++ b/CandidateReviewBusinessLogic/BusinessLogic/CompanyLogic.cs @@ -13,11 +13,13 @@ namespace CandidateReviewBusinessLogic.BusinessLogic private readonly ILogger _logger; private readonly ICompanyStorage _сompanyStorage; private readonly IVacancyStorage _vacancyStorage; - public CompanyLogic(ILogger logger, ICompanyStorage сompanyStorage, IVacancyStorage vacancyStorage) + private readonly IUserStorage _userStorage; + public CompanyLogic(ILogger logger, ICompanyStorage сompanyStorage, IVacancyStorage vacancyStorage, IUserStorage userStorage) { _logger = logger; _сompanyStorage = сompanyStorage; _vacancyStorage = vacancyStorage; + _userStorage = userStorage; } public int Create(CompanyBindingModel model) { @@ -85,7 +87,24 @@ namespace CandidateReviewBusinessLogic.BusinessLogic Status = v.Status, CreatedAt = v.CreatedAt, Tags = v.Tags - }).ToList() ?? new List(); + }).ToList() ?? new List(); + + 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(); var companyViewModel = new CompanyViewModel { @@ -96,15 +115,14 @@ namespace CandidateReviewBusinessLogic.BusinessLogic Address = company.Address, Website = company.Website, LogoFilePath = company.LogoFilePath, - Vacancies = vacancyViewModels + Vacancies = vacancyViewModels, + Employees = employeeViewModels }; _logger.LogInformation("ReadElement: Company found. Id: {Id}", company.Id); return companyViewModel; } - - public List? ReadList(CompanySearchModel? model) { var list = model == null ? _сompanyStorage.GetFullList() : _сompanyStorage.GetFilteredList(model); diff --git a/CandidateReviewClientApp/Controllers/HomeController.cs b/CandidateReviewClientApp/Controllers/HomeController.cs index cd43eb1..9c4c68d 100644 --- a/CandidateReviewClientApp/Controllers/HomeController.cs +++ b/CandidateReviewClientApp/Controllers/HomeController.cs @@ -22,11 +22,6 @@ namespace CandidateReviewUserApp.Controllers return View(); } - public IActionResult Privacy() - { - return View(); - } - [HttpGet] public IActionResult Enter() { @@ -41,14 +36,15 @@ namespace CandidateReviewUserApp.Controllers throw new Exception(" "); } APIClient.User = APIClient.GetRequest($"api/user/login?login={login}&password={password}"); - if (APIClient.User.CompanyId != null) - { - APIClient.Company = APIClient.GetRequest($"api/company/profile?id={APIClient.User?.CompanyId}"); - } if (APIClient.User == null) { throw new Exception(" /"); } + if (APIClient.User?.CompanyId != null) + { + APIClient.Company = APIClient.GetRequest($"api/company/profile?id={APIClient.User?.CompanyId}"); + } + Response.Redirect("/Home/Index"); } @@ -70,7 +66,7 @@ namespace CandidateReviewUserApp.Controllers if (login.Equals("tania.art03@gmail.com", StringComparison.OrdinalIgnoreCase)) { - role = RoleEnum.; + role = RoleEnum.; } else if (login.Equals("t.artamonova73@icloud.com", StringComparison.OrdinalIgnoreCase)) { diff --git a/CandidateReviewClientApp/Controllers/UserController.cs b/CandidateReviewClientApp/Controllers/UserController.cs index 37bde7e..9f5cdff 100644 --- a/CandidateReviewClientApp/Controllers/UserController.cs +++ b/CandidateReviewClientApp/Controllers/UserController.cs @@ -18,7 +18,7 @@ namespace CandidateReviewClientApp.Controllers [HttpGet] public IActionResult UserProfile(int? id) { - var userId = id ?? APIClient.User.Id; + var userId = id ?? APIClient.User?.Id; var model = APIClient.GetRequest($"api/user/profile?id={userId}"); @@ -31,41 +31,79 @@ namespace CandidateReviewClientApp.Controllers } [HttpGet] - public IActionResult UserProfileEdit() + public IActionResult UserProfileEdit(int? id) { if (APIClient.User == null) { return Redirect("/Home/Enter"); } - var model = APIClient.GetRequest($"api/user/profile?id={APIClient.User.Id}"); - if (model == null) + + if (APIClient.Company == null) { - return RedirectToAction("/Home/Index"); + return Redirect("/Home/Index"); } - return View(model); + + if (!id.HasValue) + { + return View(new UserViewModel()); + } + else if (id.HasValue) + { + var employee = APIClient.GetRequest($"api/user/profile?id={id}"); + return View(employee); + } + else + { + var model = APIClient.GetRequest($"api/user/profile?id={APIClient.User.Id}"); + return View(model); + } } [HttpPost] public void UserProfileEdit(UserBindingModel model) { - APIClient.PostRequest("api/user/update", new UserBindingModel + if (model.Id != 0) { - Id = model.Id, - Surname = model.Surname, - Name = model.Name, - LastName = model.LastName, - CompanyId = model.CompanyId, - Email = model.Email, - Password = model.Password, - EmailConfirmed = model.EmailConfirmed, - Role = model.Role, - AvatarFilePath = model.AvatarFilePath, - PhoneNumber = model.PhoneNumber - }); + APIClient.PostRequest("api/user/update", model); + } + else + { + APIClient.PostRequest("api/user/register", model); + if (APIClient.Company != null) + { + APIClient.Company?.Employees.Add(new UserViewModel + { + Id = model.Id, + 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}"); } + public IActionResult DeleteEmployee(int id) + { + APIClient.PostRequest("api/user/delete", new UserBindingModel + { + Id = id + }); + APIClient.Company = APIClient.GetRequest($"api/company/profile?id={APIClient.User?.CompanyId}"); + + return Redirect($"~/Company/CompanyProfile"); + } + [HttpGet] public void Logout() { diff --git a/CandidateReviewClientApp/Controllers/VacancyController.cs b/CandidateReviewClientApp/Controllers/VacancyController.cs index 3f566eb..5d16d07 100644 --- a/CandidateReviewClientApp/Controllers/VacancyController.cs +++ b/CandidateReviewClientApp/Controllers/VacancyController.cs @@ -1,6 +1,7 @@ using CandidateReviewContracts.BindingModels; using CandidateReviewContracts.ViewModels; using Microsoft.AspNetCore.Mvc; +using System.Reflection; namespace CandidateReviewClientApp.Controllers { @@ -13,7 +14,7 @@ namespace CandidateReviewClientApp.Controllers _logger = logger; } [HttpGet] - public IActionResult Vacancy(int? id) + public IActionResult VacancyDetails(int? id) { if (APIClient.User == null) { @@ -42,6 +43,7 @@ namespace CandidateReviewClientApp.Controllers return View(model); } + [HttpPost] [HttpPost] public void EditVacancy(VacancyBindingModel model) { @@ -49,6 +51,12 @@ namespace CandidateReviewClientApp.Controllers { throw new Exception("Доступно только авторизованным пользователям"); } + + if (!string.IsNullOrEmpty(model.Tags)) + { + model.Tags = model.Tags.ToLowerInvariant(); + } + if (model.Id != 0) { APIClient.PostRequest("api/vacancy/update", model); @@ -58,11 +66,16 @@ namespace CandidateReviewClientApp.Controllers APIClient.PostRequest("api/vacancy/create", model); if (APIClient.Company != null) { + if (!string.IsNullOrEmpty(model.Tags)) + { + model.Tags = model.Tags.ToLowerInvariant(); + } + APIClient.Company?.Vacancies.Add(new VacancyViewModel { Id = model.Id, CompanyId = model.CompanyId, - CreatedAt = model.CreatedAt, + CreatedAt = DateTime.Now.ToUniversalTime(), Description = model.Description, JobTitle = model.JobTitle, JobType = model.JobType, @@ -72,21 +85,39 @@ namespace CandidateReviewClientApp.Controllers Status = model.Status, Tags = model.Tags }); - } + } } Response.Redirect($"/Company/CompanyProfile/{model.CompanyId}"); } - [HttpPost] - public void Delete(int id) + public IActionResult Delete(int id) + { + if (APIClient.Company == null) + { + throw new Exception("Компания не определена"); + } + + APIClient.PostRequest($"api/vacancy/delete", new VacancyBindingModel { Id = id }); + APIClient.Company = APIClient.GetRequest($"api/company/profile?id={APIClient.User?.CompanyId}"); + + return Redirect("~/Company/CompanyProfile"); + } + + public IActionResult SearchVacancies(string? tags) { if (APIClient.User == null) { throw new Exception("Доступно только авторизованным пользователям"); } - APIClient.PostRequest($"api/vacancy/delete", new VacancyBindingModel { Id = id }); - Response.Redirect("/Home/Index"); + if (string.IsNullOrEmpty(tags)) + { + ViewBag.Message = "Пожалуйста, введите поисковый запрос."; + return View(new List()); + } + + var results = APIClient.GetRequest>($"api/vacancy/search?tags={tags}"); + return View(results); } } } diff --git a/CandidateReviewClientApp/Views/Company/CompanyProfile.cshtml b/CandidateReviewClientApp/Views/Company/CompanyProfile.cshtml index 5c07672..c31516c 100644 --- a/CandidateReviewClientApp/Views/Company/CompanyProfile.cshtml +++ b/CandidateReviewClientApp/Views/Company/CompanyProfile.cshtml @@ -3,19 +3,18 @@ @{ 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; }
- Логотип компании + Логотип компании
@Model.Name

@(Model.Description == null ? "Описание отсутствует" : Model.Description)

- @(Model.Website ?? "Веб-сайт отсутствует") + @(Model.Website != null ? "Официальный сайт" : "Веб-сайт отсутствует")
@@ -48,30 +47,36 @@ }
- @if (@Model.Vacancies != null && @Model.Vacancies.Any()) + @if (Model.Vacancies != null && Model.Vacancies.Any()) { - + - @foreach (var vacancy in @Model.Vacancies) + @foreach (var vacancy in Model.Vacancies) { - + @@ -85,6 +90,70 @@ } - +
+
+
+

Сотрудники компании

+ @if (userRole) + { + Добавить сотрудника + } +
+
+ @if (Model.Employees != null && Model.Employees.Any()) + { +
Название Тип занятостиЗарплатаСтатус Действия
@vacancy.JobTitle @vacancy.JobType@vacancy.Salary@vacancy.Status - Просмотр + + + @if (userRole) { - Редактировать - Удалить + + + + + + }
+ + + + + + + + + + @foreach (var employee in Model.Employees) + { + + + + + + + } + +
ФамилияИмяЭл. почтаДействия
@employee.Surname@employee.Name@employee.Email + + + + @if (userRole) + { + + + + + + + } +
+ @* *@ + } + else + { +

Сотрудников нет.

+ } +
+
diff --git a/CandidateReviewClientApp/Views/Shared/_Layout.cshtml b/CandidateReviewClientApp/Views/Shared/_Layout.cshtml index 2d39dc1..9d6217e 100644 --- a/CandidateReviewClientApp/Views/Shared/_Layout.cshtml +++ b/CandidateReviewClientApp/Views/Shared/_Layout.cshtml @@ -7,6 +7,7 @@ @ViewData["Title"] - CandidateReviewClientApp + @@ -21,10 +22,10 @@