feat: activity-based worklog suggestions (Step 16)

- Suggestion struct with nodeId, nodeTitle, summary, suggestedMin
- GetSuggestions binding: analyzes today's activity events, groups by
  node, skips nodes with existing today's worklog, generates summary
- AcceptSuggestion binding: creates worklog entry from suggestion
- HasTodayEntries helper on worklog.Service
- Suggestions panel in Worklog tab with Apply button
- i18n: worklog.suggestions / worklog.apply (ru + en)
This commit is contained in:
2026-06-03 09:31:40 +08:00
parent ca280a59c0
commit 57d13c9506
9 changed files with 200 additions and 2 deletions
+11
View File
@@ -0,0 +1,11 @@
package activity
// Suggestion represents a suggested worklog entry derived from today's activity.
type Suggestion struct {
NodeID string `json:"nodeId"`
NodeTitle string `json:"nodeTitle"`
Summary string `json:"summary"`
SuggestedMin int `json:"suggestedMin"`
EventCount int `json:"eventCount"`
NodeKind string `json:"nodeKind"`
}
+10
View File
@@ -140,6 +140,16 @@ func (s *Service) Delete(id string) error {
return nil
}
// HasTodayEntries checks if any worklog entries exist for today.
func (s *Service) HasTodayEntries(nodeID string) (bool, error) {
today := time.Now().Format("2006-01-02")
var count int
err := s.db.QueryRow(
`SELECT COUNT(*) FROM worklog_entries WHERE node_id=? AND date=?`,
nodeID, today).Scan(&count)
return count > 0, err
}
// SumMinutes returns total minutes for a node.
func (s *Service) SumMinutes(nodeID string) (int, error) {
var total sql.NullInt64