diff options
Diffstat (limited to 'src/plugins/reviewDB/components/ReviewsView.tsx')
-rw-r--r-- | src/plugins/reviewDB/components/ReviewsView.tsx | 179 |
1 files changed, 108 insertions, 71 deletions
diff --git a/src/plugins/reviewDB/components/ReviewsView.tsx b/src/plugins/reviewDB/components/ReviewsView.tsx index ff46cca..bd264fa 100644 --- a/src/plugins/reviewDB/components/ReviewsView.tsx +++ b/src/plugins/reviewDB/components/ReviewsView.tsx @@ -16,42 +16,113 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { Settings } from "@api/Settings"; import { classes } from "@utils/misc"; -import { useAwaiter } from "@utils/react"; +import { useAwaiter, useForceUpdater } from "@utils/react"; import { findByPropsLazy } from "@webpack"; -import { Forms, React, Text, UserStore } from "@webpack/common"; +import { Forms, React, UserStore } from "@webpack/common"; import type { KeyboardEvent } from "react"; -import { addReview, getReviews } from "../Utils/ReviewDBAPI"; -import { authorize, showToast } from "../Utils/Utils"; +import { Review } from "../entities"; +import { addReview, getReviews, Response, REVIEWS_PER_PAGE } from "../reviewDbApi"; +import { settings } from "../settings"; +import { authorize, cl, showToast } from "../utils"; import ReviewComponent from "./ReviewComponent"; const Classes = findByPropsLazy("inputDefault", "editable"); -export default function ReviewsView({ userId }: { userId: string; }) { - const { token } = Settings.plugins.ReviewDB; - const [refetchCount, setRefetchCount] = React.useState(0); - const [reviews, _, isLoading] = useAwaiter(() => getReviews(userId), { - fallbackValue: [], - deps: [refetchCount], +interface UserProps { + discordId: string; + name: string; +} + +interface Props extends UserProps { + onFetchReviews(data: Response): void; + refetchSignal?: unknown; + showInput?: boolean; + page?: number; + scrollToTop?(): void; + hideOwnReview?: boolean; +} + +export default function ReviewsView({ + discordId, + name, + onFetchReviews, + refetchSignal, + scrollToTop, + page = 1, + showInput = false, + hideOwnReview = false, +}: Props) { + const [signal, refetch] = useForceUpdater(true); + + const [reviewData] = useAwaiter(() => getReviews(discordId, (page - 1) * REVIEWS_PER_PAGE), { + fallbackValue: null, + deps: [refetchSignal, signal, page], + onSuccess: data => { + scrollToTop?.(); + onFetchReviews(data!); + } }); - const username = UserStore.getUser(userId)?.username ?? ""; - const dirtyRefetch = () => setRefetchCount(refetchCount + 1); + if (!reviewData) return null; + + return ( + <> + <ReviewList + refetch={refetch} + reviews={reviewData!.reviews} + hideOwnReview={hideOwnReview} + /> + + {showInput && ( + <ReviewsInputComponent + name={name} + discordId={discordId} + refetch={refetch} + isAuthor={reviewData!.reviews?.some(r => r.sender.discordID === UserStore.getCurrentUser().id)} + /> + )} + </> + ); +} + +function ReviewList({ refetch, reviews, hideOwnReview }: { refetch(): void; reviews: Review[]; hideOwnReview: boolean; }) { + const myId = UserStore.getCurrentUser().id; + + return ( + <div className={cl("view")}> + {reviews?.map(review => + (review.sender.discordID !== myId || !hideOwnReview) && + <ReviewComponent + key={review.id} + review={review} + refetch={refetch} + /> + )} + + {reviews?.length === 0 && ( + <Forms.FormText className={cl("placeholder")}> + Looks like nobody reviewed this user yet. You could be the first! + </Forms.FormText> + )} + </div> + ); +} - if (isLoading) return null; +export function ReviewsInputComponent({ discordId, isAuthor, refetch, name }: { discordId: string, name: string; isAuthor: boolean; refetch(): void; }) { + const { token } = settings.store; function onKeyPress({ key, target }: KeyboardEvent<HTMLTextAreaElement>) { if (key === "Enter") { addReview({ - userid: userId, + userid: discordId, comment: (target as HTMLInputElement).value, star: -1 }).then(res => { if (res?.success) { (target as HTMLInputElement).value = ""; // clear the input - dirtyRefetch(); + refetch(); } else if (res?.message) { showToast(res.message); } @@ -60,61 +131,27 @@ export default function ReviewsView({ userId }: { userId: string; }) { } return ( - <div className="vc-reviewdb-view"> - <Text - tag="h2" - variant="eyebrow" - style={{ - marginBottom: "8px", - color: "var(--header-primary)" - }} - > - User Reviews - </Text> - {reviews?.map(review => - <ReviewComponent - key={review.id} - review={review} - refetch={dirtyRefetch} - /> - )} - {reviews?.length === 0 && ( - <Forms.FormText style={{ paddingRight: "12px", paddingTop: "0px", paddingLeft: "0px", paddingBottom: "4px", fontWeight: "bold", fontStyle: "italic" }}> - Looks like nobody reviewed this user yet. You could be the first! - </Forms.FormText> - )} - <textarea - className={classes(Classes.inputDefault, "enter-comment")} - onKeyDownCapture={e => { - if (e.key === "Enter") { - e.preventDefault(); // prevent newlines - } - }} - placeholder={ - token - ? (reviews?.some(r => r.sender.discordID === UserStore.getCurrentUser().id) - ? `Update review for @${username}` - : `Review @${username}`) - : "You need to authorize to review users!" + <textarea + className={classes(Classes.inputDefault, "enter-comment", cl("input"))} + onKeyDownCapture={e => { + if (e.key === "Enter") { + e.preventDefault(); // prevent newlines } - onKeyDown={onKeyPress} - onClick={() => { - if (!token) { - showToast("Opening authorization window..."); - authorize(); - } - }} - - style={{ - marginTop: "6px", - resize: "none", - marginBottom: "12px", - overflow: "hidden", - background: "transparent", - border: "1px solid var(--profile-message-input-border-color)", - fontSize: "14px", - }} - /> - </div> + }} + placeholder={ + !token + ? "You need to authorize to review users!" + : isAuthor + ? `Update review for @${name}` + : `Review @${name}` + } + onKeyDown={onKeyPress} + onClick={() => { + if (!token) { + showToast("Opening authorization window..."); + authorize(); + } + }} + /> ); } |