diff --git a/app/module/products/mapper/products.mapper.go b/app/module/products/mapper/products.mapper.go index 60f6e02..06b9079 100644 --- a/app/module/products/mapper/products.mapper.go +++ b/app/module/products/mapper/products.mapper.go @@ -12,11 +12,34 @@ func ProductsResponseMapper(product *entity.Products, host string) *res.Products return nil } - var colors []string - if product.Colors != nil && *product.Colors != "" { - json.Unmarshal([]byte(*product.Colors), &colors) + var colors []res.ProductColorResponse + +if product.Colors != nil && *product.Colors != "" { + var rawColors []struct { + Name string `json:"name"` + ImagePath *string `json:"image_path"` } + _ = json.Unmarshal([]byte(*product.Colors), &rawColors) + + for _, c := range rawColors { + var imageUrl *string + + if c.ImagePath != nil { + filename := filepath.Base(*c.ImagePath) + url := host + "/products/viewer/" + filename + imageUrl = &url + } + + colors = append(colors, res.ProductColorResponse{ + Name: c.Name, + ImagePath: c.ImagePath, + ImageUrl: imageUrl, + }) + } +} + + response := &res.ProductsResponse{ ID: product.ID, Title: product.Title, diff --git a/app/module/products/response/products.response.go b/app/module/products/response/products.response.go index 1a78495..3d016d1 100644 --- a/app/module/products/response/products.response.go +++ b/app/module/products/response/products.response.go @@ -4,6 +4,12 @@ import ( "time" ) +type ProductColorResponse struct { + Name string `json:"name"` + ImagePath *string `json:"image_path"` + ImageUrl *string `json:"image_url"` +} + type ProductsResponse struct { ID uint `json:"id"` Title string `json:"title"` @@ -11,7 +17,7 @@ type ProductsResponse struct { Price *string `json:"price"` ThumbnailPath *string `json:"thumbnail_path"` ThumbnailUrl *string `json:"thumbnail_url"` - Colors []string `json:"colors"` + Colors []ProductColorResponse `json:"colors"` Status *string `json:"status"` StatusId *int `json:"status_id"` IsActive *bool `json:"is_active"` diff --git a/app/module/products/service/products.service.go b/app/module/products/service/products.service.go index 1b13908..01fb47f 100644 --- a/app/module/products/service/products.service.go +++ b/app/module/products/service/products.service.go @@ -17,6 +17,7 @@ import ( utilSvc "jaecoo-be/utils/service" "math/rand" "mime" + "mime/multipart" "path/filepath" "strconv" "strings" @@ -95,6 +96,55 @@ func (_i *productsService) GetOne(id uint) (product *response.ProductsResponse, return } +func (_i *productsService) uploadColorFile( + fileHeader *multipart.FileHeader, +) (*string, error) { + + minioClient, err := _i.MinioStorage.ConnectMinio() + if err != nil { + return nil, err + } + + src, err := fileHeader.Open() + if err != nil { + return nil, err + } + defer src.Close() + + now := time.Now() + ext := filepath.Ext(fileHeader.Filename) + name := strings.TrimSuffix(fileHeader.Filename, ext) + name = strings.ReplaceAll(name, " ", "") + + filename := fmt.Sprintf( + "%s_%d%s", + name, + rand.Intn(999999), + ext, + ) + + objectName := fmt.Sprintf( + "products/colors/%d/%d/%s", + now.Year(), + now.Month(), + filename, + ) + + _, err = minioClient.PutObject( + context.Background(), + _i.MinioStorage.Cfg.ObjectStorage.MinioStorage.BucketName, + objectName, + src, + fileHeader.Size, + minio.PutObjectOptions{}, + ) + if err != nil { + return nil, err + } + + return &objectName, nil +} + func (_i *productsService) Create(c *fiber.Ctx, req request.ProductsCreateRequest) (product *response.ProductsResponse, err error) { // Handle file upload if exists if filePath, uploadErr := _i.UploadFileToMinio(c, "file"); uploadErr == nil && filePath != nil { @@ -105,18 +155,41 @@ func (_i *productsService) Create(c *fiber.Ctx, req request.ProductsCreateReques productEntity := req.ToEntity() // 🔥 FIX COLORS (INI INTI MASALAH KAMU) - var colors []string - for _, c := range req.Colors { - if c.Name != "" { - colors = append(colors, c.Name) - } - } + form, _ := c.MultipartForm() + colorFiles := form.File["color_images"] + + var colorEntities []request.ProductColorRequest + + for i, cReq := range req.Colors { + if cReq.Name == "" { + continue + } + + color := request.ProductColorRequest{ + Name: cReq.Name, + } + + // 🔥 AMBIL FILE SESUAI INDEX + if len(colorFiles) > i { + fileHeader := colorFiles[i] + + path, err := _i.uploadColorFile(fileHeader) + if err == nil && path != nil { + color.ImagePath = path + } + } + + colorEntities = append(colorEntities, color) + } + + // 🔥 SIMPAN KE ENTITY + if len(colorEntities) > 0 { + bytes, _ := json.Marshal(colorEntities) + str := string(bytes) + productEntity.Colors = &str + } + - if len(colors) > 0 { - bytes, _ := json.Marshal(colors) - colorStr := string(bytes) - productEntity.Colors = &colorStr - } // SET DEFAULT ACTIVE