diff --git a/api/api.go b/api/api.go index 44d6dcd..39fc753 100644 --- a/api/api.go +++ b/api/api.go @@ -9,13 +9,14 @@ type Api struct { Client *client.Client } -type IApi interface { +type Method interface { GetParentCategories() ([]model.Category, error) GetCategories() ([]model.Category, error) + GetTreeCategories() ([]model.TreeCategories, error) GetProducts() ([]model.Product, error) } -func NewApi(credentials client.Credentials) IApi { +func NewApi(credentials client.Credentials) Method { return &Api{ Client: client.NewClient(credentials), } diff --git a/api/categories.go b/api/categories.go index 0d24182..16e967a 100644 --- a/api/categories.go +++ b/api/categories.go @@ -2,25 +2,26 @@ package api import ( "errors" - "gitea.24example.ru/spavelit/bpiek/model" + "gitea.24example.ru/spavelit/bpiek/utils" ) var categories []model.Category var parentCategories []model.Category +var treeCategories []model.TreeCategories func (a *Api) GetCategories() ([]model.Category, error) { if len(categories) > 0 { return categories, nil } - parentCategoris, err := a.GetParentCategories() + parentCategories, err := a.GetParentCategories() if err != nil { return nil, err } - for _, category := range parentCategoris { + for _, category := range parentCategories { categoriesAndProduct, err := a.GetCategoriesAndProductsBySlugParentCategory(category.Slug) if err != nil { return nil, err @@ -75,3 +76,36 @@ func (a *Api) GetCategoriesAndProductsBySlugParentCategory(slug string) (*model. return apiResponse.Result().(*model.CategoriesAndProductsBySlugParentCategoryResponse), nil } + +func (a *Api) GetTreeCategories() ([]model.TreeCategories, error) { + if len(treeCategories) > 0 { + return treeCategories, nil + } + + tree := map[string]interface{}{} + + parentCategories, err := a.GetParentCategories() + if err != nil { + return nil, err + } + + for _, parent := range parentCategories { + tree[parent.Slug] = map[string]interface{}{ + "name": parent.Name, + "slug": parent.Slug, + "url": parent.Url, + "children": map[string]interface{}{}, + } + + categoriesAndProduct, err := a.GetCategoriesAndProductsBySlugParentCategory(parent.Slug) + if err != nil { + return nil, err + } + + utils.ConvertListToNestedDict(categoriesAndProduct.Categories, tree) + } + + treeCategories = utils.ConvertToNestedList(tree) + + return treeCategories, nil +} diff --git a/api/products.go b/api/products.go index eb56af5..1525a1c 100644 --- a/api/products.go +++ b/api/products.go @@ -10,13 +10,13 @@ func (a *Api) GetProducts() ([]model.Product, error) { return products, nil } - parentCategoris, err := a.GetParentCategories() + parentCategories, err := a.GetParentCategories() if err != nil { return nil, err } - for _, category := range parentCategoris { + for _, category := range parentCategories { categoriesAndProduct, err := a.GetCategoriesAndProductsBySlugParentCategory(category.Slug) if err != nil { return nil, err diff --git a/model/category.go b/model/category.go index 02e3be7..c1bd47e 100644 --- a/model/category.go +++ b/model/category.go @@ -6,3 +6,10 @@ type Category struct { Url string `json:"url"` ApiUrl string `json:"apiUrl"` } + +type TreeCategories struct { + Slug string `json:"slug"` + Name string `json:"name"` + Url string `json:"url"` + Children []TreeCategories `json:"children"` +} diff --git a/model/response.go b/model/response.go index 552271b..46a6d7d 100644 --- a/model/response.go +++ b/model/response.go @@ -30,8 +30,3 @@ type RemainsAndPlanresiduesResponse struct { Date string `json:"date"` Products []ShortProduct `json:"products"` } - -type TreeCategoriesResponse struct { - Category - Children []Category `json:"children"` -} diff --git a/utils/utils.go b/utils/utils.go new file mode 100644 index 0000000..6b2e049 --- /dev/null +++ b/utils/utils.go @@ -0,0 +1,81 @@ +package utils + +import ( + "fmt" + "gitea.24example.ru/spavelit/bpiek/model" + "strings" +) + +func updateNested(d map[string]interface{}, keys []string, value map[string]interface{}) { + for _, key := range keys[:len(keys)-1] { + if _, exists := d[key]; !exists { + d[key] = map[string]interface{}{} + } + d = d[key].(map[string]interface{}) + } + d[keys[len(keys)-1]] = value +} + +func ConvertListToNestedDict(list []model.Category, tree map[string]interface{}) { + var tmpCategories []model.TreeCategories + for _, item := range list { + tmpCategories = append(tmpCategories, model.TreeCategories{ + Name: item.Name, + Slug: item.Slug, + Url: item.Url, + Children: []model.TreeCategories{}, + }) + } + + idx := 0 + for idx < len(tmpCategories) { + category := tmpCategories[idx] + if category.Url == "/" || category.Url == "" { + idx++ + continue + } + paths := strings.Split(strings.Trim(category.Url, "/"), "/") + + var strBuilder strings.Builder + for i, path := range paths { + if len(paths) == i+1 { + strBuilder.WriteString(path) + break + } + strBuilder.WriteString(fmt.Sprintf("%s,children,", path)) + } + updateNested( + tree, + strings.Split(strBuilder.String(), ","), + map[string]interface{}{ + "name": category.Name, + "slug": category.Slug, + "url": category.Url, + "children": map[string]interface{}{}, + }, + ) + tmpCategories = append(tmpCategories[:idx], tmpCategories[idx+1:]...) + } +} + +func ConvertToNestedList(nestedDict map[string]interface{}) []model.TreeCategories { + var result []model.TreeCategories + + for _, value := range nestedDict { + if valueMap, ok := value.(map[string]interface{}); ok { + childCategories := ConvertToNestedList(valueMap["children"].(map[string]interface{})) + + category := model.TreeCategories{ + Name: valueMap["name"].(string), + Slug: valueMap["slug"].(string), + Url: valueMap["url"].(string), + Children: childCategories, + } + + result = append(result, category) + } else if category, ok := value.(model.TreeCategories); ok { + result = append(result, category) + } + } + return result +}