package commands import ( "fmt" "punchcard/internal/actions" punchctx "punchcard/internal/context" "github.com/spf13/cobra" ) func NewInCmd() *cobra.Command { var clientFlag, projectFlag string cmd := &cobra.Command{ Use: "in []", Aliases: []string{"i"}, Short: "Start a timer", Long: `Start tracking time for the current work session. If no flags are provided, copies the most recent time entry. If -p/--project is provided without -c/--client, uses the project's client. If a timer is already active: - Same parameters: no-op - Different parameters: stops current timer and starts new one Examples: punch in # Copy most recent entry punch in "Working on website redesign" # Copy most recent but change description punch in -c "Acme Corp" "Client meeting" # Specific client punch in -p "Website Redesign" "Frontend development" # Project (client auto-selected) punch in --client 1 --project "Website Redesign" # Explicit client and project`, Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { var description string if len(args) > 0 { description = args[0] } billableRateFloat, _ := cmd.Flags().GetFloat64("hourly-rate") var billableRate *float64 if billableRateFloat > 0 { billableRate = &billableRateFloat } q := punchctx.GetDB(cmd.Context()) if q == nil { return fmt.Errorf("database not available in context") } a := actions.New(q) // Use the actions package based on what flags were provided var session *actions.TimerSession var err error if clientFlag == "" && projectFlag == "" { // Use most recent entry session, err = a.PunchInMostRecent(cmd.Context(), description, billableRate) } else { // Use specified client/project session, err = a.PunchIn(cmd.Context(), clientFlag, projectFlag, description, billableRate) } if err != nil { return err } // Handle different response types if session.WasNoOp { cmd.Printf("Timer already active with same parameters (ID: %d)\n", session.ID) return nil } // Print stopped timer message if we stopped one if session.StoppedEntryID != nil { cmd.Printf("Stopped previous timer (ID: %d)\n", *session.StoppedEntryID) } // Build output message output := fmt.Sprintf("Started timer (ID: %d) for client: %s", session.ID, session.ClientName) if session.ProjectName != "" { output += fmt.Sprintf(", project: %s", session.ProjectName) } if session.Description != "" { output += fmt.Sprintf(", description: %s", session.Description) } cmd.Print(output + "\n") return nil }, } cmd.Flags().StringVarP(&clientFlag, "client", "c", "", "Client name or ID") cmd.Flags().StringVarP(&projectFlag, "project", "p", "", "Project name or ID") cmd.Flags().Float64("hourly-rate", 0, "Override hourly billable rate for this time entry") return cmd }