Include TotalSummary in CRUD responses to eliminate redundant API calls

Backend changes:
- Add WithSummaryResponse wrappers for Task, TaskCompletion, and Residence CRUD
- Update services to return summary with all mutations (create, update, delete)
- Update handlers to pass through new response types
- Add getSummaryForUser helper for fetching summary in CRUD operations
- Wire ResidenceService into TaskService for summary access
- Add summary field to JoinResidenceResponse

This optimization eliminates the need for a separate getSummary() call after
every task/residence mutation, reducing network calls from 2 to 1.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-08 10:39:33 -06:00
parent f88409cfb4
commit 1a48fbfb20
9 changed files with 351 additions and 134 deletions

View File

@@ -156,7 +156,7 @@ func (h *TaskHandler) DeleteTask(c *gin.Context) {
return
}
err = h.taskService.DeleteTask(uint(taskID), user.ID)
response, err := h.taskService.DeleteTask(uint(taskID), user.ID)
if err != nil {
switch {
case errors.Is(err, services.ErrTaskNotFound):
@@ -168,7 +168,7 @@ func (h *TaskHandler) DeleteTask(c *gin.Context) {
}
return
}
c.JSON(http.StatusOK, gin.H{"message": i18n.LocalizedMessage(c, "message.task_deleted")})
c.JSON(http.StatusOK, response)
}
// MarkInProgress handles POST /api/tasks/:id/mark-in-progress/
@@ -192,7 +192,7 @@ func (h *TaskHandler) MarkInProgress(c *gin.Context) {
}
return
}
c.JSON(http.StatusOK, gin.H{"message": i18n.LocalizedMessage(c, "message.task_in_progress"), "task": response})
c.JSON(http.StatusOK, response)
}
// CancelTask handles POST /api/tasks/:id/cancel/
@@ -218,7 +218,7 @@ func (h *TaskHandler) CancelTask(c *gin.Context) {
}
return
}
c.JSON(http.StatusOK, gin.H{"message": i18n.LocalizedMessage(c, "message.task_cancelled"), "task": response})
c.JSON(http.StatusOK, response)
}
// UncancelTask handles POST /api/tasks/:id/uncancel/
@@ -242,7 +242,7 @@ func (h *TaskHandler) UncancelTask(c *gin.Context) {
}
return
}
c.JSON(http.StatusOK, gin.H{"message": i18n.LocalizedMessage(c, "message.task_uncancelled"), "task": response})
c.JSON(http.StatusOK, response)
}
// ArchiveTask handles POST /api/tasks/:id/archive/
@@ -268,7 +268,7 @@ func (h *TaskHandler) ArchiveTask(c *gin.Context) {
}
return
}
c.JSON(http.StatusOK, gin.H{"message": i18n.LocalizedMessage(c, "message.task_archived"), "task": response})
c.JSON(http.StatusOK, response)
}
// UnarchiveTask handles POST /api/tasks/:id/unarchive/
@@ -292,7 +292,7 @@ func (h *TaskHandler) UnarchiveTask(c *gin.Context) {
}
return
}
c.JSON(http.StatusOK, gin.H{"message": i18n.LocalizedMessage(c, "message.task_unarchived"), "task": response})
c.JSON(http.StatusOK, response)
}
// === Task Completions ===
@@ -455,7 +455,7 @@ func (h *TaskHandler) DeleteCompletion(c *gin.Context) {
return
}
err = h.taskService.DeleteCompletion(uint(completionID), user.ID)
response, err := h.taskService.DeleteCompletion(uint(completionID), user.ID)
if err != nil {
switch {
case errors.Is(err, services.ErrCompletionNotFound):
@@ -467,7 +467,7 @@ func (h *TaskHandler) DeleteCompletion(c *gin.Context) {
}
return
}
c.JSON(http.StatusOK, gin.H{"message": i18n.LocalizedMessage(c, "message.completion_deleted")})
c.JSON(http.StatusOK, response)
}
// === Lookups ===