Skip to content

Commit 5bc5b8a

Browse files
committed
Added Actions model and related apis
1 parent b5a6ce0 commit 5bc5b8a

1 file changed

Lines changed: 76 additions & 8 deletions

File tree

backend/main.go

Lines changed: 76 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,28 @@ type GoalInput struct {
6060
UnderlyingGoal string `json:"underlying_goal" validate:"required,min=1,max=255"`
6161
}
6262

63-
// type Action struct { ... }
63+
// Action represents the action entity.
64+
type Action struct {
65+
ID uint `gorm:"primarykey" json:"id"`
66+
UserID string `json:"user_id" gorm:"type:varchar(36);not null;index"`
67+
GoalID uint `json:"goal_id" gorm:"not null;index"` // Foreign key to Goal
68+
Content string `json:"content" gorm:"not null"`
69+
CompletedAt *time.Time `json:"completed_at,omitempty"` // Pointer to allow null
70+
CreatedAt time.Time `json:"created_at"`
71+
UpdatedAt time.Time `json:"updated_at"`
72+
Goal Goal `gorm:"foreignKey:GoalID"` // Belongs to Goal
73+
}
74+
75+
// ActionInput defines the expected input for creating a new action.
76+
type ActionInput struct {
77+
GoalID uint `json:"goal_id" validate:"required"`
78+
Content string `json:"content" validate:"required,min=1,max=1000"`
79+
CompletedAt string `json:"completed_at,omitempty" validate:"omitempty,datetime=2006-01-02T15:04:05Z07:00"` // ISO8601 format
80+
}
6481

6582
// --- GORM AutoMigrate Helper ---
6683
// (This can be moved to a more appropriate place like a db setup function later)
67-
var modelsToMigrate = []interface{}{&Complex{}, &Goal{}} // Add &Action{} later
84+
var modelsToMigrate = []interface{}{&Complex{}, &Goal{}, &Action{}}
6885

6986
// ErrorResponse Helper
7087
type ErrorResponse struct {
@@ -373,8 +390,59 @@ func DeleteGoalHandler(c *gin.Context) {
373390
c.Status(http.StatusNoContent)
374391
}
375392

376-
// Action Handlers (スタブ)
377-
// func CreateActionHandler(c *gin.Context) { /* ... */ }
393+
// CreateActionHandler handles the creation of a new action.
394+
func CreateActionHandler(c *gin.Context) {
395+
userID, exists := c.Get("userID")
396+
if !exists {
397+
c.JSON(http.StatusUnauthorized, NewErrorResponse(http.StatusUnauthorized, "User ID not found in context"))
398+
return
399+
}
400+
401+
var input ActionInput
402+
if err := c.ShouldBindJSON(&input); err != nil {
403+
c.JSON(http.StatusBadRequest, NewErrorResponse(http.StatusBadRequest, "Invalid request body: "+err.Error()))
404+
return
405+
}
406+
407+
if err := validate.Struct(input); err != nil {
408+
c.JSON(http.StatusBadRequest, NewErrorResponse(http.StatusBadRequest, "Validation failed: "+err.Error()))
409+
return
410+
}
411+
412+
// Check if the referenced goal exists and belongs to the user
413+
var goal Goal
414+
if err := db.Where("id = ? AND user_id = ?", input.GoalID, userID.(string)).First(&goal).Error; err != nil {
415+
if err == gorm.ErrRecordNotFound {
416+
c.JSON(http.StatusBadRequest, NewErrorResponse(http.StatusBadRequest, "Referenced goal not found or does not belong to user"))
417+
return
418+
}
419+
c.JSON(http.StatusInternalServerError, NewErrorResponse(http.StatusInternalServerError, "Error checking goal: "+err.Error()))
420+
return
421+
}
422+
423+
var completedAtParsed *time.Time
424+
if input.CompletedAt != "" {
425+
t, err := time.Parse(time.RFC3339, input.CompletedAt)
426+
if err != nil {
427+
c.JSON(http.StatusBadRequest, NewErrorResponse(http.StatusBadRequest, "Invalid completed_at format. Use ISO8601 (RFC3339)."))
428+
return
429+
}
430+
completedAtParsed = &t
431+
}
432+
433+
action := Action{
434+
UserID: userID.(string),
435+
GoalID: input.GoalID,
436+
Content: input.Content,
437+
CompletedAt: completedAtParsed,
438+
}
439+
440+
if result := db.Create(&action); result.Error != nil {
441+
c.JSON(http.StatusInternalServerError, NewErrorResponse(http.StatusInternalServerError, "Failed to create action: "+result.Error.Error()))
442+
return
443+
}
444+
c.JSON(http.StatusCreated, action)
445+
}
378446

379447
func main() {
380448
// --- 環境変数からの設定読み込み (例) ---
@@ -495,10 +563,10 @@ func main() {
495563
}
496564

497565
// Actions
498-
// actionsGroup := apiV1.Group("/actions")
499-
// {
500-
// // actionsGroup.POST("", CreateActionHandler)
501-
// }
566+
actionsGroup := apiV1.Group("/actions")
567+
{
568+
actionsGroup.POST("", CreateActionHandler)
569+
}
502570
}
503571

504572
// --- サーバー起動 ---

0 commit comments

Comments
 (0)