Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/app/(home)/books/library/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ const Booklibrary: React.FC = () => {
<BookImageCover
title={book?.title}
imageURL={book?.reviewImageURL}
totalScore={book?.totalScore}
ratingArr={book?.scoreRatings?.rating}
raterArr={book?.scoreRatings?.raterId}
hideScores={handleHideScores_NoSetter(
book?.actualDateOfMeeting,
)}
/>
</Link>
) : (
Expand Down
95 changes: 27 additions & 68 deletions src/components/books/library/BookCover.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
"use client"

import { useJwt } from "react-jwt"
import useUserFetch from "@/hooks/fetch-hooks/useUserFetch"
import { useAppSelector } from "@/store/lib/hooks"
import { config } from "@/configs/config"
import Image from "next/image"
import { useState } from "react"
import BookRatingsBox from "./BookRatingsBox"

type Props = {
title: string
Expand All @@ -25,89 +23,50 @@ const BookCover: React.FC<Props> = ({
isSingleBook,
imageURL,
}) => {
const token = useAppSelector((state) => state.token.tokenState)
const { decodedToken }: { decodedToken?: { username: string; _id: string } } =
useJwt(token)
const username = decodedToken?.username
const [isLoading, setIsLoading] = useState<boolean>(true)

const { userData, loadingUsers, error } = useUserFetch(
`${config.API_URL}/users`,
null,
)

const findUser = (id) => {
const user = userData?.find((user) => user._id === id)
return user ? user.username : "user not found"
}

const raterArr2 = raterArr?.map((id) => findUser(id))

let raterObj: object = {}
const findBookScore = () => {
if (raterArr2) {
for (let i = 0; i < raterArr2.length; i++) {
raterObj[raterArr2[i]] = ratingArr[i]
findUser(raterObj[raterArr[i]])
}
raterObj = Object.entries(raterObj)
return raterObj
}
}
findBookScore()
return (
<>
<div
className={
isSingleBook
? "w-[600px] h-[400px] border-2 border-[var(--default-border-color)] flex justify-center text-center items-center border-solid m-5 max-md:w-[275px] max-md:h-[350px]"
? "w-[600px] h-[400px] border-2 border-[var(--default-border-color)] flex justify-center text-center items-center border-solid m-5 max-md:mx-0 max-sm:h-full max-sm:w-full"
: "flex justify-center items-center text-center border-5 border-solid border-[var(--default-border-color)] h-63 aspect-[1.55/1] max-xs:w-75"
}
>
<div className="flex h-full w-full">
{imageURL.length ? (
<div className="leftcover w-[45%] max-sm:w-[60%]">
{isLoading && (
<div className="leftcover flex w-[45%] flex-col items-center justify-center bg-black text-white">
<h2 className="font-main text-2xl max-md:text-base">{title}</h2>
<h2 className="font-main text-2xl max-md:text-base">
(Image pending)
</h2>
</div>
)}
{imageURL && (
<div className="w-[45%] max-sm:w-[60%]">
<Image
key={imageURL}
src={imageURL}
width={500}
height={500}
alt={title}
className="w-fit h-full"
className={
isSingleBook
? "w-full h-100 max-sm:h-65"
: "h-60 w-50 max-sm:w-fit"
}
style={{ display: isLoading ? "hidden" : "block" }}
onLoad={() => setIsLoading(false)}
/>
</div>
) : (
<div className="leftcover flex w-[45%] flex-col items-center justify-center bg-black text-white">
<h2 className="font-main text-2xl max-md:text-base">{title}</h2>
<h2 className="font-main text-2xl max-md:text-base">
(Image pending)
</h2>
</div>
)}
<div className="flex flex-col items-start font-main text-xl ml-2 max-md:text-base">
<h2 className="underline mb-5">Book Club Brothers</h2>

{Array.isArray(raterObj) && !loadingUsers ? (
raterObj.map(([name, value]) => (
<li className="list-none mb-1 ml-2" key={name}>
{name}:{" "}
{hideScores && username !== name ? "?" : value.toFixed(2)}
</li>
))
) : error ? (
<li>{error?.message}</li>
) : (
<li className="list-none mb-1 ml-2">Score Pending...</li>
)}

<li className="list-none mt-auto font-bold">
Group Rating:{" "}
{totalScore
? hideScores
? "?"
: Math.floor(totalScore * 100) / 100
: "Pending..."}
</li>
</div>
<BookRatingsBox
totalScore={totalScore}
ratingArr={ratingArr}
raterArr={raterArr}
hideScores={hideScores}
/>
</div>
</div>
</>
Expand Down
52 changes: 42 additions & 10 deletions src/components/books/library/BookImageCover.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,53 @@
import Image from "next/image"
import BookRatingsBox from "./BookRatingsBox"

type Props = {
title?: string
imageURL: string
totalScore: number
ratingArr: number[] | number
raterArr: string[]
hideScores: boolean
isSingleBook?: boolean
}

const BookImageCover: React.FC<Props> = ({ title, imageURL }) => {
const BookImageCover: React.FC<Props> = ({
title,
imageURL,
totalScore,
ratingArr,
raterArr,
hideScores,
isSingleBook,
}) => {
return (
<>
<Image
src={imageURL}
alt={title}
className="border-[var(--default-border-color)] border-5 border-solid h-63 aspect-[1.55/1] max-xs:w-75 max-xs:aspect-auto max-xs:h-63"
width={252 * 1.55}
height={252}
/>
</>
<div
className={
isSingleBook
? "w-[600px] h-[400px] border-2 border-[var(--default-border-color)] flex justify-center text-center items-center border-solid m-5 max-md:mx-0 max-sm:h-full max-sm:w-full"
: "flex justify-center items-center text-center border-5 border-solid border-[var(--default-border-color)] h-63 aspect-[1.55/1] max-xs:w-75"
}
>
<div className="w-[45%] max-sm:w-[60%]">
<Image
src={imageURL}
alt={title}
width={500}
height={500}
className={
isSingleBook ? "w-full h-99 max-sm:h-65" : "h-60 w-50 max-sm:w-fit"
}
/>
</div>
<div className="bg-[var(--main-bg-color)] h-[calc(100%-8px)] flex w-[55%] max-sm:[40%] justify-center">
<BookRatingsBox
totalScore={totalScore}
ratingArr={ratingArr}
raterArr={raterArr}
hideScores={hideScores}
/>
</div>
</div>
)
}

Expand Down
74 changes: 74 additions & 0 deletions src/components/books/library/BookRatingsBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { config } from "@/configs/config"
import useUserFetch from "@/hooks/fetch-hooks/useUserFetch"
import { useAppSelector } from "@/store/lib/hooks"
import React, { memo, useMemo } from "react"
import { useJwt } from "react-jwt"

type Props = {
totalScore: number
ratingArr: number[] | number
raterArr: string[]
hideScores: boolean
}

const BookRatingsBox = ({
totalScore,
ratingArr,
raterArr,
hideScores,
}: Props) => {
const token = useAppSelector((state) => state.token.tokenState)
const { decodedToken }: { decodedToken?: { username: string; _id: string } } =
useJwt(token)
const username = decodedToken?.username

const { userData, loadingUsers, error } = useUserFetch(
`${config.API_URL}/users`,
null,
)

const formattedRatings = useMemo(() => {
if (!userData || !raterArr || !Array.isArray(ratingArr)) return []

const userLookup = userData.reduce(
(acc, user) => {
acc[user._id] = user.username
return acc
},
{} as Record<string, string>,
)

return raterArr.map((id, index) => ({
name: userLookup[id] || "User not found",
score: Array.isArray(ratingArr) ? ratingArr[index] : 0,
}))
}, [userData, raterArr, ratingArr])
return (
<div className="flex flex-col items-start font-main text-xl ml-2 max-md:text-base max-sm:h-65">
<h2 className="underline mb-5">Book Club Brothers</h2>

{!loadingUsers && formattedRatings.length > 0 ? (
formattedRatings.map(({ name, score }) => (
<li className="list-none mb-1 ml-2" key={name}>
{name}: {hideScores && username !== name ? "?" : score.toFixed(2)}
</li>
))
) : error ? (
<li>{error?.message}</li>
) : (
<li className="list-none mb-1 ml-2">Score Pending...</li>
)}

<li className="list-none mt-auto font-bold">
Group Rating:{" "}
{totalScore
? hideScores
? "?"
: Math.floor(totalScore * 100) / 100
: "Pending..."}
</li>
</div>
)
}

export default BookRatingsBox
17 changes: 11 additions & 6 deletions src/components/books/library/single-book/AdminViewLeftSide.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Profile from "@/components/misc/profile/Profile"
import useSingleUserFetch from "@/hooks/fetch-hooks/useSingleUserFetch"
import Image from "next/image"
import { config } from "@/configs/config"
import BookImageCover from "../BookImageCover"

type Props = {
bookData: Book
Expand Down Expand Up @@ -49,12 +50,16 @@ const AdminViewSingleBook: React.FC<Props> = ({ bookData, bookId }) => {
</div>
<div>
{bookData?.reviewImageURL ? (
<Image
src={bookData?.reviewImageURL}
alt="book_review_image"
width={600}
height={400}
className="w-[600px] h-[400px] border-2 border-solid border-[var(--default-border-color)] m-5 max-md:w-[350px] max-md:h-[275px] max-sm:w-[275px] max-sm:h-[225px]"
<BookImageCover
title={bookData?.title}
imageURL={bookData?.reviewImageURL}
totalScore={bookData?.totalScore}
ratingArr={bookData?.scoreRatings?.rating}
raterArr={bookData?.scoreRatings?.raterId}
hideScores={handleHideScores_NoSetter(
bookData?.actualDateOfMeeting,
)}
isSingleBook={true}
/>
) : (
<BookCover
Expand Down
17 changes: 11 additions & 6 deletions src/components/books/library/single-book/UserViewLeftSide.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Skeleton } from "antd"
import BookSkeleton from "../BookSkeleton"
import { useAppSelector } from "@/store/lib/hooks"
import { config } from "@/configs/config"
import BookImageCover from "../BookImageCover"

type Props = {
bookData: Book
Expand Down Expand Up @@ -37,12 +38,16 @@ const UserViewLeftSide = ({ bookData }: Props) => {
</div>
<div>
{bookData?.reviewImageURL ? (
<Image
src={bookData?.reviewImageURL}
alt="book_review_image"
width={600}
height={400}
className="w-[600px] h-[400px] border-2 border-solid border-[var(--default-border-color)] m-5 max-md:w-[350px] max-md:h-[275px] max-sm:w-[275px] max-sm:h-[225px]"
<BookImageCover
title={bookData?.title}
imageURL={bookData?.reviewImageURL}
totalScore={bookData?.totalScore}
ratingArr={bookData?.scoreRatings?.rating}
raterArr={bookData?.scoreRatings?.raterId}
hideScores={handleHideScores_NoSetter(
bookData?.actualDateOfMeeting,
)}
isSingleBook={true}
/>
) : (
<BookCover
Expand Down
28 changes: 17 additions & 11 deletions src/components/books/randomiser/RandomSectionRight.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react"
import React, { useState } from "react"
import Randomiser from "./Randomiser"
import EditUnreadBook from "@/components/forms/bookform-randomise/edit/EditUnreadBook"
import DeleteBook from "@/components/forms/bookform-randomise/DeleteBook"
Expand All @@ -16,6 +16,7 @@ type Props = {
}

const RandomSectionRight: React.FC<Props> = ({ bookData, error, userData }) => {
const [isLoading, setIsLoading] = useState<boolean>(true)
const index = useAppSelector((state) => state.randomise.index)
const showRandom = useAppSelector((state) => state.randomise.showRandom)
const { decodedToken } = useAuth()
Expand All @@ -28,16 +29,21 @@ const RandomSectionRight: React.FC<Props> = ({ bookData, error, userData }) => {

return (
<div className="grid grid-rows-2 border-[var(--default-border-color)] border-5 border-solid p-2 max-md:flex max-md:flex-col max-md:p-0 max-md:border-0 relative">
{bookData && bookData[index] ? (
<Image
key={bookData[index]?._id}
src={bookData[index]?.imageURL}
width={500}
height={500}
alt={bookData[index]?.title}
className="w-full h-full absolute z-0"
/>
) : null}
{bookData && bookData[index] && (
<>
<Image
key={bookData[index]?._id}
src={bookData[index]?.imageURL}
width={500}
height={500}
alt={bookData[index]?.title}
className="w-full h-full absolute z-0"
style={{ display: isLoading ? "hidden" : "block" }}
onLoad={() => setIsLoading(false)}
/>
<div className="w-full h-full absolute z-[-1] bg-[var(--tertiaryColor)]" />
</>
)}
{!bookData ? (
<>
<div className="bg-[var(--main-bg-color)] font-main flex flex-col justify-center items-center border-[var(--default-border-color)] border-5 border-solid h-[400px] max-md:justify-start max-md:h-[300px] max-md:m-8 gap-5">
Expand Down
Loading
Loading