Spaces:
Running
Running
| using ECommerce.Model.Data; | |
| using ECommerce.Model.Entities; | |
| using ECommerce.Model.Repositories; | |
| using ECommerce.Presenter.Presenters; | |
| using ECommerce.Presenter.ViewModels; | |
| using Microsoft.AspNetCore.Authorization; | |
| using Microsoft.AspNetCore.Identity; | |
| using Microsoft.AspNetCore.Mvc; | |
| using Microsoft.EntityFrameworkCore; | |
| namespace Ecommerce_web_project.Controllers; | |
| public class HomeController : Controller | |
| { | |
| private readonly ProductListPresenter _presenter; | |
| private readonly ReviewPresenter _reviewPresenter; | |
| private readonly IRepository<Product> _productRepo; | |
| private readonly UserManager<IdentityUser> _userManager; | |
| private readonly IEmailSender _emailSender; | |
| private readonly AppDbContext _context; | |
| public HomeController(ProductListPresenter presenter, ReviewPresenter reviewPresenter, IRepository<Product> productRepo, UserManager<IdentityUser> userManager, IEmailSender emailSender, AppDbContext context) | |
| { | |
| _presenter = presenter; | |
| _reviewPresenter = reviewPresenter; | |
| _productRepo = productRepo; | |
| _userManager = userManager; | |
| _emailSender = emailSender; | |
| _context = context; | |
| } | |
| public async Task<IActionResult> Index(Guid? categoryId, string? search) | |
| { | |
| var model = await _presenter.GetProductListAsync(search, categoryId); | |
| var allProducts = await _context.Products.Include(p => p.Category).ToListAsync(); | |
| var allProductIds = allProducts.Select(p => p.Id).ToList(); | |
| var allReviews = await _context.Reviews.Where(r => allProductIds.Contains(r.ProductId)).ToListAsync(); | |
| var ratingLookup = allReviews.GroupBy(r => r.ProductId).ToDictionary(g => g.Key, g => g.Average(r => (double)r.Rating)); | |
| var countLookup = allReviews.GroupBy(r => r.ProductId).ToDictionary(g => g.Key, g => g.Count()); | |
| ViewBag.NewArrivals = allProducts | |
| .OrderByDescending(p => p.CreatedAt) | |
| .Take(5) | |
| .Select(p => new ProductViewModel | |
| { | |
| Id = p.Id, | |
| Name = p.Name, | |
| Description = p.Description, | |
| Price = p.Price, | |
| ImageUrl = p.ImageUrl, | |
| StockQuantity = p.StockQuantity, | |
| CategoryName = p.Category.Name, | |
| CategoryId = p.CategoryId, | |
| AverageRating = ratingLookup.GetValueOrDefault(p.Id, 0), | |
| ReviewCount = countLookup.GetValueOrDefault(p.Id, 0) | |
| }).ToList(); | |
| var salesData = await _context.OrderItems | |
| .GroupBy(oi => oi.ProductId) | |
| .Select(g => new { ProductId = g.Key, TotalSold = g.Sum(oi => oi.Quantity) }) | |
| .ToListAsync(); | |
| var bestSellerIds = salesData | |
| .OrderByDescending(s => s.TotalSold) | |
| .Take(5) | |
| .Select(s => s.ProductId) | |
| .ToHashSet(); | |
| ViewBag.BestSellers = allProducts | |
| .Where(p => bestSellerIds.Contains(p.Id)) | |
| .OrderByDescending(p => bestSellerIds.Contains(p.Id) ? salesData.First(s => s.ProductId == p.Id).TotalSold : 0) | |
| .Take(5) | |
| .Select(p => new ProductViewModel | |
| { | |
| Id = p.Id, | |
| Name = p.Name, | |
| Description = p.Description, | |
| Price = p.Price, | |
| ImageUrl = p.ImageUrl, | |
| StockQuantity = p.StockQuantity, | |
| CategoryName = p.Category.Name, | |
| CategoryId = p.CategoryId, | |
| AverageRating = ratingLookup.GetValueOrDefault(p.Id, 0), | |
| ReviewCount = countLookup.GetValueOrDefault(p.Id, 0) | |
| }).ToList(); | |
| if (ViewBag.BestSellers.Count == 0) | |
| { | |
| ViewBag.BestSellers = allProducts | |
| .OrderByDescending(p => p.CreatedAt) | |
| .Take(5) | |
| .Select(p => new ProductViewModel | |
| { | |
| Id = p.Id, | |
| Name = p.Name, | |
| Description = p.Description, | |
| Price = p.Price, | |
| ImageUrl = p.ImageUrl, | |
| StockQuantity = p.StockQuantity, | |
| CategoryName = p.Category.Name, | |
| CategoryId = p.CategoryId, | |
| AverageRating = ratingLookup.GetValueOrDefault(p.Id, 0), | |
| ReviewCount = countLookup.GetValueOrDefault(p.Id, 0) | |
| }).ToList(); | |
| } | |
| ViewBag.RecentReviews = await _reviewPresenter.GetRecentReviewsAsync(6); | |
| return View(model); | |
| } | |
| public async Task<IActionResult> Shop(Guid? categoryId, string? search, string? sortBy, int page = 1) | |
| { | |
| var model = await _presenter.GetProductListAsync(search, categoryId, sortBy, page, 10); | |
| return View("Shop", model); | |
| } | |
| public async Task<IActionResult> Details(Guid id) | |
| { | |
| var product = await _presenter.GetProductByIdAsync(id); | |
| if (product is null) return NotFound(); | |
| var reviews = await _reviewPresenter.GetReviewsAsync(id); | |
| product.AverageRating = reviews.Any() ? reviews.Average(r => r.Rating) : 0; | |
| product.ReviewCount = reviews.Count; | |
| ViewBag.Reviews = reviews; | |
| return View(product); | |
| } | |
| [] | |
| [] | |
| public async Task<IActionResult> AddReview(ReviewRequest request) | |
| { | |
| var product = await _productRepo.GetByIdAsync(request.ProductId); | |
| if (product is null) return NotFound(); | |
| var user = await _userManager.GetUserAsync(User); | |
| await _reviewPresenter.AddReviewAsync(request, user!.Id, user.Email ?? "Anonymous"); | |
| TempData["ReviewSuccess"] = "Review submitted!"; | |
| return RedirectToAction("Details", new { id = request.ProductId }); | |
| } | |
| public IActionResult Privacy() => View(); | |
| public IActionResult Faq() => View(); | |
| [] | |
| public IActionResult Contact() => View(); | |
| [] | |
| public async Task<IActionResult> Contact(string name, string email, string message) | |
| { | |
| if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(email) || string.IsNullOrWhiteSpace(message)) | |
| { | |
| ModelState.AddModelError("", "All fields are required."); | |
| return View(); | |
| } | |
| var body = $""" | |
| <h2>New Contact Message</h2> | |
| <p><strong>Name:</strong> {name}</p> | |
| <p><strong>Email:</strong> {email}</p> | |
| <p><strong>Message:</strong></p> | |
| <p>{message}</p> | |
| """; | |
| try | |
| { | |
| await _emailSender.SendEmailAsync("danishnaseer000@gmail.com", $"Contact Form — {name}", body); | |
| TempData["Success"] = "Message sent! We'll get back to you soon."; | |
| } | |
| catch | |
| { | |
| ModelState.AddModelError("", "Failed to send message. Please try again."); | |
| return View(); | |
| } | |
| return RedirectToAction("Contact"); | |
| } | |
| } | |