hiling_go/api/location.go

156 lines
4.3 KiB
Go

package api
import (
"database/sql"
"fmt"
"net/http"
"os"
"path/filepath"
"time"
db "git.nochill.in/nochill/hiling_go/db/sqlc"
"git.nochill.in/nochill/hiling_go/util"
"github.com/gin-gonic/gin"
"github.com/lib/pq"
ysqlc "github.com/yiplee/sqlc"
)
type createLocationReq struct {
Address string `form:"address" binding:"required"`
Name string `form:"name" binding:"required"`
SubmittedBy int32 `form:"submitted_by" binding:"required,number"`
RegencyID int16 `form:"regency_id" binding:"required,number"`
GoogleMapsLink string `form:"google_maps_link"`
}
func (server *Server) createLocation(ctx *gin.Context) {
var req createLocationReq
var imgPath string
var thumbnail, _ = ctx.FormFile("thumbnail")
if err := ctx.Bind(&req); err != nil {
ctx.JSON(http.StatusBadRequest, ValidationErrorResponse(err))
return
}
if thumbnail != nil {
img := thumbnail
fileExt := filepath.Ext(img.Filename)
now := time.Now()
dir := fmt.Sprintf("public/upload/images/locations/%s/thumbnail", req.Name)
osFilename := fmt.Sprintf("%s%s%s", util.RandomString(5), fmt.Sprintf("%v", now.Unix()), fileExt)
imgPath = fmt.Sprintf("%s%s", dir, osFilename)
if _, err := os.Stat(dir); os.IsNotExist(err) {
os.Mkdir(dir, 0775)
}
if err := ctx.SaveUploadedFile(img, imgPath); err != nil {
ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Error while try to save thumbnail image"))
return
}
}
arg := db.CreateLocationParams{
Address: req.Address,
Name: req.Name,
SubmittedBy: req.SubmittedBy,
RegencyID: req.RegencyID,
GoogleMapsLink: sql.NullString{Valid: len(req.GoogleMapsLink) > 0, String: req.GoogleMapsLink},
}
err := server.Store.CreateLocation(ctx, arg)
if err != nil {
if pqErr, ok := err.(*pq.Error); ok {
switch pqErr.Code.Name() {
case "foreign_key_violation", "unique_violation":
if pqErr.Constraint == "locations_regency_id_fkey" {
ctx.JSON(http.StatusConflict, ErrorResponse(err, fmt.Sprintf("Failed to submit location, there's no regency with id: %d", arg.RegencyID)))
return
}
if pqErr.Constraint == "submitted_by_fkey" {
ctx.JSON(http.StatusConflict, ErrorResponse(err, fmt.Sprintf("Failed to submit location, there's no user with id: %d", arg.SubmittedBy)))
return
}
}
}
ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong"))
return
}
ctx.Writer.WriteHeader(http.StatusOK)
}
type getListLocationsReq struct {
Page int32 `form:"page" binding:"required,min=1"`
PageSize int32 `form:"page_size" binding:"required,min=5"`
}
func (server *Server) getListLocations(ctx *gin.Context) {
var req getListLocationsReq
if err := ctx.ShouldBindQuery(&req); err != nil {
ctx.JSON(http.StatusBadRequest, ValidationErrorResponse(err))
return
}
locations, err := server.Store.GetListLocations(ysqlc.Build(ctx, func(builder *ysqlc.Builder) {
builder.Limit(int(req.PageSize))
builder.Offset(int(req.Page-1) * int(req.PageSize))
builder.Order("created_at ASC")
}))
if err != nil {
ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong"))
return
}
ctx.JSON(http.StatusOK, locations)
}
type getListRecentLocationsWithRatingsReq struct {
Page int32 `form:"page_size" binding:"required,min=1"`
}
func (server *Server) getListRecentLocationsWithRatings(ctx *gin.Context) {
var req getListRecentLocationsWithRatingsReq
if err := ctx.ShouldBindQuery(&req); err != nil {
ctx.JSON(http.StatusBadRequest, ValidationErrorResponse(err))
return
}
locations, err := server.Store.GetListRecentLocationsWithRatings(ctx, req.Page)
if err != nil {
ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong"))
return
}
ctx.JSON(http.StatusOK, locations)
}
type getLocationReq struct {
ID int32 `uri:"location_id" binding:"required"`
}
func (server *Server) getLocation(ctx *gin.Context) {
var req getLocationReq
if err := ctx.ShouldBindUri(&req); err != nil {
ctx.JSON(http.StatusBadRequest, ValidationErrorResponse(err))
return
}
location, err := server.Store.GetLocation(ctx, req.ID)
if err != nil {
if err == sql.ErrNoRows {
ctx.JSON(http.StatusNotFound, ErrorResponse(err, ""))
return
}
ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong"))
return
}
ctx.JSON(http.StatusOK, location)
}