Mass refactoring
This commit is contained in:
parent
81c1fc0c14
commit
3bade8859b
@ -1,147 +0,0 @@
|
||||
using System.Data;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MyDarling.Models;
|
||||
|
||||
namespace MyDarling.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class BundleController : Controller
|
||||
{
|
||||
private DataContext context;
|
||||
private IWebHostEnvironment environment;
|
||||
|
||||
public BundleController(DataContext context, IWebHostEnvironment environment)
|
||||
{
|
||||
this.environment = environment;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public ActionResult Index()
|
||||
{
|
||||
return View(context.UnderwearBundles.Include(b => b.Figures));
|
||||
}
|
||||
|
||||
public ActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ActionResult> Create([Bind] UnderwearBundle bundle)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
await context.UnderwearBundles.AddAsync(bundle);
|
||||
context.SaveChanges();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
}
|
||||
catch (DataException)
|
||||
{
|
||||
ModelState.AddModelError("", "Unable to save changes");
|
||||
}
|
||||
return View(bundle);
|
||||
}
|
||||
|
||||
public async Task<ActionResult> Details(int id)
|
||||
{
|
||||
return View(await context.UnderwearBundles.Include(b => b.Figures).Where(b => b.Id == id).FirstOrDefaultAsync());
|
||||
}
|
||||
|
||||
public async Task<ActionResult> Edit(int id)
|
||||
{
|
||||
return View(nameof(Details), await context.UnderwearBundles.FindAsync(id));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ActionResult> Edit(int? id)
|
||||
{
|
||||
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var bundle = await context.UnderwearBundles.FindAsync(id);
|
||||
if (bundle == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var file = Request.Form.Files.FirstOrDefault();
|
||||
|
||||
if (await TryUpdateModelAsync<UnderwearBundle>(
|
||||
bundle,
|
||||
"",
|
||||
b => b.Name, b => b.Description, b => b.Figures, b => b.Price))
|
||||
{
|
||||
if (file != null)
|
||||
{
|
||||
var newFigure = new Figure();
|
||||
bundle.Figures.Add(newFigure);
|
||||
newFigure.FilePath = $"/Content/{bundle.Id}/{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";
|
||||
var savePath = environment.WebRootPath + "/Content/" + bundle.Id + "/";
|
||||
if (!Directory.Exists(savePath))
|
||||
{
|
||||
Directory.CreateDirectory(savePath);
|
||||
}
|
||||
using var fileStream = new FileStream(environment.WebRootPath + newFigure.FilePath, FileMode.Create);
|
||||
await file.CopyToAsync(fileStream);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await context.SaveChangesAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
catch (System.Exception)
|
||||
{
|
||||
ModelState.AddModelError("", "Unable to save changes");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return View(bundle);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ActionResult> Delete(int id)
|
||||
{
|
||||
var bundleToDelete = await context.UnderwearBundles.FindAsync(id);
|
||||
if (bundleToDelete == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var bundleDirPath = String.Concat(environment.WebRootPath,
|
||||
"/Content/",
|
||||
bundleToDelete.Id);
|
||||
|
||||
if (Directory.Exists(bundleDirPath))
|
||||
{
|
||||
Directory.Delete(bundleDirPath, true);
|
||||
}
|
||||
// foreach (var figure in bundleToDelete.Figures)
|
||||
// {
|
||||
// using FigureController controller = new(context, environment);
|
||||
// await controller.Delete(figure.Id);
|
||||
// }
|
||||
|
||||
context.UnderwearBundles.Remove(bundleToDelete);
|
||||
await context.SaveChangesAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
catch (DbUpdateException)
|
||||
{
|
||||
return RedirectToAction(nameof(Delete), new { id = id, saveChangesError = true });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -17,27 +17,43 @@ namespace MyDarling.Controllers
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Details(int id)
|
||||
public async Task<IActionResult> Details(string id)
|
||||
{
|
||||
return View(await context.Figures.Where(f => f.Id == id).FirstOrDefaultAsync());
|
||||
var figure = await context.Figures
|
||||
.Where(f => f.Id.Equals(id))
|
||||
.FirstOrDefaultAsync();
|
||||
if (figure == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
var product = await context.Products
|
||||
.Where(b => b.Figures.Contains(figure))
|
||||
.FirstOrDefaultAsync();
|
||||
if (product == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
return View(figure);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Edit(int? id)
|
||||
public async Task<IActionResult> Edit(string id)
|
||||
{
|
||||
if (id == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var figure = await context.Figures.FindAsync(id);
|
||||
var figure = await context.Figures
|
||||
.Where(f => f.Id.Equals(id))
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (figure == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var bundle = await context.UnderwearBundles
|
||||
var product = await context.Products
|
||||
.Where(b => b.Figures.Contains(figure))
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
@ -49,7 +65,7 @@ namespace MyDarling.Controllers
|
||||
try
|
||||
{
|
||||
await context.SaveChangesAsync();
|
||||
return RedirectToAction("Details", "Bundle", new { Id = bundle?.Id});
|
||||
return RedirectToAction("Details", "Products", new { Id = product?.Id });
|
||||
}
|
||||
catch (SystemException)
|
||||
{
|
||||
@ -60,25 +76,29 @@ namespace MyDarling.Controllers
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ActionResult> Delete(int id)
|
||||
public async Task<ActionResult> Delete(string id)
|
||||
{
|
||||
var figureToDelete = await context.Figures.FindAsync(id);
|
||||
if (figureToDelete == null)
|
||||
var figure = await context.Figures.FindAsync(id);
|
||||
if (figure == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
var product = await context.Products
|
||||
.Where(b => b.Figures.Contains(figure))
|
||||
.FirstAsync();
|
||||
|
||||
try
|
||||
{
|
||||
FileInfo figureFile = new FileInfo(environment.WebRootPath + figureToDelete.FilePath);
|
||||
string filePath = $"/Content/{product.Id}/{figure.Id}.jpg";
|
||||
FileInfo figureFile = new FileInfo(environment.WebRootPath + filePath);
|
||||
if (figureFile.Exists)
|
||||
{
|
||||
figureFile.Delete();
|
||||
}
|
||||
|
||||
context.Figures.Remove(figureToDelete);
|
||||
context.Figures.Remove(figure);
|
||||
await context.SaveChangesAsync();
|
||||
return RedirectToAction(nameof(Index), "Bundle");
|
||||
return RedirectToAction("Details", "Products", new { Id = product?.Id });
|
||||
}
|
||||
catch (DbUpdateException)
|
||||
{
|
||||
|
133
Controllers/ProductsController.cs
Normal file
133
Controllers/ProductsController.cs
Normal file
@ -0,0 +1,133 @@
|
||||
using System.Data;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MyDarling.Models;
|
||||
|
||||
namespace MyDarling.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class ProductsController : Controller
|
||||
{
|
||||
private DataContext context;
|
||||
private IWebHostEnvironment environment;
|
||||
|
||||
public ProductsController(DataContext context, IWebHostEnvironment environment)
|
||||
{
|
||||
this.environment = environment;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View(context.Products.Include(b => b.Figures));
|
||||
}
|
||||
|
||||
public IActionResult Create()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Create([Bind] Product bundle)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
await context.Products.AddAsync(bundle);
|
||||
context.SaveChanges();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
}
|
||||
catch (DataException)
|
||||
{
|
||||
ModelState.AddModelError("", "Unable to save changes");
|
||||
}
|
||||
return View(bundle);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Details(string id)
|
||||
{
|
||||
return View(await context.Products.Include(b => b.Figures).Where(b => b.Id.Equals(id)).FirstOrDefaultAsync());
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Edit(string id)
|
||||
{
|
||||
if (string.IsNullOrEmpty(id))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var product = await context.Products.FindAsync(id);
|
||||
if (product == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var file = Request.Form.Files.FirstOrDefault();
|
||||
|
||||
if (await TryUpdateModelAsync<Product>(
|
||||
product,
|
||||
"",
|
||||
b => b.Name, b => b.Description, b => b.Figures, b => b.Price))
|
||||
{
|
||||
if (file != null)
|
||||
{
|
||||
var newFigure = new Figure(string.Empty, product.Id);
|
||||
product.Figures.Add(newFigure);
|
||||
string filePath = $"/Content/{product.Id}/{newFigure.Id}.jpg";
|
||||
var savePath = environment.WebRootPath + "/Content/" + product.Id + "/";
|
||||
if (!Directory.Exists(savePath))
|
||||
{
|
||||
Directory.CreateDirectory(savePath);
|
||||
}
|
||||
using var fileStream = new FileStream(environment.WebRootPath + filePath, FileMode.Create);
|
||||
await file.CopyToAsync(fileStream);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await context.SaveChangesAsync();
|
||||
return RedirectToAction("Details", "Products", new { Id = product?.Id});
|
||||
}
|
||||
|
||||
catch (System.Exception)
|
||||
{
|
||||
ModelState.AddModelError("", "Unable to save changes");
|
||||
}
|
||||
}
|
||||
return View(product);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Delete(string id)
|
||||
{
|
||||
var productToDelete = await context.Products.FindAsync(id);
|
||||
if (productToDelete == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var bundleDirPath = String.Concat(environment.WebRootPath,
|
||||
"/Content/",
|
||||
productToDelete.Id);
|
||||
|
||||
if (Directory.Exists(bundleDirPath))
|
||||
{
|
||||
Directory.Delete(bundleDirPath, true);
|
||||
}
|
||||
context.Products.Remove(productToDelete);
|
||||
await context.SaveChangesAsync();
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
catch (DbUpdateException)
|
||||
{
|
||||
return RedirectToAction(nameof(Delete), new { id = id, saveChangesError = true });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
@ -11,8 +10,8 @@ using MyDarling.Models;
|
||||
namespace MyDarling.Migrations
|
||||
{
|
||||
[DbContext(typeof(DataContext))]
|
||||
[Migration("20230303041621_Init")]
|
||||
partial class Init
|
||||
[Migration("20230603040054_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
@ -22,33 +21,28 @@ namespace MyDarling.Migrations
|
||||
|
||||
modelBuilder.Entity("MyDarling.Models.Figure", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("FilePath")
|
||||
b.Property<string>("ProductId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("UnderwearBundleId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UnderwearBundleId");
|
||||
b.HasIndex("ProductId");
|
||||
|
||||
b.ToTable("Figures");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyDarling.Models.UnderwearBundle", b =>
|
||||
modelBuilder.Entity("MyDarling.Models.Product", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
@ -63,17 +57,19 @@ namespace MyDarling.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("UnderwearBundles");
|
||||
b.ToTable("Products");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyDarling.Models.Figure", b =>
|
||||
{
|
||||
b.HasOne("MyDarling.Models.UnderwearBundle", null)
|
||||
b.HasOne("MyDarling.Models.Product", null)
|
||||
.WithMany("Figures")
|
||||
.HasForeignKey("UnderwearBundleId");
|
||||
.HasForeignKey("ProductId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyDarling.Models.UnderwearBundle", b =>
|
||||
modelBuilder.Entity("MyDarling.Models.Product", b =>
|
||||
{
|
||||
b.Navigation("Figures");
|
||||
});
|
@ -5,50 +5,48 @@
|
||||
namespace MyDarling.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Init : Migration
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "UnderwearBundles",
|
||||
name: "Products",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Description = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Price = table.Column<decimal>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_UnderwearBundles", x => x.Id);
|
||||
table.PrimaryKey("PK_Products", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Figures",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Description = table.Column<string>(type: "TEXT", nullable: false),
|
||||
FilePath = table.Column<string>(type: "TEXT", nullable: false),
|
||||
UnderwearBundleId = table.Column<int>(type: "INTEGER", nullable: true)
|
||||
ProductId = table.Column<string>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Figures", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Figures_UnderwearBundles_UnderwearBundleId",
|
||||
column: x => x.UnderwearBundleId,
|
||||
principalTable: "UnderwearBundles",
|
||||
principalColumn: "Id");
|
||||
name: "FK_Figures_Products_ProductId",
|
||||
column: x => x.ProductId,
|
||||
principalTable: "Products",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Figures_UnderwearBundleId",
|
||||
name: "IX_Figures_ProductId",
|
||||
table: "Figures",
|
||||
column: "UnderwearBundleId");
|
||||
column: "ProductId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -58,7 +56,7 @@ namespace MyDarling.Migrations
|
||||
name: "Figures");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "UnderwearBundles");
|
||||
name: "Products");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
@ -19,33 +18,28 @@ namespace MyDarling.Migrations
|
||||
|
||||
modelBuilder.Entity("MyDarling.Models.Figure", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("FilePath")
|
||||
b.Property<string>("ProductId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("UnderwearBundleId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UnderwearBundleId");
|
||||
b.HasIndex("ProductId");
|
||||
|
||||
b.ToTable("Figures");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyDarling.Models.UnderwearBundle", b =>
|
||||
modelBuilder.Entity("MyDarling.Models.Product", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
@ -60,17 +54,19 @@ namespace MyDarling.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("UnderwearBundles");
|
||||
b.ToTable("Products");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyDarling.Models.Figure", b =>
|
||||
{
|
||||
b.HasOne("MyDarling.Models.UnderwearBundle", null)
|
||||
b.HasOne("MyDarling.Models.Product", null)
|
||||
.WithMany("Figures")
|
||||
.HasForeignKey("UnderwearBundleId");
|
||||
.HasForeignKey("ProductId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyDarling.Models.UnderwearBundle", b =>
|
||||
modelBuilder.Entity("MyDarling.Models.Product", b =>
|
||||
{
|
||||
b.Navigation("Figures");
|
||||
});
|
||||
|
@ -14,13 +14,7 @@ namespace MyDarling.Models
|
||||
{
|
||||
opts.UseSqlite(configuration.GetConnectionString("MyDarlingDb"));
|
||||
}
|
||||
|
||||
// protected override void OnModelCreating(ModelBuilder builder)
|
||||
// {
|
||||
// builder.Entity<UnderwearBundle>().HasMany(b => b.Figures).WithOne();
|
||||
// }
|
||||
|
||||
public DbSet<UnderwearBundle> UnderwearBundles => Set<UnderwearBundle>();
|
||||
public DbSet<Product> Products => Set<Product>();
|
||||
public DbSet<Figure> Figures => Set<Figure>();
|
||||
}
|
||||
}
|
@ -2,8 +2,15 @@ namespace MyDarling.Models
|
||||
{
|
||||
public class Figure
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Id { get; set; }
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public string FilePath { get; set; } = string.Empty;
|
||||
public string ProductId { get; set; }
|
||||
|
||||
public Figure(string description, string productId)
|
||||
{
|
||||
Id = Guid.NewGuid().ToString();
|
||||
Description = description;
|
||||
ProductId = productId;
|
||||
}
|
||||
}
|
||||
}
|
@ -9,5 +9,5 @@ public class LoginModel
|
||||
[Required]
|
||||
public string? Password { get; set; }
|
||||
|
||||
public string ReturnUrl { get; set; } = "/Bundle";
|
||||
public string ReturnUrl { get; set; } = "/Products";
|
||||
}
|
15
Models/Product.cs
Normal file
15
Models/Product.cs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace MyDarling.Models
|
||||
{
|
||||
public class Product
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public List<Figure> Figures { get; set; } = new List<Figure>();
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public decimal Price { get; set; } = 1000M;
|
||||
public Product()
|
||||
{
|
||||
Id = Guid.NewGuid().ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace MyDarling.Models
|
||||
{
|
||||
public class UnderwearBundle
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; } = "My Darling Bundle";
|
||||
public List<Figure> Figures { get; set; } = new List<Figure>();
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public decimal Price { get; set; }
|
||||
}
|
||||
}
|
124
Pages/Figure.cshtml
Normal file
124
Pages/Figure.cshtml
Normal file
@ -0,0 +1,124 @@
|
||||
@* @page "{id}"
|
||||
@model FigureModel;
|
||||
@using MyDarling.Models;
|
||||
@using Microsoft.EntityFrameworkCore;
|
||||
@using Microsoft.AspNetCore.Mvc.RazorPages
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Редактирование фотографии</title>
|
||||
<link href="/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-dark bg-primary">
|
||||
<a class="navbar-brand mx-4" href="/Bundle"><img height="30" src="/assets/img/logo.svg"></a>
|
||||
<a href="/Account/logout"><button class="btn btn-outline-light mx-4">Выйти</button></a>
|
||||
</nav>
|
||||
<div class="container">
|
||||
<div class="row row-cols-xl-3 row-cols-md-2 justify-content-center mt-3">
|
||||
<div class="col">
|
||||
<div class="thumbnail">
|
||||
<a href="@Model.FilePath">
|
||||
<img src="@Model.FilePath" class="img-thumbnail img-fluid" alt="@Model.Figure?.Description">
|
||||
</a>
|
||||
</div>
|
||||
<form method="post" class="m-2">
|
||||
@Html.AntiForgeryToken()
|
||||
<div class="form-group">
|
||||
<label class="form-label">Описание:</label>
|
||||
<input name="description" class="form-control" value="@Model.Figure?.Description" />
|
||||
</div>
|
||||
<button type="submit" class="btn btn-outline-success mt-2">Сохранить</button>
|
||||
</form>
|
||||
<form asp-page-handler="Delete" method="post">
|
||||
<button type="submit" class="btn btn-outline-danger mt-2">Удалить</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@functions
|
||||
{
|
||||
public class FigureModel : PageModel
|
||||
{
|
||||
private DataContext context;
|
||||
private IWebHostEnvironment environment;
|
||||
public string? FilePath { get; set; }
|
||||
public Figure? Figure { get; set; }
|
||||
public UnderwearBundle? Bundle { get; set; }
|
||||
public FigureModel(DataContext context, IWebHostEnvironment environment)
|
||||
{
|
||||
this.context = context;
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(string id)
|
||||
{
|
||||
Figure = await context.Figures
|
||||
.Where(f => f.Id.Equals(id))
|
||||
.FirstOrDefaultAsync();
|
||||
if (Figure == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
Bundle = await context.UnderwearBundles
|
||||
.Where(b => b.Figures.Contains(Figure))
|
||||
.FirstOrDefaultAsync();
|
||||
if (Bundle == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
FilePath = $"/Content/{Bundle.Id}/{Figure.Id}.jpg";
|
||||
|
||||
return Page();
|
||||
}
|
||||
public async Task<IActionResult> OnPostAsync(string id, string description)
|
||||
{
|
||||
Figure = await context.Figures
|
||||
.Where(f => f.Id.Equals(id))
|
||||
.FirstOrDefaultAsync();
|
||||
if (Figure != null)
|
||||
{
|
||||
Figure.Description = description ?? string.Empty;
|
||||
}
|
||||
await context.SaveChangesAsync();
|
||||
return RedirectToPage();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostDeleteAsync(string id)
|
||||
{
|
||||
Figure = await context.Figures.FindAsync(id);
|
||||
if (Figure == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
var parentBundle = await context.UnderwearBundles
|
||||
.Where(b => b.Figures.Contains(Figure))
|
||||
.FirstAsync();
|
||||
|
||||
try
|
||||
{
|
||||
string filePath = $"/Content/{parentBundle.Id}/{Figure}.jpg";
|
||||
FileInfo figureFile = new FileInfo(environment.WebRootPath + filePath);
|
||||
if (figureFile.Exists)
|
||||
{
|
||||
figureFile.Delete();
|
||||
}
|
||||
|
||||
context.Figures.Remove(Figure);
|
||||
await context.SaveChangesAsync();
|
||||
return RedirectToPage($"/Bundle/{Bundle.Id}");
|
||||
}
|
||||
catch (DbUpdateException)
|
||||
{
|
||||
return RedirectToPage($"/Bundle/{Bundle.Id}");
|
||||
}
|
||||
}
|
||||
}
|
||||
} *@
|
@ -9,5 +9,5 @@
|
||||
<partial name="_Navigation" />
|
||||
<partial name="_Masthead" />
|
||||
<partial name="_About" />
|
||||
<partial name="_Projects" />
|
||||
<partial name="_Products" />
|
||||
<partial name="_SignUp" />
|
@ -10,7 +10,7 @@
|
||||
<div class="collapse navbar-collapse" id="navbarResponsive">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item"><a class="nav-link" href="#about">О нас</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#projects">Комплекты</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#products">Комплекты</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#signup">Заказать</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
44
Pages/Shared/_Products.cshtml
Normal file
44
Pages/Shared/_Products.cshtml
Normal file
@ -0,0 +1,44 @@
|
||||
@using System.Globalization
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
@using MyDarling.Models
|
||||
@inject DataContext context
|
||||
|
||||
@{
|
||||
var products = context.Products
|
||||
.Include(b => b.Figures)
|
||||
.Where(b => b.Price != 0 && b.Figures.Count > 0)
|
||||
.OrderByDescending(b => b.Id);
|
||||
}
|
||||
|
||||
<section class="projects-section bg-light" id="products">
|
||||
<div class="container px-3 px-lg-4 mt-4">
|
||||
<div class="row gx-4 gx-lg-5 row-cols-2 row-cols-md-3 row-cols-xl-4 justify-content-center">
|
||||
@foreach (var product in products)
|
||||
{
|
||||
<div class="col mb-5">
|
||||
<div class="card h-100">
|
||||
@{
|
||||
var figure = product.Figures.First();
|
||||
var filePath = $"/Content/{product.Id}/{figure.Id}.jpg";
|
||||
}
|
||||
<a data-src="@filePath" data-fancybox="@product.Id"
|
||||
data-caption="@figure.Description"><img class="card-img-top"
|
||||
src="@filePath" alt="@product.Name" /></a>
|
||||
@for (int i = 1; i < product.Figures.Count(); i++)
|
||||
{
|
||||
filePath = $"/Content/{product.Id}/{product.Figures[i].Id}.jpg";
|
||||
<a data-src="@filePath" data-fancybox="@product.Id"
|
||||
data-caption="@product.Figures[i].Description"></a>
|
||||
}
|
||||
<div class="card-body p-4">
|
||||
<div class="text-center">
|
||||
<h5 class="fw-bolder">@product.Name</h5>
|
||||
@String.Format(new CultureInfo("ru-RU"), "{0:C0}", product.Price)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
@ -1,39 +0,0 @@
|
||||
@using System.Globalization
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
@using MyDarling.Models
|
||||
@inject DataContext context
|
||||
|
||||
@{
|
||||
var bundles = context.UnderwearBundles
|
||||
.Include(b => b.Figures)
|
||||
.Where(b => b.Price != 0 && b.Figures.Count > 0)
|
||||
.OrderByDescending(b => b.Id);
|
||||
}
|
||||
|
||||
<section class="projects-section bg-light" id="projects">
|
||||
<div class="container px-3 px-lg-4 mt-4">
|
||||
<div class="row gx-4 gx-lg-5 row-cols-2 row-cols-md-3 row-cols-xl-4 justify-content-center">
|
||||
@foreach (var bundle in bundles)
|
||||
{
|
||||
<div class="col mb-5">
|
||||
<div class="card h-100">
|
||||
<a data-src="@bundle.Figures[0].FilePath" data-fancybox="@bundle.Id"
|
||||
data-caption="@bundle.Figures[0].Description"><img class="card-img-top"
|
||||
src="@bundle.Figures[0].FilePath" alt="@bundle.Name" /></a>
|
||||
@for (int i = 1; i < @bundle.Figures.Count(); i++)
|
||||
{
|
||||
<a data-src="@bundle.Figures[i].FilePath" data-fancybox="@bundle.Id"
|
||||
data-caption="@bundle.Figures[i].Description"></a>
|
||||
}
|
||||
<div class="card-body p-4">
|
||||
<div class="text-center">
|
||||
<h5 class="fw-bolder">@bundle.Name</h5>
|
||||
@String.Format(new CultureInfo("ru-RU"), "{0:C0}", @bundle.Price)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
@ -5,7 +5,7 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>User Acccounts</title>
|
||||
<title>User Acсounts</title>
|
||||
<link href="/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
<form method="post">
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label>User Name</label>
|
||||
<label>Имя пользователя</label>
|
||||
<input name="UserName" class="form-control" value="@Model.UserName" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@ -22,11 +22,11 @@
|
||||
<input name="Email" class="form-control" value="@Model.Email" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Password</label>
|
||||
<label>Пароль</label>
|
||||
<input name="Password" class="form-control" value="" />
|
||||
</div>
|
||||
<div class="py-2">
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
<button type="submit" class="btn btn-primary">Сохранить</button>
|
||||
<a class="btn btn-secondary" asp-page="list">Back</a>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -1,53 +0,0 @@
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@model MyDarling.Models.UnderwearBundle
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Bundles list</title>
|
||||
<link href="/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<container>
|
||||
<form asp-action="Edit" asp-route-id="@Model.Id" method="post" enctype="multipart/form-data" class="m-2">
|
||||
<div asp-validation-summary="All"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Name" class="form-label">Name:</label>
|
||||
<input asp-for="Name" class="form-control" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Description" class="form-label">Description:</label>
|
||||
@Html.TextAreaFor(model => model.Description, new { @class="form-control", @rows = 2 })
|
||||
</div>
|
||||
<div>
|
||||
<label class="form-label">Figures:</label>
|
||||
<div class="row gx-4 gx-lg-5 row-cols-2 row-cols-md-3 row-cols-xl-4">
|
||||
@foreach (var figure in @Model.Figures)
|
||||
{
|
||||
<div class="col mb-5">
|
||||
<div class="thumbnail h-100">
|
||||
<a asp-controller="Figure" asp-action="Details" asp-route-id="@figure.Id">
|
||||
<img src="@figure.FilePath" class="img-thumbnail img-fluid" alt="@figure.Description">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="file" name="file" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Price" class="form-label">Price:</label>
|
||||
<input asp-for="Price" class="form-control" />
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mt-3">Save</button>
|
||||
<button asp-action="Delete" asp-route-id="@Model.Id" method="post"
|
||||
class="btn btn-primary mt-3">Delete</button>
|
||||
</form>
|
||||
</container>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,49 +0,0 @@
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@model IQueryable<MyDarling.Models.UnderwearBundle>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Bundles list</title>
|
||||
<link href="/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="navbar-brand ml-2">Underwear bundle list</span>
|
||||
</div>
|
||||
<div class="col-2 text-right">
|
||||
<a class="btn btn-sm btn-primary" href="/account/logout">Log Out</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<container>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Descrition</th>
|
||||
<th scope="col">Price</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var bundle in Model)
|
||||
{
|
||||
<tr>
|
||||
<th scope="row">@bundle.Id</th>
|
||||
<td><a asp-action="Details" asp-route-id="@bundle.Id">@bundle.Name</a></td>
|
||||
<td>@bundle.Description</td>
|
||||
<td>@bundle.Price</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<a asp-action="Create">Add bundle</a>
|
||||
</container>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -5,30 +5,39 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Figure</title>
|
||||
<title>Редактирование фотографии</title>
|
||||
<link href="/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="row gx-4 gx-lg-5 row-cols-2 row-cols-md-3 row-cols-xl-4 justify-content-center">
|
||||
<div class="col mb-5">
|
||||
<div class="thumbnail h-100">
|
||||
<a href="@Model.FilePath">
|
||||
<img src="@Model.FilePath" class="img-thumbnail img-fluid" alt="@Model.Description">
|
||||
<nav class="navbar navbar-dark bg-primary">
|
||||
<a class="navbar-brand mx-4" href="/Products"><img height="30" src="/assets/img/logo.svg"></a>
|
||||
<a href="/Account/logout"><button class="btn btn-outline-light mx-4">Выйти</button></a>
|
||||
</nav>
|
||||
<div class="container">
|
||||
<div class="row row-cols-xl-3 row-cols-md-2 justify-content-center mt-3">
|
||||
<div class="col">
|
||||
<div class="thumbnail">
|
||||
@{
|
||||
var filePath = $"/Content/{Model.ProductId}/{Model.Id}.jpg";
|
||||
}
|
||||
<a href="@filePath">
|
||||
<img src="@filePath" class="img-thumbnail img-fluid" alt="@Model.Description">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form asp-action="Edit" asp-route-id="@Model.Id" method="post" class="m-2">
|
||||
<div asp-validation-summary="All"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Description" class="form-label">Description:</label>
|
||||
<label asp-for="Description" class="form-label">Описание:</label>
|
||||
@Html.TextAreaFor(model => model.Description, new { @class="form-control", @rows = 2 })
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mt-3">Save</button>
|
||||
<button asp-action="Delete" asp-route-id="@Model.Id" method="post" class="btn btn-primary mt-3">Delete</button>
|
||||
<button type="submit" class="btn btn-outline-success mt-3">Сохранить</button>
|
||||
<button asp-action="Delete" asp-route-id="@Model.Id" method="post"
|
||||
class="btn btn-outline-danger mt-3">Удалить</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,5 +1,5 @@
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@model MyDarling.Models.UnderwearBundle
|
||||
@model MyDarling.Models.Product
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
@ -10,24 +10,28 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<container>
|
||||
<form asp-action="Create" method="post" class="m-2">
|
||||
<nav class="navbar navbar-dark bg-primary" aria-label="breadcrumb">
|
||||
<a class="navbar-brand mx-4" href="/Products"><img height="30" src="/assets/img/logo.svg"></a>
|
||||
<a href="/Account/logout"><button class="btn btn-outline-light mx-4">Выйти</button></a>
|
||||
</nav>
|
||||
<div class="row container-fluid justify-content-center">
|
||||
<form asp-action="Create" method="post" class="m-2 col-8">
|
||||
<div asp-validation-summary="All"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Name" class="form-label">Name:</label>
|
||||
<label asp-for="Name" class="form-label">Название:</label>
|
||||
<input asp-for="Name" class="form-control" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Description" class="form-label">Descrition:</label>
|
||||
<label asp-for="Description" class="form-label">Описание:</label>
|
||||
@Html.TextAreaFor(model => model.Description, new { @class="form-control", @rows = 2 })
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Price" class="form-label">Price:</label>
|
||||
<label asp-for="Price" class="form-label">Цена:</label>
|
||||
<input asp-for="Price" class="form-control" />
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mt-3">Submit</button>
|
||||
<button type="submit" class="btn btn-outline-success mt-3">Сохранить</button>
|
||||
</form>
|
||||
</container>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
60
Views/Products/Details.cshtml
Normal file
60
Views/Products/Details.cshtml
Normal file
@ -0,0 +1,60 @@
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@model MyDarling.Models.Product
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Комплект: @Model.Name</title>
|
||||
<link href="/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-dark bg-primary" aria-label="breadcrumb">
|
||||
<a class="navbar-brand mx-4" href="/Products"><img height="30" src="/assets/img/logo.svg"></a>
|
||||
<a href="/Account/logout"><button class="btn btn-outline-light mx-4">Выйти</button></a>
|
||||
</nav>
|
||||
<div class="row container-fluid justify-content-center">
|
||||
<form asp-action="Edit" asp-route-id="@Model.Id" method="post" enctype="multipart/form-data" class="m-2 col-8">
|
||||
<div asp-validation-summary="All"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Name" class="form-label">Название:</label>
|
||||
<input asp-for="Name" class="form-control" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Description" class="form-label">Описание:</label>
|
||||
@Html.TextAreaFor(model => model.Description, new { @class="form-control", @rows = 2 })
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Price" class="form-label">Цена:</label>
|
||||
<input asp-for="Price" class="form-control" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="form-label">Фотографии:</label>
|
||||
<div class="row row-cols-md-2 row-cols-xl-3">
|
||||
@foreach (var figure in @Model.Figures)
|
||||
{
|
||||
<div class="mb-3">
|
||||
<div class="thumbnail h-100">
|
||||
<a href="/Figure/Details/@figure.Id">
|
||||
@{
|
||||
var filePath = $"/Content/{@Model.Id}/{figure.Id}.jpg";
|
||||
}
|
||||
<img src="@filePath" class="img-thumbnail img-fluid" alt="@figure.Description">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="form-group mb-3">
|
||||
<input type="file" name="file" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-outline-success">Сохранить</button>
|
||||
<button asp-action="Delete" asp-route-id="@Model.Id" method="post"
|
||||
class="btn btn-outline-danger">Удалить</button>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
43
Views/Products/Index.cshtml
Normal file
43
Views/Products/Index.cshtml
Normal file
@ -0,0 +1,43 @@
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@model IQueryable<MyDarling.Models.Product>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>My Darling Underwear</title>
|
||||
<link href="/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-dark bg-primary">
|
||||
<a class="navbar-brand mx-4" href="/Products"><img height="30" src="/assets/img/logo.svg"></a>
|
||||
<a href="/Account/logout"><button class="btn btn-outline-light mx-4">Выйти</button></a>
|
||||
</nav>
|
||||
<div class="row container-fluid justify-content-center row-cols-xl-2">
|
||||
<div class="col">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Название</th>
|
||||
<th scope="col">Описание</th>
|
||||
<th scope="col">Цена</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var bundle in Model)
|
||||
{
|
||||
<tr>
|
||||
<td><a asp-action="Details" asp-route-id="@bundle.Id">@bundle.Name</a></td>
|
||||
<td>@bundle.Description</td>
|
||||
<td>@bundle.Price</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<a asp-action="Create"><button class="btn btn-primary">Добавить</button></a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user