1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5package event
6
7import (
8 "time"
9
10 "git.secluded.site/np/internal/goal"
11 "git.secluded.site/np/internal/task"
12 "git.secluded.site/np/internal/timeutil"
13)
14
15// GoalSnapshot captures relevant goal fields for event payloads.
16type GoalSnapshot struct {
17 Title string `json:"title"`
18 Description string `json:"description"`
19 UpdatedAt time.Time `json:"updated_at"`
20}
21
22// GoalSetPayload records a goal being established.
23type GoalSetPayload struct {
24 Goal GoalSnapshot `json:"goal"`
25}
26
27// GoalUpdatedPayload records a goal changing.
28type GoalUpdatedPayload struct {
29 Before GoalSnapshot `json:"goal_before"`
30 After GoalSnapshot `json:"goal_after"`
31}
32
33// TaskAddedPayload records a newly added task.
34type TaskAddedPayload struct {
35 Task task.Task `json:"task"`
36}
37
38// TaskStateSnapshot captures mutable task fields for updates.
39type TaskStateSnapshot struct {
40 Title string `json:"title"`
41 Description string `json:"description"`
42 UpdatedAt time.Time `json:"updated_at"`
43}
44
45// TaskUpdatedPayload captures title/description edits.
46type TaskUpdatedPayload struct {
47 TaskID string `json:"task_id"`
48 Before TaskStateSnapshot `json:"before"`
49 After TaskStateSnapshot `json:"after"`
50}
51
52// TaskStatusChangedPayload captures status transitions.
53type TaskStatusChangedPayload struct {
54 TaskID string `json:"task_id"`
55 Title string `json:"title"`
56 StatusBefore task.Status `json:"status_before"`
57 StatusAfter task.Status `json:"status_after"`
58 UpdatedAt time.Time `json:"updated_at"`
59}
60
61// GoalSnapshotFrom converts a goal document into an event snapshot.
62func GoalSnapshotFrom(doc goal.Document) GoalSnapshot {
63 return GoalSnapshot{
64 Title: doc.Title,
65 Description: doc.Description,
66 UpdatedAt: timeutil.EnsureUTC(doc.UpdatedAt),
67 }
68}
69
70// TaskStateSnapshotFrom converts a task into a mutable-field snapshot.
71func TaskStateSnapshotFrom(t task.Task) TaskStateSnapshot {
72 return TaskStateSnapshot{
73 Title: t.Title,
74 Description: t.Description,
75 UpdatedAt: timeutil.EnsureUTC(t.UpdatedAt),
76 }
77}
78
79// BuildGoalSet constructs AppendInput for goal_set events.
80func BuildGoalSet(command, reason string, doc goal.Document) AppendInput {
81 return AppendInput{
82 Type: TypeGoalSet,
83 Command: command,
84 Reason: reason,
85 Payload: GoalSetPayload{
86 Goal: GoalSnapshotFrom(doc),
87 },
88 }
89}
90
91// BuildGoalUpdated constructs AppendInput for goal_updated events.
92func BuildGoalUpdated(command, reason string, before, after goal.Document) AppendInput {
93 return AppendInput{
94 Type: TypeGoalUpdated,
95 Command: command,
96 Reason: reason,
97 Payload: GoalUpdatedPayload{
98 Before: GoalSnapshotFrom(before),
99 After: GoalSnapshotFrom(after),
100 },
101 }
102}
103
104// BuildTaskAdded constructs AppendInput for task_added events.
105func BuildTaskAdded(command, reason string, t task.Task) AppendInput {
106 return AppendInput{
107 Type: TypeTaskAdded,
108 Command: command,
109 Reason: reason,
110 Payload: TaskAddedPayload{
111 Task: t,
112 },
113 }
114}
115
116// BuildTaskUpdated constructs AppendInput for task_updated events.
117func BuildTaskUpdated(command, reason, taskID string, before, after task.Task) AppendInput {
118 return AppendInput{
119 Type: TypeTaskUpdated,
120 Command: command,
121 Reason: reason,
122 Payload: TaskUpdatedPayload{
123 TaskID: taskID,
124 Before: TaskStateSnapshotFrom(before),
125 After: TaskStateSnapshotFrom(after),
126 },
127 }
128}
129
130// BuildTaskStatusChanged constructs AppendInput for task_status_changed events.
131func BuildTaskStatusChanged(command, reason string, before task.Task, after task.Task) AppendInput {
132 return AppendInput{
133 Type: TypeTaskStatusChange,
134 Command: command,
135 Reason: reason,
136 Payload: TaskStatusChangedPayload{
137 TaskID: after.ID,
138 Title: after.Title,
139 StatusBefore: before.Status,
140 StatusAfter: after.Status,
141 UpdatedAt: timeutil.EnsureUTC(after.UpdatedAt),
142 },
143 }
144}