173 lines
5.1 KiB
Plaintext
173 lines
5.1 KiB
Plaintext
package detailsview
|
|
|
|
import "github.com/tigorlazuardi/redmage/views"
|
|
import "github.com/tigorlazuardi/redmage/models"
|
|
import "github.com/tigorlazuardi/redmage/views/components"
|
|
import "strconv"
|
|
import "github.com/tigorlazuardi/redmage/api"
|
|
import "fmt"
|
|
|
|
type Data struct {
|
|
Subreddit *models.Subreddit
|
|
Devices models.DeviceSlice
|
|
Images models.ImageSlice
|
|
TotalImages int64
|
|
Error string
|
|
Params api.SubredditGetByNameImageParams
|
|
}
|
|
|
|
templ Detailsview(c *views.Context, data Data) {
|
|
@components.Doctype() {
|
|
if data.Subreddit != nil {
|
|
@components.Head(c, components.HeadTitle(fmt.Sprintf("Subreddit - %s", data.Subreddit.Name)))
|
|
} else {
|
|
@components.Head(c, components.HeadTitle("Subreddit - 404 NOT FOUND"))
|
|
}
|
|
@components.Body(c) {
|
|
@DetailsContent(c, data)
|
|
@components.NotificationContainer()
|
|
}
|
|
}
|
|
}
|
|
|
|
templ DetailsContent(c *views.Context, data Data) {
|
|
<main class="prose min-w-full">
|
|
@components.Container() {
|
|
if data.Error != "" {
|
|
<h1>Error: { data.Error }</h1>
|
|
} else {
|
|
<div class="flex items-center justify-between">
|
|
<h1>Subreddit { data.Subreddit.Name }</h1>
|
|
</div>
|
|
<div class="flex flex-wrap justify-center xs:justify-between content-center gap-4">
|
|
<h2 class="my-auto">
|
|
Total Images:
|
|
{ strconv.FormatInt(data.TotalImages, 10) }
|
|
</h2>
|
|
<button
|
|
hx-post="/htmx/subreddits/start"
|
|
hx-include="this"
|
|
class="btn btn-primary text-base-100"
|
|
hx-target={ components.NotificationContainerID }
|
|
hx-target-error={ components.NotificationContainerID }
|
|
hx-swap="afterbegin"
|
|
>
|
|
Start Download
|
|
<input type="hidden" name="subreddit" value={ data.Subreddit.Name }/>
|
|
</button>
|
|
</div>
|
|
<div class="divider"></div>
|
|
@FilterBar(c, data)
|
|
<div class="grid justify-center my-4">
|
|
@components.Pagination(c, components.PaginationData{
|
|
Offset: data.Params.Offset,
|
|
Limit: data.Params.Limit,
|
|
BaseURL: fmt.Sprintf("/subreddits/details/%s", data.Subreddit.Name),
|
|
Total: data.TotalImages,
|
|
})
|
|
</div>
|
|
@showingImageFromTo(data)
|
|
<div class="flex flex-wrap gap-4 my-8 justify-around">
|
|
for _, image := range data.Images {
|
|
@components.ImageCard(image, components.HideNothing.SetCond(components.HideDevice, data.Params.Device != ""))
|
|
}
|
|
</div>
|
|
<div class="flex w-full justify-center">
|
|
@components.Pagination(c, components.PaginationData{
|
|
Offset: data.Params.Offset,
|
|
Limit: data.Params.Limit,
|
|
BaseURL: fmt.Sprintf("/subreddits/details/%s", data.Subreddit.Name),
|
|
Total: data.TotalImages,
|
|
})
|
|
</div>
|
|
}
|
|
}
|
|
</main>
|
|
}
|
|
|
|
templ FilterBar(c *views.Context, data Data) {
|
|
<div
|
|
id="filter-bar"
|
|
hx-get={ fmt.Sprintf("/subreddits/details/%s", data.Subreddit.Name) }
|
|
hx-include="this"
|
|
hx-trigger="change, on-rapid delay:500ms, on-demand"
|
|
hx-target="main"
|
|
hx-select="main"
|
|
hx-push-url="true"
|
|
class="grid sm:grid-cols-2 md:grid-cols-3 gap-4"
|
|
>
|
|
<label class="input input-bordered flex items-center gap-2 sm:col-span-2 md:col-auto">
|
|
<input
|
|
id="search"
|
|
type="text"
|
|
class="grow"
|
|
placeholder="Search"
|
|
name="q"
|
|
value={ data.Params.Q }
|
|
oninput="htmx.trigger('#filter-bar', 'on-rapid')"
|
|
/>
|
|
<svg
|
|
onclick="htmx.trigger('#filter-bar', 'on-demand')"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 16 16"
|
|
fill="currentColor"
|
|
class="w-4 h-4 opacity-70"
|
|
><path fill-rule="evenodd" d="M9.965 11.026a5 5 0 1 1 1.06-1.06l2.755 2.754a.75.75 0 1 1-1.06 1.06l-2.755-2.754ZM10.5 7a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0Z" clip-rule="evenodd"></path></svg>
|
|
</label>
|
|
<label class="flex items-center gap-2">
|
|
Limit
|
|
<select name="limit" class="select select-bordered w-full">
|
|
@limitOption(data.Params, 25)
|
|
@limitOption(data.Params, 50)
|
|
@limitOption(data.Params, 75)
|
|
@limitOption(data.Params, 100)
|
|
</select>
|
|
</label>
|
|
<label class="flex items-center gap-2">
|
|
Device
|
|
<select name="device" class="select select-bordered w-full">
|
|
if len(data.Devices) == 0 {
|
|
<option disabled selected>No Devices</option>
|
|
} else {
|
|
<option value="" selected?={ data.Params.Device == "" }>*No Filter</option>
|
|
}
|
|
for _, device := range data.Devices {
|
|
@deviceOption(data.Params, device)
|
|
}
|
|
</select>
|
|
</label>
|
|
</div>
|
|
}
|
|
|
|
templ limitOption(params api.SubredditGetByNameImageParams, value int) {
|
|
if int(params.Limit) == value {
|
|
<option selected>{ strconv.Itoa(value) }</option>
|
|
} else {
|
|
<option>{ strconv.Itoa(value) }</option>
|
|
}
|
|
}
|
|
|
|
templ deviceOption(params api.SubredditGetByNameImageParams, device *models.Device) {
|
|
if params.Device == device.Slug {
|
|
<option value={ device.Slug } selected>{ device.Name }</option>
|
|
} else {
|
|
<option value={ device.Slug }>{ device.Name }</option>
|
|
}
|
|
}
|
|
|
|
templ showingImageFromTo(data Data) {
|
|
if data.TotalImages > 1 {
|
|
<p class="text-center my-4">{ showingFromToImages(data) }</p>
|
|
}
|
|
}
|
|
|
|
func showingFromToImages(data Data) string {
|
|
params := data.Params
|
|
start := params.Offset + 1
|
|
end := params.Limit + params.Offset
|
|
if end > data.TotalImages {
|
|
end = data.TotalImages
|
|
}
|
|
return fmt.Sprintf("Showing from %d to %d", start, end)
|
|
}
|