Commit fc4c5aa0 authored by TTrueBenji's avatar TTrueBenji

Добавить функционал добавления продукта в корзину.

***
- добавил таблицу корзины в БД.
- реализовал сервис для функционала корзины.
- добавил страницу для отображения продуктов в корзине.
- Реализовал функционал удаления продукта из корзины.
***
parent 4e1e1d4a
using Microsoft.AspNetCore.Mvc;
using PhoneStore.Enums;
using PhoneStore.Services.Abstractions;
using PhoneStore.ViewModels;
namespace PhoneStore.Controllers
{
public class BasketController : Controller
{
private readonly IBasketService _basketService;
public BasketController(IBasketService basketService)
{
_basketService = basketService;
}
[HttpGet]
public IActionResult Add(int id)
{
var result = _basketService.AddPhone(id);
ResponseMessageViewModel response = result switch
{
StatusCodes.Success => new ResponseMessageViewModel {Message = "Продукт успешно добавлен"},
StatusCodes.EntityNotFound => new ResponseMessageViewModel {Message = "Продукт не найден"},
_ => new ResponseMessageViewModel {Message = "Продукт не найден"}
};
response.Status = result;
return View(response);
}
public IActionResult Index()
{
var baskets = _basketService.GetAll();
return View(baskets);
}
[HttpGet]
public IActionResult Remove(int id)
{
_basketService.Remove(id);
return RedirectToAction("Index");
}
}
}
\ No newline at end of file
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using PhoneStore.Models;
......@@ -13,7 +14,10 @@ namespace PhoneStore.Controllers
{
_db = db;
}
/// <summary>
/// Действие, которое возвращает страницу со списком смартфонов
/// </summary>
/// <returns></returns>
[HttpGet]
public IActionResult Index()
{
......
namespace PhoneStore.Enums
{
public enum StatusCodes
{
Success = 200,
Error = 500,
EntityNotFound = 400
}
}
\ No newline at end of file
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using PhoneStore.Models;
namespace PhoneStore.Migrations
{
[DbContext(typeof(MobileContext))]
[Migration("20220616111154_AddBasketEntity")]
partial class AddBasketEntity
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "5.0.17");
modelBuilder.Entity("PhoneStore.Models.Basket", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("PhoneId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("PhoneId");
b.ToTable("Baskets");
});
modelBuilder.Entity("PhoneStore.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Address")
.HasColumnType("TEXT");
b.Property<string>("ContactPhone")
.HasColumnType("TEXT");
b.Property<int>("PhoneId")
.HasColumnType("INTEGER");
b.Property<string>("UserName")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("PhoneId");
b.ToTable("Orders");
});
modelBuilder.Entity("PhoneStore.Models.Phone", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Company")
.HasColumnType("TEXT");
b.Property<string>("Name")
.HasColumnType("TEXT");
b.Property<decimal>("Price")
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Phones");
});
modelBuilder.Entity("PhoneStore.Models.Basket", b =>
{
b.HasOne("PhoneStore.Models.Phone", "Phone")
.WithMany()
.HasForeignKey("PhoneId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Phone");
});
modelBuilder.Entity("PhoneStore.Models.Order", b =>
{
b.HasOne("PhoneStore.Models.Phone", "Phone")
.WithMany()
.HasForeignKey("PhoneId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Phone");
});
#pragma warning restore 612, 618
}
}
}
using Microsoft.EntityFrameworkCore.Migrations;
namespace PhoneStore.Migrations
{
public partial class AddBasketEntity : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Baskets",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
PhoneId = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Baskets", x => x.Id);
table.ForeignKey(
name: "FK_Baskets_Phones_PhoneId",
column: x => x.PhoneId,
principalTable: "Phones",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Baskets_PhoneId",
table: "Baskets",
column: "PhoneId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Baskets");
}
}
}
......@@ -15,6 +15,22 @@ namespace PhoneStore.Migrations
modelBuilder
.HasAnnotation("ProductVersion", "5.0.17");
modelBuilder.Entity("PhoneStore.Models.Basket", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("PhoneId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("PhoneId");
b.ToTable("Baskets");
});
modelBuilder.Entity("PhoneStore.Models.Order", b =>
{
b.Property<int>("Id")
......@@ -60,6 +76,17 @@ namespace PhoneStore.Migrations
b.ToTable("Phones");
});
modelBuilder.Entity("PhoneStore.Models.Basket", b =>
{
b.HasOne("PhoneStore.Models.Phone", "Phone")
.WithMany()
.HasForeignKey("PhoneId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Phone");
});
modelBuilder.Entity("PhoneStore.Models.Order", b =>
{
b.HasOne("PhoneStore.Models.Phone", "Phone")
......
using PhoneStore.ViewModels;
namespace PhoneStore.Models
{
public class Basket : BaseEntity
{
public int PhoneId { get; set; }
public virtual Phone Phone { get; set; }
}
}
\ No newline at end of file
......@@ -6,6 +6,7 @@ namespace PhoneStore.Models
{
public DbSet<Phone> Phones { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<Basket> Baskets { get; set; }
public MobileContext(DbContextOptions<MobileContext> options) : base(options)
{
......
using System.Collections.Generic;
using PhoneStore.Enums;
using PhoneStore.Models;
namespace PhoneStore.Services.Abstractions
{
public interface IBasketService
{
StatusCodes AddPhone(int id);
List<Basket> GetAll();
void Remove(int id);
}
}
\ No newline at end of file
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using PhoneStore.Enums;
using PhoneStore.Models;
using PhoneStore.Services.Abstractions;
namespace PhoneStore.Services
{
public class BasketService : IBasketService
{
private readonly MobileContext _context;
public BasketService(MobileContext context)
{
_context = context;
}
public StatusCodes AddPhone(int id)
{
var exists = _context.Phones.Any(p => p.Id == id);
if (!exists) return StatusCodes.EntityNotFound;
_context.Baskets.Add(new Basket{PhoneId = id});
_context.SaveChanges();
return StatusCodes.Success;
}
public List<Basket> GetAll()
{
return _context.Baskets
.Include(b => b.Phone)
.ToList();
}
public void Remove(int id)
{
var basket = _context.Baskets.FirstOrDefault(b => b.PhoneId == id);
if (basket is null)
{
return;
}
_context.Baskets.Remove(basket);
_context.SaveChanges();
}
}
}
\ No newline at end of file
using System.Text;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using PhoneStore.Models;
using PhoneStore.Services;
using PhoneStore.Services.Abstractions;
namespace PhoneStore
{
......@@ -16,18 +20,39 @@ namespace PhoneStore
}
public IConfiguration Configuration { get; }
private IServiceCollection _services;
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
_services = services;
string connection = Configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<MobileContext>(options => options.UseSqlite(connection));
services.AddControllersWithViews();
services.AddScoped<IBasketService, BasketService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// app.Run(async context =>
// {
// var sb = new StringBuilder();
// sb.Append("<h1>Все сервисы</h1>");
// sb.Append("<table>");
// sb.Append("<tr><th>Тип</th><th>Lifetime</th><th>Реализация</th></tr>");
// foreach (var svc in _services)
// {
// sb.Append("<tr>");
// sb.Append($"<td>{svc.ServiceType.FullName}</td>");
// sb.Append($"<td>{svc.Lifetime}</td>");
// sb.Append($"<td>{svc.ImplementationType?.FullName}</td>");
// sb.Append("</tr>");
// }
// sb.Append("</table>");
// context.Response.ContentType = "text/html;charset=utf-8";
// await context.Response.WriteAsync(sb.ToString());
// });
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
......@@ -43,9 +68,7 @@ namespace PhoneStore
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
......
namespace PhoneStore.ViewModels
{
public class BaseEntity
{
public int Id { get; set; }
}
}
\ No newline at end of file
using PhoneStore.Enums;
namespace PhoneStore.ViewModels
{
public class ResponseMessageViewModel
{
public string Message { get; set; }
public StatusCodes Status { get; set; }
}
}
\ No newline at end of file
@model ResponseMessageViewModel
@{
ViewBag.Title = "title";
Layout = "_Layout";
}
<h2>@Model.Status : @Model.Message</h2>
<a asp-action="Index" asp-controller="Basket">Перейти в корзину</a>
@model List<Basket>
@{
ViewBag.Title = "title";
Layout = "_Layout";
}
<h2>Корзина</h2>
<table style="width: 100%">
<tr>
<th>Id</th>
<th>Наименование</th>
<th>Компания</th>
<th>Стоимость</th>
<th></th>
</tr>
@foreach (var basket in Model)
{
<tr>
<td>@basket.PhoneId</td>
<td>@basket.Phone.Name</td>
<td>@basket.Phone.Company</td>
<td>@basket.Phone.Price</td>
<td><a asp-route-id="@basket.PhoneId" asp-action="Remove" asp-controller="Basket" class="btn btn-outline-danger">Удалить из корзины</a></td>
</tr>
}
</table>
\ No newline at end of file
......@@ -6,7 +6,7 @@
}
<a asp-action="Create" asp-controller="Phone">Добавить устройство</a>
@* https://localhost:5001/Phone/Create method GET*@
@if (Model.Count == 0)
{
<h2>Список пуст.</h2>
......@@ -20,6 +20,7 @@ else
<th>Наименование</th>
<th>Компания</th>
<th>Стоимость</th>
<th></th>
</tr>
@foreach (var phone in Model)
{
......@@ -28,6 +29,14 @@ else
<td>@phone.Name</td>
<td>@phone.Company</td>
<td>@phone.Price</td>
<td>
<a asp-route-id="@phone.Id"
asp-action="Add"
asp-controller="Basket"
class="btn btn-outline-warning">
В корзину
</a>
</td>
</tr>
}
</table>
......
@using PhoneStore
@using PhoneStore.Models
@using PhoneStore.ViewModels
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment