From 164dd0f2827a90c0937e7e8acb1f8ba4c6368751 Mon Sep 17 00:00:00 2001 From: heimoshuiyu Date: Mon, 13 Dec 2021 06:18:14 +0800 Subject: [PATCH] Add: show reviews created by user --- pkg/api/api.go | 1 + pkg/api/handle_user.go | 25 ++++++++++++++++ pkg/database/method_review.go | 32 ++++++++++++++++++++ pkg/database/sql_stmt.go | 18 +++++++++++ web/src/App.js | 5 ++++ web/src/component/ReviewEntry.js | 30 +++++++++++++++++++ web/src/component/ReviewPage.js | 26 ++-------------- web/src/component/UserProfile.js | 51 ++++++++++++++++++++++++++++++++ 8 files changed, 165 insertions(+), 23 deletions(-) create mode 100644 web/src/component/ReviewEntry.js create mode 100644 web/src/component/UserProfile.js diff --git a/pkg/api/api.go b/pkg/api/api.go index ceafb0c..cc81fdc 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -98,6 +98,7 @@ func NewAPI(config Config) (*API, error) { apiMux.HandleFunc("/get_review", api.HandleGetReview) apiMux.HandleFunc("/update_review", api.HandleUpdateReview) apiMux.HandleFunc("/delete_review", api.HandleDeleteReview) + apiMux.HandleFunc("/get_reviews_by_user", api.HandleGetReviewsByUser) // below needs token apiMux.HandleFunc("/walk", api.HandleWalk) apiMux.HandleFunc("/reset", api.HandleReset) diff --git a/pkg/api/handle_user.go b/pkg/api/handle_user.go index 105974a..0fd8751 100644 --- a/pkg/api/handle_user.go +++ b/pkg/api/handle_user.go @@ -192,3 +192,28 @@ func (api *API) GetUserID(w http.ResponseWriter, r *http.Request) (int64, error) return userId.(int64), nil } + +type GetReviewsByUserRequest struct { + ID int64 `json:"id"` +} + +func (api *API) HandleGetReviewsByUser(w http.ResponseWriter, r *http.Request) { + req := &GetReviewsByUserRequest{} + err := json.NewDecoder(r.Body).Decode(req) + if err != nil { + api.HandleError(w, r, err) + return + } + + reviews, err := api.Db.GetReviewsByUser(req.ID) + if err != nil { + api.HandleError(w, r, err) + return + } + + err = json.NewEncoder(w).Encode(reviews) + if err != nil { + api.HandleError(w, r, err) + return + } +} diff --git a/pkg/database/method_review.go b/pkg/database/method_review.go index f6d29c9..748e3f7 100644 --- a/pkg/database/method_review.go +++ b/pkg/database/method_review.go @@ -71,3 +71,35 @@ func (database *Database) DeleteReview(reviewId int64) error { _, err := database.stmt.deleteReview.Exec(reviewId) return err } + +func (database *Database) GetReviewsByUser(userId int64) ([]*Review, error) { + rows, err := database.stmt.getReviewsByUser.Query(userId) + if err != nil { + return nil, err + } + defer rows.Close() + + reviews := make([]*Review, 0) + for rows.Next() { + review := &Review{ + User: &User{}, + File: &File{}, + } + err := rows.Scan( + &review.ID, + &review.CreatedAt, + &review.UpdatedAt, + &review.Content, + &review.User.ID, + &review.User.Username, + &review.User.Role, + &review.User.AvatarId, + &review.File.ID, + &review.File.Filename) + if err != nil { + return nil, err + } + reviews = append(reviews, review) + } + return reviews, nil +} diff --git a/pkg/database/sql_stmt.go b/pkg/database/sql_stmt.go index da3f0cd..0afbbb0 100644 --- a/pkg/database/sql_stmt.go +++ b/pkg/database/sql_stmt.go @@ -224,6 +224,17 @@ var updateReviewQuery = `UPDATE reviews SET content = ?, updated_at = ? WHERE id var deleteReviewQuery = `DELETE FROM reviews WHERE id = ?;` +var getReviewsByUserQuery = `SELECT +reviews.id, reviews.created_at, reviews.updated_at, reviews.content, +users.id, users.username, users.role, users.avatar_id, +files.id, files.filename +FROM reviews +JOIN users ON reviews.user_id = users.id +JOIN files ON reviews.file_id = files.id +WHERE reviews.user_id = ? +ORDER BY reviews.created_at +;` + type Stmt struct { initFilesTable *sql.Stmt initFoldersTable *sql.Stmt @@ -269,6 +280,7 @@ type Stmt struct { getReview *sql.Stmt updateReview *sql.Stmt deleteReview *sql.Stmt + getReviewsByUser *sql.Stmt } func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) { @@ -603,5 +615,11 @@ func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) { return nil, err } + // init getReviewsByUser + stmt.getReviewsByUser, err = sqlConn.Prepare(getReviewsByUserQuery) + if err != nil { + return nil, err + } + return stmt, err } diff --git a/web/src/App.js b/web/src/App.js index 0129e5f..2b79f9c 100644 --- a/web/src/App.js +++ b/web/src/App.js @@ -16,6 +16,7 @@ import EditReview from "./component/EditReview"; import AudioPlayer from "./component/AudioPlayer"; import UserStatus from "./component/UserStatus"; import ReviewPage from "./component/ReviewPage"; +import UserProfile from "./component/UserProfile"; import { useState } from "react"; function App() { @@ -88,6 +89,10 @@ function App() { path="/manage/reviews/:id" element={} /> + } + /> } diff --git a/web/src/component/ReviewEntry.js b/web/src/component/ReviewEntry.js new file mode 100644 index 0000000..b5cf648 --- /dev/null +++ b/web/src/component/ReviewEntry.js @@ -0,0 +1,30 @@ +import { Link } from "react-router-dom"; +import { useNavigate } from "react-router"; +import { convertIntToDateTime } from "./Common"; + +function ReviewEntry(props) { + let navigate = useNavigate(); + return ( +
+

+ + @{props.review.user.username} + {" "} + wrote on {convertIntToDateTime(props.review.created_at)}{" "} +

+

{props.review.content}

+ {(props.user.role === 1 || props.review.user.id === props.user.id) && + props.user.role != 0 && ( + + )} +
+ ); +} + +export default ReviewEntry; diff --git a/web/src/component/ReviewPage.js b/web/src/component/ReviewPage.js index 817bf05..fba6bf2 100644 --- a/web/src/component/ReviewPage.js +++ b/web/src/component/ReviewPage.js @@ -1,11 +1,9 @@ import { useState, useEffect } from "react"; -import { useParams, useNavigate } from "react-router"; -import { Link } from "react-router-dom"; -import { convertIntToDateTime } from "./Common"; +import { useParams } from "react-router"; +import ReviewEntry from "./ReviewEntry"; function ReviewPage(props) { let params = useParams(); - let navigate = useNavigate(); const [newReview, setNewReview] = useState(""); const [reviews, setReviews] = useState([]); @@ -60,25 +58,7 @@ function ReviewPage(props) {

Review Page

{reviews.map((review) => ( -
-

- - @{review.user.username} - {" "} - wrote on {convertIntToDateTime(review.created_at)}{" "} -

-

{review.content}

- {(props.user.role === 1 || review.user.id === props.user.id) && - props.user.role != 0 && ( - - )} -
+ ))}
diff --git a/web/src/component/UserProfile.js b/web/src/component/UserProfile.js new file mode 100644 index 0000000..96ad64f --- /dev/null +++ b/web/src/component/UserProfile.js @@ -0,0 +1,51 @@ +import { useState, useEffect } from "react"; +import { useParams } from "react-router"; +import ReviewEntry from "./ReviewEntry"; + +function UserProfile(props) { + let params = useParams(); + const [reviews, setReviews] = useState([]); + + function getReviews() { + fetch("/api/v1/get_reviews_by_user", { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify({ + id: parseInt(params.id), + }), + }) + .then((response) => response.json()) + .then((data) => { + if (data.error) { + alert(data.error); + } else { + setReviews(data); + } + }); + } + + useEffect(() => { + getReviews(); + }, []); + + return ( +
+

User Profile

+
+

Reviews

+ {reviews.map((review) => ( + + ))} +
+
+ ); +} + +export default UserProfile;