edited admin page, added request viewer
This commit is contained in:
@@ -1,28 +1,37 @@
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace ApplianceRepair.Components.Pages
|
||||
{
|
||||
public partial class Home(IMemoryCache cache, HomePageReader homePageReader, ContentCardReader contentCardReader, BusinessConfigReader businessConfigReader)
|
||||
public partial class Home(IMemoryCache cache, HomePageReader homePageReader, ContentCardReader contentCardReader, BusinessConfigReader businessConfigReader) : ComponentBase
|
||||
{
|
||||
private HomePageModel? Model;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (!cache.TryGetValue(nameof(HomePageModel), out Model))
|
||||
{
|
||||
var businessConfig = await businessConfigReader.ReadLatestRecord() ?? Defaults.DefaultBusinessConfig;
|
||||
var latestHomeRecord = await homePageReader.ReadLatestRecord() ?? Defaults.DefaultHomePageContent;
|
||||
var servicesList = await contentCardReader.ReadAllByPageAndGroup(HomePageModel.PageName, nameof(HomePageModel.ContentCardTypes.Services)) ?? [];
|
||||
var trustList = await contentCardReader.ReadAllByPageAndGroup(HomePageModel.PageName, nameof(HomePageModel.ContentCardTypes.Trust)) ?? [];
|
||||
// TODO: Figure out a better cache system, needs to be marked dirty if admin makes a config change
|
||||
//if (!cache.TryGetValue(nameof(HomePageModel), out Model))
|
||||
//{
|
||||
// var businessConfig = await businessConfigReader.ReadLatestRecord() ?? Defaults.DefaultBusinessConfig;
|
||||
// var latestHomeRecord = await homePageReader.ReadLatestRecord() ?? Defaults.DefaultHomePageContent;
|
||||
// var servicesList = await contentCardReader.ReadAllByPageAndGroup(HomePageModel.PageName, nameof(HomePageModel.ContentCardTypes.Services)) ?? [];
|
||||
// var trustList = await contentCardReader.ReadAllByPageAndGroup(HomePageModel.PageName, nameof(HomePageModel.ContentCardTypes.Trust)) ?? [];
|
||||
|
||||
Model = new HomePageModel(latestHomeRecord, businessConfig, servicesList, trustList);
|
||||
// Model = new HomePageModel(latestHomeRecord, businessConfig, servicesList, trustList);
|
||||
|
||||
var cacheOptions = new MemoryCacheEntryOptions()
|
||||
.SetAbsoluteExpiration(TimeSpan.FromHours(24))
|
||||
.SetSlidingExpiration(TimeSpan.FromHours(2));
|
||||
// var cacheOptions = new MemoryCacheEntryOptions()
|
||||
// .SetAbsoluteExpiration(TimeSpan.FromHours(24))
|
||||
// .SetSlidingExpiration(TimeSpan.FromHours(2));
|
||||
|
||||
cache.Set(nameof(HomePageModel), Model, cacheOptions);
|
||||
}
|
||||
// cache.Set(nameof(HomePageModel), Model, cacheOptions);
|
||||
//}
|
||||
|
||||
var businessConfig = await businessConfigReader.ReadLatestRecord() ?? Defaults.DefaultBusinessConfig;
|
||||
var latestHomeRecord = await homePageReader.ReadLatestRecord() ?? Defaults.DefaultHomePageContent;
|
||||
var servicesList = await contentCardReader.ReadAllByPageAndGroup(HomePageModel.PageName, nameof(HomePageModel.ContentCardTypes.Services)) ?? [];
|
||||
var trustList = await contentCardReader.ReadAllByPageAndGroup(HomePageModel.PageName, nameof(HomePageModel.ContentCardTypes.Trust)) ?? [];
|
||||
|
||||
Model = new HomePageModel(latestHomeRecord, businessConfig, servicesList, trustList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
@page "/admin/editpages"
|
||||
@page "/admin"
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@attribute [Authorize]
|
||||
@rendermode InteractiveServer
|
||||
|
||||
<div class="admin-wrapper">
|
||||
<div class="container">
|
||||
<header class="admin-header">
|
||||
<h1>Page Content Management</h1>
|
||||
<h1>Admin Panel</h1>
|
||||
<p>Update your business details and home page content below.</p>
|
||||
</header>
|
||||
|
||||
@@ -32,6 +34,12 @@
|
||||
Business Info
|
||||
</button>
|
||||
</div>
|
||||
<div class="tab-container">
|
||||
<button class="tab-btn @(CurrentTab == AdminTab.Requests ? "active" : "")"
|
||||
@onclick="() => CurrentTab = AdminTab.Requests">
|
||||
Requests
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@if (CurrentTab == AdminTab.Home)
|
||||
@@ -136,6 +144,57 @@
|
||||
</div>
|
||||
</EditForm>
|
||||
}
|
||||
else if (CurrentTab == AdminTab.Requests)
|
||||
{
|
||||
<div class="form-section">
|
||||
<h3><i class="icon">📋</i> Service Requests</h3>
|
||||
|
||||
@if (RepairRequests == null || !RepairRequests.Any())
|
||||
{
|
||||
<p class="text-muted">No service requests found.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="requests-list">
|
||||
@foreach (var request in RepairRequests)
|
||||
{
|
||||
<div class="content-card request-card">
|
||||
<div class="request-header">
|
||||
<span class="request-id">@request.RequestNumber</span>
|
||||
<span class="request-date">@request.CreatedAt.ToString("MMM dd, yyyy")</span>
|
||||
</div>
|
||||
|
||||
<div class="request-body">
|
||||
<div class="info-row">
|
||||
<span class="label">Customer:</span>
|
||||
<span class="value">@request.Name</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">Phone:</span>
|
||||
<span class="value">@request.FormattedPhoneNumber</span>
|
||||
<a href="tel:@request.Phone" class="phone-link">
|
||||
<i class="icon">📞</i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">Appliance:</span>
|
||||
<span class="value"><strong>@request.Brand</strong> @request.Type</span>
|
||||
</div>
|
||||
<div class="info-notes">
|
||||
<span class="label">Issue Notes:</span>
|
||||
<p>@request.Notes</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="request-actions">
|
||||
<button class="btn-small btn-view" @onclick="() => {}">View Images</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -1,11 +1,14 @@
|
||||
namespace ApplianceRepair.Components.Pages.admin
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace ApplianceRepair.Components.Pages.admin
|
||||
{
|
||||
public partial class EditPages(HomePageReader homePageReader, ContentCardReader contentCardReader, BusinessConfigReader businessConfigReader)
|
||||
public partial class Admin(HomePageReader homePageReader, ContentCardReader contentCardReader, BusinessConfigReader businessConfigReader, RepairRequestReader repairRequestReader) : ComponentBase
|
||||
{
|
||||
public HomePageModel? HomePageModel;
|
||||
public BusinessInfoModel? BusinessInfo;
|
||||
public List<RepairRequestModel>? RepairRequests;
|
||||
|
||||
private enum AdminTab { Home, About, BusinessInfo }
|
||||
private enum AdminTab { Home, Requests, BusinessInfo }
|
||||
private AdminTab CurrentTab = AdminTab.Home;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
@@ -17,6 +20,12 @@
|
||||
|
||||
BusinessInfo = new BusinessInfoModel(businessConfig);
|
||||
HomePageModel = new HomePageModel(latestHomeRecord, businessConfig, servicesList, trustList);
|
||||
|
||||
RepairRequests = [];
|
||||
(await repairRequestReader.ReadAll()).ForEach((record) =>
|
||||
{
|
||||
RepairRequests.Add(new RepairRequestModel(record));
|
||||
});
|
||||
}
|
||||
|
||||
private async void RevertHomePageModel()
|
||||
@@ -164,6 +164,75 @@ label {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.requests-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.request-card {
|
||||
display: grid;
|
||||
grid-template-columns: 150px 1fr 180px;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.request-id {
|
||||
font-weight: 700;
|
||||
color: #2a5298;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.request-date {
|
||||
font-size: 0.85rem;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.request-body {
|
||||
border-left: 1px solid #eee;
|
||||
border-right: 1px solid #eee;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
margin-bottom: 5px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.info-row .label {
|
||||
display: inline;
|
||||
text-transform: none;
|
||||
margin: 0;
|
||||
color: #666;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.info-notes {
|
||||
margin-top: 10px;
|
||||
font-size: 0.85rem;
|
||||
font-style: italic;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.phone-link {
|
||||
color: #2a5298;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.phone-link:hover {
|
||||
color: #4CAF50; /* Changes to green on hover to signify 'Call' */
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.request-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.btn-save {
|
||||
background: #4CAF50;
|
||||
color: white;
|
||||
@@ -182,6 +251,23 @@ label {
|
||||
background: #43a047;
|
||||
}
|
||||
|
||||
.btn-small {
|
||||
padding: 8px 20px;
|
||||
border-radius: 20px;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
border: 1px solid #2a5298;
|
||||
background: transparent;
|
||||
color: #2a5298;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-small:hover {
|
||||
background: #2a5298;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-revert {
|
||||
background: transparent;
|
||||
color: #666;
|
||||
@@ -237,4 +323,16 @@ label {
|
||||
justify-content: center;
|
||||
row-gap: 2rem;
|
||||
}
|
||||
|
||||
.request-card {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.request-body {
|
||||
border: none;
|
||||
padding: 10px 0;
|
||||
border-top: 1px solid #eee;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
}
|
||||
41
Models.cs
41
Models.cs
@@ -123,7 +123,46 @@
|
||||
}
|
||||
}
|
||||
|
||||
public class RepairRequestModel : RepairRequestRecord { }
|
||||
public class RepairRequestModel : RepairRequestRecord
|
||||
{
|
||||
public string FormattedPhoneNumber
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Phone))
|
||||
{
|
||||
return $"({Phone[0..3]})-{Phone[3..6]}-{Phone[6..10]}";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public string PhoneNumberCallLink
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Phone))
|
||||
{
|
||||
return $"tel:{Phone}";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public RepairRequestModel() { }
|
||||
|
||||
public RepairRequestModel(RepairRequestRecord record)
|
||||
{
|
||||
RequestNumber = record.RequestNumber;
|
||||
Type = record.Type;
|
||||
Brand = record.Brand;
|
||||
Notes = record.Notes;
|
||||
Phone = record.Phone;
|
||||
Name = record.Name;
|
||||
}
|
||||
}
|
||||
|
||||
public class BusinessInfoModel : BusinessConfigRecord
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user