Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Binary file added backend - Shortcut.lnk
Binary file not shown.
71 changes: 71 additions & 0 deletions backend/Controllers/AboutContentController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using backend.Data;
using backend.Models;

namespace backend.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class AboutContentController : ControllerBase
{
private readonly AppDbContext _context;

public AboutContentController(AppDbContext context)
{
_context = context;
}

[HttpGet]
public async Task<IActionResult> GetAll()
{
var contents = await _context.AboutContents.ToListAsync();
return Ok(contents);
}

[HttpPost]
public async Task<IActionResult> Add(AboutContent content)
{
_context.AboutContents.Add(content);
await _context.SaveChangesAsync();
return Ok(content);
}

[HttpPut("{id}")]
public async Task<IActionResult> Update(int id, [FromBody] AboutContent updatedContent)
{
// Find the existing entity by its primary key
var existing = await _context.AboutContents.FindAsync(id);
if (existing == null)
{
return NotFound();
}

// Update specific properties
existing.Content = updatedContent.Content;

// Check if the Section property is also part of the update
if (updatedContent.Section != null)
{
existing.Section = updatedContent.Section;
}

await _context.SaveChangesAsync();
return NoContent(); // Use NoContent for a successful PUT update
}

[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
var content = await _context.AboutContents.FindAsync(id);
if (content == null)
{
return NotFound();
}

_context.AboutContents.Remove(content);
await _context.SaveChangesAsync();
return NoContent();
}
}
}
43 changes: 43 additions & 0 deletions backend/Controllers/AddressesController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using backend.Data;
using backend.Models;

namespace backend.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class AddressesController : ControllerBase
{
private readonly AppDbContext _context;

public AddressesController(AppDbContext context)
{
_context = context;
}

// GET api/addresses/user/{email}
[HttpGet("user/{email}")]
public async Task<ActionResult<IEnumerable<Address>>> GetAddressesByUserEmail(string email)
{
var addresses = await _context.Addresses
.Where(a => a.Email == email)
.ToListAsync();

if (addresses == null || !addresses.Any())
{
return NotFound($"No addresses found for user with email {email}");
}

return Ok(addresses);
}

[HttpPost]
public async Task<ActionResult<Address>> PostAddress(Address address)
{
_context.Addresses.Add(address);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(PostAddress), new { id = address.Id }, address);
}
}
}
135 changes: 135 additions & 0 deletions backend/Controllers/AdminController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using backend.Data;
using System.Linq;

namespace backend.Controllers
{
[ApiController]
[Route("api/admin")]
public class AdminController : ControllerBase
{
private readonly AppDbContext _context;

public AdminController(AppDbContext context)
{
_context = context;
}

[HttpGet("sales-report")]
public async Task<IActionResult> GetSalesReport()
{
// Combine multiple queries into a single database call
var allOrders = await _context.Orders.ToListAsync();
var allOrderItems = await _context.OrderItems.Include(oi => oi.Book).ToListAsync();

var totalOrders = allOrders.Count;
var totalRevenue = allOrders.Sum(o => o.Total);
var totalBooksSold = allOrderItems.Sum(oi => oi.Quantity);

var topSelling = allOrderItems
.Where(oi => oi.Book != null)
.GroupBy(oi => oi.Book!.Title)
.Select(g => new { Title = g.Key, Count = g.Sum(x => x.Quantity) })
.OrderByDescending(g => g.Count)
.FirstOrDefault();

var leastSelling = allOrderItems
.Where(oi => oi.Book != null)
.GroupBy(oi => oi.Book!.Title)
.Select(g => new { Title = g.Key, Count = g.Sum(x => x.Quantity) })
.OrderBy(g => g.Count)
.FirstOrDefault();

var lastOrder = allOrders
.OrderByDescending(o => o.Date)
.FirstOrDefault();

var placedOrders = allOrders.Count(o => o.Status == "Placed");
var deliveredOrders = allOrders.Count(o => o.Status == "Delivered");
var cancelledOrders = allOrders.Count(o => o.Status == "Cancelled");
var returnedOrders = allOrders.Count(o => o.Status == "Returned");

return Ok(new
{
totalOrders,
totalRevenue,
totalBooksSold,
placedOrders,
deliveredOrders,
cancelledOrders,
returnedOrders,
topBook = topSelling?.Title ?? "N/A",
leastBook = leastSelling?.Title ?? "N/A",
lastOrderDate = lastOrder?.Date ?? DateTime.MinValue
});
}

// No changes needed for GetStockReport - it is already optimized.
[HttpGet("stock-report")]
public async Task<IActionResult> GetStockReport()
{
var stock = await _context.Books
.Select(book => new
{
book.Id,
book.Title,
book.Category,
book.Quantity,
Status = book.Quantity == 0 ? "Out of Stock" :
book.Quantity < 5 ? "Low Stock" : "In Stock"
})
.ToListAsync();

return Ok(stock);
}

// Refactored to use a single database query
[HttpGet("earnings-report")]
public async Task<IActionResult> GetEarningsReport()
{
var deliveredOrders = await _context.Orders
.Where(o => o.Status == "Delivered" && o.DeliveryDate != null)
.ToListAsync();

var revenueDelivered = deliveredOrders.Sum(o => o.Total);
var revenueReturned = await _context.Orders.Where(o => o.Status == "Returned").SumAsync(o => o.Total);
var revenueCancelled = await _context.Orders.Where(o => o.Status == "Cancelled").SumAsync(o => o.Total);
var revenuePlaced = await _context.Orders.Where(o => o.Status == "Placed").SumAsync(o => o.Total);
var revenueAll = revenueDelivered + revenueReturned + revenueCancelled + revenuePlaced;

var monthlyRevenue = deliveredOrders
.GroupBy(o => new { o.DeliveryDate!.Value.Year, o.DeliveryDate.Value.Month })
.OrderBy(g => g.Key.Year).ThenBy(g => g.Key.Month)
.Select(g => new
{
month = new DateTime(g.Key.Year, g.Key.Month, 1).ToString("MMMM yyyy"),
revenue = g.Sum(x => x.Total)
})
.ToList();

return Ok(new
{
revenueAll,
revenueDelivered,
revenueReturned,
revenueCancelled,
revenuePlaced,
monthlyRevenue
});
}

[HttpDelete("{id}")]
public async Task<IActionResult> DeleteExperience(int id)
{
var experience = await _context.Experiences.FindAsync(id);
if (experience == null)
return NotFound();

_context.Experiences.Remove(experience);
await _context.SaveChangesAsync();

return NoContent();
}
}
}
65 changes: 65 additions & 0 deletions backend/Controllers/BookQuizController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using Microsoft.AspNetCore.Mvc;
using backend.Data;
using backend.Models;
using System.Linq;

namespace backend.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class BookQuizController : ControllerBase
{
private readonly AppDbContext _context;

public BookQuizController(AppDbContext context)
{
_context = context;
}

[HttpPost("recommend")]
public IActionResult RecommendBooks([FromBody] QuizData quiz)
{
var query = _context.Books.AsQueryable();

if (!string.IsNullOrEmpty(quiz.Genre))
query = query.Where(b => b.Category != null &&
b.Category.ToLower().Contains(quiz.Genre.ToLower()));

if (!string.IsNullOrEmpty(quiz.Mood))
{
var moodKeyword = quiz.Mood.ToLower() switch
{
"adventurous" => "adventure",
"romantic" => "romance",
"thoughtful" => "philosophy",
"curious" => "facts",
_ => ""
};

if (!string.IsNullOrEmpty(moodKeyword))
query = query.Where(b => b.Description != null &&
b.Description.ToLower().Contains(moodKeyword));
}

if (!string.IsNullOrEmpty(quiz.Length))
{
query = quiz.Length.ToLower() switch
{
"short" => query.Where(b => b.PageCount <= 200),
"medium" => query.Where(b => b.PageCount > 200 && b.PageCount <= 400),
"long" => query.Where(b => b.PageCount > 400),
_ => query
};
}

if (!string.IsNullOrEmpty(quiz.Style))
{
query = query.Where(b => (b.ThemeType ?? "").ToLower().Contains(quiz.Style.ToLower())
|| (b.StoryType ?? "").ToLower().Contains(quiz.Style.ToLower()));
}

var result = query.Take(5).ToList();
return Ok(result);
}
}
}
Loading