add comments loader, cache stories

This commit is contained in:
maddalax 2024-10-10 17:59:08 -05:00
parent 78f7a68c1e
commit c2b3b439e6
2 changed files with 38 additions and 14 deletions

View file

@ -12,10 +12,14 @@ import (
func StoryComments(ctx *h.RequestContext) *h.Partial { func StoryComments(ctx *h.RequestContext) *h.Partial {
return h.NewPartial( return h.NewPartial(
h.Fragment(
h.OobSwap(ctx, h.Div(h.Id("comments-loader"))),
h.Div( h.Div(
h.Class("flex flex-col gap-3 prose max-w-none"), h.Class("flex flex-col gap-3 prose max-w-none"),
CachedStoryComments(news.MustItemId(ctx)), CachedStoryComments(news.MustItemId(ctx)),
)) ),
),
)
} }
var CachedStoryComments = h.CachedPerKeyT[string, int](time.Minute*3, func(itemId int) (string, h.GetElementFunc) { var CachedStoryComments = h.CachedPerKeyT[string, int](time.Minute*3, func(itemId int) (string, h.GetElementFunc) {

View file

@ -5,13 +5,12 @@ import (
"github.com/maddalax/htmgo/framework/h" "github.com/maddalax/htmgo/framework/h"
"hackernews/internal/news" "hackernews/internal/news"
"hackernews/internal/timeformat" "hackernews/internal/timeformat"
"strconv" "time"
) )
func Story(ctx *h.RequestContext) *h.Partial { func Story(ctx *h.RequestContext) *h.Partial {
storyId, err := strconv.ParseInt(ctx.QueryParam("item"), 10, 64) storyId := news.MustItemId(ctx)
if storyId == 0 {
if storyId == 0 || err != nil {
return h.NewPartial( return h.NewPartial(
h.Div( h.Div(
h.Class("flex justify-center bg-neutral-300"), h.Class("flex justify-center bg-neutral-300"),
@ -20,29 +19,42 @@ func Story(ctx *h.RequestContext) *h.Partial {
) )
} }
story, err := news.GetStory(int(storyId))
if ctx.IsHxRequest() { if ctx.IsHxRequest() {
return h.SwapManyPartialWithHeaders( return h.SwapManyPartialWithHeaders(
ctx, ctx,
h.PushUrlHeader(fmt.Sprintf("/?item=%d", storyId)), h.PushUrlHeader(fmt.Sprintf("/?item=%d", storyId)),
StoryBody(story), h.Div(
h.Id("story-body"),
CachedStoryBody(storyId),
),
) )
} }
return h.NewPartial( return h.NewPartial(
StoryBody(story), CachedStoryBody(storyId),
) )
} }
var CachedStoryBody = h.CachedPerKeyT[string, int](time.Minute*3, func(itemId int) (string, h.GetElementFunc) {
return fmt.Sprintf("story-%d", itemId), func() *h.Element {
story, err := news.GetStory(itemId)
if err != nil {
return h.Div(
h.Id("story-body"),
h.Text("Failed to load story"),
)
}
return StoryBody(story)
}
})
func StoryBody(story *news.Story) *h.Element { func StoryBody(story *news.Story) *h.Element {
return h.Div( return h.Div(
h.Class("min-w-3xl"),
h.Id("story-body"), h.Id("story-body"),
h.Div( h.Div(
h.Class("prose prose-2xl bg-white border-b border-gray-200 pb-3 min-w-3xl max-w-3xl"), h.Class("prose prose-2xl bg-white border-b border-gray-200 pb-3 min-w-3xl max-w-3xl"),
h.H5( h.H5(
h.Class("flex gap-2 items-center font-bold"), h.Class("flex gap-2 items-left font-bold"),
h.UnsafeRaw(story.Title), h.UnsafeRaw(story.Title),
), ),
h.A( h.A(
@ -63,6 +75,14 @@ func StoryBody(story *news.Story) *h.Element {
h.TextF(" %s", timeformat.RelativeTime(story.Time)), h.TextF(" %s", timeformat.RelativeTime(story.Time)),
), ),
), ),
h.TriggerChildren(),
h.Div(
h.Id("comments-loader"),
h.Class("flex justify-center items-center h-24"),
h.Div(
h.Class("animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-rose-500"),
),
),
h.Div( h.Div(
h.Class("mt-2 min-w-3xl max-w-3xl"), h.Class("mt-2 min-w-3xl max-w-3xl"),
h.GetPartial(StoryComments, "load"), h.GetPartial(StoryComments, "load"),