From 1098c22738d9c58e281176848661dc23d100d2c5 Mon Sep 17 00:00:00 2001 From: Anang Yusman Date: Tue, 27 Jan 2026 17:28:17 +0800 Subject: [PATCH] update:api product --- app/module/products/mapper/products.mapper.go | 47 ++++--- .../products/service/products.service.go | 115 ++++++++++++------ 2 files changed, 100 insertions(+), 62 deletions(-) diff --git a/app/module/products/mapper/products.mapper.go b/app/module/products/mapper/products.mapper.go index 06b9079..0de47c0 100644 --- a/app/module/products/mapper/products.mapper.go +++ b/app/module/products/mapper/products.mapper.go @@ -4,7 +4,6 @@ import ( "encoding/json" "jaecoo-be/app/database/entity" res "jaecoo-be/app/module/products/response" - "path/filepath" ) func ProductsResponseMapper(product *entity.Products, host string) *res.ProductsResponse { @@ -14,31 +13,29 @@ func ProductsResponseMapper(product *entity.Products, host string) *res.Products 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 + if product.Colors != nil && *product.Colors != "" { + var rawColors []struct { + Name string `json:"name"` + ImagePath *string `json:"image_path"` } - colors = append(colors, res.ProductColorResponse{ - Name: c.Name, - ImagePath: c.ImagePath, - ImageUrl: imageUrl, - }) - } -} + _ = json.Unmarshal([]byte(*product.Colors), &rawColors) + for _, c := range rawColors { + var imageUrl *string + + if c.ImagePath != nil && *c.ImagePath != "" { + url := host + "/products/viewer/" + *c.ImagePath + imageUrl = &url + } + + colors = append(colors, res.ProductColorResponse{ + Name: c.Name, + ImagePath: c.ImagePath, + ImageUrl: imageUrl, + }) + } + } response := &res.ProductsResponse{ ID: product.ID, @@ -55,9 +52,7 @@ if product.Colors != nil && *product.Colors != "" { } if product.ThumbnailPath != nil && *product.ThumbnailPath != "" { - // Extract filename from path - filename := filepath.Base(*product.ThumbnailPath) - thumbnailUrl := host + "/products/viewer/" + filename + thumbnailUrl := host + "/products/viewer/" + *product.ThumbnailPath response.ThumbnailUrl = &thumbnailUrl } diff --git a/app/module/products/service/products.service.go b/app/module/products/service/products.service.go index a9721f2..cadde46 100644 --- a/app/module/products/service/products.service.go +++ b/app/module/products/service/products.service.go @@ -307,69 +307,112 @@ func (_i *productsService) Delete(id uint) (err error) { return } -func (_i *productsService) Viewer(c *fiber.Ctx) (err error) { - filename := c.Params("filename") +// func (_i *productsService) Viewer(c *fiber.Ctx) (err error) { +// filename := c.Params("filename") - // Find product by filename (repository will search using LIKE pattern) - result, err := _i.Repo.FindByThumbnailPath(filename) - if err != nil { - return c.Status(fiber.StatusNotFound).JSON(fiber.Map{ - "error": true, - "msg": "Product file not found", - }) - } +// // Find product by filename (repository will search using LIKE pattern) +// result, err := _i.Repo.FindByThumbnailPath(filename) +// if err != nil { +// return c.Status(fiber.StatusNotFound).JSON(fiber.Map{ +// "error": true, +// "msg": "Product file not found", +// }) +// } - if result.ThumbnailPath == nil || *result.ThumbnailPath == "" { - return c.Status(fiber.StatusNotFound).JSON(fiber.Map{ +// if result.ThumbnailPath == nil || *result.ThumbnailPath == "" { +// return c.Status(fiber.StatusNotFound).JSON(fiber.Map{ +// "error": true, +// "msg": "Product thumbnail path not found", +// }) +// } + +// ctx := context.Background() +// bucketName := _i.MinioStorage.Cfg.ObjectStorage.MinioStorage.BucketName +// objectName := *result.ThumbnailPath + +// _i.Log.Info().Str("timestamp", time.Now(). +// Format(time.RFC3339)).Str("Service:Resource", "Products:Viewer"). +// Interface("data", objectName).Msg("") + +// // Create minio connection +// minioClient, err := _i.MinioStorage.ConnectMinio() +// if err != nil { +// return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ +// "error": true, +// "msg": err.Error(), +// }) +// } + +// fileContent, err := minioClient.GetObject(ctx, bucketName, objectName, minio.GetObjectOptions{}) +// if err != nil { +// _i.Log.Error().Str("timestamp", time.Now(). +// Format(time.RFC3339)).Str("Service:Resource", "Products:Viewer"). +// Interface("Error getting file", err).Msg("") +// return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ +// "error": true, +// "msg": "Failed to retrieve file", +// }) +// } +// defer fileContent.Close() + +// // Determine Content-Type based on file extension +// contentType := mime.TypeByExtension("." + getFileExtension(objectName)) +// if contentType == "" { +// contentType = "application/octet-stream" // fallback if no MIME type matches +// } + +// c.Set("Content-Type", contentType) + +// if _, err := io.Copy(c.Response().BodyWriter(), fileContent); err != nil { +// return err +// } + +// return +// } + +func (_i *productsService) Viewer(c *fiber.Ctx) error { + // ambil full path setelah /viewer + objectPath := strings.TrimPrefix(c.Params("*"), "/") + + if objectPath == "" { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "error": true, - "msg": "Product thumbnail path not found", + "msg": "File path is required", }) } ctx := context.Background() bucketName := _i.MinioStorage.Cfg.ObjectStorage.MinioStorage.BucketName - objectName := *result.ThumbnailPath - _i.Log.Info().Str("timestamp", time.Now(). - Format(time.RFC3339)).Str("Service:Resource", "Products:Viewer"). - Interface("data", objectName).Msg("") - - // Create minio connection minioClient, err := _i.MinioStorage.ConnectMinio() if err != nil { - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + return c.Status(500).JSON(fiber.Map{ "error": true, "msg": err.Error(), }) } - fileContent, err := minioClient.GetObject(ctx, bucketName, objectName, minio.GetObjectOptions{}) + file, err := minioClient.GetObject(ctx, bucketName, objectPath, minio.GetObjectOptions{}) if err != nil { - _i.Log.Error().Str("timestamp", time.Now(). - Format(time.RFC3339)).Str("Service:Resource", "Products:Viewer"). - Interface("Error getting file", err).Msg("") - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + return c.Status(404).JSON(fiber.Map{ "error": true, - "msg": "Failed to retrieve file", + "msg": "Product file not found", }) } - defer fileContent.Close() + defer file.Close() - // Determine Content-Type based on file extension - contentType := mime.TypeByExtension("." + getFileExtension(objectName)) + // content-type + contentType := mime.TypeByExtension(filepath.Ext(objectPath)) if contentType == "" { - contentType = "application/octet-stream" // fallback if no MIME type matches + contentType = "application/octet-stream" } - c.Set("Content-Type", contentType) - if _, err := io.Copy(c.Response().BodyWriter(), fileContent); err != nil { - return err - } - - return + _, err = io.Copy(c.Response().BodyWriter(), file) + return err } + func getFileExtension(filename string) string { // split file name parts := strings.Split(filename, ".")