From 0f41f76679ff4c80f351d4626dfc3ce95f3761b6 Mon Sep 17 00:00:00 2001 From: Robin Olsen Date: Thu, 19 Feb 2026 17:26:16 +0100 Subject: [PATCH] add builders and chaining methods for various types and variables for better reusability and readability --- cmd/survey/init.go | 8 +---- cmd/survey/tasks/base.go | 38 ++++++++------------ cmd/survey/tasks/codingTask.go | 22 ++++++------ cmd/survey/tasks/createIssue.go | 23 ++++-------- internal/models/issue.go | 64 +++++++++++++++++++++++++++++++++ internal/service/beads.go | 10 ++++++ internal/service/config.go | 34 ++++++++++++++++++ pkg/task/ui/questionnaire.go | 2 -- pkg/task/ui/task.go | 7 ---- pkg/task/ui/types.go | 39 ++++++++++++++++++++ 10 files changed, 179 insertions(+), 68 deletions(-) create mode 100644 internal/models/issue.go create mode 100644 internal/service/config.go create mode 100644 pkg/task/ui/types.go diff --git a/cmd/survey/init.go b/cmd/survey/init.go index 78c64c7..6016132 100644 --- a/cmd/survey/init.go +++ b/cmd/survey/init.go @@ -37,13 +37,7 @@ func initTasks(svc *service.Services) []task.Tasker { } func initializeServices(ctx context.Context) (*service.Services, func(), error) { - config := service.Config{ - IssuePrefix: "pm", - BeadsDBPath: "./.pm/db.db", - StatisticsStoragePath: "./.pm/stats.json", - WebAddress: ":8080", - } - return service.NewServices(ctx, config) + return service.NewServices(ctx, tasks.BaseConfig()) } func initInterfaces() map[string]task.Interface { diff --git a/cmd/survey/tasks/base.go b/cmd/survey/tasks/base.go index ea9adf3..582f8cf 100644 --- a/cmd/survey/tasks/base.go +++ b/cmd/survey/tasks/base.go @@ -1,6 +1,7 @@ package tasks import ( + "github.com/LazyBachelor/LazyPM/internal/service" "github.com/LazyBachelor/LazyPM/pkg/cli/repl" "github.com/LazyBachelor/LazyPM/pkg/task" taskui "github.com/LazyBachelor/LazyPM/pkg/task/ui" @@ -40,12 +41,16 @@ func BaseDetails() taskui.TaskDetails { func BaseConfig() task.TaskConfig { return task.TaskConfig{ IssuePrefix: "pm", + WebAddress: ":8080", BeadsDBPath: "./.pm/db.db", StatisticsStoragePath: "./.pm/stats.json", - WebAddress: ":8080", } } +func ClearIssues(svc *service.Services) error { + return svc.Beads.DeleteIssues() +} + func BaseQuestions(interfaceType task.InterfaceType) taskui.Questions { var taskRating int return taskui.Questions{ @@ -66,36 +71,23 @@ func BaseQuestions(interfaceType task.InterfaceType) taskui.Questions { } } -func AppendGroup(questions *taskui.Questions, group *huh.Group) taskui.Questions { - *questions = append(*questions, group) - return *questions -} - -func AppendQuestion(questions *taskui.Questions, interfaceType task.InterfaceType, field ...huh.Field) taskui.Questions { - *questions = append(*questions, huh.NewGroup(field...)) - return *questions -} - -func AppendReplQuestion(questions *taskui.Questions, interfaceType task.InterfaceType, field ...huh.Field) taskui.Questions { +func ReplQuestion(interfaceType task.InterfaceType, fields ...huh.Field) *huh.Group { if interfaceType != InterfaceREPL { - return *questions + return nil } - *questions = append(*questions, huh.NewGroup(field...)) - return *questions + return huh.NewGroup(fields...) } -func AppendWebQuestion(questions *taskui.Questions, interfaceType task.InterfaceType, field ...huh.Field) taskui.Questions { +func WebQuestion(questions *taskui.Questions, interfaceType task.InterfaceType, fields ...huh.Field) *huh.Group { if interfaceType != InterfaceWeb { - return *questions + return nil } - *questions = append(*questions, huh.NewGroup(field...)) - return *questions + return huh.NewGroup(fields...) } -func AppendTUIQuestion(questions *taskui.Questions, interfaceType task.InterfaceType, field ...huh.Field) taskui.Questions { +func TUIQuestion(questions *taskui.Questions, interfaceType task.InterfaceType, fields ...huh.Field) *huh.Group { if interfaceType != InterfaceTUI { - return *questions + return nil } - *questions = append(*questions, huh.NewGroup(field...)) - return *questions + return huh.NewGroup(fields...) } diff --git a/cmd/survey/tasks/codingTask.go b/cmd/survey/tasks/codingTask.go index 09a11e6..3f45eee 100644 --- a/cmd/survey/tasks/codingTask.go +++ b/cmd/survey/tasks/codingTask.go @@ -9,6 +9,7 @@ import ( "github.com/LazyBachelor/LazyPM/internal/service" "github.com/LazyBachelor/LazyPM/pkg/task" taskui "github.com/LazyBachelor/LazyPM/pkg/task/ui" + "github.com/charmbracelet/huh" ) const codingDescription = `You are tasked with writing a simple function. @@ -30,31 +31,28 @@ func NewCodingTask(svc *service.Services) *CodingTask { } func (t *CodingTask) Config() task.TaskConfig { - config := BaseConfig() - config.StatisticsStoragePath = "./.pm/coding-task-stats.json" - return config + return BaseConfig().WithStatisticsStoragePath("./.pm/coding-task-stats.json") } func (t *CodingTask) Details() taskui.TaskDetails { - details := BaseDetails() - details.Title = "Coding Task" - details.Description = codingDescription - return details + return BaseDetails().WithTitle("Coding Task").WithDescription(codingDescription) } func (t *CodingTask) Questions(interfaceType task.InterfaceType) (questions taskui.Questions) { - questions = append(questions, BaseQuestions(interfaceType)...) - - return questions + return BaseQuestions(interfaceType). + With(ReplQuestion(interfaceType, + huh.NewInput().Title("Please write your code in the 'code.txt' file and save it."). + Placeholder("Write your code here...")), + ) } func (t *CodingTask) Setup(ctx context.Context) error { - if err := t.svc.DeleteIssues(); err != nil { + if err := ClearIssues(t.svc); err != nil { return err } content := textFileContent - + if err := os.WriteFile("./code.txt", []byte(content), 0644); err != nil { return err } diff --git a/cmd/survey/tasks/createIssue.go b/cmd/survey/tasks/createIssue.go index f4f1c73..f6552d1 100644 --- a/cmd/survey/tasks/createIssue.go +++ b/cmd/survey/tasks/createIssue.go @@ -25,36 +25,25 @@ func NewCreateIssueTask(svc *service.Services) *CreateIssueTask { } func (t *CreateIssueTask) Config() task.TaskConfig { - config := BaseConfig() - config.StatisticsStoragePath = "./.pm/create-issue-stats.json" - return config + return BaseConfig().WithStatisticsStoragePath("./.pm/create-issue-stats.json") } func (t *CreateIssueTask) Details() taskui.TaskDetails { - details := BaseDetails() - details.Title = "Create Issue Task" - details.Description = description - return details + return BaseDetails().WithTitle("Create Issue Task").WithDescription(description) } func (t *CreateIssueTask) Questions(interfaceType task.InterfaceType) taskui.Questions { - questions := BaseQuestions(interfaceType) - return questions + return BaseQuestions(interfaceType) } func (t *CreateIssueTask) Setup(ctx context.Context) error { // Clear existing issues to ensure a clean state for the task - if err := t.svc.DeleteIssues(); err != nil { + if err := ClearIssues(t.svc); err != nil { return err } - issue := models.Issue{ - ID: "pm-abc", - Title: "Create A New Issue", - Description: description, - IssueType: models.TypeTask, - Status: models.StatusOpen, - } + issue := models.NewBaseIssue(). + WithTitle("Create a New Issue").WithDescription(description).Build() return t.svc.Beads.CreateIssue(ctx, &issue, "") } diff --git a/internal/models/issue.go b/internal/models/issue.go new file mode 100644 index 0000000..e751bfa --- /dev/null +++ b/internal/models/issue.go @@ -0,0 +1,64 @@ +package models + +type IssueBuilder struct { + ID string + Title string + Description string + Status Status + IssueType IssueType + Priority int +} + +func NewIssueBuilder() *IssueBuilder { + return &IssueBuilder{} +} + +func NewBaseIssue() *IssueBuilder { + return NewIssueBuilder(). + WithID("pm-abc"). + WithTitle("Basic Issue"). + WithDescription("Basic Description"). + WithIssueType(TypeTask). + WithStatus(StatusOpen) +} + +func (b *IssueBuilder) WithID(id string) *IssueBuilder { + b.ID = id + return b +} + +func (b *IssueBuilder) WithTitle(title string) *IssueBuilder { + b.Title = title + return b +} + +func (b *IssueBuilder) WithDescription(description string) *IssueBuilder { + b.Description = description + return b +} + +func (b *IssueBuilder) WithStatus(status Status) *IssueBuilder { + b.Status = status + return b +} + +func (b *IssueBuilder) WithIssueType(issueType IssueType) *IssueBuilder { + b.IssueType = issueType + return b +} + +func (b *IssueBuilder) WithPriority(priority int) *IssueBuilder { + b.Priority = priority + return b +} + +func (b IssueBuilder) Build() Issue { + return Issue{ + ID: b.ID, + Title: b.Title, + Description: b.Description, + Status: b.Status, + IssueType: b.IssueType, + Priority: b.Priority, + } +} diff --git a/internal/service/beads.go b/internal/service/beads.go index 06c8373..1a9bc66 100644 --- a/internal/service/beads.go +++ b/internal/service/beads.go @@ -41,3 +41,13 @@ func (s *BeadsService) AllIssues(ctx context.Context) ([]models.Issue, error) { return issues, nil } + +func (s *BeadsService) DeleteIssues() error { + + var deleteIssues = "DELETE FROM issues;" + + if _, err := s.UnderlyingDB().Exec(deleteIssues); err != nil { + return err + } + return nil +} diff --git a/internal/service/config.go b/internal/service/config.go new file mode 100644 index 0000000..7532ab5 --- /dev/null +++ b/internal/service/config.go @@ -0,0 +1,34 @@ +package service + +type Config struct { + RootCmd string + WebAddress string + BeadsDBPath string + IssuePrefix string + StatisticsStoragePath string +} + +func (c Config) WithRootCmd(rootCmd string) Config { + c.RootCmd = rootCmd + return c +} + +func (c Config) WithWebAddress(webAddress string) Config { + c.WebAddress = webAddress + return c +} + +func (c Config) WithBeadsDBPath(beadsDBPath string) Config { + c.BeadsDBPath = beadsDBPath + return c +} + +func (c Config) WithIssuePrefix(issuePrefix string) Config { + c.IssuePrefix = issuePrefix + return c +} + +func (c Config) WithStatisticsStoragePath(path string) Config { + c.StatisticsStoragePath = path + return c +} diff --git a/pkg/task/ui/questionnaire.go b/pkg/task/ui/questionnaire.go index b8db8b9..69fd767 100644 --- a/pkg/task/ui/questionnaire.go +++ b/pkg/task/ui/questionnaire.go @@ -7,8 +7,6 @@ import ( "github.com/charmbracelet/huh" ) -type Questions []*huh.Group - type QuestionnaireModel struct { Questions form *huh.Form diff --git a/pkg/task/ui/task.go b/pkg/task/ui/task.go index a041421..858b3bc 100644 --- a/pkg/task/ui/task.go +++ b/pkg/task/ui/task.go @@ -10,13 +10,6 @@ import ( tea "github.com/charmbracelet/bubbletea" ) -type TaskDetails struct { - Title string - Description string - TimeToComplete string - Difficulty string -} - type TaskModel struct { TaskDetails keys TaskHelpKeys diff --git a/pkg/task/ui/types.go b/pkg/task/ui/types.go new file mode 100644 index 0000000..421bdb5 --- /dev/null +++ b/pkg/task/ui/types.go @@ -0,0 +1,39 @@ +package taskui + +import "github.com/charmbracelet/huh" + +type TaskDetails struct { + Title string + Description string + TimeToComplete string + Difficulty string +} + +func (td TaskDetails) WithTitle(title string) TaskDetails { + td.Title = title + return td +} + +func (td TaskDetails) WithDescription(description string) TaskDetails { + td.Description = description + return td +} + +func (td TaskDetails) WithTimeToComplete(time string) TaskDetails { + td.TimeToComplete = time + return td +} + +func (td TaskDetails) WithDifficulty(difficulty string) TaskDetails { + td.Difficulty = difficulty + return td +} + +type Questions []*huh.Group + +func (q Questions) With(group *huh.Group) Questions { + if group == nil { + return q + } + return append(q, group) +}