Files
LazyPM/cmd/survey/tasks/teamCapacity.go
2026-02-25 15:14:09 +01:00

128 lines
3.8 KiB
Go

package tasks
import (
"context"
"time"
"github.com/LazyBachelor/LazyPM/internal/models"
"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 teamCapacityDescription = `You are tasked with managing team capacity.
You have a team of 4 developers with varying skill and availability.
Review the upcoming sprint workload and:
1. Review assigned issues and their priorities
2. Identify overloaded team members based on issue assignments
3. Rebalance workload to match capacity
4. Consider vacations and time off mentioned in issue descriptions
5. Ensure critical tasks have coverage
Team member Alice is on vacation next week (mentioned in her issues). Bob can only work 50% time due to other commitments.`
type TeamCapacityTask struct {
done bool
app *service.App
setupIssue *models.Issue
}
func NewTeamCapacityTask(app *service.App) *TeamCapacityTask {
return &TeamCapacityTask{app: app, done: false}
}
func (t *TeamCapacityTask) Config() task.Config {
return BaseConfig().WithStatisticsStoragePath("./.pm/capacity-task-stats.json")
}
func (t *TeamCapacityTask) Details() taskui.TaskDetails {
return BaseDetails().
WithTitle("Team Capacity Management").
WithDescription(teamCapacityDescription).
WithTimeToComplete("12m").
WithDifficulty("Medium")
}
func (t *TeamCapacityTask) Questions(interfaceType task.InterfaceType) taskui.Questions {
return BaseQuestions(interfaceType).With(
huh.NewGroup(
huh.NewSelect[int]().
Title("How many issues did you reassign or update?").
Options(
huh.NewOption("0", 0),
huh.NewOption("1-2", 1),
huh.NewOption("3+", 2),
),
),
)
}
func (t *TeamCapacityTask) Setup(ctx context.Context) error {
if err := ClearIssues(t.app); err != nil {
return err
}
capacityIssues := []*models.Issue{
models.NewIssueBuilder().
WithTitle("Authentication module").
WithDescription("Implement OAuth2 flow. Assigned to: Alice (on vacation next week)").
WithPriority(1).
WithStatus(models.StatusInProgress).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Payment integration").
WithDescription("Integrate Stripe API. Assigned to: Alice (on vacation next week)").
WithPriority(1).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Dashboard widgets").
WithDescription("Create reusable widget components. Assigned to: Bob (50% capacity)").
WithPriority(2).
WithStatus(models.StatusInProgress).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("API rate limiting").
WithDescription("Add rate limiting middleware. Assigned to: Bob (50% capacity)").
WithPriority(2).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Data migration").
WithDescription("Migrate legacy data to new schema. Assigned to: Charlie (full capacity)").
WithPriority(3).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Bug fixes batch").
WithDescription("Fix reported bugs from QA. Assigned to: Diana (full capacity)").
WithPriority(1).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
}
if err := t.app.Issues.CreateIssues(ctx, capacityIssues, ""); err != nil {
return err
}
t.setupIssue = models.NewBaseIssue().
WithTitle("Team Capacity Planning").
WithDescription(teamCapacityDescription).
Build()
return t.app.Issues.CreateIssue(ctx, t.setupIssue, "")
}
func (t *TeamCapacityTask) Validate(ctx context.Context) (bool, error) {
return EndTaskWithTimeout(&t.done, "Team capacity task completed!", 5*time.Second)
}