initial commit
This commit is contained in:
36
Components/Pages/Error.razor
Normal file
36
Components/Pages/Error.razor
Normal file
@@ -0,0 +1,36 @@
|
||||
@page "/Error"
|
||||
@using System.Diagnostics
|
||||
|
||||
<PageTitle>Error</PageTitle>
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (ShowRequestId)
|
||||
{
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||
It can result in displaying sensitive information from exceptions to end users.
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||
and restarting the app.
|
||||
</p>
|
||||
|
||||
@code{
|
||||
[CascadingParameter]
|
||||
private HttpContext? HttpContext { get; set; }
|
||||
|
||||
private string? RequestId { get; set; }
|
||||
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
protected override void OnInitialized() =>
|
||||
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
|
||||
}
|
||||
48
Components/Pages/Home.Razor.cs
Normal file
48
Components/Pages/Home.Razor.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace ApplianceRepair.Components.Pages
|
||||
{
|
||||
public partial class Home(IMemoryCache cache, HomePageReader homePageReader, ContentCardReader contentCardReader)
|
||||
{
|
||||
private HomePageModel? Model;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (!cache.TryGetValue(nameof(HomePageModel), out Model))
|
||||
{
|
||||
Model = Defaults.DefaultHomePageContent;
|
||||
|
||||
var homePageRecord = await homePageReader.ReadLatestRecord();
|
||||
if (homePageRecord != null)
|
||||
{
|
||||
Model = new HomePageModel(homePageRecord);
|
||||
|
||||
var serviceCardRecords = await contentCardReader.ReadAllByPageAndGroup(nameof(Home), "Services");
|
||||
if (serviceCardRecords != null)
|
||||
{
|
||||
foreach (var record in serviceCardRecords)
|
||||
{
|
||||
Model.ServicesCards!.Add(new ContentCardModel(record));
|
||||
}
|
||||
}
|
||||
|
||||
var trustCardRecords = await contentCardReader.ReadAllByPageAndGroup(nameof(Home), "Trust");
|
||||
if (trustCardRecords != null)
|
||||
{
|
||||
foreach (var record in trustCardRecords)
|
||||
{
|
||||
Model.TrustCards!.Add(new ContentCardModel(record));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var cacheOptions = new MemoryCacheEntryOptions()
|
||||
.SetAbsoluteExpiration(TimeSpan.FromHours(24))
|
||||
.SetSlidingExpiration(TimeSpan.FromHours(2));
|
||||
|
||||
cache.Set(nameof(HomePageModel), Model, cacheOptions);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
67
Components/Pages/Home.razor
Normal file
67
Components/Pages/Home.razor
Normal file
@@ -0,0 +1,67 @@
|
||||
@page "/"
|
||||
@rendermode InteractiveServer
|
||||
|
||||
<PageTitle>Home</PageTitle>
|
||||
|
||||
@if (Model == null)
|
||||
{
|
||||
<p>Loading...</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<nav class="navbar">
|
||||
<div class="container">
|
||||
<div class="logo">@Model.BusinessName</div>
|
||||
<a href="@Model.PhoneNumberCallLink" class="nav-phone">📞 @Model.FormattedPhoneNumber</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<header class="hero">
|
||||
<div class="container">
|
||||
<h1>@Model.HeaderLine1 <br><span>@Model.HeaderLine2</span></h1>
|
||||
<p>@Model.HeaderText</p>
|
||||
<div class="cta-group">
|
||||
<a href="@Model.HeaderButton1Link" class="btn btn-primary">@Model.HeaderButton1Text</a>
|
||||
<a href="@Model.HeaderButton2Link" class="btn btn-secondary">@Model.HeaderButton2Text</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="services">
|
||||
<div class="container">
|
||||
<h2 class="section-title">@Model.SecondaryHeaderText</h2>
|
||||
<div class="service-grid">
|
||||
@if (Model.ServicesCards != null)
|
||||
{
|
||||
foreach (var serviceCard in Model.ServicesCards)
|
||||
{
|
||||
<div class="service-card">
|
||||
<h3>@serviceCard.Header</h3>
|
||||
<p>@serviceCard.Text</p>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="trust">
|
||||
<div class="container">
|
||||
@if (Model.TrustCards != null)
|
||||
{
|
||||
foreach (var trustCard in Model.TrustCards)
|
||||
{
|
||||
<div class="trust-item">
|
||||
<strong>@trustCard.Header</strong>
|
||||
<p>@trustCard.Text</p>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<p>@Model.CopyrightText</p>
|
||||
</footer>
|
||||
}
|
||||
|
||||
148
Components/Pages/Home.razor.css
Normal file
148
Components/Pages/Home.razor.css
Normal file
@@ -0,0 +1,148 @@
|
||||
|
||||
/* General Styles */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1100px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
/* Navbar */
|
||||
.navbar {
|
||||
background: #fff;
|
||||
padding: 1rem 0;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.navbar .container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
color: #0056b3;
|
||||
}
|
||||
|
||||
.logo span {
|
||||
color: #e63946;
|
||||
}
|
||||
|
||||
.nav-phone {
|
||||
text-decoration: none;
|
||||
color: #0056b3;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Hero Section */
|
||||
.hero {
|
||||
background: linear-gradient(rgba(0,0,0,0.6), rgba(0,0,0,0.6)), url('https://images.unsplash.com/photo-1581092918056-0c4c3acd3789?auto=format&fit=crop&w=1200&q=80');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
color: #fff;
|
||||
padding: 100px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.hero h1 span {
|
||||
color: #4cc9f0;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 12px 25px;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
margin: 10px;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #e63946;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: #fff;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
opacity: 0.9;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Services */
|
||||
.services {
|
||||
padding: 60px 0;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.service-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.service-card {
|
||||
background: #fff;
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
border-bottom: 4px solid #0056b3;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
/* Trust Section */
|
||||
.trust {
|
||||
background: #0056b3;
|
||||
color: #fff;
|
||||
padding: 40px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.trust .container {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.trust-item {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
font-size: 0.9rem;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
/* Mobile Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.hero h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user