Files
LazyPM/pkg/web/components/issue.templ
2026-02-25 12:39:21 +01:00

141 lines
3.4 KiB
Plaintext

package components
import (
"fmt"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/pkg/web/components/base"
)
type IssueFormProps struct {
PostAction string
PatchAction string
Title string
Description string
Status string
Priority int
IssueType string
Class string
Attrs templ.Attributes
Target string // Optional: if empty, server controls via HX-Target header
}
templ IssueForm(props IssueFormProps) {
<div class={ "w-full max-w-lg mx-auto ", props.Class }>
<form
class="form space-y-1"
if props.PatchAction != "" {
hx-patch={ props.PatchAction }
}
if props.PostAction != "" {
hx-post={ props.PostAction }
}
if props.Target != "" {
hx-target={ props.Target }
}
hx-swap="innerHTML"
{ props.Attrs... }
>
@base.Input(base.InputProps{
Name: "title",
Label: "Title",
Value: props.Title,
Class: "w-full",
Required: true,
})
@base.Textarea(base.TextareaProps{
Name: "description",
Label: "Description",
Value: props.Description,
Class: "w-full",
Required: true,
})
@base.Select(base.SelectProps{
Name: "status",
Label: "Status",
Required: true,
Options: []base.SelectOption{
{Label: "Open", Value: "open", Selected: props.Status == "open"},
{Label: "In Progress", Value: "in_progress", Selected: props.Status == "in_progress"},
{Label: "Closed", Value: "closed", Selected: props.Status == "closed"},
},
Size: "md",
})
@base.Select(base.SelectProps{
Name: "issue_type",
Label: "Issue Type",
Required: true,
Options: []base.SelectOption{
{Label: "Task", Value: "task", Selected: props.IssueType == "task"},
{Label: "Bug", Value: "bug", Selected: props.IssueType == "bug"},
{Label: "Feature", Value: "feature", Selected: props.IssueType == "feature"},
{Label: "Chore", Value: "chore", Selected: props.IssueType == "chore"},
},
Size: "md",
})
@base.Range(base.RangeProps{
Name: "priority",
Label: "Priority",
Class: "flex-1",
Min: 0,
Max: 4,
Value: props.Priority,
Step: 1,
})
<button type="submit" class="btn btn-primary w-full mt-4">
Submit Issue
</button>
</form>
if props.Target == "" {
<div id="result"></div>
}
</div>
}
type IssueTableProps struct {
Issues []*models.Issue
}
templ IssueTable(props IssueTableProps) {
@base.Table(
[]templ.Component{
base.PlainText("ID"),
base.PlainText("Title"),
base.PlainText("Status"),
base.PlainText("Type"),
base.PlainText("Priority"),
},
[]templ.Component{
IssueRows(props.Issues),
},
templ.Attributes{},
)
}
templ IssueRows(issues []*models.Issue) {
for _, issue := range issues {
<tr class="hover">
<td class="px-4 py-2 border">
<a
class="link link-primary font-mono"
hx-get={ "/issues/" + issue.ID }
hx-target="main"
hx-swap="innerHTML"
hx-push-url="true"
>{ issue.ID }</a>
</td>
<td class="px-4 py-2 border">
<a
class="hover:text-primary"
hx-get={ "/issues/" + issue.ID }
hx-target="main"
hx-swap="innerHTML"
hx-push-url="true"
>{ issue.Title }</a>
</td>
<td class="px-4 py-2 border">{ string(issue.Status) }</td>
<td class="px-4 py-2 border">{ string(issue.IssueType) }</td>
<td class="px-4 py-2 border">{ fmt.Sprintf("P%d", issue.Priority) }</td>
</tr>
}
}