In Part 22, we are stepping into the most powerful side of our application: the Admin Dashboard. This is where the restaurant management happens. The AdminController acts as the command center, gathering high-level statistics to give the admin a bird's-eye view of the entire system.
Step-by-Step Code Explanation
Dependency Injection: We inject
ApplicationDbContextthrough the constructor. This allows the controller to communicate with the database to fetch orders, users, and food items.The
IsAdmin()Security Guard: This is a private helper method. It checks the session for anIsAdminflag. Instead of repeating the check everywhere, we call this to ensure only authorized staff can access these pages.The
DashboardAction:Authorization Check: The first thing the code does is call
!IsAdmin(). If the user isn't an admin, it kicks them back to the Home page for security.Data Aggregation: We use Entity Framework's
.Count()method to fetch three vital numbers:Total Orders: Every transaction made by customers.
Total Users: The size of your customer base.
Total Items: How many dishes are currently on your menu.
ViewBag Delivery: These counts are stored in
ViewBagproperties so they can be displayed as "Stat Cards" in the HTML view (e.g., "Total Orders: 150").
using FoodOrderingSystem.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq;
namespace FoodOrderingSystem.Controllers
{
public class AdminController : Controller
{
private readonly ApplicationDbContext _context;
public AdminController(ApplicationDbContext context)
{
_context = context;
}
private bool IsAdmin()
{
return HttpContext.Session.GetString("IsAdmin") == "True";
}
public IActionResult Dashboard()
{
if (!IsAdmin()) return RedirectToAction("Index", "Home");
ViewBag.TotalOrders = _context.Orders.Count();
ViewBag.TotalUsers = _context.Users.Count();
ViewBag.TotalItems = _context.FoodItems.Count();
return View();
}
}
}
We are building the visual interface for the Admin Dashboard. This View takes the statistics we calculated in the Controller and presents them using professional Bootstrap 5 Stat Cards, giving the store owner an immediate overview of their business performance.
Step-by-Step Code Explanation
ViewBag Integration: The code uses
@ViewBag.TotalOrders,@ViewBag.TotalUsers, and@ViewBag.TotalItemsto inject real-time data directly into the dashboard cards.Color-Coded Stat Cards:
Primary (Blue): Used for Orders to highlight sales activity.
Success (Green): Used for Users to show growth in the customer base.
Info (Cyan): Used for Menu Items to represent the inventory/catalog.
Responsive Grid (
col-md-4): Using the Bootstrap grid ensures that on a desktop, the three cards sit side-by-side, but on a mobile device, they stack vertically for better readability.Bootstrap Icons: We use
bi-speedometer2,bi-cart-check, andbi-peopleto give the UI a modern, "SaaS-like" look.Quick Actions: This section provides a central hub for the admin to navigate to the most important management tasks, like updating the menu or checking the latest incoming orders.
@{
ViewData["Title"] = "Admin Dashboard";
}
<div class="container-fluid my-4">
<h2 class="mb-4"><i class="bi bi-speedometer2"></i> Admin Dashboard</h2>
<div class="row">
<div class="col-md-4 mb-4">
<div class="card bg-primary text-white">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="card-title">Total Orders</h6>
<h2>@ViewBag.TotalOrders</h2>
</div>
<i class="bi bi-cart-check display-4"></i>
</div>
</div>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card bg-success text-white">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="card-title">Total Users</h6>
<h2>@ViewBag.TotalUsers</h2>
</div>
<i class="bi bi-people display-4"></i>
</div>
</div>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card bg-info text-white">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="card-title">Menu Items</h6>
<h2>@ViewBag.TotalItems</h2>
</div>
<i class="bi bi-menu-button-wide display-4"></i>
</div>
</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-md-6">
<div class="card shadow">
<div class="card-header">
<h5>Quick Actions</h5>
</div>
<div class="card-body">
<a href="#" class="btn btn-outline-primary w-100 mb-2">
<i class="bi bi-menu-up"></i> Manage Menu
</a>
<a href="#" class="btn btn-outline-success w-100 mb-2">
<i class="bi bi-list-check"></i> View Orders
</a>
<a href="#" class="btn btn-outline-secondary w-100">
<i class="bi bi-shop"></i> View Site
</a>
</div>
</div>
</div>
</div>
</div>
To wrap up the navigation setup for Part 22, we are adding a conditional link to the Shared Layout. This ensures that the "Admin" menu option only appears for authorized personnel, keeping your site's management area hidden from regular customers.
Step-by-Step Code Explanation
@if (Context.Session.GetString("IsAdmin") == "True"): This is a server-side security check. It looks into the current user's session for theIsAdminkey. If the value is "True", the server renders the HTML inside the brackets. If not, the code is completely ignored and never sent to the user's browser.Context.Session: We useContexthere because the Shared Layout doesn't have a dedicated Controller to pass data. This allows the view to talk directly to the session data.class="nav-item"&class="nav-link": These are standard Bootstrap classes. They ensure that the Admin link looks exactly like your "Home," "Menu," or "Contact" links, maintaining a consistent professional design.Direct Routing: The
href="/Admin/Dashboard"points directly to the Action we created in theAdminController, allowing for a quick one-click jump to the stats page.
@if (Context.Session.GetString("IsAdmin") == "True")
{
<li class="nav-item"><a class="nav-link" href="/Admin/Dashboard">Admin</a></li>
}

Comments
Post a Comment