Files

86 lines
3.0 KiB
HTML

{{ define "card-grid" }}
{{/*
Card grid component - displays repository cards in a responsive grid
Required:
- .Repositories: []db.RepoCardData - list of repositories to display
Optional:
- .Columns: int - number of columns on xl screens (3 or 4, default 3)
- .EmptyMessage: string - message when no repositories (default: "No repositories found.")
- .EmptyIcon: string - lucide icon name for empty state
- .EmptySubtext: string - secondary text for empty state
- .LoadMoreURL: string - URL for Load More button (HTMX)
- .TargetID: string - HTMX target ID for Load More
- .HasMore: bool - whether to show Load More button
*/}}
{{ if .Repositories }}
<div{{ if .TargetID }} id="{{ .TargetID }}"{{ end }} aria-live="polite" aria-busy="false" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3{{ if eq .Columns 4 }} xl:grid-cols-4{{ end }} gap-6">
{{ range .Repositories }}
{{ template "repo-card" . }}
{{ end }}
</div>
{{ if and .HasMore .LoadMoreURL .TargetID }}
<div id="{{ .TargetID }}-lm" class="mt-6 text-center">
<button
class="btn btn-outline"
hx-get="{{ .LoadMoreURL }}"
hx-trigger="click"
hx-target="#{{ .TargetID }}-lm"
hx-swap="outerHTML"
hx-indicator="#{{ .TargetID }}-lm-spinner"
>
<span id="{{ .TargetID }}-lm-spinner" class="htmx-indicator loading loading-spinner loading-sm"></span>
Load More
</button>
</div>
{{ end }}
{{ else }}
<div class="py-12 text-center">
{{ if .EmptyIcon }}
<div class="text-base-content/60">
{{ icon .EmptyIcon "size-12 mx-auto mb-4" }}
<p class="text-lg">{{ or .EmptyMessage "No repositories found." }}</p>
</div>
{{ else }}
<p class="text-base-content/60">{{ or .EmptyMessage "No repositories found." }}</p>
{{ end }}
{{ if .EmptySubtext }}
<p class="text-base-content/70 text-sm mt-2">{{ .EmptySubtext }}</p>
{{ end }}
</div>
{{ end }}
{{ end }}
{{/*
card-grid-append — response fragment for Load More pagination.
Emits the new page's cards OOB-swapped into #{{ .TargetID }} and
replaces the existing #{{ .TargetID }}-lm button wrapper via the
primary outerHTML swap. When .HasMore is false, the button wrapper
is replaced with an empty div, removing the Load More control.
*/}}
{{ define "card-grid-append" }}
<div hx-swap-oob="beforeend:#{{ .TargetID }}">
{{ range .Repositories }}
{{ template "repo-card" . }}
{{ end }}
</div>
{{ if and .HasMore .LoadMoreURL }}
<div id="{{ .TargetID }}-lm" class="mt-6 text-center">
<button
class="btn btn-outline"
hx-get="{{ .LoadMoreURL }}"
hx-trigger="click"
hx-target="#{{ .TargetID }}-lm"
hx-swap="outerHTML"
hx-indicator="#{{ .TargetID }}-lm-spinner"
>
<span id="{{ .TargetID }}-lm-spinner" class="htmx-indicator loading loading-spinner loading-sm"></span>
Load More
</button>
</div>
{{ else }}
<div id="{{ .TargetID }}-lm"></div>
{{ end }}
{{ end }}