90 lines
4.0 KiB
C#
90 lines
4.0 KiB
C#
using Htmx.ApiDemo;
|
|
using Htmx.ApiDemo.Templates.Components;
|
|
using Immediate.Apis.Shared;
|
|
using Immediate.Handlers.Shared;
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
namespace Htmx.ApiDemo.Templates;
|
|
|
|
public sealed class MainLayout : MainLayoutBase
|
|
{
|
|
private byte[] _titleData = [];
|
|
private byte[] _appNameData = [];
|
|
private byte[] _pageTitleData = [];
|
|
private byte[] _userSectionData = [];
|
|
|
|
public IHtmxComponent Body { get; }
|
|
|
|
public MainLayout(IHtmxComponent body, string title = "App", string appName = "MyApp",
|
|
string pageTitle = "Dashboard", string? userName = null, string? afToken = null)
|
|
{
|
|
Body = body;
|
|
_titleData = title.ToUtf8Bytes();
|
|
_appNameData = appName.ToUtf8Bytes();
|
|
_pageTitleData = pageTitle.ToUtf8Bytes();
|
|
|
|
var afInput = string.IsNullOrEmpty(afToken)
|
|
? ""
|
|
: $"""<input type="hidden" name="__RequestVerificationToken" value="{System.Web.HttpUtility.HtmlAttributeEncode(afToken)}" />""";
|
|
|
|
_userSectionData = userName is not null
|
|
? $"""
|
|
<div class="flex items-center gap-2">
|
|
<div class="flex h-9 w-9 items-center justify-center rounded-full bg-primary text-primary-foreground text-sm font-semibold select-none" title="{System.Web.HttpUtility.HtmlAttributeEncode(userName)}">
|
|
{System.Web.HttpUtility.HtmlEncode(GetInitials(userName))}
|
|
</div>
|
|
<form method="post" action="/logout">
|
|
{afInput}
|
|
<button type="submit"
|
|
class="inline-flex h-8 items-center rounded-md border border-input bg-transparent px-3 text-xs
|
|
font-medium transition-colors hover:bg-accent hover:text-accent-foreground
|
|
focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring">
|
|
Sign out
|
|
</button>
|
|
</form>
|
|
</div>
|
|
""".ToUtf8Bytes()
|
|
: """
|
|
<a href="/login"
|
|
class="inline-flex h-8 items-center rounded-md border border-input bg-transparent px-3 text-xs
|
|
font-medium transition-colors hover:bg-accent hover:text-accent-foreground
|
|
focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring">
|
|
Sign in
|
|
</a>
|
|
""".ToUtf8Bytes();
|
|
}
|
|
|
|
private static string GetInitials(string name)
|
|
{
|
|
var parts = name.Trim().Split(' ', System.StringSplitOptions.RemoveEmptyEntries);
|
|
return parts.Length >= 2
|
|
? $"{parts[0][0]}{parts[^1][0]}".ToUpperInvariant()
|
|
: name.Length > 0 ? name[0].ToString().ToUpperInvariant() : "?";
|
|
}
|
|
|
|
protected override void RenderBody(HtmxRenderContext context) => Body.Render(context);
|
|
protected override void RenderTitle(HtmxRenderContext context) => context.Writer.WriteUtf8(_titleData);
|
|
protected override void RenderAppName(HtmxRenderContext context) => context.Writer.WriteUtf8(_appNameData);
|
|
protected override void RenderPageTitle(HtmxRenderContext context) => context.Writer.WriteUtf8(_pageTitleData);
|
|
protected override void RenderUserSection(HtmxRenderContext context) => context.Writer.WriteUtf8(_userSectionData);
|
|
}
|
|
|
|
|
|
[Handler]
|
|
[MapGet("/")]
|
|
public static partial class GetIndexHandler
|
|
{
|
|
public class Command;
|
|
|
|
private static ValueTask<IResult> HandleAsync(
|
|
Command command,
|
|
IHttpContextAccessor httpContextAccessor,
|
|
CancellationToken token)
|
|
{
|
|
var context = httpContextAccessor.HttpContext
|
|
?? throw new InvalidOperationException("HttpContext is not available.");
|
|
|
|
var greet = new Greeting { Username = "Enciphered", Count = 0, GreetingId = Guid.NewGuid() };
|
|
return ValueTask.FromResult<IResult>(context.WriteHtmxPage(greet, title: "Home", appName: "HtmxApp", pageTitle: "Home"));
|
|
}
|
|
} |