package command import ( "errors" "fmt" "time" "github.com/google/uuid" "github.com/urfave/cli/v2" "go-mod.ewintr.nl/planner/item" "go-mod.ewintr.nl/planner/plan/storage" ) var ( ErrInvalidArg = errors.New("invalid argument") ) var AddCmd = &Command{ Name: "add", Description: "Add a new event", Flags: []*Flag{ &Flag{ Name: "name", Short: "n", Description: "The event that will happen", Required: true, }, &Flag{ Name: "on", Short: "o", Description: "The date, in YYYY-MM-DD format", Required: true, }, &Flag{ Name: "at", Short: "a", Description: "The time, in HH:MM format. If omitted, the event will last the whole day", }, &Flag{ Name: "for", Short: "f", Description: "The duration, in show format (e.g. 1h30m)", }, }, } func NewAddCmd(localRepo storage.LocalID, eventRepo storage.Event, syncRepo storage.Sync) *cli.Command { AddCmd.Action = func(cCtx *cli.Context) error { return Add(localRepo, eventRepo, syncRepo, cCtx.String("name"), cCtx.String("on"), cCtx.String("at"), cCtx.String("for")) } return AddCmd } func Add(localIDRepo storage.LocalID, eventRepo storage.Event, syncRepo storage.Sync, nameStr, onStr, atStr, frStr string) error { if nameStr == "" { return fmt.Errorf("%w: name is required", ErrInvalidArg) } if onStr == "" { return fmt.Errorf("%w: date is required", ErrInvalidArg) } if atStr == "" && frStr != "" { return fmt.Errorf("%w: can not have duration without start time", ErrInvalidArg) } if atStr == "" && frStr == "" { frStr = "24h" } startFormat := "2006-01-02" startStr := onStr if atStr != "" { startFormat = fmt.Sprintf("%s 15:04", startFormat) startStr = fmt.Sprintf("%s %s", startStr, atStr) } start, err := time.Parse(startFormat, startStr) if err != nil { return fmt.Errorf("%w: could not parse start time and date: %v", ErrInvalidArg, err) } e := item.Event{ ID: uuid.New().String(), EventBody: item.EventBody{ Title: nameStr, Start: start, }, } if frStr != "" { fr, err := time.ParseDuration(frStr) if err != nil { return fmt.Errorf("%w: could not parse duration: %s", ErrInvalidArg, err) } e.Duration = fr } if err := eventRepo.Store(e); err != nil { return fmt.Errorf("could not store event: %v", err) } localID, err := localIDRepo.Next() if err != nil { return fmt.Errorf("could not create next local id: %v", err) } if err := localIDRepo.Store(e.ID, localID); err != nil { return fmt.Errorf("could not store local id: %v", err) } it, err := e.Item() if err != nil { return fmt.Errorf("could not convert event to sync item: %v", err) } if err := syncRepo.Store(it); err != nil { return fmt.Errorf("could not store sync item: %v", err) } return nil }