diff --git a/cmd/server/main.go b/cmd/server/main.go index fdf7c77..7d2a3e5 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -423,7 +423,7 @@ func main() { return c.HTML(http.StatusOK, buf.String()) }) - // Device Management route (protected) + // Device Management route (protected) - SSR version protected.GET("/devices", func(c echo.Context) error { userID := c.Get("user_id").(string) userEmail := c.Get("user_email").(string) @@ -437,15 +437,63 @@ func main() { Role: userRole, } + // Fetch devices for SSR (uses new helper method) + devices, err := deviceHandler.GetDevicesData(c) + if err != nil { + return c.HTML(http.StatusInternalServerError, "Error loading devices") + } + + // Convert to template format + deviceData := make([]templates.DeviceData, len(devices)) + for i, device := range devices { + var lastSync, lastSeen string + if device.LastSync != nil { + lastSync = device.LastSync.Format("2006-01-02T15:04:05Z07:00") + } + if device.LastSeen != nil { + lastSeen = device.LastSeen.Format("2006-01-02T15:04:05Z07:00") + } + + deviceData[i] = templates.DeviceData{ + ID: device.ID.String(), + DeviceName: device.DeviceName, + DeviceType: device.DeviceType, + SyncEnabled: device.SyncEnabled, + AutoSync: device.AutoSync, + SyncFrequency: device.SyncFrequency, + LastSync: lastSync, + LastSeen: lastSeen, + } + } + + // Fetch pending registrations for SSR (uses new helper) + pendingRegs, err := deviceHandler.GetPendingRegistrationsData(c) + if err != nil { + return c.HTML(http.StatusInternalServerError, "Error loading pending registrations") + } + + // Convert to template format + pendingData := make([]templates.PendingRegistrationData, len(pendingRegs)) + for i, reg := range pendingRegs { + expiresAt := reg["expires_at"].(time.Time) + pendingData[i] = templates.PendingRegistrationData{ + RegistrationID: reg["registration_id"].(string), + DeviceName: reg["device_name"].(string), + DeviceType: reg["device_type"].(string), + ExpiresAt: expiresAt.Format("2006-01-02T15:04:05Z07:00"), + } + } + + // Render template WITH data (SSR) var buf bytes.Buffer - err := templates.Devices(user).Render(c.Request().Context(), &buf) + err = templates.Devices(user, deviceData, pendingData).Render(c.Request().Context(), &buf) if err != nil { return err } return c.HTML(http.StatusOK, buf.String()) }) - // Conflicts route (protected) + // Conflicts route (protected) - SSR version protected.GET("/conflicts", func(c echo.Context) error { userID := c.Get("user_id").(string) userEmail := c.Get("user_email").(string) @@ -459,15 +507,22 @@ func main() { Role: userRole, } + // Fetch conflicts for SSR (uses existing handler method) + apiConflicts, total, unresolved, err := conflictHandler.GetConflictsData(c) + if err != nil { + return c.HTML(http.StatusInternalServerError, "Error loading conflicts") + } + + // Render template WITH data (SSR) - use apiConflicts directly var buf bytes.Buffer - err := templates.Conflicts(user).Render(c.Request().Context(), &buf) + err = templates.Conflicts(user, apiConflicts, total, unresolved).Render(c.Request().Context(), &buf) if err != nil { return err } return c.HTML(http.StatusOK, buf.String()) }) - // Queue Management route (protected) + // Queue Management route (protected) - SSR version protected.GET("/queue", func(c echo.Context) error { userID := c.Get("user_id").(string) userEmail := c.Get("user_email").(string) @@ -481,8 +536,36 @@ func main() { Role: userRole, } + // Fetch queue items for SSR (uses existing handler method) + queueItems, err := queueHandler.GetQueueData(c) + if err != nil { + return c.HTML(http.StatusInternalServerError, "Error loading queue") + } + + // Calculate stats from items + stats := handlers.QueueStatsResponse{ + PendingCount: 0, + ProcessingCount: 0, + FailedCount: 0, + CompletedCount: 0, + TotalCount: int64(len(queueItems)), + } + for _, item := range queueItems { + switch item.Status { + case "pending": + stats.PendingCount++ + case "processing": + stats.ProcessingCount++ + case "failed": + stats.FailedCount++ + case "completed": + stats.CompletedCount++ + } + } + + // Render template WITH data (SSR) var buf bytes.Buffer - err := templates.Queue(user).Render(c.Request().Context(), &buf) + err = templates.Queue(user, queueItems, stats).Render(c.Request().Context(), &buf) if err != nil { return err } diff --git a/templates/collections.templ b/templates/collections.templ index 4e3ff83..a7ec276 100644 --- a/templates/collections.templ +++ b/templates/collections.templ @@ -55,10 +55,9 @@ templ Collection(user User, collections []CollectionData) { -

{ col.Name }

-

{ col.Description }

-

Created { col.CreatedAt }

- +

{ col.Name }

+

{ col.Description }

+ } diff --git a/templates/collections_templ.go b/templates/collections_templ.go index 9ba9262..65b167d 100644 --- a/templates/collections_templ.go +++ b/templates/collections_templ.go @@ -68,7 +68,7 @@ func Collection(user User, collections []CollectionData) templ.Component { var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(col.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 58, Col: 108} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 58, Col: 109} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -81,31 +81,18 @@ func Collection(user User, collections []CollectionData) templ.Component { var templ_7745c5c3_Var4 string templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(col.Description) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 59, Col: 102} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 59, Col: 103} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "

Created ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(col.CreatedAt) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 60, Col: 103} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "

Create Collection

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "

Create Collection

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -129,25 +116,25 @@ func CollectionDetail(user User, collection CollectionDetailData, books []BookDa }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var6 := templ.GetChildren(ctx) - if templ_7745c5c3_Var6 == nil { - templ_7745c5c3_Var6 = templ.NopComponent + templ_7745c5c3_Var5 := templ.GetChildren(ctx) + if templ_7745c5c3_Var5 == nil { + templ_7745c5c3_Var5 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var7 string - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name) + var templ_7745c5c3_Var6 string + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 220, Col: 32} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 219, Col: 32} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, " - Bookmann") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " - Bookmann") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -155,98 +142,98 @@ func CollectionDetail(user User, collection CollectionDetailData, books []BookDa if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var7 string + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Icon) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 234, Col: 95} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var8 string - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Icon) + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 235, Col: 95} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 236, Col: 107} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var9 string - templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name) + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Description) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 237, Col: 107} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 237, Col: 88} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "

") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var10 string - templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Description) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 238, Col: 88} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "

Books in this Collection

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "

Books in this Collection

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if len(books) == 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
No books in this collection yet.
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
No books in this collection yet.
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } for _, book := range books { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "
\"Cover\"

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
\"Cover\"

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var11 string - templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(book.Title) + var templ_7745c5c3_Var10 string + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(book.Title) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 263, Col: 123} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 262, Col: 123} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.Author != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "

by ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "

by ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var12 string - templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(book.Author) + var templ_7745c5c3_Var11 string + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(book.Author) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 265, Col: 100} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 264, Col: 100} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "

Add Books to Collection

Search and select books to add to this collection.

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "

Add Books to Collection

Search and select books to add to this collection.

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/templates/conflicts.templ b/templates/conflicts.templ index 79ef86d..58b9941 100644 --- a/templates/conflicts.templ +++ b/templates/conflicts.templ @@ -1,6 +1,8 @@ package templates -templ Conflicts(user User) { +import "bookmann/internal/handlers" + +templ Conflicts(user User, conflicts []handlers.ConflictDetailResponse, total int, unresolved int) { @@ -69,24 +71,52 @@ templ Conflicts(user User) {
- Total: 0 - Unresolved: 0 - Resolved: 0 + Total: { total } + Unresolved: { unresolved } + Resolved: { total - unresolved }
-
-
-

Loading conflicts...

-
+ - + - +
+ if len(conflicts) == 0 { +
+
+

No Conflicts

+

Your devices are in sync! No conflicts to resolve.

+
+ } + + for _, conflict := range conflicts { +
+
+
+

{ conflict.MediaItemTitle }

+

Type: { conflict.ConflictType }

+
+ +
+
+ Created: { conflict.CreatedAt.Format("2006-01-02 15:04:05") } + if conflict.ResolvedBy != "" { + | Resolved by: { conflict.ResolvedBy } + } +
+
+ } +
-
+ @@ -135,7 +137,42 @@ templ Queue(user User) {

No items in the sync queue

- +
+ if len(queueItems) == 0 { +
+
📭
+

Queue Empty

+

No items in the sync queue

+
+ } + + for _, item := range queueItems { +
+
+
+ { item.Status } + { item.SyncType } +
+ P{ item.Priority } +
+
+ Device ID: { item.DeviceID } + if item.MediaTitle != nil { + | Book: { *item.MediaTitle } + } +
+
+ Attempts: { item.Attempts }/{ item.MaxAttempts } + { item.CreatedAt } +
+ if item.ErrorMessage != nil { +
+ Error: { *item.ErrorMessage } +
+ } +
+ } +