- Refactored `BuyController` for improved click logging and centralized link management. - Updated `DiscoveryController` to enhance user request handling and added country context dependency. - Introduced `ClicksController` for managing click tracking and redirects. - Added `GeoResolutionMiddleware` to resolve user locations based on IP. - Created `BuyCatalog` for centralized management of buy links. - Introduced view models (`BuyLinksViewModel`, `DiscoveryPageViewModel`) for better data handling in views. - Added new files for geographical data handling (`GeoIpResult`, `HttpContextItemKeys`, `LinkChoice`, etc.). - Updated `_BuyBox.cshtml` to render buy options based on user location. - Modified `DataAccess` for saving and retrieving geographical data.
166 lines
6.7 KiB
Plaintext
166 lines
6.7 KiB
Plaintext
@model CatherineLynwood.Models.DiscoveryPageViewModel
|
|
@{
|
|
var L = Model?.Buy ?? new CatherineLynwood.Models.BuyLinksViewModel();
|
|
var iso2 = (Model?.UserIso2 ?? "GB").ToUpperInvariant();
|
|
if (iso2 == "UK") { iso2 = "GB"; }
|
|
var pingBase = "/track/click";
|
|
var flagSvg = $"/images/flags/{iso2}.svg";
|
|
var flagPng = $"/images/flags/{iso2}.png";
|
|
}
|
|
|
|
<div id="buyBox" class="border border-2 border-dark rounded-4 p-3 bg-light mt-auto">
|
|
|
|
<div class="d-flex flex-wrap align-items-center justify-content-between mb-2">
|
|
<h3 class="h5 mb-2 mb-sm-0">Buy the Book</h3>
|
|
<small id="buyCountryHint" class="text-muted d-flex align-items-center">
|
|
<img id="buyCountryFlag"
|
|
class="me-1"
|
|
alt=""
|
|
width="20"
|
|
height="14"
|
|
loading="lazy"
|
|
src="@flagSvg"
|
|
onerror="this.onerror=null;this.src='@flagPng';" />
|
|
<span id="buyCountryText">Best options for @iso2</span>
|
|
</small>
|
|
</div>
|
|
|
|
@* ---------------------------
|
|
Row 1: Direct via printers (GB/US only)
|
|
--------------------------- *@
|
|
@if (L.IngramHardback != null || L.IngramPaperback != null)
|
|
{
|
|
<div id="rowDirect" class="mb-3">
|
|
<div class="d-flex align-items-center gap-2 mb-2">
|
|
<span>Best price direct from our printers</span>
|
|
</div>
|
|
<div class="row g-2">
|
|
@if (L.IngramHardback != null)
|
|
{
|
|
<div class="col-12 col-sm-6">
|
|
<a class="btn btn-dark w-100"
|
|
href="@L.IngramHardback.Url"
|
|
ping="@($"{pingBase}?slug={L.IngramHardback.Slug}&src=discovery")"
|
|
rel="nofollow noindex">
|
|
<i class="fad fa-gem me-1"></i> Hardback, direct
|
|
<span class="price-chip d-none" aria-hidden="true"></span>
|
|
</a>
|
|
</div>
|
|
}
|
|
@if (L.IngramPaperback != null)
|
|
{
|
|
<div class="col-12 col-sm-6">
|
|
<a class="btn btn-dark w-100"
|
|
href="@L.IngramPaperback.Url"
|
|
ping="@($"{pingBase}?slug={L.IngramPaperback.Slug}&src=discovery")"
|
|
rel="nofollow noindex">
|
|
<i class="fad fa-book me-1"></i> Paperback, direct
|
|
<span class="price-chip d-none" aria-hidden="true"></span>
|
|
</a>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<div class="d-flex align-items-center gap-2 mb-2">
|
|
<span>From other retailers</span>
|
|
</div>
|
|
|
|
@* ---------------------------
|
|
Row 2: Amazon (always present)
|
|
--------------------------- *@
|
|
<div id="rowAmazon" class="mb-3">
|
|
<div class="row g-2">
|
|
<div class="col-12 col-sm-6">
|
|
<a class="btn btn-outline-dark w-100"
|
|
href="@L.AmazonHardback.Url"
|
|
ping="@($"{pingBase}?slug={L.AmazonHardback.Slug}&src=discovery")"
|
|
rel="nofollow noindex">
|
|
<i class="fad fa-gem me-1"></i> Hardback, Amazon
|
|
</a>
|
|
</div>
|
|
<div class="col-12 col-sm-6">
|
|
<a class="btn btn-outline-dark w-100"
|
|
href="@L.AmazonPaperback.Url"
|
|
ping="@($"{pingBase}?slug={L.AmazonPaperback.Slug}&src=discovery")"
|
|
rel="nofollow noindex">
|
|
<i class="fad fa-book me-1"></i> Paperback, Amazon
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@* ---------------------------
|
|
Row 3: National retailer (conditional)
|
|
--------------------------- *@
|
|
@if (L.NationalHardback != null || L.NationalPaperback != null)
|
|
{
|
|
<div id="rowNational" class="mb-2">
|
|
<div class="row g-2">
|
|
@if (L.NationalHardback != null)
|
|
{
|
|
<div class="col-12 col-sm-6">
|
|
<a class="btn btn-outline-dark w-100"
|
|
href="@L.NationalHardback.Url"
|
|
ping="@($"{pingBase}?slug={L.NationalHardback.Slug}&src=discovery")"
|
|
rel="nofollow noindex">
|
|
<i class="fad fa-gem me-1"></i> Hardback, @(L.NationalLabel ?? "National")
|
|
</a>
|
|
</div>
|
|
}
|
|
@if (L.NationalPaperback != null)
|
|
{
|
|
<div class="col-12 col-sm-6">
|
|
<a class="btn btn-outline-dark w-100"
|
|
href="@L.NationalPaperback.Url"
|
|
ping="@($"{pingBase}?slug={L.NationalPaperback.Slug}&src=discovery")"
|
|
rel="nofollow noindex">
|
|
<i class="fad fa-book-open me-1"></i> Paperback, @(L.NationalLabel ?? "National")
|
|
</a>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
@* ---------------------------
|
|
Row 4: eBook stores (Apple, Kobo, Kindle)
|
|
--------------------------- *@
|
|
<div id="rowEbooks" class="mb-2">
|
|
<div class="d-flex align-items-center gap-2 mb-2">
|
|
<span>Choose your preferred e-book store</span>
|
|
</div>
|
|
<div class="row g-2">
|
|
<div class="col-12 col-sm-4">
|
|
<a class="btn btn-outline-dark w-100"
|
|
href="@L.Apple.Url"
|
|
ping="@($"{pingBase}?slug={L.Apple.Slug}&src=discovery")"
|
|
rel="nofollow noindex">
|
|
<i class="fab fa-apple me-1"></i> Apple Books
|
|
</a>
|
|
</div>
|
|
<div class="col-12 col-sm-4">
|
|
<a class="btn btn-outline-dark w-100"
|
|
href="@L.Kobo.Url"
|
|
ping="@($"{pingBase}?slug={L.Kobo.Slug}&src=discovery")"
|
|
rel="nofollow noindex">
|
|
<i class="fad fa-book-open me-1"></i> Kobo
|
|
</a>
|
|
</div>
|
|
<div class="col-12 col-sm-4">
|
|
<a class="btn btn-outline-dark w-100"
|
|
href="@L.AmazonKindle.Url"
|
|
ping="@($"{pingBase}?slug={L.AmazonKindle.Slug}&src=discovery")"
|
|
rel="nofollow noindex">
|
|
<i class="fab fa-amazon me-1"></i> Kindle
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-2">
|
|
<a asp-action="HowToBuy" class="link-dark small">See all buying options</a>
|
|
</div>
|
|
</div>
|