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
|
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;
|
private HomePageModel? Model;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
if (!cache.TryGetValue(nameof(HomePageModel), out Model))
|
// 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 businessConfig = await businessConfigReader.ReadLatestRecord() ?? Defaults.DefaultBusinessConfig;
|
||||||
var servicesList = await contentCardReader.ReadAllByPageAndGroup(HomePageModel.PageName, nameof(HomePageModel.ContentCardTypes.Services)) ?? [];
|
// var latestHomeRecord = await homePageReader.ReadLatestRecord() ?? Defaults.DefaultHomePageContent;
|
||||||
var trustList = await contentCardReader.ReadAllByPageAndGroup(HomePageModel.PageName, nameof(HomePageModel.ContentCardTypes.Trust)) ?? [];
|
// 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()
|
// var cacheOptions = new MemoryCacheEntryOptions()
|
||||||
.SetAbsoluteExpiration(TimeSpan.FromHours(24))
|
// .SetAbsoluteExpiration(TimeSpan.FromHours(24))
|
||||||
.SetSlidingExpiration(TimeSpan.FromHours(2));
|
// .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
|
@rendermode InteractiveServer
|
||||||
|
|
||||||
<div class="admin-wrapper">
|
<div class="admin-wrapper">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<header class="admin-header">
|
<header class="admin-header">
|
||||||
<h1>Page Content Management</h1>
|
<h1>Admin Panel</h1>
|
||||||
<p>Update your business details and home page content below.</p>
|
<p>Update your business details and home page content below.</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@@ -32,6 +34,12 @@
|
|||||||
Business Info
|
Business Info
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tab-container">
|
||||||
|
<button class="tab-btn @(CurrentTab == AdminTab.Requests ? "active" : "")"
|
||||||
|
@onclick="() => CurrentTab = AdminTab.Requests">
|
||||||
|
Requests
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@if (CurrentTab == AdminTab.Home)
|
@if (CurrentTab == AdminTab.Home)
|
||||||
@@ -136,6 +144,57 @@
|
|||||||
</div>
|
</div>
|
||||||
</EditForm>
|
</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>
|
||||||
</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 HomePageModel? HomePageModel;
|
||||||
public BusinessInfoModel? BusinessInfo;
|
public BusinessInfoModel? BusinessInfo;
|
||||||
|
public List<RepairRequestModel>? RepairRequests;
|
||||||
|
|
||||||
private enum AdminTab { Home, About, BusinessInfo }
|
private enum AdminTab { Home, Requests, BusinessInfo }
|
||||||
private AdminTab CurrentTab = AdminTab.Home;
|
private AdminTab CurrentTab = AdminTab.Home;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
@@ -17,6 +20,12 @@
|
|||||||
|
|
||||||
BusinessInfo = new BusinessInfoModel(businessConfig);
|
BusinessInfo = new BusinessInfoModel(businessConfig);
|
||||||
HomePageModel = new HomePageModel(latestHomeRecord, businessConfig, servicesList, trustList);
|
HomePageModel = new HomePageModel(latestHomeRecord, businessConfig, servicesList, trustList);
|
||||||
|
|
||||||
|
RepairRequests = [];
|
||||||
|
(await repairRequestReader.ReadAll()).ForEach((record) =>
|
||||||
|
{
|
||||||
|
RepairRequests.Add(new RepairRequestModel(record));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void RevertHomePageModel()
|
private async void RevertHomePageModel()
|
||||||
@@ -164,6 +164,75 @@ label {
|
|||||||
line-height: 1.5;
|
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 {
|
.btn-save {
|
||||||
background: #4CAF50;
|
background: #4CAF50;
|
||||||
color: white;
|
color: white;
|
||||||
@@ -182,6 +251,23 @@ label {
|
|||||||
background: #43a047;
|
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 {
|
.btn-revert {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #666;
|
color: #666;
|
||||||
@@ -237,4 +323,16 @@ label {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
row-gap: 2rem;
|
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
|
public class BusinessInfoModel : BusinessConfigRecord
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user