@inherits LayoutComponentBase @namespace MidrandBooks.Components.Layout @using Microsoft.AspNetCore.Components @using MidrandBooks.Components @using MidrandBooks.Models
@if (ActiveTab == "catalog") { } else if (ActiveTab == "library") { } else if (ActiveTab == "author") { } else if (ActiveTab == "terms") { } else if (ActiveTab == "privacy") { } @Body
@if (SelectedBook != null) { var isEbookOwned = PurchasedRecords.Any(p => p.BookId == SelectedBook.Id && p.Format == "ebook"); var isEbookCached = OfflineCachedBooks.Contains(SelectedBook.Id); var isAudioOwned = PurchasedRecords.Any(p => p.BookId == SelectedBook.Id && p.Format == "audiobook"); var ebookInCart = CartItems.Any(i => i.Book.Id == SelectedBook.Id && i.Format == "ebook"); var audioInCart = CartItems.Any(i => i.Book.Id == SelectedBook.Id && i.Format == "audiobook"); } @if (ActiveReadingBook != null) { } @if (ActivePlayingBook != null) { }
Midrandbooks.co.za

Legal Deposit Compliant • National Library Services of South Africa • Est. 2026

Midrand, Gauteng

© 2026 Midrand Books. Securely compiled under sandbox rules.

Designed, maintained, owned & hosted by LiteCharms (PTY) Ltd

@code { private string ActiveTab { get; set; } = "catalog"; private bool IsCartOpen { get; set; } = false; private bool IsOfflineMode { get; set; } = false; // Master list of categories private List Categories { get; set; } = new() { "Fiction", "Non-Fiction", "African Literature", "Poetry", "Academic & History", "Biography" }; // Books and States private List CatalogBooks { get; set; } = new(); private List FeaturedBooks { get; set; } = new(); private BookModel? SelectedBook { get; set; } private List CartItems { get; set; } = new(); private List PurchasedRecords { get; set; } = new(); private List OfflineCachedBooks { get; set; } = new(); private Dictionary UserRatings { get; set; } = new(); // Active Reader/Player Overlays private BookModel? ActiveReadingBook { get; set; } private int ActiveReadingPage { get; set; } = 0; private BookModel? ActivePlayingBook { get; set; } private bool IsAudioPlaying { get; set; } = false; protected override void OnInitialized() { // Load default premium seed publications var random = new Random(2026); var categoriesList = new[] { "Fiction", "African Literature", "Poetry", "Academic & History", "Biography", "Non-Fiction" }; var colors = new[] { "from-indigo-900 to-purple-950", "from-rose-950 to-orange-900", "from-slate-900 to-teal-950", "from-amber-950 to-emerald-950" }; var titles = new[] { "Whispers of the Highveld", "Gauteng Gold Rush Chronicles", "Soweto Symphony of Dreams", "Limpopo Rain Queen", "The Karoo Echoes", "Table Mountain Sunrise", "Durban Beachfront Rhythms", "Zululand Warriors" }; var authors = new[] { "N. Khumalo", "S. Ndlovu", "T. Mokoena", "K. Naidoo", "M. van der Merwe", "L. Sibanda", "J. Govender", "Z. Zuma" }; var descriptions = new[] { "An epic South African saga highlighting historical transformations, personal sacrifices, and cultural richness in the Gauteng plains.", "A comprehensive investigative review documenting the rich socio-economic changes driven by gold discoveries in early Johannesburg.", "A beautifully written modern poetry collection exploring life, struggle, and celebratory musical triumphs in South Africa's heartland.", "An enchanting fantasy drawing on classical folklore, rainmaking traditions, and political intrigue in the northern provinces.", "A mystery novel detailing hidden family histories buried deep in the silent, expansive landscapes of the great Karoo desert." }; for (int i = 0; i < titles.Length; i++) { var book = new BookModel { Id = $"book-seed-{i + 1}", Title = titles[i], Author = authors[i], AuthorId = $"seed-auth-{i + 1}", Description = descriptions[i % descriptions.Length], Price = random.Next(95, 295), Category = categoriesList[i % categoriesList.Length], CoverColor = colors[i % colors.Length], Rating = 4.0 + random.NextDouble(), ReviewsCount = random.Next(5, 85), PublishedYear = random.Next(2018, 2026), PagesCount = random.Next(120, 480), AudioDuration = $"{random.Next(4, 12)}h {random.Next(10, 59)}m", Narrator = authors[(i + 2) % authors.Length], Bestseller = i < 2, Trending = i >= 2 && i < 4, Status = "published" }; // Populate some dummy chapters book.FullText = new List { $"Chapter 1 of {book.Title}.\n\nThe morning sun breaks across the rolling hills of the Highveld, painting the Gauteng skies in shades of gold and amber. The dusty streets of Midrand begin to hum with the early morning life, as commuters fill the platforms and local merchants raise their shutters.\n\nIt was here that Khwezi first realized that the stories written in these lands had a rhythm of their own—a heartbeat that echoed the rich histories of those who walked before.", "Chapter 2.\n\nAs the afternoon heat settles over the vast landscapes, a quiet stillness descends. Under the shade of an ancient thorn tree, old journals are opened, revealing handwritten accounts of early migrations, family secrets, and triumphant breakthroughs. The digital DRM safeguards preserve these fragile pages for generations to come." }; CatalogBooks.Add(book); } FeaturedBooks = CatalogBooks.Where(b => b.Bestseller || b.Trending).Take(3).ToList(); // Pre-purchase one book to show active items in Library immediately PurchasedRecords.Add(new PurchaseRecord { BookId = "book-seed-3", Format = "ebook", CurrentPage = 0, Progress = 15 }); } private void HandleActiveTabChanged(string tab) { ActiveTab = tab; } private void HandleOpenCart() { IsCartOpen = true; } private void HandleCloseCart() { IsCartOpen = false; } private void HandleOfflineToggle(bool value) { IsOfflineMode = value; } private void HandleSelectBook(BookModel book) { SelectedBook = book; } private void HandleCloseModal() { SelectedBook = null; } private void HandleAddToCart((BookModel Book, string Format) tuple) { if (!CartItems.Any(i => i.Book.Id == tuple.Book.Id && i.Format == tuple.Format)) { CartItems.Add(new CartItem { Book = tuple.Book, Format = tuple.Format }); } } private void HandleAddToCartFromModal(string format) { if (SelectedBook != null) { HandleAddToCart((SelectedBook, format)); } } private void HandleRemoveFromCart(CartItem item) { CartItems.Remove(item); } private void HandleCheckoutSuccess(List items) { foreach (var item in items) { if (!PurchasedRecords.Any(p => p.BookId == item.Book.Id && p.Format == item.Format)) { PurchasedRecords.Add(new PurchaseRecord { BookId = item.Book.Id, Format = item.Format, CurrentPage = 0, Progress = 0 }); } } CartItems.Clear(); ActiveTab = "library"; } private void HandleReadEbook(BookModel book) { ActiveReadingBook = book; var purchase = PurchasedRecords.FirstOrDefault(p => p.BookId == book.Id && p.Format == "ebook"); ActiveReadingPage = purchase?.CurrentPage ?? 0; SelectedBook = null; // Close detail modal if open } private void HandleCloseReader() { ActiveReadingBook = null; } private void HandlePageProgressChanged(int page) { ActiveReadingPage = page; if (ActiveReadingBook != null) { var purchase = PurchasedRecords.FirstOrDefault(p => p.BookId == ActiveReadingBook.Id && p.Format == "ebook"); if (purchase != null) { purchase.CurrentPage = page; } } } private void HandlePlayAudiobook(BookModel book) { ActivePlayingBook = book; IsAudioPlaying = true; SelectedBook = null; // Close detail modal if open } private void HandleCloseAudioPlayer() { ActivePlayingBook = null; IsAudioPlaying = false; } private void HandleAudioPlayToggle(bool isPlaying) { IsAudioPlaying = isPlaying; } private void HandleCacheBookOffline(string bookId) { if (!OfflineCachedBooks.Contains(bookId)) { OfflineCachedBooks.Add(bookId); } } private void HandleAddCategory(string category) { if (!Categories.Contains(category)) { Categories.Add(category); } } private void HandlePublishBook(BookModel book) { CatalogBooks.Insert(0, book); } private void HandleRateBook(string bookId, int rating) { int? oldRating = UserRatings.ContainsKey(bookId) ? UserRatings[bookId] : null; UserRatings[bookId] = rating; var book = CatalogBooks.FirstOrDefault(b => b.Id == bookId); if (book != null) { double oldTotal = book.Rating * book.ReviewsCount; if (oldRating.HasValue) { book.Rating = (oldTotal - oldRating.Value + rating) / Math.Max(1, book.ReviewsCount); } else { book.ReviewsCount += 1; book.Rating = (oldTotal + rating) / book.ReviewsCount; } book.Rating = Math.Round(book.Rating * 10) / 10; } } }