Added legal pages, contact and abut us
continuous-integration/drone/pr Build is passing

Redesigned account, checkout
Added stock management design elements
This commit is contained in:
Khwezi Mngoma
2026-06-16 23:32:44 +02:00
parent 5d614d2a94
commit 8d2efbeb4a
18 changed files with 1642 additions and 555 deletions
+219 -207
View File
@@ -4,225 +4,237 @@
@rendermode InteractiveServer
@attribute [Authorize]
<div class="container py-5">
<h2 class="fw-bold mb-5 tracking-tight">My Account</h2>
<div class="account-page-container py-5">
<header class="account-header mb-5">
<span class="text-uppercase font-monospace text-muted tracking-wider small d-block mb-1">Customer Dashboard</span>
<h1 class="account-main-title fw-bold">My Account</h1>
</header>
<div class="row g-5">
<div class="col-md-3">
<div class="nav flex-column nav-pills" role="tablist">
<button class="nav-link active text-start" data-bs-toggle="pill" data-bs-target="#orders" role="tab">Order History</button>
<button class="nav-link text-start" data-bs-toggle="pill" data-bs-target="#shipping" role="tab">Shipping Address</button>
<button class="nav-link text-start" data-bs-toggle="pill" data-bs-target="#profile" role="tab">Profile Settings</button>
<hr />
<button class="nav-link text-danger text-start" @onclick="TriggerLogout">Logout</button>
<div class="col-lg-3">
<div class="nav flex-column account-nav-stack gap-1" role="tablist">
<button class="nav-link active text-start d-flex align-items-center gap-2" data-bs-toggle="pill" data-bs-target="#orders" role="tab">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"></path><line x1="3" y1="6" x2="21" y2="6"></line><path d="M16 10a4 4 0 0 1-8 0"></path></svg>
<span>Order History</span>
</button>
<button class="nav-link text-start d-flex align-items-center gap-2" data-bs-toggle="pill" data-bs-target="#shipping" role="tab">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg>
<span>Shipping Address</span>
</button>
<button class="nav-link text-start d-flex align-items-center gap-2" data-bs-toggle="pill" data-bs-target="#profile" role="tab">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>
<span>Profile Settings</span>
</button>
<hr class="my-3 opacity-10" />
<button class="nav-link nav-logout text-danger text-start d-flex align-items-center gap-2" @onclick="TriggerLogout">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg>
<span>Logout Account</span>
</button>
</div>
</div>
<div class="col-md-9">
<div class="col-lg-9">
<AuthorizeView>
<Authorized>
<div class="profile-hero-banner mb-5 d-flex align-items-center justify-content-between p-4 border border-light bg-white">
<div class="hero-text-content">
<div class="meta-tag font-monospace text-uppercase text-muted mb-1">Customer Profile // Active Session</div>
<h4 class="fw-bold mb-1 brand-greeting">Welcome back, @(context.User.FindFirst("given_name")?.Value ?? context.User.Identity?.Name ?? "Reader")!</h4>
<p class="text-muted small mb-0 font-monospace">@context.User.FindFirst("email")?.Value</p>
<div class="tab-content account-panels-deck">
<div class="tab-pane fade show active" id="orders" role="tabpanel">
<div class="panel-card-wrapper mb-4">
<h5 class="panel-section-title fw-bold text-dark font-monospace text-uppercase tracking-wider mb-4">Order History</h5>
@if (orderHistory == null || !orderHistory.Any())
{
<div class="text-center py-5 border rounded-3 bg-light bg-opacity-50">
<p class="text-muted small mb-0">You haven't placed any orders with us yet.</p>
</div>
}
else
{
<div class="orders-stack d-flex flex-column gap-4">
@foreach (var order in orderHistory)
{
<div class="premium-order-card p-4 border rounded-3 bg-white shadow-sm">
<div class="d-flex justify-content-between align-items-start flex-wrap gap-3 pb-3 border-b-dashed mb-3">
<div>
<span class="font-monospace text-dark fw-bold d-block h6 mb-1">@order.OrderId</span>
<small class="text-muted d-block mb-1">Ordered on @order.OrderDate.ToString("dd MMMM yyyy")</small>
<small class="text-secondary d-flex align-items-center gap-1" style="font-size: 0.8rem;">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg>
<span>Shipped to: <span class="fw-semibold text-dark">@order.ShippingAddressName</span></span>
</small>
</div>
<div class="text-md-end d-flex flex-column align-items-md-end gap-2">
<div class="d-flex align-items-center gap-1.5 flex-wrap justify-content-md-end">
<span class="badge status-badge-base @GetPaymentStatusClass(order.PaymentStatus)">
Pay: @order.PaymentStatus
</span>
<span class="badge status-badge-base @GetStatusClass(order.Status)">
Logistics: @order.Status
</span>
</div>
@if (order.PaymentStatus?.ToLower() == "paid")
{
<button class="btn btn-outline-dark btn-premium-sm font-monospace text-uppercase d-inline-flex align-items-center gap-1.5 py-1 px-2.5"
style="font-size: 0.7rem;"
@onclick="() => DownloadInvoice(order.OrderId)">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
<span>Invoice</span>
</button>
}
</div>
</div>
<div class="order-manifest-details d-flex align-items-center justify-content-between gap-4 py-1">
<div class="item-meta">
<h6 class="text-dark fw-bold mb-0 small" style="line-height: 1.4;">@order.ProductTitle</h6>
</div>
<div class="item-value text-end flex-shrink-0">
<span class="font-monospace text-dark fw-bold d-block">R @order.Total.ToString("F2")</span>
<small class="text-muted extra-small font-monospace">VAT Inclusive</small>
</div>
</div>
</div>
}
</div>
}
</div>
</div>
<div class="hero-crest-svg d-none d-sm-block">
<svg viewBox="0 0 100 100" width="70" height="70" stroke="#1A1A1A" stroke-width="1.5" fill="none">
<circle cx="50" cy="50" r="40" stroke-dasharray="2 2" stroke="#DDD" />
<circle cx="50" cy="50" r="30" />
<polygon points="50,20 76,65 24,65" stroke="#1A1A1A" />
<line x1="50" y1="20" x2="50" y2="80" stroke-width="1" stroke="#1A1A1A" />
</svg>
<div class="tab-pane fade" id="shipping" role="tabpanel">
<div class="panel-card-wrapper mb-4">
<div class="d-flex justify-content-between align-items-baseline mb-4">
<h5 class="panel-section-title fw-bold text-dark font-monospace text-uppercase tracking-wider mb-0">Saved Addresses</h5>
@if (!showAddForm && editingAddress == null)
{
<button class="btn btn-outline-dark btn-premium-sm font-monospace text-uppercase" @onclick="() => showAddForm = true">
Add New Address
</button>
}
</div>
@if (showAddForm || editingAddress != null)
{
<div class="premium-interactive-form p-4 border rounded-3 mb-4 bg-light bg-opacity-20 animate-fade-in">
<h6 class="fw-bold text-dark mb-3">@(editingAddress != null ? "Modify Curated Address" : "Register Destination Address")</h6>
<div class="row g-3">
<div class="col-md-6">
<label class="form-label extra-small font-monospace text-uppercase text-muted">Address Name Label</label>
<input type="text" class="form-control premium-plaintext-field" placeholder="e.g., Home" @bind="newAddressName" />
</div>
<div class="col-md-6">
<label class="form-label extra-small font-monospace text-uppercase text-muted">Postal Routing Code</label>
<input type="text" class="form-control premium-plaintext-field" placeholder="e.g., 1685" @bind="newPostalCode" />
</div>
<div class="col-12">
<label class="form-label extra-small font-monospace text-uppercase text-muted">Street Address Lines</label>
<input type="text" class="form-control premium-plaintext-field" placeholder="e.g., 12 Main Road" @bind="newStreetAddress" />
</div>
<div class="col-md-12">
<label class="form-label extra-small font-monospace text-uppercase text-muted">City / Region</label>
<input type="text" class="form-control premium-plaintext-field" placeholder="e.g., Midrand" @bind="newCity" />
</div>
<div class="col-12 d-flex flex-wrap gap-4 py-2 border-y my-2 bg-white px-3 rounded border">
<div class="form-check d-flex align-items-center gap-2 m-0">
<input type="checkbox" class="form-check-input custom-box-tick m-0" id="isBillingCheck" @bind="isBilling" />
<label class="form-check-label context-clickable small fw-medium text-dark" for="isBillingCheck">Default Billing Endpoint</label>
</div>
<div class="form-check d-flex align-items-center gap-2 m-0">
<input type="checkbox" class="form-check-input custom-box-tick m-0" id="isShippingCheck" @bind="isShipping" />
<label class="form-check-label context-clickable small fw-medium text-dark" for="isShippingCheck">Default Fulfillment Endpoint</label>
</div>
</div>
<div class="col-12 d-flex justify-content-end gap-2 mt-3">
<button class="btn btn-clean-cancel font-monospace text-uppercase small" @onclick="CancelAddressActions">Cancel</button>
<button class="btn btn-dark px-4 py-2 text-uppercase font-monospace small" @onclick="SaveAddress">Save Address Details</button>
</div>
</div>
</div>
}
<div class="row g-4">
@foreach (var addr in savedAddresses)
{
<div class="col-md-6">
<div class="address-curated-card p-4 border rounded-3 position-relative d-flex flex-column h-100 bg-white @(addr.IsPrimary ? "border-dark shadow-sm" : "opacity-90")">
<div class="d-flex justify-content-between align-items-start mb-2">
<span class="fw-bold text-dark font-monospace tracking-wide text-uppercase" style="font-size: 0.82rem;">@addr.Name</span>
<div class="form-check d-flex align-items-center gap-1.5 p-0 m-0">
<input type="radio" class="form-check-input custom-box-tick m-0" name="primaryAddr" id="@($"primary-{addr.Id}")" checked="@addr.IsPrimary" @onchange="(e) => SetPrimary(addr, e)" />
<label class="form-check-label extra-small text-muted font-monospace text-uppercase context-clickable ms-1" for="@($"primary-{addr.Id}")">Primary</label>
</div>
</div>
<div class="address-body-text text-muted mb-4 mt-1 flex-grow-1" style="font-size: 0.88rem; line-height: 1.6;">
<span class="d-block text-dark fw-medium">@addr.Street</span>
<span class="d-block">@addr.City</span>
<span class="font-monospace text-secondary extra-small d-block mt-1">ZA-@addr.PostalCode</span>
</div>
<div class="address-metadata-badges d-flex flex-wrap gap-1 mb-3">
@if (addr.IsBilling)
{
<span class="badge bg-light text-secondary font-monospace tracking-wide border text-uppercase extra-small px-2 py-1">Billing</span>
}
@if (addr.IsShipping)
{
<span class="badge bg-light text-dark font-monospace tracking-wide border border-secondary text-uppercase extra-small px-2 py-1">Shipping</span>
}
</div>
<div class="address-actions-row border-top-dashed pt-3 d-flex gap-3 justify-content-end mt-auto">
<button class="btn-action-trigger text-uppercase font-monospace extra-small text-muted border-0 bg-transparent" @onclick="() => EditAddress(addr)">Edit</button>
<button class="btn-action-trigger text-uppercase font-monospace extra-small text-danger border-0 bg-transparent" @onclick="() => DeleteAddress(addr)">Delete</button>
</div>
</div>
</div>
}
</div>
</div>
</div>
<div class="tab-pane fade" id="profile" role="tabpanel">
<div class="panel-card-wrapper mb-4">
<h5 class="panel-section-title fw-bold text-dark font-monospace text-uppercase tracking-wider mb-4">Profile Settings</h5>
<div class="profile-hero-banner mb-4 d-flex align-items-center justify-content-between p-4 border rounded-3 bg-light bg-opacity-20 flex-wrap gap-3">
<div class="hero-text-content">
<div class="meta-tag font-monospace text-uppercase text-muted extra-small tracking-wider mb-1">Active Identity</div>
<h5 class="fw-bold text-dark mb-1 h6">@User?.Identity?.Name</h5>
<p class="text-muted small mb-0 font-monospace extra-small opacity-75">Secure Connection Authorized</p>
</div>
<span class="badge rounded-pill bg-success bg-opacity-10 text-success border border-success border-opacity-20 font-monospace px-3 py-1.5 small text-uppercase tracking-wide">
Verified
</span>
</div>
<div class="card p-5 text-center bg-white border rounded-3 shadow-sm my-4">
<div class="mb-4 text-muted opacity-40">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="44" height="44" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
</svg>
</div>
<h5 class="fw-bold text-dark mb-2 h6">Centralized Identity Node Settings</h5>
<p class="text-muted small mx-auto mb-4" style="max-width: 480px; line-height: 1.5;">
For your structural protection, password alterations, account recovery preferences, cross-tenant factors, and core credential manifests are handled through our global Identity Node security layer.
</p>
<a href="https://sts.security.khongisa.co.za/Manage/Index?returnUrl=https://midrandbooks.co.za/account"
target="_blank"
rel="noopener noreferrer"
class="btn btn-dark rounded-pill px-4 py-2.5 btn-sm font-monospace text-uppercase tracking-wider d-inline-flex align-items-center gap-2 mx-auto"
style="font-size: 0.75rem;">
<span>Access Central Security Center</span>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>
</a>
</div>
</div>
</div>
</div>
</Authorized>
</AuthorizeView>
<div class="tab-content">
<div class="tab-pane fade show active" id="orders" role="tabpanel">
<div class="d-flex justify-content-between align-items-center mb-4">
<h5 class="fw-bold m-0 text-uppercase tracking-wider fs-6 text-muted">Order History</h5>
</div>
<div class="d-flex flex-column gap-3">
@if (orderHistory != null)
{
@foreach (var order in orderHistory)
{
<div class="card p-4 shadow-sm order-history-card">
<div class="d-flex flex-column flex-sm-row justify-content-between align-items-start gap-3">
<div class="flex-grow-1 w-100">
<div class="order-meta-track mb-2">
<div class="meta-item-id">
<span class="fw-bold text-dark">@order.OrderId</span>
</div>
<div class="meta-item-date">
<span class="text-muted small">@order.OrderDate.ToString("MMM dd, yyyy")</span>
</div>
<div class="meta-item-status">
<span class="badge status-badge-base status-@order.Status?.ToLower() text-uppercase">
@order.Status
</span>
</div>
</div>
<h6 class="mb-2">
<a href="/products/@order.ProductId" class="product-link fw-medium text-dark text-decoration-none" title="@order.ProductTitle">
@order.ProductTitle
</a>
</h6>
<div class="d-flex align-items-center text-secondary small">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="12" height="12" fill="currentColor" class="me-1 text-muted flex-shrink-0">
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z" />
</svg>
<span class="text-muted text-uppercase tracking-wider font-monospace" style="font-size: 0.7rem;">Shipping to:</span>&nbsp;<span class="text-dark fw-medium">@order.ShippingAddressName</span>
</div>
</div>
<div class="d-flex flex-row flex-sm-column align-items-center align-items-sm-end justify-content-between w-100 w-sm-auto pt-2 pt-sm-0 border-top border-sm-top-0 border-light">
<div class="text-sm-end mb-sm-2">
<span class="text-muted xx-small d-block text-uppercase font-monospace tracking-wider" style="font-size: 0.6rem;">Total Paid</span>
<span class="fw-bold text-dark fs-5">R @order.Total.ToString("N2")</span>
</div>
<button class="btn btn-link p-0 text-dark action-btn mt-sm-1" title="Download Invoice" @onclick="() => DownloadInvoice(order.OrderId)">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="currentColor" class="svg-icon">
<path d="M19 12v7H5v-7H3v7c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-7h-2zm-6 .67l2.59-2.58L17 11.5l-5 5-5-5 1.41-1.41L11 12.67V3h2v9.67z" />
</svg>
</button>
</div>
</div>
</div>
}
}
else
{
<div class="card p-4 text-center text-muted">
Loading order history...
</div>
}
</div>
</div>
<div class="tab-pane fade" id="shipping" role="tabpanel">
<div class="d-flex justify-content-between align-items-center mb-4">
<h5 class="fw-bold m-0 text-uppercase tracking-wider fs-6 text-muted">Saved Addresses</h5>
@if (!showAddForm && editingAddress == null)
{
<button class="btn btn-dark btn-sm rounded-pill px-4" @onclick="OpenAddForm">+ Add New</button>
}
</div>
@if (showAddForm)
{
<div class="card p-4 border shadow-sm mb-4 bg-light">
<div class="d-flex justify-content-between align-items-center mb-3">
<h6 class="fw-bold m-0">New Address</h6>
<button type="button" class="btn-close" @onclick="() => showAddForm = false"></button>
</div>
<input type="text" class="form-control mb-2" placeholder="Address Name (e.g. Home, Office)" @bind="newAddressName" />
<input type="text" class="form-control mb-2" placeholder="Street Address" @bind="newStreetAddress" />
<div class="d-flex gap-2 mb-3">
<input type="text" class="form-control" placeholder="City" @bind="newCity" />
<input type="text" class="form-control" placeholder="Postal Code" @bind="newPostalCode" />
</div>
<div class="mb-3 d-flex gap-3">
<label class="pointer-label"><input type="checkbox" @bind="isBilling" /> Billing</label>
<label class="pointer-label"><input type="checkbox" @bind="isShipping" /> Shipping</label>
</div>
<div class="d-flex">
<button class="btn btn-dark btn-sm rounded-pill px-4" @onclick="SaveAddress">Save Address</button>
</div>
</div>
}
@if (editingAddress != null)
{
<div class="card p-4 border shadow-sm mb-4 bg-light">
<div class="d-flex justify-content-between align-items-center mb-3">
<h6 class="fw-bold m-0">Edit Address</h6>
<button type="button" class="btn-close" @onclick="CancelEditing"></button>
</div>
<input type="text" class="form-control mb-2" placeholder="Address Name" @bind="editingAddress.Name" />
<input type="text" class="form-control mb-2" placeholder="Street Address" @bind="editingAddress.Street" />
<div class="d-flex gap-2 mb-3">
<input type="text" class="form-control" placeholder="City" @bind="editingAddress.City" />
<input type="text" class="form-control" placeholder="Postal Code" @bind="editingAddress.PostalCode" />
</div>
<div class="mb-3 d-flex gap-3">
<label class="pointer-label"><input type="checkbox" @bind="editingAddress.IsBilling" /> Billing</label>
<label class="pointer-label"><input type="checkbox" @bind="editingAddress.IsShipping" /> Shipping</label>
</div>
<div class="d-flex">
<button class="btn btn-dark btn-sm rounded-pill px-4" @onclick="UpdateAddress">Update Address</button>
</div>
</div>
}
@foreach (var addr in savedAddresses)
{
<div class="card p-4 shadow-sm mb-3 address-card">
<div class="d-flex justify-content-between align-items-start">
<div>
<h6 class="fw-bold mb-1">@addr.Name</h6>
<p class="mb-2 text-muted">@addr.Street, @addr.City, @addr.PostalCode</p>
<div class="d-flex gap-2 text-uppercase font-monospace text-muted small">
@if (addr.IsBilling)
{
<span class="badge bg-light text-dark border">[Billing]</span>
}
@if (addr.IsShipping)
{
<span class="badge bg-light text-dark border">[Shipping]</span>
}
</div>
</div>
<div class="d-flex align-items-center gap-2 actions-container">
<label class="small text-muted d-flex align-items-center gap-1 m-0 pointer-label me-2">
<input type="checkbox" checked="@addr.IsPrimary" @onchange="(e) => SetPrimary(addr, e)" /> Primary
</label>
<button class="btn btn-link p-0 text-dark action-btn" title="Edit Address" @onclick="() => StartEditing(addr)">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="14" height="14" fill="currentColor">
<path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" />
</svg>
</button>
<button class="btn btn-link p-0 text-danger action-btn" title="Delete Address" @onclick="() => DeleteAddress(addr)">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="14" height="14" fill="currentColor">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" />
</svg>
</button>
</div>
</div>
</div>
}
</div>
<div class="tab-pane fade" id="profile" role="tabpanel">
<div class="d-flex justify-content-between align-items-center mb-4">
<h5 class="fw-bold m-0 text-uppercase tracking-wider fs-6 text-muted">Profile Settings</h5>
</div>
<div class="card p-5 text-center bg-white border">
<div class="mb-4">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="48" height="48" fill="none" stroke="#1A1A1A" stroke-width="1.5">
<rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
</svg>
</div>
<h5 class="fw-bold mb-2">Centralized Identity Management</h5>
<p class="text-muted small mx-auto mb-4" style="max-width: 480px;">
For your protection, password modifications, recovery settings, authentication methods, and core credentials are managed through our secure Identity Node.
</p>
<a href="https://sts.security.khongisa.co.za/Manage/Index?returnUrl=https://midrandbooks.co.za/account" class="btn btn-dark rounded-pill px-5 py-2.5 btn-sm font-monospace text-uppercase tracking-wider">
Access Security Center
</a>
</div>
</div>
</div>
</div>
</div>
</div>