add user profile stats

This commit is contained in:
nochill 2023-10-04 19:51:29 +07:00
parent a2d4dfb282
commit b31bc76a24
5 changed files with 130 additions and 3 deletions

View File

@ -39,7 +39,7 @@ func (server *Server) getRoutes() {
router.Use(cors.New(cors.Config{
AllowOrigins: []string{"http://localhost:5173"},
AllowCredentials: true,
AllowHeaders: []string{"Content-Type", "Content-Length", "Accept-Encoding", "X-CSRF-Token", "Authorization", "accept", "origin", "Cache-Control", "X-Requested-With"},
AllowHeaders: []string{"Content-Type", "Content-Length", "Accept-Encoding", "Authorization", "accept", "origin", "Cache-Control", "X-Requested-With", "X-XSRF-TOKEN"},
AllowMethods: []string{"POST", "PUT", "GET", "DELETE", "PATCH"},
}))
@ -68,6 +68,7 @@ func (server *Server) getRoutes() {
authRoutes := router.Use(authMiddleware(server.TokenMaker))
authRoutes.POST("/review/location", server.createReview)
authRoutes.GET("/user/review/location/:location_id", server.getUserReviewByLocation)
authRoutes.GET("/user/profile", server.getUserStats)
server.Router = router
}

View File

@ -2,11 +2,13 @@ package api
import (
"database/sql"
"encoding/json"
"net/http"
"time"
db "git.nochill.in/nochill/hiling_go/db/sqlc"
"git.nochill.in/nochill/hiling_go/util"
"git.nochill.in/nochill/hiling_go/util/token"
"github.com/gin-gonic/gin"
"github.com/lib/pq"
)
@ -124,6 +126,41 @@ func (server *Server) createUser(ctx *gin.Context) {
ctx.JSON(http.StatusOK, res)
}
func (server *Server) getUserStats(ctx *gin.Context) {
var scoreDistribution []map[string]int8
authPayload := ctx.MustGet(authorizationPayloadKey).(*token.Payload)
userStats, err := server.Store.GetUserStats(ctx, int32(authPayload.UserID))
if err != nil {
ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong while try to get user stats"))
return
}
err = json.Unmarshal(userStats.ScoresDistribution, &scoreDistribution)
if err != nil {
ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong whilet try to parse score distribution"))
return
}
var userReviews []map[string]any
if userStats.Reviews != nil {
err = json.Unmarshal(userStats.Reviews, &userReviews)
if err != nil {
ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something wrong while try to parse user reviwes stats"))
return
}
} else {
userReviews = make([]map[string]any, 0)
}
ctx.JSON(http.StatusOK, gin.H{
"reviews": userReviews,
"scores_distribution": scoreDistribution,
"user_stats": userStats,
})
}
func (server *Server) login(ctx *gin.Context) {
var req createUserRequest

View File

@ -362,6 +362,21 @@ func (mr *MockStoreMockRecorder) GetUserReviewByLocation(arg0, arg1 interface{})
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserReviewByLocation", reflect.TypeOf((*MockStore)(nil).GetUserReviewByLocation), arg0, arg1)
}
// GetUserStats mocks base method.
func (m *MockStore) GetUserStats(arg0 context.Context, arg1 int32) (db.GetUserStatsRow, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetUserStats", arg0, arg1)
ret0, _ := ret[0].(db.GetUserStatsRow)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetUserStats indicates an expected call of GetUserStats.
func (mr *MockStoreMockRecorder) GetUserStats(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserStats", reflect.TypeOf((*MockStore)(nil).GetUserStats), arg0, arg1)
}
// RemoveFollowUser mocks base method.
func (m *MockStore) RemoveFollowUser(arg0 context.Context, arg1 db.RemoveFollowUserParams) error {
m.ctrl.T.Helper()

View File

@ -14,6 +14,7 @@ type Store interface {
GetImagesByLocation(ctx context.Context, arg GetImagesByLocationParams) ([]GetImagesByLocationRow, error)
GetLocation(ctx context.Context, location_id int32) (GetLocationRow, error)
GetUser(ctx context.Context, username string) (GetUserRow, error)
GetUserStats(ctx context.Context, user_id int32) (GetUserStatsRow, error)
CreateReview(ctx context.Context, arg CreateReviewParams) (Review, error)
GetListLocationReviews(ctx context.Context, arg GetListLocationReviewsParams) ([]GetListLocationReviewsRow, error)
CreateLocation(ctx context.Context, arg CreateLocationParams) (int32, error)

View File

@ -3,11 +3,13 @@ package db
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"github.com/sqlc-dev/pqtype"
)
const getUser = `-- name: GetUser :one
const getUserQ = `-- name: GetUser :one
SELECT
id,
COALESCE(email, '') as email,
@ -43,7 +45,7 @@ type GetUserRow struct {
}
func (q *Queries) GetUser(ctx context.Context, username string) (GetUserRow, error) {
row := q.db.QueryRowContext(ctx, getUser, username)
row := q.db.QueryRowContext(ctx, getUserQ, username)
var i GetUserRow
err := row.Scan(
&i.ID,
@ -62,3 +64,74 @@ func (q *Queries) GetUser(ctx context.Context, username string) (GetUserRow, err
)
return i, err
}
const getUserStatsQ = `
SELECT
json_agg(ur.*) AS reviews,
( SELECT COUNT(id) FROM user_follow u WHERE u.followee_id = $1) as followers,
( SELECT COUNT(id) FROM reviews r WHERE r.submitted_by = $1 ) as score_count,
( SELECT
json_agg(r1.*) AS scores_distribution
FROM
(
SELECT
*
FROM
( SELECT COUNT(id) as "0" FROM reviews r WHERE r.score >= 0 AND r.score <= 9 AND r.submitted_by = $1) as score0,
( SELECT COUNT(id) as "1" FROM reviews r WHERE r.score >= 10 AND r.score <= 19 AND r.submitted_by = $1) as score1,
( SELECT COUNT(id) as "2" FROM reviews r WHERE r.score >= 20 AND r.score <= 29 AND r.submitted_by = $1) as score2,
( SELECT COUNT(id) as "3" FROM reviews r WHERE r.score >= 30 AND r.score <= 39 AND r.submitted_by = $1) as score3,
( SELECT COUNT(id) as "4" FROM reviews r WHERE r.score >= 40 AND r.score <= 49 AND r.submitted_by = $1) as score4,
( SELECT COUNT(id) as "5" FROM reviews r WHERE r.score >= 50 AND r.score <= 59 AND r.submitted_by = $1) as score5,
( SELECT COUNT(id) as "6" FROM reviews r WHERE r.score >= 60 AND r.score <= 69 AND r.submitted_by = $1) as score6,
( SELECT COUNT(id) as "7" FROM reviews r WHERE r.score >= 70 AND r.score <= 79 AND r.submitted_by = $1) as score7,
( SELECT COUNT(id) as "8" FROM reviews r WHERE r.score >= 80 AND r.score <= 89 AND r.submitted_by = $1) as score8,
( SELECT COUNT(id) as "9" FROM reviews r WHERE r.score >= 90 AND r.score <= 99 AND r.submitted_by = $1) as score9,
( SELECT COUNT(id) as "99" FROM reviews r WHERE r.score = 100 AND r.submitted_by = $1) as score10
) r1
)
FROM (
SELECT
reviews.id,
reviews.comments,
score,
l.name,
p.province_name,
COALESCE(l.thumbnail, '') as thumbnail
FROM
reviews
JOIN locations l on reviews.location_id = l.id
JOIN regencies r on l.regency_id = r.id
JOIN provinces p on r.province_id = p.id
WHERE reviews.submitted_by = $1
ORDER BY score ASC
LIMIT 10
) ur
`
type GetUserStatsRow struct {
Reviews []byte `json:"-"`
Followers int32 `json:"followers"`
ScoreCount int32 `json:"score_count"`
ScoresDistribution []byte `json:"-"`
}
func (q *Queries) GetUserStats(ctx context.Context, user_id int32) (GetUserStatsRow, error) {
var i GetUserStatsRow
row := q.db.QueryRowContext(ctx, getUserStatsQ, user_id)
err := row.Scan(
&i.Reviews,
&i.Followers,
&i.ScoreCount,
&i.ScoresDistribution,
)
var r []map[string]any
err = json.Unmarshal(i.ScoresDistribution, &r)
fmt.Println(r)
return i, err
}