Не работает

This commit is contained in:
2025-05-13 23:06:50 +04:00
parent 0d15923b94
commit 87708ee1e6
213 changed files with 92085 additions and 2 deletions

View File

@@ -6,4 +6,12 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ComputerStoreContracts\ComputerStoreContracts.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,163 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.BusinessLogicContracts;
using ComputerStoreContracts.StoragesContracts;
using ComputerStoreContracts.ViewModels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreBusinessLogic.Implementations;
public class AssemblyBusinessLogicContract : IAssemblyBusinessLogicContract
{
private readonly ILogger<AssemblyBusinessLogicContract> _logger;
private readonly IAssemblyStorageContract _assemblyStorage;
public AssemblyBusinessLogicContract(ILogger<AssemblyBusinessLogicContract> logger, IAssemblyStorageContract assemblyStorage)
{
_logger = logger;
_assemblyStorage = assemblyStorage;
}
public List<AssemblyViewModel>? ReadList(AssemblyBindingModel? model)
{
_logger.LogInformation("ReadList for assembly. UserID: {UserID}", model?.UserID);
List<AssemblyViewModel> list;
try
{
list = model == null ? _assemblyStorage.GetFullList() : _assemblyStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("GetFullList/GetFilteredList returned null. Returning empty list instead.");
list = new List<AssemblyViewModel>();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving assembly list from storage.");
return new List<AssemblyViewModel>();
}
_logger.LogInformation("ReadList. Count: {Count}", list.Count);
return list;
}
public AssemblyViewModel? ReadElement(AssemblyBindingModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement for assembly: {Id}, UserID: {UserID}", model.Id, model.UserID);
try
{
var element = _assemblyStorage.GetElement(model);
_logger.LogInformation("ReadElement found: {Id}", element.Id);
return element;
}
catch (Exception ex)
{
_logger.LogWarning(ex, "ReadElement: Assembly not found for ID: {Id}", model.Id);
return null;
}
}
public void Create(AssemblyBindingModel model)
{
CheckModel(model);
try
{
_assemblyStorage.Insert(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Insert operation failed for assembly: {Name}", model.Name);
throw new Exception("Insert operation failed", ex);
}
}
public void Update(AssemblyBindingModel model)
{
CheckModel(model);
try
{
_assemblyStorage.Update(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Update operation failed for assembly: {Id}", model.Id);
throw new Exception("Update operation failed", ex);
}
}
public void Delete(AssemblyBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Assembly: {Id}", model.Id);
try
{
_assemblyStorage.Delete(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Delete operation failed for assembly: {Id}", model.Id);
throw new Exception("Delete operation failed", ex);
}
}
private void CheckModel(AssemblyBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.Name))
{
throw new ArgumentNullException("Название сборки обязательно", nameof(model.Name));
}
if (model.Name.Length > 100)
{
throw new ArgumentException("Название сборки не должно превышать 100 символов", nameof(model.Name));
}
if (string.IsNullOrEmpty(model.Description))
{
throw new ArgumentNullException("Описание сборки обязательно", nameof(model.Description));
}
if (model.Description.Length > 500)
{
throw new ArgumentException("Описание сборки не должно превышать 500 символов", nameof(model.Description));
}
if (model.UserID <= 0)
{
throw new ArgumentException("ID пользователя должен быть больше 0", nameof(model.UserID));
}
if (model.OrderRequestId.HasValue && model.OrderRequestId <= 0)
{
throw new ArgumentException("ID заявки должен быть больше 0", nameof(model.OrderRequestId));
}
_logger.LogInformation("Assembly validation passed for: {Name}", model.Name);
var existingAssembly = _assemblyStorage.GetElement(new AssemblyBindingModel { Name = model.Name });
if (existingAssembly != null && existingAssembly.Id != (model.Id ?? 0))
{
throw new InvalidOperationException($"Сборка с названием {model.Name} уже существует");
}
}
}

View File

@@ -0,0 +1,186 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.BusinessLogicContracts;
using ComputerStoreContracts.StoragesContracts;
using ComputerStoreContracts.ViewModels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreBusinessLogic.Implementations;
public class ComponentBusinessLogicContract : IComponentBusinessLogicContract
{
private readonly ILogger<ComponentBusinessLogicContract> _logger;
private readonly IComponentStorageContract _componentStorage;
public ComponentBusinessLogicContract(ILogger<ComponentBusinessLogicContract> logger, IComponentStorageContract componentStorage)
{
_logger = logger;
_componentStorage = componentStorage;
}
public List<ComponentViewModel>? ReadList(ComponentBindingModel? model)
{
_logger.LogInformation("ReadList for component. UserID: {UserID}", model?.UserID);
List<ComponentViewModel> list;
try
{
list = model == null ? _componentStorage.GetFullList() : _componentStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("GetFullList/GetFilteredList returned null. Returning empty list instead.");
list = new List<ComponentViewModel>();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving component list from storage.");
return new List<ComponentViewModel>();
}
_logger.LogInformation("ReadList. Count: {Count}", list.Count);
return list;
}
public ComponentViewModel? ReadElement(ComponentBindingModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement for component: {Id}, UserID: {UserID}", model.Id, model.UserID);
try
{
var element = _componentStorage.GetElement(model);
_logger.LogInformation("ReadElement found: {Id}", element.Id);
return element;
}
catch (Exception ex)
{
_logger.LogWarning(ex, "ReadElement: Component not found for ID: {Id}", model.Id);
return null;
}
}
public void Create(ComponentBindingModel model)
{
CheckModel(model);
try
{
_componentStorage.Insert(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Insert operation failed for component: {ComponentName}", model.ComponentName);
throw new Exception("Insert operation failed", ex);
}
}
public void Update(ComponentBindingModel model)
{
CheckModel(model);
try
{
_componentStorage.Update(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Update operation failed for component: {Id}", model.Id);
throw new Exception("Update operation failed", ex);
}
}
public void Delete(ComponentBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Component: {Id}", model.Id);
try
{
_componentStorage.Delete(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Delete operation failed for component: {Id}", model.Id);
throw new Exception("Delete operation failed", ex);
}
}
public List<ComponentRequestAssemblyReportViewModel>? GetComponentsReport(DateTime startDate, DateTime endDate, int userId)
{
_logger.LogInformation("Generating components report for user: {UserID}, Period: {StartDate} - {EndDate}", userId, startDate, endDate);
try
{
var report = _componentStorage.GetComponentsReport(startDate, endDate, userId);
if (report == null)
{
_logger.LogWarning("GetComponentsReport returned null. Returning empty list instead.");
return new List<ComponentRequestAssemblyReportViewModel>();
}
_logger.LogInformation("Components report generated. Count: {Count}", report.Count);
return report;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error generating components report for user: {UserID}", userId);
return new List<ComponentRequestAssemblyReportViewModel>();
}
}
private void CheckModel(ComponentBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.ComponentName))
{
throw new ArgumentNullException("Название комплектующего обязательно", nameof(model.ComponentName));
}
if (model.ComponentName.Length > 100)
{
throw new ArgumentException("Название комплектующего не должно превышать 100 символов", nameof(model.ComponentName));
}
if (string.IsNullOrEmpty(model.Manufacturer))
{
throw new ArgumentNullException("Производитель обязателен", nameof(model.Manufacturer));
}
if (model.Manufacturer.Length > 100)
{
throw new ArgumentException("Производитель не должен превышать 100 символов", nameof(model.Manufacturer));
}
if (model.Price <= 0)
{
throw new ArgumentException("Цена должна быть больше 0", nameof(model.Price));
}
if (model.UserID <= 0)
{
throw new ArgumentException("ID пользователя должен быть больше 0", nameof(model.UserID));
}
_logger.LogInformation("Component validation passed for: {ComponentName}", model.ComponentName);
var existingComponent = _componentStorage.GetElement(new ComponentBindingModel { ComponentName = model.ComponentName });
if (existingComponent != null && existingComponent.Id != (model.Id ?? 0))
{
throw new InvalidOperationException($"Комплектующее с названием {model.ComponentName} уже существует");
}
}
}

View File

@@ -0,0 +1,163 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.BusinessLogicContracts;
using ComputerStoreContracts.StoragesContracts;
using ComputerStoreContracts.ViewModels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreBusinessLogic.Implementations;
public class ProductBusinessLogicContract : IProductBusinessLogicContract
{
private readonly ILogger<ProductBusinessLogicContract> _logger;
private readonly IProductStorageContract _productStorage;
public ProductBusinessLogicContract(ILogger<ProductBusinessLogicContract> logger, IProductStorageContract productStorage)
{
_logger = logger;
_productStorage = productStorage;
}
public List<ProductViewModel>? ReadList(ProductBindingModel? model)
{
_logger.LogInformation("ReadList for product. UserID: {UserID}", model?.UserID);
List<ProductViewModel> list;
try
{
list = model == null ? _productStorage.GetFullList() : _productStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("GetFullList/GetFilteredList returned null. Returning empty list instead.");
list = new List<ProductViewModel>();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving product list from storage.");
return new List<ProductViewModel>();
}
_logger.LogInformation("ReadList. Count: {Count}", list.Count);
return list;
}
public ProductViewModel? ReadElement(ProductBindingModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement for product: {Id}, UserID: {UserID}", model.Id, model.UserID);
try
{
var element = _productStorage.GetElement(model);
_logger.LogInformation("ReadElement found: {Id}", element.Id);
return element;
}
catch (Exception ex)
{
_logger.LogWarning(ex, "ReadElement: Product not found for ID: {Id}", model.Id);
return null;
}
}
public void Create(ProductBindingModel model)
{
CheckModel(model);
try
{
_productStorage.Insert(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Insert operation failed for product: {Name}", model.Name);
throw new Exception("Insert operation failed", ex);
}
}
public void Update(ProductBindingModel model)
{
CheckModel(model);
try
{
_productStorage.Update(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Update operation failed for product: {Id}", model.Id);
throw new Exception("Update operation failed", ex);
}
}
public void Delete(ProductBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Product: {Id}", model.Id);
try
{
_productStorage.Delete(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Delete operation failed for product: {Id}", model.Id);
throw new Exception("Delete operation failed", ex);
}
}
private void CheckModel(ProductBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.Name))
{
throw new ArgumentNullException("Название товара обязательно", nameof(model.Name));
}
if (model.Name.Length > 100)
{
throw new ArgumentException("Название товара не должно превышать 100 символов", nameof(model.Name));
}
if (string.IsNullOrEmpty(model.Category))
{
throw new ArgumentNullException("Категория товара обязательна", nameof(model.Category));
}
if (model.Category.Length > 100)
{
throw new ArgumentException("Категория товара не должна превышать 100 символов", nameof(model.Category));
}
if (model.Price <= 0)
{
throw new ArgumentException("Цена должна быть больше 0", nameof(model.Price));
}
if (model.UserID <= 0)
{
throw new ArgumentException("ID пользователя должен быть больше 0", nameof(model.UserID));
}
_logger.LogInformation("Product validation passed for: {Name}", model.Name);
var existingProduct = _productStorage.GetElement(new ProductBindingModel { Name = model.Name });
if (existingProduct != null && existingProduct.Id != (model.Id ?? 0))
{
throw new InvalidOperationException($"Товар с названием {model.Name} уже существует");
}
}
}

View File

@@ -0,0 +1,142 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.BusinessLogicContracts;
using ComputerStoreContracts.StoragesContracts;
using ComputerStoreContracts.ViewModels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreBusinessLogic.Implementations;
public class RequestBusinessLogicContract : IRequestBusinessLogicContract
{
private readonly ILogger<RequestBusinessLogicContract> _logger;
private readonly IRequestStorageContract _requestStorage;
public RequestBusinessLogicContract(ILogger<RequestBusinessLogicContract> logger, IRequestStorageContract requestStorage)
{
_logger = logger;
_requestStorage = requestStorage;
}
public List<RequestViewModel>? ReadList(RequestBindingModel? model)
{
_logger.LogInformation("ReadList for request. UserID: {UserID}", model?.UserID);
List<RequestViewModel> list;
try
{
list = model == null ? _requestStorage.GetFullList() : _requestStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("GetFullList/GetFilteredList returned null. Returning empty list instead.");
list = new List<RequestViewModel>();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving request list from storage.");
return new List<RequestViewModel>();
}
_logger.LogInformation("ReadList. Count: {Count}", list.Count);
return list;
}
public RequestViewModel? ReadElement(RequestBindingModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement for request: {Id}, UserID: {UserID}", model.Id, model.UserID);
try
{
var element = _requestStorage.GetElement(model);
_logger.LogInformation("ReadElement found: {Id}", element.Id);
return element;
}
catch (Exception ex)
{
_logger.LogWarning(ex, "ReadElement: Request not found for ID: {Id}", model.Id);
return null;
}
}
public void Create(RequestBindingModel model)
{
CheckModel(model);
try
{
_requestStorage.Insert(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Insert operation failed for request: {Id}", model.Id);
throw new Exception("Insert operation failed", ex);
}
}
public void Update(RequestBindingModel model)
{
CheckModel(model);
try
{
_requestStorage.Update(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Update operation failed for request: {Id}", model.Id);
throw new Exception("Update operation failed", ex);
}
}
public void Delete(RequestBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Request: {Id}", model.Id);
try
{
_requestStorage.Delete(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Delete operation failed for request: {Id}", model.Id);
throw new Exception("Delete operation failed", ex);
}
}
private void CheckModel(RequestBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (model.DateRequest == default)
{
throw new ArgumentNullException("Дата заявки обязательна", nameof(model.DateRequest));
}
if (model.UserID <= 0)
{
throw new ArgumentException("ID пользователя должен быть больше 0", nameof(model.UserID));
}
if (model.AssemblyId.HasValue && model.AssemblyId <= 0)
{
throw new ArgumentException("ID сборки должен быть больше 0", nameof(model.AssemblyId));
}
_logger.LogInformation("Request validation passed for: {Id}", model.Id);
}
}

View File

@@ -0,0 +1,190 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.BusinessLogicContracts;
using ComputerStoreContracts.StoragesContracts;
using ComputerStoreContracts.ViewModels;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreBusinessLogic.Implementations;
public class UserBusinessLogicContract : IUserBusinessLogicContract
{
private readonly ILogger<UserBusinessLogicContract> _logger;
private readonly IUserStorageContract _userStorage;
public UserBusinessLogicContract(ILogger<UserBusinessLogicContract> logger, IUserStorageContract userStorage)
{
_logger = logger;
_userStorage = userStorage;
}
public List<UserViewModel>? ReadList(UserBindingModel? model)
{
_logger.LogInformation("ReadList for user: {Login}", model?.Login);
List<UserViewModel> list;
try
{
list = model == null ? _userStorage.GetFullList() : _userStorage.GetFilteredList(model);
if (list == null)
{
_logger.LogWarning("GetFullList/GetFilteredList returned null. Returning empty list instead.");
list = new List<UserViewModel>();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving user list from storage.");
return new List<UserViewModel>();
}
_logger.LogInformation("ReadList. Count: {Count}", list.Count);
return list;
}
public UserViewModel? ReadElement(UserBindingModel model)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
_logger.LogInformation("ReadElement for user: {Login}", model.Login);
try
{
var element = _userStorage.GetElement(model);
_logger.LogInformation("ReadElement found: {Login}", element.Login);
return element;
}
catch (Exception ex)
{
_logger.LogWarning(ex, "ReadElement: User not found for login: {Login}", model.Login);
return null;
}
}
public void Create(UserBindingModel model)
{
CheckModel(model);
try
{
_userStorage.Insert(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Insert operation failed for user: {Login}", model.Login);
throw new Exception("Insert operation failed", ex);
}
}
public void Update(UserBindingModel model)
{
CheckModel(model);
try
{
_userStorage.Update(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Update operation failed for user: {Login}", model.Login);
throw new Exception("Update operation failed", ex);
}
}
public void Delete(UserBindingModel model)
{
CheckModel(model, false);
_logger.LogInformation("Delete. Login: {Login}", model.Login);
try
{
_userStorage.Delete(model);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Delete operation failed for user: {Login}", model.Login);
throw new Exception("Delete operation failed", ex);
}
}
private void CheckModel(UserBindingModel model, bool withParams = true)
{
if (model == null)
{
throw new ArgumentNullException(nameof(model));
}
if (!withParams)
{
return;
}
if (string.IsNullOrEmpty(model.Login))
{
throw new ArgumentNullException("Логин обязателен", nameof(model.Login));
}
if (model.Login.Length > 50)
{
throw new ArgumentException("Логин не должен превышать 50 символов", nameof(model.Login));
}
if (string.IsNullOrEmpty(model.Password))
{
throw new ArgumentNullException("Пароль обязателен", nameof(model.Password));
}
if (model.Password.Length > 8)
{
throw new ArgumentException("Пароль не должен превышать 8 символов", nameof(model.Password));
}
if (!model.Password.Any(char.IsLetter) || !model.Password.Any(char.IsDigit))
{
throw new ArgumentException("Пароль должен содержать хотя бы одну букву и одну цифру", nameof(model.Password));
}
if (string.IsNullOrEmpty(model.FIO))
{
throw new ArgumentNullException("ФИО обязательно", nameof(model.FIO));
}
if (model.FIO.Length > 100)
{
throw new ArgumentException("ФИО не должно превышать 100 символов", nameof(model.FIO));
}
if (string.IsNullOrEmpty(model.Email))
{
throw new ArgumentNullException("Email обязателен", nameof(model.Email));
}
if (model.Email.Length > 100)
{
throw new ArgumentException("Email не должен превышать 100 символов", nameof(model.Email));
}
if (!new System.ComponentModel.DataAnnotations.EmailAddressAttribute().IsValid(model.Email))
{
throw new ArgumentException("Некорректный формат email", nameof(model.Email));
}
_logger.LogInformation("User validation passed for: {Login}", model.Login);
var existingUserByLogin = _userStorage.GetElement(new UserBindingModel { Login = model.Login });
var existingUserByEmail = _userStorage.GetElement(new UserBindingModel { Email = model.Email });
if (existingUserByLogin != null && existingUserByLogin.ID != (model.Id ?? 0))
{
throw new InvalidOperationException($"Пользователь с логином {model.Login} уже существует");
}
if (existingUserByEmail != null && existingUserByEmail.ID != (model.Id ?? 0))
{
throw new InvalidOperationException($"Пользователь с email {model.Email} уже существует");
}
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.BindingModels;
public class AssemblyBindingModel
{
public int? Id { get; set; }
public string? AssemblyName { get; set; }
public string? Description { get; set; }
public int UserId { get; set; }
public int? OrderRequestId { get; set; }
public List<int>? Components { get; set; }
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.BindingModels;
public class ComponentBindingModel
{
public int? Id { get; set; }
public string? ComponentName { get; set; }
public string? Manufacturer { get; set; }
public double Price { get; set; }
public int UserId { get; set; }
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.BindingModels;
public class ProductBindingModel
{
public int? Id { get; set; }
public string? ProductName { get; set; }
public string? Category { get; set; }
public double Price { get; set; }
public int UserId { get; set; }
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.BindingModels;
public class RequestBindingModel
{
public int? Id { get; set; }
public DateTime DateRequest { get; set; }
public int? AssemblyId { get; set; }
public int UserId { get; set; }
}

View File

@@ -0,0 +1,18 @@
using ComputerStoreContracts.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.BindingModels;
public class UserBindingModel
{
public int? Id { get; set; }
public string? Login { get; set; }
public string? Password { get; set; }
public string? FIO { get; set; }
public string? Email { get; set; }
public UserType UserType { get; set; }
}

View File

@@ -0,0 +1,18 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.BusinessLogicContracts;
public interface IAssemblyBusinessLogicContract
{
List<AssemblyViewModel>? ReadList(AssemblyBindingModel? model);
AssemblyViewModel? ReadElement(AssemblyBindingModel model);
void Create(AssemblyBindingModel model);
void Update(AssemblyBindingModel model);
void Delete(AssemblyBindingModel model);
}

View File

@@ -0,0 +1,19 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.BusinessLogicContracts;
public interface IComponentBusinessLogicContract
{
List<ComponentViewModel>? ReadList(ComponentBindingModel? model);
ComponentViewModel? ReadElement(ComponentBindingModel model);
void Create(ComponentBindingModel model);
void Update(ComponentBindingModel model);
void Delete(ComponentBindingModel model);
List<ComponentRequestAssemblyReportViewModel>? GetComponentsReport(DateTime startDate, DateTime endDate, int userId);
}

View File

@@ -0,0 +1,18 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.BusinessLogicContracts;
public interface IProductBusinessLogicContract
{
List<ProductViewModel>? ReadList(ProductBindingModel? model);
ProductViewModel? ReadElement(ProductBindingModel model);
void Create(ProductBindingModel model);
void Update(ProductBindingModel model);
void Delete(ProductBindingModel model);
}

View File

@@ -0,0 +1,18 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.BusinessLogicContracts;
public interface IRequestBusinessLogicContract
{
List<RequestViewModel>? ReadList(RequestBindingModel? model);
RequestViewModel? ReadElement(RequestBindingModel model);
void Create(RequestBindingModel model);
void Update(RequestBindingModel model);
void Delete(RequestBindingModel model);
}

View File

@@ -0,0 +1,18 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.BusinessLogicContracts;
public interface IUserBusinessLogicContract
{
List<UserViewModel>? ReadList(UserBindingModel? model);
UserViewModel? ReadElement(UserBindingModel model);
void Create(UserBindingModel model);
void Update(UserBindingModel model);
void Delete(UserBindingModel model);
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.Enums;
public enum UserType
{
None = 0,
Executor = 1, // Исполнитель
Guarantor = 2, // Поручитель
}

View File

@@ -0,0 +1,19 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.StoragesContracts;
public interface IAssemblyStorageContract
{
List<AssemblyViewModel> GetFullList();
List<AssemblyViewModel> GetFilteredList(AssemblyBindingModel model);
AssemblyViewModel GetElement(AssemblyBindingModel model);
AssemblyViewModel Insert(AssemblyBindingModel model);
AssemblyViewModel Update(AssemblyBindingModel model);
AssemblyViewModel Delete(AssemblyBindingModel model);
}

View File

@@ -0,0 +1,21 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.StoragesContracts;
public interface IComponentStorageContract
{
List<ComponentViewModel> GetFullList();
List<ComponentViewModel> GetFilteredList(ComponentBindingModel model);
ComponentViewModel GetElement(ComponentBindingModel model);
ComponentViewModel Insert(ComponentBindingModel model);
ComponentViewModel Update(ComponentBindingModel model);
ComponentViewModel Delete(ComponentBindingModel model);
List<ProductViewModel> GetProductsByComponent(int componentId, int userId);
List<ComponentRequestAssemblyReportViewModel> GetComponentsReport(DateTime startDate, DateTime endDate, int userId);
}

View File

@@ -0,0 +1,19 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.StoragesContracts;
public interface IProductStorageContract
{
List<ProductViewModel> GetFullList();
List<ProductViewModel> GetFilteredList(ProductBindingModel model);
ProductViewModel GetElement(ProductBindingModel model);
ProductViewModel Insert(ProductBindingModel model);
ProductViewModel Update(ProductBindingModel model);
ProductViewModel Delete(ProductBindingModel model);
}

View File

@@ -0,0 +1,19 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.StoragesContracts;
public interface IRequestStorageContract
{
List<RequestViewModel> GetFullList();
List<RequestViewModel> GetFilteredList(RequestBindingModel model);
RequestViewModel GetElement(RequestBindingModel model);
RequestViewModel Insert(RequestBindingModel model);
RequestViewModel Update(RequestBindingModel model);
RequestViewModel Delete(RequestBindingModel model);
}

View File

@@ -0,0 +1,20 @@
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.StoragesContracts;
public interface IUserStorageContract
{
List<UserViewModel> GetFullList();
List<UserViewModel> GetFilteredList(UserBindingModel model);
UserViewModel GetElement(UserBindingModel model);
UserViewModel Insert(UserBindingModel model);
UserViewModel Update(UserBindingModel model);
UserViewModel Delete(UserBindingModel model);
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.ViewModels;
public class AssemblyViewModel
{
public int Id { get; set; }
[DisplayName("Имя сборки")]
public string AssemblyName { get; set; } = string.Empty;
[DisplayName("Описание сборки")]
public string Description { get; set; } = string.Empty;
public int UserID { get; set; }
public int? OrderRequestId { get; set; }
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.ViewModels;
public class ComponentRequestAssemblyReportViewModel
{
public string ComponentName { get; set; } = string.Empty;
[DisplayName("Даты запросов")]
public List<DateTime> DateRequests { get; set; } = new();
[DisplayName("Сборки")]
public List<string> Assemblies { get; set; } = new();
[DisplayName("Производитель")]
public string Manufacturer { get; set; } = string.Empty;
[DisplayName("ID компонента")]
public int ComponentId { get; set; }
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.ViewModels;
public class ComponentViewModel
{
public int Id { get; set; }
[DisplayName("Имя комплектующего")]
public string ComponentName { get; set; } = string.Empty;
[DisplayName("Производитель")]
public string Manufacturer { get; set; } = string.Empty;
public double Price { get; set; }
public int UserId { get; set; }
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.ViewModels;
public class ProductViewModel
{
public int Id { get; set; }
[DisplayName("Название товара")]
public string ProductName { get; set; } = string.Empty;
[DisplayName("Категория товара")]
public string Category { get; set; } = string.Empty;
[DisplayName("Цена")]
public double Price { get; set; }
public int UserID { get; set; }
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.ViewModels;
public class RequestViewModel
{
[DisplayName("Дата создания")]
public DateTime DateRequest { get; set; } = DateTime.Now;
[DisplayName("ID сборки")]
public int? AssemblyId { get; set; }
public AssemblyViewModel? Assembly { get; set; }
[DisplayName("Номер")]
public int Id { get; set; }
[DisplayName("ID пользователя")]
public int UserID { get; set; }
}

View File

@@ -0,0 +1,27 @@
using ComputerStoreContracts.Enums;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreContracts.ViewModels;
public class UserViewModel
{
public int Id { get; set; }
[DisplayName("Логин")]
public string Login { get; set; } = string.Empty;
[DisplayName("Пароль")]
public string Password { get; set; } = string.Empty;
[DisplayName("ФИО")]
public string FIO { get; set; } = string.Empty;
[DisplayName("Почта")]
public string Email { get; set; } = string.Empty;
public UserType UserType { get; set; }
}

View File

@@ -6,4 +6,12 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ComputerStoreContracts\ComputerStoreContracts.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreDatabase
{
internal class ComputerStoreDbContext
{
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreDatabase.Models;
public class Assembly
{
public int Id { get; set; }
[Required]
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public int UserID { get; set; }
[ForeignKey("UserID")]
public virtual User User { get; set; } = new();
public int? OrderRequestId { get; set; }
[ForeignKey("OrderRequestId")]
public virtual Request Request { get; set; } = new();
[ForeignKey("AssemblyId")]
public virtual List<ComponentsAssemblies> ComponentsAssemblies { get; set; } = new();
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreDatabase.Models;
public class Component
{
public int Id { get; set; }
[Required]
public string Name { get; set; } = string.Empty;
[Required]
public string Manufacturer { get; set; } = string.Empty;
[Required]
public double Price { get; set; }
public int UserID { get; set; }
[ForeignKey("UserID")]
public virtual User User { get; set; } = new();
[ForeignKey("ComponentId")]
public virtual List<ProductsComponents> ProductsComponents { get; set; } = new();
[ForeignKey("ComponentId")]
public virtual List<ComponentsAssemblies> ComponentsAssemblies { get; set; } = new();
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreDatabase.Models;
public class ComponentsAssemblies
{
public int AssemblyId { get; set; }
[ForeignKey("AssemblyId")]
public virtual Assembly Assembly { get; set; } = new();
public int ComponentId { get; set; }
[ForeignKey("ComponentId")]
public virtual Component Component { get; set; } = new();
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreDatabase.Models;
public class Product
{
public int Id { get; set; }
[Required]
public string Name { get; set; } = string.Empty;
[Required]
public string Category { get; set; } = string.Empty;
[Required]
public double Price { get; set; }
public int UserID { get; set; }
[ForeignKey("UserID")]
public virtual User User { get; set; } = new();
[ForeignKey("ProductId")]
public virtual List<ProductsComponents> ProductsComponents { get; set; } = new();
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreDatabase.Models;
public class ProductsComponents
{
public int ProductId { get; set; }
[ForeignKey("ProductId")]
public virtual Product Product { get; set; } = new();
public int ComponentId { get; set; }
[ForeignKey("ComponentId")]
public virtual Component Component { get; set; } = new();
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ComputerStoreDatabase.Models;
public class Request
{
public int Id { get; set; }
[Required]
public DateTime DateRequest { get; set; }
public int? AssemblyId { get; set; }
[ForeignKey("AssemblyId")]
public virtual Assembly Assembly { get; set; } = new();
public int UserID { get; set; }
[ForeignKey("UserID")]
public virtual User User { get; set; } = new();
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using ComputerStoreContracts.Enums;
namespace ComputerStoreDatabase.Models;
public class User
{
public int ID { get; set; }
[Required]
public string Login { get; set; } = string.Empty;
[Required]
public string Password { get; set; } = string.Empty;
[Required]
public string FIO { get; set; } = string.Empty;
[Required]
public string Email { get; set; } = string.Empty;
public UserType UserType { get; set; }
[ForeignKey("UserID")]
public virtual List<Product> Products { get; set; } = new();
[ForeignKey("UserID")]
public virtual List<Component> Components { get; set; } = new();
[ForeignKey("UserID")]
public virtual List<Assembly> Assemblies { get; set; } = new();
[ForeignKey("UserID")]
public virtual List<Request> Requests { get; set; } = new();
}

View File

@@ -5,9 +5,11 @@ VisualStudioVersion = 17.8.34330.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComputerStoreContracts", "ComputerStoreContracts\ComputerStoreContracts.csproj", "{DE750B8C-D9EC-4563-99C7-98D2EF835A80}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComputerStoreDatabase", "ComputerStoreDatabase\ComputerStoreDatabase.csproj", "{CEDA00AE-6E2D-482C-8BDA-82F0038C1DD5}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComputerStoreDatabase", "ComputerStoreDatabase\ComputerStoreDatabase.csproj", "{CEDA00AE-6E2D-482C-8BDA-82F0038C1DD5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComputerStoreBusinessLogic", "ComputerStoreBusinessLogic\ComputerStoreBusinessLogic.csproj", "{0F764D8C-71D0-4655-947B-91DF5663C822}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComputerStoreBusinessLogic", "ComputerStoreBusinessLogic\ComputerStoreBusinessLogic.csproj", "{0F764D8C-71D0-4655-947B-91DF5663C822}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComputerStoreWebApp", "ComputerStoreWebApp\ComputerStoreWebApp.csproj", "{779490C3-FEBB-4EBC-926E-ED6C5A5F0211}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -27,6 +29,10 @@ Global
{0F764D8C-71D0-4655-947B-91DF5663C822}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0F764D8C-71D0-4655-947B-91DF5663C822}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0F764D8C-71D0-4655-947B-91DF5663C822}.Release|Any CPU.Build.0 = Release|Any CPU
{779490C3-FEBB-4EBC-926E-ED6C5A5F0211}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{779490C3-FEBB-4EBC-926E-ED6C5A5F0211}.Debug|Any CPU.Build.0 = Debug|Any CPU
{779490C3-FEBB-4EBC-926E-ED6C5A5F0211}.Release|Any CPU.ActiveCfg = Release|Any CPU
{779490C3-FEBB-4EBC-926E-ED6C5A5F0211}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -0,0 +1,49 @@
using ComputerStoreContracts.ViewModels;
using Newtonsoft.Json;
using System.Net.Http.Headers;
using System.Text;
namespace ComputerStoreWebApp;
public class APIUser
{
private static readonly HttpClient _user = new();
public static UserViewModel? User { get; set; } = null;
public static void Connect(IConfiguration configuration)
{
_user.BaseAddress = new Uri(configuration["IPAddress"]);
_user.DefaultRequestHeaders.Accept.Clear();
_user.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public static T? GetRequest<T>(string requestUrl)
{
var response = _user.GetAsync(requestUrl);
var result = response.Result.Content.ReadAsStringAsync().Result;
if (response.Result.IsSuccessStatusCode)
{
return JsonConvert.DeserializeObject<T>(result);
}
else
{
throw new Exception(result);
}
}
public static void PostRequest<T>(string requestUrl, T model)
{
var json = JsonConvert.SerializeObject(model);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = _user.PostAsync(requestUrl, data);
var result = response.Result.Content.ReadAsStringAsync().Result;
if (!response.Result.IsSuccessStatusCode)
{
throw new Exception(result);
}
}
}

View File

@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\js\" />
<Folder Include="wwwroot\images\" />
<Folder Include="wwwroot\lib\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ComputerStoreContracts\ComputerStoreContracts.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,6 @@
@ComputerStoreWebApp_HostAddress = http://localhost:5173
GET {{ComputerStoreWebApp_HostAddress}}/weatherforecast/
Accept: application/json
###

View File

@@ -0,0 +1,288 @@
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using ComputerStoreContracts.BindingModels;
using ComputerStoreContracts.ViewModels;
using ComputerStoreWebApp;
using System.IO.Pipelines;
using ComputerStoreWebApp.Models;
namespace ComputerShopImplementerApp.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
if (APIUser.User == null)
{
return Redirect("~/Home/Enter");
}
return View();
}
[HttpGet]
public IActionResult Privacy()
{
if (APIUser.User == null)
{
return Redirect("~/Home/Enter");
}
return View(APIUser.User);
}
[HttpPost]
public void Privacy(string fio, string login, string password, string email)
{
if (APIUser.User == null)
{
throw new Exception("Требуется авторизация");
}
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(email))
{
throw new Exception("Требуется логин, пароль и email");
}
APIUser.PostRequest("api/user/updatedata", new UserBindingModel
{
Id = APIUser.User.Id,
FIO = fio,
Login = login,
Password = password,
Email = email
});
APIUser.User.FIO = fio;
APIUser.User.Password = password;
APIUser.User.Email = email;
Response.Redirect("Index");
}
[HttpGet]
public IActionResult CreateComponent()
{
return View();
}
[HttpPost]
public void CreateComponent(string title, double price, string manufacturer)
{
if (string.IsNullOrEmpty(title) || price <= 0 || string.IsNullOrEmpty(manufacturer))
{
throw new Exception("Введите название, цену и описание");
}
APIUser.PostRequest("api/component/create", new ComponentBindingModel
{
ComponentName = title,
Price = price,
Manufacturer = manufacturer,
UserId = APIUser.User.Id
});
Response.Redirect("IndexComponent");
}
[HttpGet]
public IActionResult CreateProduct()
{
return View();
}
[HttpPost]
public void CreateProduct(string title, string category, double price)
{
if (string.IsNullOrEmpty(title) || price <= 0 || string.IsNullOrEmpty(category))
{
throw new Exception("Введите название, цену и описание");
}
APIUser.PostRequest("api/product/create", new ProductBindingModel
{
ProductName = title,
Category = category,
Price = price,
UserId = APIUser.User.Id
});
Response.Redirect("IndexProduct");
}
[HttpGet]
public IActionResult CreateRequest()
{
var assemblies = APIUser.GetRequest<List<AssemblyViewModel>>("api/assembly/getlist");
return View(assemblies ?? new List<AssemblyViewModel>());
}
[HttpPost]
public void CreateRequest(int[] assemblies)
{
if (assemblies == null || assemblies.Length == 0)
{
throw new Exception("Выберите хотя бы одну сборку");
}
foreach (var assemblyId in assemblies)
{
APIUser.PostRequest("api/request/create", new RequestBindingModel
{
AssemblyId = assemblyId,
UserId = APIUser.User.Id
});
}
Response.Redirect("IndexRequest");
}
[HttpGet]
public IActionResult CreateAssembly()
{
var components = APIUser.GetRequest<List<ComponentViewModel>>("api/component/getlist");
return View(components ?? new List<ComponentViewModel>());
}
[HttpPost]
public void CreateAssembly(string assemblyName, string description, int[] components)
{
if (string.IsNullOrEmpty(assemblyName) || components == null || components.Length == 0)
{
throw new Exception("Введите название сборки и выберите хотя бы одно комплектующее");
}
APIUser.PostRequest("api/assembly/create", new AssemblyBindingModel
{
AssemblyName = assemblyName,
Description = description,
UserId = APIUser.User.Id,
Components = components.ToList()
});
Response.Redirect("IndexAssembly");
}
[HttpGet]
public IActionResult CreateBatch()
{
var products = APIUser.GetRequest<List<ProductViewModel>>("api/product/getlist");
return View(products ?? new List<ProductViewModel>());
}
[HttpGet]
public IActionResult IndexComponent()
{
var components = APIUser.GetRequest<List<ComponentViewModel>>("api/component/getlist");
return View(components ?? new List<ComponentViewModel>());
}
[HttpGet]
public IActionResult IndexProduct()
{
var products = APIUser.GetRequest<List<ProductViewModel>>("api/product/getlist");
return View(products ?? new List<ProductViewModel>());
}
[HttpGet]
public IActionResult IndexRequest()
{
var requests = APIUser.GetRequest<List<RequestViewModel>>("api/request/getlist");
return View(requests ?? new List<RequestViewModel>());
}
[HttpGet]
public IActionResult IndexAssembly()
{
var assemblies = APIUser.GetRequest<List<AssemblyViewModel>>("api/assembly/getlist");
return View(assemblies ?? new List<AssemblyViewModel>());
}
[HttpGet]
public IActionResult ComponentRequestAssemblyReport()
{
var reports = APIUser.GetRequest<List<ComponentRequestAssemblyReportViewModel>>("api/report/componentrequestassembly");
return View(reports ?? new List<ComponentRequestAssemblyReportViewModel>());
}
[HttpGet]
public IActionResult ReportsMenu()
{
return View();
}
[HttpGet]
public IActionResult Enter()
{
return View();
}
[HttpPost]
public void Enter(string login, string password)
{
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password))
{
throw new Exception("Введите логин и пароль");
}
APIUser.User = APIUser.GetRequest<UserViewModel>($"api/user/loginimplementer?login={login}&password={password}");
if (APIUser.User == null)
{
throw new Exception("Неверный логин или пароль");
}
Response.Redirect("Index");
}
[HttpGet]
public IActionResult Register()
{
return View();
}
[HttpPost]
public void Register(string fio, string login, string password, string email)
{
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(email))
{
throw new Exception("Введите логин, пароль, почту");
}
APIUser.PostRequest("api/user/registerimplementer", new UserBindingModel
{
FIO = fio,
Login = login,
Password = password,
Email = email
});
Response.Redirect("Enter");
}
[HttpGet]
public IActionResult DeleteProduct(int id)
{
APIUser.PostRequest("api/product/delete", new { Id = id });
return RedirectToAction("IndexProduct");
}
[HttpGet]
public IActionResult DeleteComponent(int id)
{
APIUser.PostRequest("api/component/delete", new { Id = id });
return RedirectToAction("IndexComponent");
}
[HttpGet]
public IActionResult DeleteAssembly(int id)
{
APIUser.PostRequest("api/assembly/delete", new { Id = id });
return RedirectToAction("IndexAssembly");
}
[HttpGet]
public IActionResult DeleteRequest(int id)
{
APIUser.PostRequest("api/request/delete", new { Id = id });
return RedirectToAction("IndexRequest");
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}

View File

@@ -0,0 +1,9 @@
namespace ComputerStoreWebApp.Models
{
public class ErrorViewModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
}

View File

@@ -0,0 +1,28 @@
using ComputerStoreWebApp;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
var app = builder.Build();
APIUser.Connect(builder.Configuration);
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Login}/{id?}");
app.Run();

View File

@@ -0,0 +1,41 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:58388",
"sslPort": 44394
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "Home/Index",
"applicationUrl": "http://localhost:5173",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "Home/Index",
"applicationUrl": "https://localhost:7001;http://localhost:6843",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "Home/Index",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,29 @@
@{
ViewData["Title"] = "Сборки";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<main>
<h1 style="text-align: center;">Сборки</h1>
<table>
<thead>
<tr>
<th>Номер</th>
<th>Название</th>
<th>Описание</th>
<th>Изменить сборку</th>
<th>Удалить сборку</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Сборка 1</td>
<td>Описание 1</td>
<td><button class="edit-button">Изменить</button></td>
<td><button class="delete-button">Удалить</button></td>
</tr>
<!-- Добавь больше строк для прототипа -->
</tbody>
</table>
<button>Создать</button>
</main>

View File

@@ -0,0 +1,49 @@
@using ComputerStoreContracts.ViewModels
@model List<ComponentRequestAssemblyReportViewModel>
@{
ViewData["Title"] = "Отчёт по комплектующим, заявкам и сборкам";
}
<div class="text-center">
<h1 class="display-4">Сборки и заявки по комплектующим</h1>
</div>
<form method="post">
<button type="submit" class="btn btn-primary">Отправить отчёт на почту</button>
</form>
<table class="table">
<thead>
<tr>
<th>Комплектующее</th>
<th>Сборки</th>
<th>Заявки</th>
</tr>
</thead>
<tbody>
@foreach (var component in Model)
{
<tr>
<td>@component.ComponentName</td>
<td>
<ul>
@foreach (var assembly in component.Assemblies)
{
<li>@assembly</li>
}
</ul>
</td>
<td>
<ul>
@foreach (var request in component.DateRequests)
{
<li>@request</li>
}
</ul>
</td>
</tr>
}
</tbody>
</table>

View File

@@ -0,0 +1,23 @@
@{
ViewData["Title"] = "Комплектующие";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<main>
<h1>Комплектующие</h1>
<table>
<thead>
<tr>
<th>Название</th>
<th>Производитель</th>
<th>Цена</th>
</tr>
</thead>
<tbody>
<tr><td>Комплектующее 1</td><td>Производитель 1</td><td>500</td></tr>
<!-- Добавь больше строк для прототипа -->
</tbody>
</table>
<button>Создать</button>
<button>Изменить</button>
<button>Удалить</button>
</main>

View File

@@ -0,0 +1,59 @@
@using ComputerStoreContracts.ViewModels
@model List<ComponentViewModel>
@{
ViewData["Title"] = "Создание сборки";
}
<div class="text-center">
<h2 class="display-4">Создание сборки</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Название сборки:</div>
<div class="col-8"><input type="text" name="assemblyName" id="assemblyName" required /></div>
</div>
<div class="row">
<div class="col-4">Описание:</div>
<div class="col-8"><input type="text" name="description" id="description" required /></div>
</div>
<div class="container">
<div>Комплектующие</div>
<div class="table-responsive-lg">
<table id="componentsTable" class="table">
<thead>
<tr>
<th>Выбор</th>
<th>Название</th>
</tr>
</thead>
<tbody>
@foreach (var component in Model)
{
<tr>
<td>
<input type="checkbox" name="components" value="@component.Id" />
</td>
<td>@component.ComponentName</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Сохранить" class="btn btn-primary" /></div>
</div>
</form>
@section Scripts {
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.js"></script>
<script>
$(document).ready(function () {
$('#componentsTable').DataTable();
});
</script>
}

View File

@@ -0,0 +1,25 @@
@{
ViewData["Title"] = "Создание комплектующего";
}
<div class="text-center">
<h2 class="display-4">Создание комплектующего</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Название:</div>
<div class="col-8"><input type="text" name="title" id="title" required /></div>
</div>
<div class="row">
<div class="col-4">Цена:</div>
<div class="col-8"><input type="text" name="cost" id="cost" required /></div>
</div>
<div class="row">
<div class="col-4">Описание:</div>
<div class="col-8"><input type="text" name="description" id="description" required /></div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Сохранить" class="btn btn-primary" /></div>
</div>
</form>

View File

@@ -0,0 +1,25 @@
@{
ViewData["Title"] = "Создание товара";
}
<div class="text-center">
<h2 class="display-4">Создание товара</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Название:</div>
<div class="col-8"><input type="text" name="title" id="title" required /></div>
</div>
<div class="row">
<div class="col-4">Цена:</div>
<div class="col-8"><input type="text" name="cost" id="cost" required /></div>
</div>
<div class="row">
<div class="col-4">Описание:</div>
<div class="col-8"><input type="text" name="description" id="description" required /></div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Сохранить" class="btn btn-primary" /></div>
</div>
</form>

View File

@@ -0,0 +1,51 @@
@using ComputerStoreContracts.ViewModels
@model List<AssemblyViewModel>
@{
ViewData["Title"] = "Создание заявки";
}
<div class="text-center">
<h2 class="display-4">Создание заявки</h2>
</div>
<form method="post">
<div class="container">
<div>Сборки</div>
<div class="table-responsive-lg">
<table id="assembliesTable" class="table">
<thead>
<tr>
<th>Выбор</th>
<th>Название</th>
</tr>
</thead>
<tbody>
@foreach (var assembly in Model)
{
<tr>
<td>
<input type="checkbox" name="assemblies" value="@assembly.Id" />
</td>
<td>@assembly.AssemblyName</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Сохранить" class="btn btn-primary" /></div>
</div>
</form>
@section Scripts {
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.js"></script>
<script>
$(document).ready(function () {
$('#assembliesTable').DataTable();
});
</script>
}

View File

@@ -0,0 +1,21 @@
@{
ViewData["Title"] = "Вход";
}
<div class="text-center">
<h2 class="display-4">Вход</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">Логин:</div>
<div class="col-8"><input type="text" name="login" required /></div>
</div>
<div class="row">
<div class="col-4">Пароль:</div>
<div class="col-8"><input type="password" name="password" required /></div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Вход" class="btn btn-primary" /></div>
</div>
</form>

View File

@@ -0,0 +1,8 @@
@{
ViewData["Title"] = "Главная страница";
}
<div class="text-center">
<h1 class="display-4">Добро пожаловать в компьютерный магазин "Ты ж программист"</h1>
<p>Здесь вы можете управлять товарами, комплектующими, сборками и заявками.</p>
</div>

View File

@@ -0,0 +1,51 @@
@using ComputerStoreContracts.ViewModels
@model List<AssemblyViewModel>
@{
ViewData["Title"] = "Сборки";
}
<div class="text-center">
<h1 class="display-4">Сборки</h1>
</div>
<div class="text-center">
<p>
<a asp-action="CreateAssembly" class="nav-link">Создать сборку</a>
</p>
@if (Model == null || !Model.Any())
{
<p class="text-warning">Список сборок пуст.</p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Номер</th>
<th>@Html.DisplayNameFor(model => model[0].Id)</th>
<th>@Html.DisplayNameFor(model => model[0].AssemblyName)</th>
<th>@Html.DisplayNameFor(model => model[0].Description)</th> <!-- Добавлено отображение описания -->
<th>Действия</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@Html.DisplayFor(modelItem => item.Id)</td>
<td>@Html.DisplayFor(modelItem => item.AssemblyName)</td>
<td>@Html.DisplayFor(modelItem => item.Description)</td> <!-- Добавлено отображение описания -->
<td>
<a asp-action="CreateAssembly" asp-route-id="@item.Id" class="btn btn-primary">Изменить</a>
</td>
<td>
<a asp-action="DeleteAssembly" asp-route-id="@item.Id" class="btn btn-danger">Удалить</a>
</td>
</tr>
}
</tbody>
</table>
}
</div>

View File

@@ -0,0 +1,46 @@
@using ComputerStoreContracts.ViewModels
@model List<ComponentViewModel>
@{
ViewData["Title"] = "Комплектующие";
}
<div class="text-center">
<h1 class="display-4">Комплектующие</h1>
</div>
<div class="text-center">
<p>
<a asp-action="CreateComponent" class="nav-link">Создать комплектующее</a>
</p>
<table class="table">
<thead>
<tr>
<th>Номер</th>
<th>Название комплектующего</th>
<th>Цена</th>
<th>Производитель</th>
<th>Изменить комплектующее</th>
<th>Удалить комплектующее</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@Html.DisplayFor(modelItem => item.Id)</td>
<td>@Html.DisplayFor(modelItem => item.ComponentName)</td>
<td>@Html.DisplayFor(modelItem => item.Price)</td>
<td>@Html.DisplayFor(modelItem => item.Manufacturer)</td>
<td>
<a asp-action="CreateComponent" asp-route-id="@item.Id" class="btn btn-primary">Изменить</a>
</td>
<td>
<a asp-action="DeleteComponent" asp-route-id="@item.Id" class="btn btn-danger">Удалить</a>
</td>
</tr>
}
</tbody>
</table>
</div>

View File

@@ -0,0 +1,46 @@
@using ComputerStoreContracts.ViewModels
@model List<ProductViewModel>
@{
ViewData["Title"] = "Товары";
}
<div class="text-center">
<h1 class="display-4">Товары</h1>
</div>
<div class="text-center">
<p>
<a asp-action="CreateProduct" class="nav-link">Создать товар</a>
</p>
<table class="table">
<thead>
<tr>
<th>Номер</th>
<th>Название товара</th>
<th>Цена</th>
<th>Категория</th>
<th>Изменить товар</th>
<th>Удалить товар</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@Html.DisplayFor(modelItem => item.Id)</td>
<td>@Html.DisplayFor(modelItem => item.ProductName)</td>
<td>@Html.DisplayFor(modelItem => item.Price)</td>
<td>@Html.DisplayFor(modelItem => item.Category)</td>
<td>
<a asp-action="CreateProduct" asp-route-id="@item.Id" class="btn btn-primary">Изменить</a>
</td>
<td>
<a asp-action="DeleteProduct" asp-route-id="@item.Id" class="btn btn-danger">Удалить</a>
</td>
</tr>
}
</tbody>
</table>
</div>

View File

@@ -0,0 +1,40 @@
@using ComputerStoreContracts.ViewModels
@model List<RequestViewModel>
@{
ViewData["Title"] = "Заявки";
}
<div class="text-center">
<h1 class="display-4">Заявки</h1>
</div>
<div class="text-center">
<p>
<a asp-action="CreateRequest" class="nav-link">Создать заявку</a>
</p>
<table class="table">
<thead>
<tr>
<th>Номер</th>
<th>Дата</th>
<th>Сборка</th>
<th>Удалить заявку</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@Html.DisplayFor(modelItem => item.Id)</td>
<td>@Html.DisplayFor(modelItem => item.DateRequest)</td>
<td>@Html.DisplayFor(modelItem => item.AssemblyId)</td>
<td>
<a asp-action="DeleteRequest" asp-route-id="@item.Id" class="btn btn-danger">Удалить</a>
</td>
</tr>
}
</tbody>
</table>
</div>

View File

@@ -0,0 +1,15 @@
@{
Layout = "~/Views/Shared/_Layout.cshtml";
ViewData["Title"] = "Авторизация";
}
<main>
<h1>Авторизация</h1>
<form>
<label for="login">Логин:</label>
<input type="text" id="login" maxlength="50" required><br>
<label for="password">Пароль:</label>
<input type="password" id="password" maxlength="8" required><br>
<button type="submit">Вход</button>
</form>
<div id="errorMessage" style="color:red;"></div>
</main>

View File

@@ -0,0 +1,34 @@
@using ComputerStoreContracts.ViewModels
@model UserViewModel
@{
ViewData["Title"] = "Личные данные";
}
<div class="text-center">
<h2 class="display-4">Данные пользователя</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">ФИО:</div>
<div class="col-8"><input type="text" name="Fio" value="@Model.FIO" required /></div>
</div>
<div class="row">
<div class="col-4">Логин:</div>
<div class="col-8"><input type="text" name="login" value="@Model.Login" required /></div>
</div>
<div class="row">
<div class="col-4">Пароль:</div>
<div class="col-8"><input type="password" name="password" value="@Model.Password" required /></div>
</div>
<div class="row">
<div class="col-4">Почта:</div>
<div class="col-8"><input type="text" name="email" value="@Model.Email" required /></div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Сохранить" class="btn btn-primary" /></div>
</div>
</form>

View File

@@ -0,0 +1,39 @@
@{
ViewData["Title"] = "Товары";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<main>
<h1 style="text-align: center;">Товары</h1>
<table>
<thead>
<tr>
<th>Номер</th>
<th>Название товара</th>
<th>Цена</th>
<th>Описание</th>
<th>Изменить товар</th>
<th>Удалить товар</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Товар 1</td>
<td>10.99</td>
<td>Описание</td>
<td><button style="background-color: #007bff; color: white; border: none; padding: 5px 10px; cursor: pointer;">Изменить</button></td>
<td><button style="background-color: #dc3545; color: white; border: none; padding: 5px 10px; cursor: pointer;">Удалить</button></td>
</tr>
<tr>
<td>1</td>
<td>Товар 1</td>
<td>18.00</td>
<td>Описание</td>
<td><button style="background-color: #007bff; color: white; border: none; padding: 5px 10px; cursor: pointer;">Изменить</button></td>
<td><button style="background-color: #dc3545; color: white; border: none; padding: 5px 10px; cursor: pointer;">Удалить</button></td>
</tr>
<!-- Добавь больше строк для прототипа по необходимости -->
</tbody>
</table>
<button style="padding: 5px 10px; margin: 5px; background-color: #007bff; color: white; border: none; cursor: pointer;">Создать</button>
</main>

View File

@@ -0,0 +1,29 @@
@{
ViewData["Title"] = "Регистрация";
}
<div class="text-center">
<h2 class="display-4">Регистрация</h2>
</div>
<form method="post">
<div class="row">
<div class="col-4">ФИО:</div>
<div class="col-8"><input type="text" name="fio" required /></div>
</div>
<div class="row">
<div class="col-4">Логин:</div>
<div class="col-8"><input type="text" name="login" required /></div>
</div>
<div class="row">
<div class="col-4">Пароль:</div>
<div class="col-8"><input type="password" name="password" required /></div>
</div>
<div class="row">
<div class="col-4">Почта:</div>
<div class="col-8"><input type="text" name="email" required /></div>
</div>
<div class="row">
<div class="col-8"></div>
<div class="col-4"><input type="submit" value="Регистрация" class="btn btn-primary" /></div>
</div>
</form>

View File

@@ -0,0 +1,17 @@
@{
ViewData["Title"] = "Отчёты";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<main>
<h1>Отчёты</h1>
<label for="startDate">Начальная дата:</label>
<input type="date" id="startDate" required><br>
<label for="endDate">Конечная дата:</label>
<input type="date" id="endDate" required><br>
<label for="deliveryMethod">Способ получения:</label>
<select id="deliveryMethod">
<option value="email">На почту</option>
<option value="form">На форму</option>
</select><br>
<button>Получить</button>
</main>

View File

@@ -0,0 +1,11 @@
@{
ViewData["Title"] = "Меню создания отчётов";
}
<div class="text-center">
<h1 class="display-4">Меню создания отчётов</h1>
<div class="list-group">
<a class="nav-link text-dark list-group-item" asp-area="" asp-controller="Home" asp-action="ComponentBatchReport">Отчёт по комплектующим по партиям</a>
<a class="nav-link text-dark list-group-item" asp-area="" asp-controller="Home" asp-action="ComponentRequestAssemblyReport">Отчёт по комплектующим по заявкам и сборкам</a>
</div>
</div>

View File

@@ -0,0 +1,27 @@
@{
ViewData["Title"] = "Заявки";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<main>
<h1 style="text-align: center;">Заявки</h1>
<table>
<thead>
<tr>
<th>Номер</th>
<th>Дата заявки</th>
<th>Изменить заявку</th>
<th>Удалить заявку</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2025-05-11</td>
<td><button class="edit-button">Изменить</button></td>
<td><button class="delete-button">Удалить</button></td>
</tr>
<!-- Добавь больше строк для прототипа -->
</tbody>
</table>
<button>Создать</button>
</main>

View File

@@ -0,0 +1,66 @@
<!DOCTYPE html>
<html lang="ru" style="height: 100%;">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - Компьютерный магазин "Ты ж программист"</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/style.css" asp-append-version="true" />
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">
<img src="/src/logo.png" alt="Ты ж программист" style="height: 40px;">
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link" asp-area="" asp-controller="Home" asp-action="ReportsMenu">Отчёты</a>
</li>
<li class="nav-item">
<a class="nav-link" asp-area="" asp-controller="Home" asp-action="IndexComponent">Комплектующие</a>
</li>
<li class="nav-item">
<a class="nav-link" asp-area="" asp-controller="Home" asp-action="IndexProduct">Товары</a>
</li>
<li class="nav-item">
<a class="nav-link" asp-area="" asp-controller="Home" asp-action="IndexAssembly">Сборки</a>
</li>
<li class="nav-item">
<a class="nav-link" asp-area="" asp-controller="Home" asp-action="IndexRequest">Заявки</a>
</li>
<li class="nav-item">
<a class="nav-link" asp-area="" asp-controller="Home" asp-action="Privacy">Личные данные</a>
</li>
<li class="nav-item">
<a class="nav-link" asp-area="" asp-controller="Home" asp-action="Enter">Вход</a>
</li>
<li class="nav-item">
<a class="nav-link" asp-area="" asp-controller="Home" asp-action="Register">Регистрация</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="footer text-muted">
<div class="container">
© 2024 - Компьютерный магазин "Ты ж программист"
</div>
</footer>
<script src="~/js/site.js" asp-append-version="true"></script>
@RenderSection("Scripts", required: false)
</body>
</html>

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"IPAddress": "http://localhost:5060/"
}

View File

@@ -0,0 +1,14 @@
{
"version": "1.0",
"defaultProvider": "cdnjs",
"libraries": [
{
"library": "bootstrap@5.3.3",
"destination": "wwwroot/lib/bootstrap/"
},
{
"library": "jquery@3.7.1",
"destination": "wwwroot/lib/jquery/"
}
]
}

View File

@@ -0,0 +1,160 @@
html, body {
height: 100%;
margin: 0;
}
body {
display: flex;
flex-direction: column;
font-family: 'Arial', sans-serif;
background-color: #f4f4f9;
color: #333;
}
.container {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.footer {
background-color: #fff;
padding: 20px 0;
box-shadow: 0 -2px 4px rgba(0,0,0,.1);
}
.navbar {
background-color: #ffffff;
box-shadow: 0 2px 4px rgba(0,0,0,.1);
justify-content: right;
}
.nav-link {
color: #505050;
transition: color 0.3s;
}
.nav-link:hover {
color: #007bff;
}
/* Стили для таблиц */
.table {
width: 100%;
margin-bottom: 1rem;
color: #212529;
}
.table th,
.table td {
padding: 0.75rem;
vertical-align: top;
border-top: 1px solid #dee2e6;
}
.table thead th {
vertical-align: bottom;
border-bottom: 2px solid #dee2e6;
background-color: #f8f9fa;
}
/* Стили для форм */
.row {
display: flex;
flex-wrap: wrap;
margin-bottom: 1rem;
}
.col-4, .col-8 {
padding: 0 15px;
}
.col-4 {
flex: 0 0 33.333333%;
max-width: 33.333333%;
}
.col-8 {
flex: 0 0 66.666667%;
max-width: 66.666667%;
}
input[type="text"],
input[type="password"],
input[type="date"],
select {
width: 100%;
padding: 0.375rem 0.75rem;
font-size: 1rem;
line-height: 1.5;
color: #495057;
background-color: #fff;
border: 1px solid #ced4da;
border-radius: 0.25rem;
}
/* Стили для кнопок */
.btn {
padding: 0.375rem 0.75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: 0.25rem;
text-align: center;
vertical-align: middle;
cursor: pointer;
}
.btn-primary {
color: #fff;
background-color: #007bff;
border-color: #007bff;
}
.btn-primary:hover {
background-color: #0056b3;
border-color: #004085;
}
.btn-danger {
color: #fff;
background-color: #dc3545;
border-color: #dc3545;
}
.btn-danger:hover {
background-color: #c82333;
border-color: #bd2130;
}
/* Стили для списка в меню отчётов */
.list-group {
display: flex;
flex-direction: column;
padding-left: 0;
margin-bottom: 0;
}
.list-group-item {
position: relative;
display: block;
padding: 0.75rem 1.25rem;
background-color: #fff;
border: 1px solid rgba(0,0,0,.125);
}
.list-group-item:hover {
background-color: #f8f9fa;
}
/* Центрирование текста */
.text-center {
text-align: center;
}
/* Стили для заголовков */
.display-4 {
font-size: 2.5rem;
font-weight: 300;
line-height: 1.2;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,597 @@
/*!
* Bootstrap Reboot v5.3.3 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root,
[data-bs-theme=light] {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #052c65;
--bs-secondary-text-emphasis: #2b2f32;
--bs-success-text-emphasis: #0a3622;
--bs-info-text-emphasis: #055160;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #58151c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #cfe2ff;
--bs-secondary-bg-subtle: #e2e3e5;
--bs-success-bg-subtle: #d1e7dd;
--bs-info-bg-subtle: #cff4fc;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #f8d7da;
--bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #9ec5fe;
--bs-secondary-border-subtle: #c4c8cb;
--bs-success-border-subtle: #a3cfbb;
--bs-info-border-subtle: #9eeaf9;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #f1aeb5;
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg: #fff;
--bs-body-bg-rgb: 255, 255, 255;
--bs-emphasis-color: #000;
--bs-emphasis-color-rgb: 0, 0, 0;
--bs-secondary-color: rgba(33, 37, 41, 0.75);
--bs-secondary-color-rgb: 33, 37, 41;
--bs-secondary-bg: #e9ecef;
--bs-secondary-bg-rgb: 233, 236, 239;
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
--bs-tertiary-color-rgb: 33, 37, 41;
--bs-tertiary-bg: #f8f9fa;
--bs-tertiary-bg-rgb: 248, 249, 250;
--bs-heading-color: inherit;
--bs-link-color: #0d6efd;
--bs-link-color-rgb: 13, 110, 253;
--bs-link-decoration: underline;
--bs-link-hover-color: #0a58ca;
--bs-link-hover-color-rgb: 10, 88, 202;
--bs-code-color: #d63384;
--bs-highlight-color: #212529;
--bs-highlight-bg: #fff3cd;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-xxl: 2rem;
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
--bs-border-radius-pill: 50rem;
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 0.25rem;
--bs-focus-ring-opacity: 0.25;
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
--bs-form-valid-color: #198754;
--bs-form-valid-border-color: #198754;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
}
[data-bs-theme=dark] {
color-scheme: dark;
--bs-body-color: #dee2e6;
--bs-body-color-rgb: 222, 226, 230;
--bs-body-bg: #212529;
--bs-body-bg-rgb: 33, 37, 41;
--bs-emphasis-color: #fff;
--bs-emphasis-color-rgb: 255, 255, 255;
--bs-secondary-color: rgba(222, 226, 230, 0.75);
--bs-secondary-color-rgb: 222, 226, 230;
--bs-secondary-bg: #343a40;
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
--bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: #6ea8fe;
--bs-secondary-text-emphasis: #a7acb1;
--bs-success-text-emphasis: #75b798;
--bs-info-text-emphasis: #6edff6;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ea868f;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #031633;
--bs-secondary-bg-subtle: #161719;
--bs-success-bg-subtle: #051b11;
--bs-info-bg-subtle: #032830;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #2c0b0e;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #084298;
--bs-secondary-border-subtle: #41464b;
--bs-success-border-subtle: #0f5132;
--bs-info-border-subtle: #087990;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #842029;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #6ea8fe;
--bs-link-hover-color: #8bb9fe;
--bs-link-color-rgb: 110, 168, 254;
--bs-link-hover-color-rgb: 139, 185, 254;
--bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6;
--bs-highlight-bg: #664d03;
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #75b798;
--bs-form-valid-border-color: #75b798;
--bs-form-invalid-color: #ea868f;
--bs-form-invalid-border-color: #ea868f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: var(--bs-border-width) solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
color: var(--bs-heading-color);
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
color: var(--bs-highlight-color);
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
text-decoration: underline;
}
a:hover {
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: var(--bs-secondary-color);
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,594 @@
/*!
* Bootstrap Reboot v5.3.3 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root,
[data-bs-theme=light] {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #052c65;
--bs-secondary-text-emphasis: #2b2f32;
--bs-success-text-emphasis: #0a3622;
--bs-info-text-emphasis: #055160;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #58151c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #cfe2ff;
--bs-secondary-bg-subtle: #e2e3e5;
--bs-success-bg-subtle: #d1e7dd;
--bs-info-bg-subtle: #cff4fc;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #f8d7da;
--bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #9ec5fe;
--bs-secondary-border-subtle: #c4c8cb;
--bs-success-border-subtle: #a3cfbb;
--bs-info-border-subtle: #9eeaf9;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #f1aeb5;
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg: #fff;
--bs-body-bg-rgb: 255, 255, 255;
--bs-emphasis-color: #000;
--bs-emphasis-color-rgb: 0, 0, 0;
--bs-secondary-color: rgba(33, 37, 41, 0.75);
--bs-secondary-color-rgb: 33, 37, 41;
--bs-secondary-bg: #e9ecef;
--bs-secondary-bg-rgb: 233, 236, 239;
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
--bs-tertiary-color-rgb: 33, 37, 41;
--bs-tertiary-bg: #f8f9fa;
--bs-tertiary-bg-rgb: 248, 249, 250;
--bs-heading-color: inherit;
--bs-link-color: #0d6efd;
--bs-link-color-rgb: 13, 110, 253;
--bs-link-decoration: underline;
--bs-link-hover-color: #0a58ca;
--bs-link-hover-color-rgb: 10, 88, 202;
--bs-code-color: #d63384;
--bs-highlight-color: #212529;
--bs-highlight-bg: #fff3cd;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-xxl: 2rem;
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
--bs-border-radius-pill: 50rem;
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 0.25rem;
--bs-focus-ring-opacity: 0.25;
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
--bs-form-valid-color: #198754;
--bs-form-valid-border-color: #198754;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
}
[data-bs-theme=dark] {
color-scheme: dark;
--bs-body-color: #dee2e6;
--bs-body-color-rgb: 222, 226, 230;
--bs-body-bg: #212529;
--bs-body-bg-rgb: 33, 37, 41;
--bs-emphasis-color: #fff;
--bs-emphasis-color-rgb: 255, 255, 255;
--bs-secondary-color: rgba(222, 226, 230, 0.75);
--bs-secondary-color-rgb: 222, 226, 230;
--bs-secondary-bg: #343a40;
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
--bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: #6ea8fe;
--bs-secondary-text-emphasis: #a7acb1;
--bs-success-text-emphasis: #75b798;
--bs-info-text-emphasis: #6edff6;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ea868f;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #031633;
--bs-secondary-bg-subtle: #161719;
--bs-success-bg-subtle: #051b11;
--bs-info-bg-subtle: #032830;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #2c0b0e;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #084298;
--bs-secondary-border-subtle: #41464b;
--bs-success-border-subtle: #0f5132;
--bs-info-border-subtle: #087990;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #842029;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #6ea8fe;
--bs-link-hover-color: #8bb9fe;
--bs-link-color-rgb: 110, 168, 254;
--bs-link-hover-color-rgb: 139, 185, 254;
--bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6;
--bs-highlight-bg: #664d03;
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #75b798;
--bs-form-valid-border-color: #75b798;
--bs-form-invalid-color: #ea868f;
--bs-form-invalid-border-color: #ea868f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: var(--bs-border-width) solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
color: var(--bs-heading-color);
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
color: var(--bs-highlight-color);
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
text-decoration: underline;
}
a:hover {
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: var(--bs-secondary-color);
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More