so much stuff

This commit is contained in:
maddalax 2024-09-11 13:09:55 -05:00
parent 3d18f2d89b
commit c0137247b7
10 changed files with 153 additions and 25 deletions

View file

@ -55,6 +55,27 @@ func HtmlView(c *fiber.Ctx, page *Page) error {
) )
} }
func PartialViewWithHeaders(c *fiber.Ctx, headers *Headers, partial *Partial) error {
c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
if partial.Headers != nil {
for s, a := range *partial.Headers {
c.Set(s, a)
}
}
if headers != nil {
for s, a := range *headers {
c.Set(s, a)
}
}
return c.SendString(
Render(
partial.Root,
),
)
}
func PartialView(c *fiber.Ctx, partial *Partial) error { func PartialView(c *fiber.Ctx, partial *Partial) error {
c.Set(fiber.HeaderContentType, fiber.MIMETextHTML) c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
if partial.Headers != nil { if partial.Headers != nil {

View file

@ -251,13 +251,13 @@ func Input(inputType string, children ...*Node) *Node {
} }
} }
func List[T any](items []T, mapper func(item T) *Node) *Node { func List[T any](items []T, mapper func(item T, index int) *Node) *Node {
node := &Node{ node := &Node{
tag: "", tag: "",
children: make([]*Node, len(items)), children: make([]*Node, len(items)),
} }
for index, value := range items { for index, value := range items {
node.children[index] = mapper(value) node.children[index] = mapper(value, index)
} }
return node return node
} }
@ -298,6 +298,10 @@ func P(text string, children ...*Node) *Node {
} }
} }
func Form(children ...*Node) *Node {
return Tag("form", children...)
}
func A(text string, children ...*Node) *Node { func A(text string, children ...*Node) *Node {
return &Node{ return &Node{
tag: "a", tag: "a",
@ -374,6 +378,10 @@ func Children(children []*Node) *Node {
} }
} }
func Label(text string) *Node {
return Tag("label", Text(text))
}
func If(condition bool, node *Node) *Node { func If(condition bool, node *Node) *Node {
if condition { if condition {
return node return node

19
main.go
View file

@ -4,9 +4,11 @@ import (
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/google/uuid" "github.com/google/uuid"
"log" "log"
"mhtml/database"
"mhtml/h" "mhtml/h"
"mhtml/pages" "mhtml/pages"
"mhtml/partials" "mhtml/partials"
"mhtml/partials/sheet"
"time" "time"
) )
@ -50,6 +52,23 @@ func main() {
pages.RegisterPages(f) pages.RegisterPages(f)
f.Post("/api/patients", func(ctx *fiber.Ctx) error {
name := ctx.FormValue("name")
reason := ctx.FormValue("reason-for-visit")
location := ctx.FormValue("location-name")
database.HSet("patients", uuid.New().String(), partials.Patient{
Name: name,
ReasonForVisit: reason,
AppointmentDate: time.Now(),
LocationName: location,
})
return h.PartialViewWithHeaders(ctx, &map[string]string{
"HX-Trigger": "patient-added",
}, sheet.Close(ctx))
})
h.Start(f, h.App{ h.Start(f, h.App{
LiveReload: true, LiveReload: true,
}) })

View file

@ -21,7 +21,7 @@ func StoryList() *h.Node {
} }
return h.Fragment( return h.Fragment(
h.Div(h.List(*posts, func(item Post) *h.Node { h.Div(h.List(*posts, func(item Post, index int) *h.Node {
return StoryCard(item) return StoryCard(item)
})), })),
) )

View file

@ -10,12 +10,15 @@ import (
func PatientsIndex(ctx *fiber.Ctx) *h.Page { func PatientsIndex(ctx *fiber.Ctx) *h.Page {
return h.NewPage(base.RootPage( return h.NewPage(base.RootPage(
h.Div( h.Div(
h.Class("flex flex-col p-4"), h.Class("flex flex-col p-4 w-full"),
h.Div( h.Div(
h.Class("flex justify-between items-center"), h.Div(
h.P("Manage Patients", h.Class("text-lg font-bold")), h.Class("flex justify-between items-center"),
partials.AddPatientButton()), h.P("Manage Patients", h.Class("text-lg font-bold")),
h.ViewWithTriggers(partials.PatientList, "load", "every 3s"), partials.AddPatientButton(),
),
h.ViewWithTriggers(partials.PatientList, "load", "patient-added from:body"),
),
), ),
)) ))
} }

View file

@ -16,8 +16,8 @@ func GetPartialFromContext(ctx *fiber.Ctx) *h.Partial {
if path == "PatientList" || path == "/mhtml/partials.PatientList" { if path == "PatientList" || path == "/mhtml/partials.PatientList" {
return PatientList(ctx) return PatientList(ctx)
} }
if path == "AddPatientForm" || path == "/mhtml/partials.AddPatientForm" { if path == "AddPatientSheet" || path == "/mhtml/partials.AddPatientSheet" {
return AddPatientForm(ctx) return AddPatientSheet(ctx)
} }
if path == "Close" || path == "/mhtml/partials/sheet.Close" { if path == "Close" || path == "/mhtml/partials/sheet.Close" {
return sheet.Close(ctx) return sheet.Close(ctx)

View file

@ -34,21 +34,59 @@ func PatientList(ctx *fiber.Ctx) *h.Partial {
} }
return h.NewPartial(h.Div( return h.NewPartial(h.Div(
h.Class("mt-8"),
h.Id("patient-list"), h.Id("patient-list"),
h.List(patients, PatientRow), h.List(patients, PatientRow),
)) ))
} }
func AddPatientForm(ctx *fiber.Ctx) *h.Partial { func AddPatientSheet(ctx *fiber.Ctx) *h.Partial {
return h.NewPartial(sheet.Opened(h.Div( return h.NewPartial(sheet.Opened(
h.Class("flex flex-col gap-4"), sheet.Props{
h.P("Add Patient", h.Class("text-lg font-bold")), ClassName: "w-[400px] bg-gray-100 p-4",
))) Root: h.Div(
h.Class("flex flex-col gap-4"),
h.P("Add Patient", h.Class("text-lg font-bold")),
addPatientForm(),
),
}))
} }
func PatientRow(patient *Patient) *h.Node { func addPatientForm() *h.Node {
return h.Div( return h.Form(
h.Post("/api/patients"),
h.Class("flex flex-col gap-2"), h.Class("flex flex-col gap-2"),
ui.Input(ui.InputProps{
Type: "text",
Label: "Name",
Name: "name",
}),
ui.Input(ui.InputProps{
Type: "text",
Label: "Reason for visit",
Name: "reason-for-visit",
}),
ui.Input(ui.InputProps{
Type: "date",
Label: "Appointment Date",
Name: "appointment-date",
}),
ui.Input(ui.InputProps{
Type: "text",
Label: "Location Name",
Name: "location-name",
}),
ui.PrimaryButton(ui.ButtonProps{
Text: "Add Patient",
Class: "rounded p-2",
Type: "submit",
}),
)
}
func PatientRow(patient *Patient, index int) *h.Node {
return h.Div(
h.Class("flex flex-col gap-2 rounded p-4", h.Ternary(index%2 == 0, "bg-red-100", "")),
h.Pf("Name: %s", patient.Name), h.Pf("Name: %s", patient.Name),
h.Pf("Reason for visit: %s", patient.ReasonForVisit), h.Pf("Reason for visit: %s", patient.ReasonForVisit),
) )
@ -59,7 +97,7 @@ func AddPatientButton() *h.Node {
Id: "add-patient", Id: "add-patient",
Text: "Add Patient", Text: "Add Patient",
Class: "bg-blue-700 text-white rounded p-2 h-12", Class: "bg-blue-700 text-white rounded p-2 h-12",
Target: "#active-modal", Target: sheet.Id,
Get: h.GetPartialPath(AddPatientForm), Get: h.GetPartialPath(AddPatientSheet),
}) })
} }

View file

@ -5,17 +5,25 @@ import (
"mhtml/h" "mhtml/h"
) )
func Opened(children ...*h.Node) *h.Node { type Props struct {
ClassName string
Root *h.Node
}
var Id = "#active-modal"
func Opened(props Props) *h.Node {
return h.Fragment(h.Div( return h.Fragment(h.Div(
h.Class(`fixed top-0 right-0 h-full w-96 bg-gray-100 shadow-lg z-50`), h.Class(`fixed top-0 right-0 h-full shadow-lg z-50`,
CloseButton(), h.Ternary(props.ClassName != "", props.ClassName, "w-96 bg-gray-100")),
closeButton(),
h.Div( h.Div(
children..., props.Root,
))) )))
} }
func Closed() *h.Node { func Closed() *h.Node {
return h.Div(h.Id("active-modal")) return h.Div(h.Id(Id))
} }
func Close(ctx *fiber.Ctx) *h.Partial { func Close(ctx *fiber.Ctx) *h.Partial {
@ -24,7 +32,7 @@ func Close(ctx *fiber.Ctx) *h.Partial {
) )
} }
func CloseButton() *h.Node { func closeButton() *h.Node {
return h.Div( return h.Div(
h.Class("absolute top-0 right-0 p-3"), h.Class("absolute top-0 right-0 p-3"),
h.Button( h.Button(

View file

@ -8,6 +8,7 @@ type ButtonProps struct {
Id string Id string
Text string Text string
Target string Target string
Type string
Trigger string Trigger string
Get string Get string
Class string Class string
@ -35,6 +36,7 @@ func Button(props ButtonProps) *h.Node {
h.Class("flex gap-1 items-center border p-4 rounded cursor-hover", props.Class), h.Class("flex gap-1 items-center border p-4 rounded cursor-hover", props.Class),
h.If(props.Get != "", h.Get(props.Get)), h.If(props.Get != "", h.Get(props.Get)),
h.If(props.Target != "", h.Target(props.Target)), h.If(props.Target != "", h.Target(props.Target)),
h.IfElse(props.Type != "", h.Type(props.Type), h.Type("button")),
text, text,
) )

29
ui/input.go Normal file
View file

@ -0,0 +1,29 @@
package ui
import "mhtml/h"
type InputProps struct {
Id string
Label string
Name string
Type string
DefaultValue string
}
func Input(props InputProps) *h.Node {
input := h.Input(
props.Type,
h.Class("border p-2 rounded"),
h.If(props.Id != "", h.Id(props.Id)),
h.If(props.Name != "", h.Name(props.Name)),
h.If(props.DefaultValue != "", h.Attribute("defaultValue", props.DefaultValue)),
)
if props.Label != "" {
return h.Div(
h.Class("flex flex-col gap-1"),
h.Label(props.Label),
input,
)
}
return input
}