package storage import ( "fmt" "sort" "time" bolt "go.etcd.io/bbolt" ) func (s *Storage) CreateCategory(name string, order int) error { return s.db.Update(func(tx *bolt.Tx) error { b := tx.Bucket(bucketCategories) if b.Get([]byte(name)) != nil { return fmt.Errorf("category %q already exists", name) } cat := Category{ Name: name, Order: order, CreatedAt: time.Now(), } data, err := encodeJSON(cat) if err != nil { return err } return b.Put([]byte(name), data) }) } func (s *Storage) DeleteCategory(name string) error { return s.db.Update(func(tx *bolt.Tx) error { b := tx.Bucket(bucketCategories) if b.Get([]byte(name)) == nil { return fmt.Errorf("category %q not found", name) } return b.Delete([]byte(name)) }) } func (s *Storage) GetCategory(name string) (*Category, error) { var cat *Category err := s.db.View(func(tx *bolt.Tx) error { b := tx.Bucket(bucketCategories) data := b.Get([]byte(name)) if data == nil { return fmt.Errorf("category %q not found", name) } cat = &Category{} return decodeJSON(data, cat) }) return cat, err } func (s *Storage) ListCategories() ([]Category, error) { var categories []Category err := s.db.View(func(tx *bolt.Tx) error { b := tx.Bucket(bucketCategories) return b.ForEach(func(k, v []byte) error { var cat Category if err := decodeJSON(v, &cat); err != nil { return err } categories = append(categories, cat) return nil }) }) if err != nil { return nil, err } sort.Slice(categories, func(i, j int) bool { if categories[i].Order != categories[j].Order { return categories[i].Order < categories[j].Order } return categories[i].CreatedAt.Before(categories[j].CreatedAt) }) return categories, nil } func (s *Storage) UpdateCategoryOrder(name string, order int) error { return s.db.Update(func(tx *bolt.Tx) error { b := tx.Bucket(bucketCategories) data := b.Get([]byte(name)) if data == nil { return fmt.Errorf("category %q not found", name) } var cat Category if err := decodeJSON(data, &cat); err != nil { return err } cat.Order = order newData, err := encodeJSON(cat) if err != nil { return err } return b.Put([]byte(name), newData) }) } func (s *Storage) CategoryExists(name string) bool { exists := false s.db.View(func(tx *bolt.Tx) error { b := tx.Bucket(bucketCategories) exists = b.Get([]byte(name)) != nil return nil }) return exists }