summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2024-04-14 23:51:04 +0200
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2024-04-14 23:51:04 +0200
commit1e9b8d0fa114ce706c4fa05004991e516cbddcd7 (patch)
tree2ba185a018f7b9653e703cdebc90ed643b12f731
parent3928c520e8b152f47c17ca75fcf5beed4f33f095 (diff)
Add time to timer
-rw-r--r--model/time.go38
-rw-r--r--model/timer.go11
-rw-r--r--model/uuid.go55
-rw-r--r--timer.go79
-rw-r--r--view/timer.templ53
-rw-r--r--view/timer_templ.go142
6 files changed, 302 insertions, 76 deletions
diff --git a/model/time.go b/model/time.go
index baf3ce6..e0c399c 100644
--- a/model/time.go
+++ b/model/time.go
@@ -1,34 +1,42 @@
package model
import (
- "time"
- "errors"
- sqldriver "database/sql/driver"
+ sqldriver "database/sql/driver"
+ "errors"
+ "time"
)
type Time time.Time
func MakeTimeNow() Time {
- return Time(time.Now().UTC())
+ return Time(time.Now().UTC())
}
func (self Time) AsUTCString() string {
- return time.Time(self).Format(time.RFC3339)
+ return time.Time(self).Format(time.RFC3339)
}
func (self Time) Value() (sqldriver.Value, error) {
- return self.AsUTCString(), nil
+ return self.AsUTCString(), nil
}
func (self *Time) Scan(value any) error {
- if valueStr, ok := value.(string); ok {
- parsedTime, err := time.Parse(time.RFC3339, valueStr)
- if err == nil {
- *self = Time(parsedTime.UTC())
- }
- return err
- } else {
- return errors.New("Expected a string")
- }
+ if valueStr, ok := value.(string); ok {
+ parsedTime, err := time.Parse(time.RFC3339, valueStr)
+ if err == nil {
+ *self = Time(parsedTime.UTC())
+ }
+ return err
+ } else {
+ return errors.New("Expected a string")
+ }
+}
+
+func (from Time) Compare(to Time) int {
+ return time.Time(from).Compare(time.Time(to))
+}
+
+func (self *Time) Add(duration time.Duration) {
+ *self = Time(time.Time(*self).Add(duration))
}
diff --git a/model/timer.go b/model/timer.go
index 4c81962..a47369d 100644
--- a/model/timer.go
+++ b/model/timer.go
@@ -1,9 +1,12 @@
package model
type Timer struct {
- Id UUID
- Name string
- StartTime Time
- EndTime Time
+ Id UUID
+ Name string
+ StartTime Time
+ EndTime Time
}
+func (self Timer) IsFinished() bool {
+ return MakeTimeNow().Compare(self.EndTime) >= 0
+}
diff --git a/model/uuid.go b/model/uuid.go
index 4a25e41..6cade35 100644
--- a/model/uuid.go
+++ b/model/uuid.go
@@ -1,28 +1,27 @@
-package model
-
-import (
- sqldriver "database/sql/driver"
- "github.com/google/uuid"
-)
-
-type UUID struct {
- payload uuid.UUID
-}
-
-func MakeUUID() UUID {
- id, _ := uuid.NewV7()
- return UUID { payload: id }
-}
-
-func (self UUID) Value() (sqldriver.Value, error) {
- return self.payload[:], nil
-}
-
-func (self *UUID) Scan(value any) error {
- return self.payload.Scan(value)
-}
-
-func (self UUID) String() string {
- return self.payload.String()
-}
-
+package model
+
+import (
+ sqldriver "database/sql/driver"
+ "github.com/google/uuid"
+)
+
+type UUID struct {
+ payload uuid.UUID
+}
+
+func MakeUUID() UUID {
+ id, _ := uuid.NewV7()
+ return UUID{payload: id}
+}
+
+func (self UUID) Value() (sqldriver.Value, error) {
+ return self.payload[:], nil
+}
+
+func (self *UUID) Scan(value any) error {
+ return self.payload.Scan(value)
+}
+
+func (self UUID) String() string {
+ return self.payload.String()
+}
diff --git a/timer.go b/timer.go
index 587d24e..e76f950 100644
--- a/timer.go
+++ b/timer.go
@@ -3,6 +3,7 @@ package main
import (
"context"
"database/sql"
+ "errors"
"log"
"net/http"
"strconv"
@@ -50,12 +51,12 @@ func initializeDatabase(db *sql.DB) error {
return err
}
- err = insertTimer(tx, "My timer", 600)
+ err = insertTimer(tx, "My timer", 6)
if err != nil {
return err
}
- err = insertTimer(tx, "My timer2", 600)
+ err = insertTimer(tx, "My timer2", 6)
if err != nil {
return err
}
@@ -86,7 +87,7 @@ func initializeDatabase(db *sql.DB) error {
return err
}
- _, err = tx.Exec(`INSERT INTO Timer VALUES ($1, $2, $3, $4)`, userId, "steven", userUuidStr, password)
+ _, err = tx.Exec(`INSERT INTO User VALUES ($1, $2, $3, $4)`, userId, "steven", userUuidStr, password)
if err != nil {
return err
}
@@ -139,7 +140,17 @@ func deleteTimer(db *sql.DB, idStr string) bool {
}
affected, err := res.RowsAffected()
- return err == nil && affected > 0
+ return err == nil && affected == 1
+}
+
+func updateTimerEndTime(db *sql.DB, id model.UUID, endTime model.Time) bool {
+ res, err := db.Exec("UPDATE Timer SET EndTime=$1 WHERE Id=$2", endTime, id)
+ if err != nil {
+ return false
+ }
+
+ affected, err := res.RowsAffected()
+ return err == nil && affected == 1
}
type Session struct {
@@ -174,6 +185,65 @@ func (server *MyServer) handleTimer(w http.ResponseWriter, r *http.Request) {
}
}
+func parseDuration(value string) (time.Duration, error) {
+ const nullDuration = time.Duration(0)
+ if len(value) == 0 {
+ return nullDuration, errors.New("Empty duration string")
+ }
+
+ var unit time.Duration
+ switch value[len(value)-1] {
+ case 's':
+ unit = time.Second
+ case 'm':
+ unit = time.Minute
+ case 'h':
+ unit = time.Hour
+ case 'd':
+ unit = time.Duration(24) * time.Hour
+ case 'w':
+ unit = time.Duration(24*7) * time.Hour
+ default:
+ return nullDuration, errors.New("Invalid duration format")
+ }
+
+ amount, err := strconv.ParseInt(value[0:len(value)-1], 10, 64)
+ if err != nil || amount < 0 {
+ return nullDuration, errors.New("Invalid duration value")
+ }
+
+ return time.Duration(amount) * unit, nil
+}
+
+func (server *MyServer) handleTimerAddTime(w http.ResponseWriter, r *http.Request) {
+ timer := queryTimer(server.db, r.PathValue("timerId"))
+ if timer == nil {
+ server.handleNotFound(w, r)
+ return
+ }
+
+ if timer.IsFinished() {
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+
+ duration, err := parseDuration(r.PathValue("timeToAdd"))
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(err.Error()))
+ return
+ }
+
+ timer.EndTime.Add(duration)
+ res := updateTimerEndTime(server.db, timer.Id, timer.EndTime)
+ if !res {
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+
+ view.TimerView(*timer).Render(context.Background(), w)
+}
+
func (server *MyServer) handleDeleteTimer(w http.ResponseWriter, r *http.Request) {
success := deleteTimer(server.db, r.PathValue("timerId"))
if !success {
@@ -244,6 +314,7 @@ func main() {
http.Handle("GET /static/", http.StripPrefix("/static/", fs))
http.HandleFunc("GET /timer/{timerId}", myServer.handleTimer)
+ http.HandleFunc("POST /timer/{timerId}/addTime/{timeToAdd}", myServer.handleTimerAddTime)
http.HandleFunc("DELETE /timer/{timerId}", myServer.handleDeleteTimer)
http.HandleFunc("PUT /timer", myServer.handlePutTimer)
http.HandleFunc("GET /", myServer.handleMain)
diff --git a/view/timer.templ b/view/timer.templ
index 8d20933..a447d01 100644
--- a/view/timer.templ
+++ b/view/timer.templ
@@ -1,26 +1,43 @@
package view
import (
- "stevenlr.com/timer/model"
+ "fmt"
+ "stevenlr.com/timer/model"
)
templ TimerView(timer model.Timer) {
- <h1>This is timer { timer.Name } </h1>
- <p><a href="/">Back to list</a></p>
- <p>Start time: <local-date>{ timer.StartTime.AsUTCString() }</local-date></p>
- <p>End time: <local-date>{ timer.EndTime.AsUTCString() }</local-date></p>
- <p>
- Total time:
- <timer-countdown
- start={ timer.StartTime.AsUTCString() }
- end={ timer.EndTime.AsUTCString() }
- ></timer-countdown>
- </p>
- <p>
- Remaining time:
- <timer-countdown
- end={ timer.EndTime.AsUTCString() }
- ></timer-countdown>
- </p>
+ <div class="timer">
+ <h1>This is timer { timer.Name } </h1>
+ <p><a href="/">Back to list</a></p>
+ <p>Start time: <local-date>{ timer.StartTime.AsUTCString() }</local-date></p>
+ <p>End time: <local-date>{ timer.EndTime.AsUTCString() }</local-date></p>
+ <p>
+ Total time:
+ <timer-countdown
+ start={ timer.StartTime.AsUTCString() }
+ end={ timer.EndTime.AsUTCString() }
+ ></timer-countdown>
+ </p>
+ <p>
+ Remaining time:
+ <timer-countdown
+ end={ timer.EndTime.AsUTCString() }
+ ></timer-countdown>
+ </p>
+ if !timer.IsFinished() {
+ <h3>Add time</h3>
+ <p>
+ <button hx-target="closest .timer" hx-post={ fmt.Sprint("/timer/", timer.Id, "/addTime/15m") }>15 minutes</button>
+ <button hx-target="closest .timer" hx-post={ fmt.Sprint("/timer/", timer.Id, "/addTime/30m") }>30 minutes</button>
+ <button hx-target="closest .timer" hx-post={ fmt.Sprint("/timer/", timer.Id, "/addTime/1h") }>1 hour</button>
+ <button hx-target="closest .timer" hx-post={ fmt.Sprint("/timer/", timer.Id, "/addTime/2h") }>2 hours</button>
+ <button hx-target="closest .timer" hx-post={ fmt.Sprint("/timer/", timer.Id, "/addTime/6h") }>6 hours</button>
+ <button hx-target="closest .timer" hx-post={ fmt.Sprint("/timer/", timer.Id, "/addTime/12h") }>12 hours</button>
+ <button hx-target="closest .timer" hx-post={ fmt.Sprint("/timer/", timer.Id, "/addTime/1d") }>1 day</button>
+ <button hx-target="closest .timer" hx-post={ fmt.Sprint("/timer/", timer.Id, "/addTime/1w") }>1 week</button>
+ <button hx-target="closest .timer" hx-post={ fmt.Sprint("/timer/", timer.Id, "/addTime/4w") }>4 weeks</button>
+ </p>
+ }
+ </div>
}
diff --git a/view/timer_templ.go b/view/timer_templ.go
index 55e5346..1cafffd 100644
--- a/view/timer_templ.go
+++ b/view/timer_templ.go
@@ -11,6 +11,7 @@ import "io"
import "bytes"
import (
+ "fmt"
"stevenlr.com/timer/model"
)
@@ -27,14 +28,14 @@ func TimerView(timer model.Timer) templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h1>This is timer ")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"timer\"><h1>This is timer ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(timer.Name)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 8, Col: 34}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 10, Col: 32}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
@@ -47,7 +48,7 @@ func TimerView(timer model.Timer) templ.Component {
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(timer.StartTime.AsUTCString())
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 10, Col: 62}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 12, Col: 60}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
@@ -60,7 +61,7 @@ func TimerView(timer model.Timer) templ.Component {
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(timer.EndTime.AsUTCString())
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 11, Col: 58}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 13, Col: 56}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
@@ -73,7 +74,7 @@ func TimerView(timer model.Timer) templ.Component {
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(timer.StartTime.AsUTCString())
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 15, Col: 49}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 17, Col: 41}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
@@ -86,7 +87,7 @@ func TimerView(timer model.Timer) templ.Component {
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(timer.EndTime.AsUTCString())
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 16, Col: 45}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 18, Col: 37}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
@@ -99,7 +100,7 @@ func TimerView(timer model.Timer) templ.Component {
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(timer.EndTime.AsUTCString())
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 22, Col: 45}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 24, Col: 37}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
@@ -109,6 +110,133 @@ func TimerView(timer model.Timer) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
+ if !timer.IsFinished() {
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h3>Add time</h3><p><button hx-target=\"closest .timer\" hx-post=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var8 string
+ templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint("/timer/", timer.Id, "/addTime/15m"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 30, Col: 96}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">15 minutes</button> <button hx-target=\"closest .timer\" hx-post=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var9 string
+ templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint("/timer/", timer.Id, "/addTime/30m"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 31, Col: 96}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">30 minutes</button> <button hx-target=\"closest .timer\" hx-post=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var10 string
+ templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint("/timer/", timer.Id, "/addTime/1h"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 32, Col: 95}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">1 hour</button> <button hx-target=\"closest .timer\" hx-post=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var11 string
+ templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint("/timer/", timer.Id, "/addTime/2h"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 33, Col: 95}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">2 hours</button> <button hx-target=\"closest .timer\" hx-post=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var12 string
+ templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint("/timer/", timer.Id, "/addTime/6h"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 34, Col: 95}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">6 hours</button> <button hx-target=\"closest .timer\" hx-post=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var13 string
+ templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint("/timer/", timer.Id, "/addTime/12h"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 35, Col: 96}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">12 hours</button> <button hx-target=\"closest .timer\" hx-post=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var14 string
+ templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint("/timer/", timer.Id, "/addTime/1d"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 36, Col: 95}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">1 day</button> <button hx-target=\"closest .timer\" hx-post=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var15 string
+ templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint("/timer/", timer.Id, "/addTime/1w"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 37, Col: 95}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">1 week</button> <button hx-target=\"closest .timer\" hx-post=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var16 string
+ templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprint("/timer/", timer.Id, "/addTime/4w"))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\timer.templ`, Line: 38, Col: 95}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">4 weeks</button></p>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}