]> localhost Git - tq-wave11-pf.git/commitdiff
feat: list ingredients main
authorJansen <[email protected]>
Thu, 7 Aug 2025 22:11:16 +0000 (18:11 -0400)
committerJansen <[email protected]>
Thu, 7 Aug 2025 22:11:16 +0000 (18:11 -0400)
persistence/ingredient.go
persistence/inmemory/ingredients.go
persistence/persistence.go
pkg/core/ingrendient.go
pkg/http/ingredient.go
pkg/services/ingredient.go

index 795944e1a116fdb02fa011765227d065c3daf35f..bead4e05bc99ac17c15f4e7035372f8582ac5552 100644 (file)
@@ -8,8 +8,10 @@ type IngredientRepository interface {
        IngredientCreate(core.Ingredient) (core.Ingredient, error)
        IngredientUpdate(core.Ingredient) error
        IngredientDeactivate(int) error
+
        IngredientGet(int) (*core.Ingredient, error)
        IngredientGetByName(name string) (*core.Ingredient, error)
-       // TODO: add search params
-       IngredientList() ([]core.Ingredient, error)
+
+       IngredientCount(core.IngredientSearch) (int, error)
+       IngredientList(core.IngredientSearch) ([]core.Ingredient, error)
 }
index 4f699224c5d833123cf70c81135bd0de14ad77bd..cd5deeca5ed045d821056320d4d3fbdedc34ba38 100644 (file)
@@ -2,8 +2,12 @@ package inmemory
 
 import (
        "errors"
+       "fmt"
+       "math"
+       "regexp"
        "time"
 
+       "jsdaj.tq/pf/persistence"
        "jsdaj.tq/pf/pkg/core"
        "jsdaj.tq/pf/pkg/util"
 )
@@ -60,7 +64,7 @@ func (p *InmemoryPersistence) IngredientDeactivate(id int) error {
        }
 
        now := time.Now()
-       p.ingredients[id-1].DeletedAt = &now 
+       p.ingredients[id-1].DeletedAt = &now
 
        return nil
 }
@@ -87,8 +91,46 @@ func (p *InmemoryPersistence) IngredientGetByName(name string) (*core.Ingredient
        return nil, nil
 }
 
-func (p *InmemoryPersistence) IngredientList() ([]core.Ingredient, error) {
-       filtered := util.Filter(p.ingredients, func(i core.Ingredient) bool { return i.DeletedAt == nil })
+func (p *InmemoryPersistence) IngredientCount(search core.IngredientSearch) (int, error) {
+       not_deleted := util.Filter(p.ingredients, filterByDeleted())
+       filtered := util.Filter(not_deleted, filterBySearch(search))
 
-       return filtered, nil
+       return len(filtered), nil
+}
+
+func (p *InmemoryPersistence) IngredientList(search core.IngredientSearch) ([]core.Ingredient, error) {
+       not_deleted := util.Filter(p.ingredients, filterByDeleted())
+       filtered := util.Filter(not_deleted, filterBySearch(search))
+
+       if search.Skip > len(filtered) {
+               return []core.Ingredient{}, nil
+       }
+
+       highBound := persistence.DEFAULT_MAX_PAGE_SIZE + search.Skip
+       highBound = int(math.Min(float64(highBound), float64(len(filtered))))
+
+       return filtered[search.Skip:highBound], nil
+}
+
+func filterByDeleted() util.FilterFunc[core.Ingredient] {
+       return func(i core.Ingredient) bool {
+               return i.DeletedAt == nil
+       }
+}
+
+func filterBySearch(search core.IngredientSearch) util.FilterFunc[core.Ingredient] {
+       return func(i core.Ingredient) bool {
+               if !search.ShowNotAvailable && *i.Quantity == 0 {
+                       return false
+               }
+
+               if len(search.NameLike) > 0 {
+                       re := regexp.MustCompile(fmt.Sprintf("(?i).*%s.*", search.NameLike))
+
+                       if !re.Match([]byte(i.Name)) {
+                               return false
+                       }
+               }
+               return true
+       }
 }
index 8fe6d8496555c53e2b2ac3e802fc4ea733fb430c..21c2b908163e23dbd4ef1d8c6a38fd0ee70fa27c 100644 (file)
@@ -1,5 +1,7 @@
 package persistence
 
+const DEFAULT_MAX_PAGE_SIZE int = 10
+
 type Persistence interface {
        IngredientRepository
 }
index 657e8823e724bce83f25e05416dd78a82d5fe89d..75f043df8223fe09b9ed2f53601a26448852e9b9 100644 (file)
@@ -9,7 +9,7 @@ import (
 type Ingredient struct {
        Id          int        `json:"id,omitempty"`
        Name        string     `json:"name"`
-       Quantity    *int        `json:"quantity"`
+       Quantity    *int       `json:"quantity"`
        Description string     `json:"description"`
        CreatedAt   *time.Time `json:"-"`
        DeletedAt   *time.Time `json:"-"`
@@ -32,3 +32,9 @@ func (ingredient Ingredient) IsValid() error {
 
        return nil
 }
+
+type IngredientSearch struct {
+       NameLike         string
+       ShowNotAvailable bool
+       Skip             int
+}
index efc534ebdcb1c4e947477adc7a2b07c58fceb008..61676c9a633e252d43c3ce490fdba5f74d0ff4de 100644 (file)
@@ -2,6 +2,7 @@ package http
 
 import (
        shttp "net/http"
+       "strconv"
 
        "jsdaj.tq/pf/pkg/core"
        "jsdaj.tq/pf/pkg/http/util"
@@ -79,7 +80,20 @@ func (s *Server) ingredientHandleGet(w shttp.ResponseWriter, r *shttp.Request) {
 }
 
 func (s *Server) ingredientHandleList(w shttp.ResponseWriter, r *shttp.Request) {
-       ingredients, err := s.ingredients.List()
+       queryParams := r.URL.Query()
+
+       skip, err := strconv.Atoi(queryParams.Get("skip"))
+       if err != nil {
+               skip = 0
+       }
+
+       search := core.IngredientSearch{
+               NameLike: queryParams.Get("name"),
+               ShowNotAvailable: queryParams.Get("showNotAvailable") == "true",
+               Skip: skip,
+       }
+
+       ingredients, err := s.ingredients.List(search)
        if err != nil {
                util.HandleError(w, r, shttp.StatusInternalServerError, err.Error())
                return
index 01742fdab8853395877df62ea6a93d6218646bb3..728361f081f51e6270daa05f74818387a07e4b86 100644 (file)
@@ -36,14 +36,6 @@ func (s *Ingredient) Update(ingredient core.Ingredient) error {
        return nil
 }
 
-func (s *Ingredient) List() ([]core.Ingredient, error) {
-       ingredients, err := s.repository.IngredientList()
-       if err != nil {
-               return []core.Ingredient{}, errors.MapError(err)
-       }
-       return ingredients, nil
-}
-
 func (s *Ingredient) Delete(id int) error {
        in, err := s.repository.IngredientGet(id)
        if err != nil {
@@ -71,6 +63,36 @@ func (s *Ingredient) Get(id int) (*core.Ingredient, error) {
        return in, nil
 }
 
+type IngredientList struct {
+       NextPageSkip int               `json:"nextPageSkip"`
+       IsLastPage   bool              `json:"isLastPage"`
+       Data         []core.Ingredient `json:"data"`
+}
+
+func (s *Ingredient) List(search core.IngredientSearch) (*IngredientList, error) {
+       total, err := s.repository.IngredientCount(search)
+       if err != nil {
+               return nil, errors.MapError(err)
+       }
+
+       ingredients, err := s.repository.IngredientList(search)
+       if err != nil {
+               return nil, errors.MapError(err)
+       }
+       nextPageSkip := search.Skip + len(ingredients)
+       isLastPage := nextPageSkip >= total
+
+       if isLastPage {
+               nextPageSkip = 0
+       }
+
+       return &IngredientList{
+               NextPageSkip: nextPageSkip,
+               IsLastPage:   isLastPage,
+               Data:         ingredients,
+       }, nil
+}
+
 func InitIngredientService(repository persistence.IngredientRepository) Ingredient {
        return Ingredient{
                repository,