package commands import ( "errors" "fmt" "git.tjp.lol/punchcard/internal/actions" punchctx "git.tjp.lol/punchcard/internal/context" "github.com/spf13/cobra" ) func NewArchiveCmd() *cobra.Command { var clientFlag, projectFlag string cmd := &cobra.Command{ Use: "archive", Short: "Archive a client or project", Long: `Archive a client or project to hide it from the default view. Archived clients and projects will not be shown in the "Clients & Projects" pane by default, but can be toggled visible. All historical time entries remain accessible. Examples: punch archive --client "Acme Corp" punch archive --client 1 punch archive --project "Website Redesign" punch archive --project 5`, RunE: func(cmd *cobra.Command, args []string) error { if clientFlag == "" && projectFlag == "" { return errors.New("either --client or --project must be specified") } if clientFlag != "" && projectFlag != "" { return errors.New("cannot specify both --client and --project") } q := punchctx.GetDB(cmd.Context()) if q == nil { return fmt.Errorf("database not available in context") } a := actions.New(q) if clientFlag != "" { client, err := a.FindClient(cmd.Context(), clientFlag) if err != nil { return fmt.Errorf("failed to find client: %w", err) } if err := a.ArchiveClient(cmd.Context(), client.ID); err != nil { return fmt.Errorf("failed to archive client: %w", err) } cmd.Printf("Archived client: %s\n", client.Name) } else { project, err := a.FindProject(cmd.Context(), projectFlag) if err != nil { return fmt.Errorf("failed to find project: %w", err) } if err := a.ArchiveProject(cmd.Context(), project.ID); err != nil { return fmt.Errorf("failed to archive project: %w", err) } cmd.Printf("Archived project: %s\n", project.Name) } return nil }, } cmd.Flags().StringVarP(&clientFlag, "client", "c", "", "Client name or ID") cmd.Flags().StringVarP(&projectFlag, "project", "p", "", "Project name or ID") return cmd } func NewUnarchiveCmd() *cobra.Command { var clientFlag, projectFlag string cmd := &cobra.Command{ Use: "unarchive", Short: "Unarchive a client or project", Long: `Unarchive a client or project to show it in the default view again. Examples: punch unarchive --client "Acme Corp" punch unarchive --client 1 punch unarchive --project "Website Redesign" punch unarchive --project 5`, RunE: func(cmd *cobra.Command, args []string) error { if clientFlag == "" && projectFlag == "" { return errors.New("either --client or --project must be specified") } if clientFlag != "" && projectFlag != "" { return errors.New("cannot specify both --client and --project") } q := punchctx.GetDB(cmd.Context()) if q == nil { return fmt.Errorf("database not available in context") } a := actions.New(q) if clientFlag != "" { client, err := a.FindClient(cmd.Context(), clientFlag) if err != nil { return fmt.Errorf("failed to find client: %w", err) } if err := a.UnarchiveClient(cmd.Context(), client.ID); err != nil { return fmt.Errorf("failed to unarchive client: %w", err) } cmd.Printf("Unarchived client: %s\n", client.Name) } else { project, err := a.FindProject(cmd.Context(), projectFlag) if err != nil { return fmt.Errorf("failed to find project: %w", err) } if err := a.UnarchiveProject(cmd.Context(), project.ID); err != nil { return fmt.Errorf("failed to unarchive project: %w", err) } cmd.Printf("Unarchived project: %s\n", project.Name) } return nil }, } cmd.Flags().StringVarP(&clientFlag, "client", "c", "", "Client name or ID") cmd.Flags().StringVarP(&projectFlag, "project", "p", "", "Project name or ID") return cmd }