147 lines
5.9 KiB
Plaintext
147 lines
5.9 KiB
Plaintext
@inherits LayoutComponentBase
|
|
@inject IJSRuntime JSRuntime
|
|
@using Blazored.Toast
|
|
|
|
<header class="top-bar">
|
|
<a href="/" class="brand">
|
|
<svg class="brand-mark" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M70,25 C65,18 58,15 50,15 C30,15 15,30 15,50 C15,70 30,85 50,85 C58,85 65,82 70,75 L62,68 C58,72 54,74 50,74 C37,74 27,63 27,50 C27,37 37,26 50,26 C54,26 58,28 62,32 L70,25 Z" fill="#0096c7" />
|
|
<circle cx="85" cy="50" r="8" fill="#4dabff" opacity="0.9" />
|
|
<circle cx="75" cy="80" r="5" fill="#4dabff" opacity="0.6" />
|
|
<circle cx="75" cy="20" r="5" fill="#4dabff" opacity="0.6" />
|
|
</svg>
|
|
|
|
<div class="text-column">
|
|
<span class="brand-main">Lite<span class="brand-accent">Charms</span></span>
|
|
<span class="payoff-line">Affordable Technology Today</span>
|
|
</div>
|
|
</a>
|
|
|
|
<button class="hamburger" @onclick="ToggleMenu" aria-label="Toggle Menu" aria-expanded="@isMenuOpen.ToString().ToLower()">
|
|
<div class="bar @(isMenuOpen ? "animate" : "")"></div>
|
|
</button>
|
|
|
|
<nav class="nav-links @(isMenuOpen ? "open" : "")">
|
|
<a href="services" class="nav-link" @onclick="CloseMenu">Services</a>
|
|
<a href="shop" class="nav-link nav-shop" @onclick="CloseMenu">Shop</a>
|
|
<a href="about" class="nav-link" @onclick="CloseMenu">About</a>
|
|
<a href="contact" class="nav-link" @onclick="CloseMenu">Contact</a>
|
|
<button class="btn-login mobile-only" @onclick="CloseMenu">Login</button>
|
|
</nav>
|
|
|
|
<div class="header-actions desktop-only">
|
|
<div class="contact-info">
|
|
<span class="contact-item">
|
|
<svg class="contact-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path></svg>
|
|
+27872650198
|
|
</span>
|
|
<span class="blue-dot"></span>
|
|
@* Refactored: Mailto link with subject and body *@
|
|
<a href="mailto:contact@litecharms.co.za?subject=Enquiry%20from%20Shop&body=Hi%20Lite%20Charms%20Team," class="contact-item">
|
|
<svg class="contact-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg>
|
|
contact@litecharms.co.za
|
|
</a>
|
|
</div>
|
|
|
|
<button class="btn-login">
|
|
<svg class="btn-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path><polyline points="10 17 15 12 10 7"></polyline><line x1="15" y1="12" x2="3" y2="12"></line></svg>
|
|
Login
|
|
</button>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="page-wrapper">
|
|
<main>
|
|
@Body
|
|
</main>
|
|
|
|
@* Cookie Banner Added Here *@
|
|
@if (showBanner)
|
|
{
|
|
<div class="cookie-banner">
|
|
<div class="cookie-content">
|
|
<p>We use cookies to enhance your experience. By continuing to visit this site you agree to our use of cookies.</p>
|
|
<div class="cookie-actions">
|
|
<button class="btn-cookie accept" @onclick="() => HandleConsent(true)">Accept</button>
|
|
<button class="btn-cookie decline" @onclick="() => HandleConsent(false)">Decline</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<BlazoredToasts />
|
|
|
|
<footer class="bottom-bar">
|
|
<div class="footer-left">
|
|
© 2026 Lite Charms (PTY) LTD. All rights reserved.
|
|
</div>
|
|
<div class="footer-right">
|
|
<a href="terms" class="footer-link">Terms & Conditions</a>
|
|
<span class="divider">|</span>
|
|
<a href="privacy" class="footer-link">Privacy Policy</a>
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
|
|
@code {
|
|
private bool isMenuOpen = false;
|
|
private bool showBanner = false;
|
|
private bool isInitialized = false;
|
|
|
|
private void ToggleMenu()
|
|
{
|
|
isMenuOpen = !isMenuOpen;
|
|
}
|
|
|
|
private void CloseMenu()
|
|
{
|
|
isMenuOpen = false;
|
|
}
|
|
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
{
|
|
// Only run this logic once when the component first renders
|
|
if (firstRender && !isInitialized)
|
|
{
|
|
isInitialized = true;
|
|
|
|
try
|
|
{
|
|
// Attempt to read from localStorage
|
|
var consent = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "litecharms_cookie_consent");
|
|
|
|
// If no consent is found, show the banner
|
|
if (string.IsNullOrWhiteSpace(consent))
|
|
{
|
|
await Task.Delay(500); // Wait for page to settle
|
|
showBanner = true;
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// If JS Interop fails (e.g., storage blocked), default to showing the banner
|
|
Console.WriteLine($"Cookie check failed: {ex.Message}");
|
|
showBanner = true;
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task HandleConsent(bool accepted)
|
|
{
|
|
showBanner = false;
|
|
|
|
try
|
|
{
|
|
// Save preference
|
|
await JSRuntime.InvokeVoidAsync("localStorage.setItem", "litecharms_cookie_consent", accepted ? "accepted" : "rejected");
|
|
}
|
|
catch
|
|
{
|
|
// Fail silently if storage is unavailable
|
|
}
|
|
|
|
StateHasChanged();
|
|
}
|
|
} |