package ticket import ( "time" "unicode" ) // Status represents the workflow state of a ticket. type Status string const ( StatusTodo Status = "todo" StatusInProgress Status = "in_progress" StatusDone Status = "done" ) // AllStatuses is the ordered list shown in the status picker. var AllStatuses = []Status{StatusTodo, StatusInProgress, StatusDone} // Label returns a short display label for the status. func (s Status) Label() string { switch s { case StatusTodo: return "OPEN" case StatusInProgress: return "WIP" case StatusDone: return "DONE" default: return string(s) } } // Shortcut returns the status-menu hotkey (first letter of the label). func (s Status) Shortcut() rune { label := s.Label() if label == "" { return 0 } return unicode.ToLower([]rune(label)[0]) } // Index returns the position in AllStatuses, or 0 if unknown. func (s Status) Index() int { for i, st := range AllStatuses { if st == s { return i } } return 0 } const ( // SourceYouTrack marks tickets imported from YouTrack. SourceYouTrack = "youtrack" ) // Ticket is the domain model for a work item. // Title (headline) and Description are Markdown. type Ticket struct { ID string `json:"id"` Title string `json:"title"` Description string `json:"description,omitempty"` Status Status `json:"status"` ProjectID string `json:"projectId"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` // External sync (optional). Local UUID stays in ID. Source string `json:"source,omitempty"` ExternalID string `json:"externalId,omitempty"` ExternalURL string `json:"externalUrl,omitempty"` SyncedAt time.Time `json:"syncedAt,omitempty"` }