Skip to content

Commit

Permalink
Implementing review
Browse files Browse the repository at this point in the history
  • Loading branch information
raphaelcordon committed Nov 26, 2024
1 parent 64a59f4 commit 39c1629
Show file tree
Hide file tree
Showing 17 changed files with 463 additions and 40 deletions.
4 changes: 3 additions & 1 deletion src/axios/reviewAxios.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ const getAxiosConfig = () => {

export const Create = async (data) => {
try {
await axios.post("review", data);
const config = getAxiosConfig();
const res = await axios.post("review", data, config);
return res;
} catch (error) {
console.log('Registration error response:', error.response);
throw new Error("Fail, please try again");
Expand Down
11 changes: 7 additions & 4 deletions src/components/Main/MainAlbumsComponent.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {useSelector} from "react-redux";
import useGetReview from "../../hooks/useGetReview.jsx";
import useGetReview from "../../hooks/useGetReviews.jsx";
import {useEffect, useState} from "react";
import ReviewCardComponent from "../review/reviewCardComponent.jsx";
import LoaderComponent from "../Common/LoaderComponent.jsx";
import {NavLink} from "react-router-dom";

const MainAlbumsComponent = () => {
const review = useSelector((state) => state.reviewAlbum.reviewAlbumData);
Expand Down Expand Up @@ -35,9 +36,11 @@ const MainAlbumsComponent = () => {
?.slice()
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
.map((item) => (
<div key={item.id}>
<ReviewCardComponent review={item}/>
</div>
<NavLink to={`/review/${item.id}`} key={item.id}>
<div className="">
<ReviewCardComponent review={item} />
</div>
</NavLink>
))}
{review.items.length < review.totalCount && (
<div className="w-full flex items-center justify-center m-4">
Expand Down
11 changes: 7 additions & 4 deletions src/components/Main/MainArtistsComponent.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useEffect, useState } from "react";
import ReviewCardComponent from "../review/reviewCardComponent.jsx";
import { useSelector } from "react-redux";
import useGetReview from "../../hooks/useGetReview.jsx";
import useGetReview from "../../hooks/useGetReviews.jsx";
import LoaderComponent from "../Common/LoaderComponent.jsx";
import {NavLink} from "react-router-dom";

const MainArtistsComponent = () => {
const review = useSelector((state) => state.reviewArtist.reviewArtistData);
Expand Down Expand Up @@ -35,9 +36,11 @@ const MainArtistsComponent = () => {
?.slice()
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
.map((item) => (
<div key={item.id}>
<ReviewCardComponent review={item} />
</div>
<NavLink to={`/review/${item.id}`} key={item.id}>
<div>
<ReviewCardComponent review={item} />
</div>
</NavLink>
))}
{review.items.length < review.totalCount && (
<div className="w-full flex items-center justify-center m-4">
Expand Down
11 changes: 7 additions & 4 deletions src/components/Main/MainTracksComponent.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {useSelector} from "react-redux";
import useGetReview from "../../hooks/useGetReview.jsx";
import useGetReview from "../../hooks/useGetReviews.jsx";
import {useEffect, useState} from "react";
import ReviewCardComponent from "../review/reviewCardComponent.jsx";
import LoaderComponent from "../Common/LoaderComponent.jsx";
import {NavLink} from "react-router-dom";

const MainTracksComponent = () => {
const review = useSelector((state) => state.reviewTrack.reviewTrackData);
Expand Down Expand Up @@ -35,9 +36,11 @@ const MainTracksComponent = () => {
?.slice()
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
.map((item) => (
<div key={item.id}>
<ReviewCardComponent review={item}/>
</div>
<NavLink to={`/review/${item.id}`} key={item.id}>
<div>
<ReviewCardComponent review={item} />
</div>
</NavLink>
))}
{review.items.length < review.totalCount && (
<div className="w-full flex items-center justify-center m-4">
Expand Down
1 change: 0 additions & 1 deletion src/components/NavBar/UserMenuComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ const UserMenuComponent = () => {
window.localStorage.removeItem("resenhando:authToken");
navigate("/");
};

return (
<div className="h-full w-full flex justify-end">
{!token || !user ? (
Expand Down
100 changes: 100 additions & 0 deletions src/components/review/ReviewReadArtist.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// import {useLocation, useNavigate} from "react-router-dom";
// import ButtonSubmitDefault from "../Buttons/ButtonSubmitDefault.jsx";
// import {useEffect, useState} from "react";
// import {useSelector} from "react-redux";
// import useCreateReview from "../../hooks/useCreateReview.jsx";
//
// const ReviewReadArtist = ({ reviewId }) => {
// const [reviewTitle, setReviewTitle] = useState('');
// const [reviewBody, setReviewBody] = useState('');
// const [spotifyId, setSpotifyId] = useState('');
// const [name, setName] = useState('');
// const [coverImage, setCoverImage] = useState('');
//
// const userId = useSelector((state) => state.user.userData);
// const reviews = useSelector((state) => state.reviewArtistData.items);
// const review = reviews.find((review) => review.id === reviewId);
//
// useEffect(() => {
// if (review) {
// setReviewTitle(review.title || '');
// setReviewBody(review.body || '');
// setSpotifyId(review.spotifyId || '');
// setName(review.name || '');
// setCoverImage(review.coverImage || '');
// }
// }, [review]);
//
// const [errorReview, setErrorReview] = useState("");
// const [isLoading, setIsLoading] = useState(false);
// const navigate = useNavigate();
// const location = useLocation();
//
// const to = location.state?.from || "/artists";
//
// const getSubmitData = async (e) => {
// e.preventDefault();
// setErrorReview("");
// setIsLoading(true);
// try {
// const data = { spotifyId, coverImage, reviewTitle, reviewBody, reviewType ,userId };
// const res = await createReview(data);
// if (res === 200)
// navigate(to);
// } catch (error) {
// setErrorReview(error.message || "Failed to register. Please try again.");
// } finally {
// setIsLoading(false);
// }
// };
//
// return (
// <div className="flex flex-col justify-start pt-6 items-center min-h-[60vh]">
//
// <div className="max-w-lg w-[95vw] p-6">
// <h2 className="text-xl font-semibold text-start mt-2 mb-2">A new review about: "{item.name}"</h2>
// <form onSubmit={getSubmitData}>
// <div className="mb-4">
// <label htmlFor="reviewTitle" className="block mb-2 text-sm text-accent-content">
// Review title
// </label>
// <input
// name="reviewTitle"
// id="reviewTitle"
// type="text"
// value={reviewTitle}
// onChange={(e) => setReviewTitle(e.target.value)}
// required
// className="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-secondary"
// />
// </div>
// <div className="mb-2">
// <label htmlFor="reviewBody" className="block mb-2 text-sm text-accent-content">
// Review (accepts HTML)
// </label>
// <textarea
// name="reviewBody"
// id="reviewBody"
// value={reviewBody}
// onChange={(e) => setReviewBody(e.target.value)}
// required
// rows={5}
// className="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-secondary"
// />
// </div>
//
// <div className="text-center">
// {errorReview && <p className="text-error text-sm mt-2">{errorReview}</p>}
// <ButtonSubmitDefault
// buttonName={isLoading ? "Sending review..." : "Send the review"}
// type="submit"
// disabled={isLoading || reviewTitle === "" || reviewBody === ""}
// />
// </div>
// </form>
// {error && <p className="text-error text-sm mt-2">{error}</p>}
// </div>
// </div>
// )
// }
// export default ReviewReadArtist;
90 changes: 90 additions & 0 deletions src/components/review/ReviewWriteArtist.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import {useLocation, useNavigate} from "react-router-dom";
import ButtonSubmitDefault from "../Buttons/ButtonSubmitDefault.jsx";
import {useState} from "react";
import {useSelector} from "react-redux";
import useCreateReview from "../../hooks/useCreateReview.jsx";

const ReviewWriteArtist = ({ item }) => {
const [reviewTitle, setReviewTitle] = useState('');
const [reviewBody, setReviewBody] = useState('');
const spotifyId = item.id;
const name = item.name;
const image = item.images?.[0];
const coverImage = image?.url;
const userId = useSelector((state) => state.user.userData).id;
const reviewType = 0; // Artist = 0

const { createReview, error } = useCreateReview();
const [errorReview, setErrorReview] = useState("");
const [isLoading, setIsLoading] = useState(false);
const navigate = useNavigate();
const location = useLocation();

const to = location.state?.from || "/artists";

const getSubmitData = async (e) => {
e.preventDefault();
setErrorReview("");
setIsLoading(true);
try {
const data = { spotifyId, coverImage, reviewTitle, reviewBody, reviewType ,userId };
const res = await createReview(data);
if (res === 200)
navigate(to);
} catch (error) {
setErrorReview(error.message || "Failed to register. Please try again.");
} finally {
setIsLoading(false);
}
};

return (
<div className="flex flex-col justify-start pt-6 items-center min-h-[60vh]">

<div className="max-w-lg w-[95vw] p-6">
<h2 className="text-xl font-semibold text-start mt-2 mb-2">A new review about: "{item.name}"</h2>
<form onSubmit={getSubmitData}>
<div className="mb-4">
<label htmlFor="reviewTitle" className="block mb-2 text-sm text-accent-content">
Review title
</label>
<input
name="reviewTitle"
id="reviewTitle"
type="text"
value={reviewTitle}
onChange={(e) => setReviewTitle(e.target.value)}
required
className="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-secondary"
/>
</div>
<div className="mb-2">
<label htmlFor="reviewBody" className="block mb-2 text-sm text-accent-content">
Review (accepts HTML)
</label>
<textarea
name="reviewBody"
id="reviewBody"
value={reviewBody}
onChange={(e) => setReviewBody(e.target.value)}
required
rows={5}
className="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-secondary"
/>
</div>

<div className="text-center">
{errorReview && <p className="text-error text-sm mt-2">{errorReview}</p>}
<ButtonSubmitDefault
buttonName={isLoading ? "Sending review..." : "Send the review"}
type="submit"
disabled={isLoading || reviewTitle === "" || reviewBody === ""}
/>
</div>
</form>
{error && <p className="text-error text-sm mt-2">{error}</p>}
</div>
</div>
)
}
export default ReviewWriteArtist;
17 changes: 14 additions & 3 deletions src/components/review/reviewArtistDetailed.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import ButtonCreateReview from "../Buttons/ButtonCreateReview.jsx";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCircleDown } from '@fortawesome/free-solid-svg-icons';
import {Link, NavLink} from "react-router-dom";
import ReviewWriteArtist from "./ReviewWriteArtist.jsx";
import {useState} from "react";


const ReviewArtistDetailed = ({ item }) => {
Expand All @@ -12,7 +13,16 @@ const ReviewArtistDetailed = ({ item }) => {

const externalUrl = item.externalUrls.spotify;
const radio = `${externalUrl.substring(0, 25)}embed/${externalUrl.substring(25, externalUrl.length)}`;


const [writingReview, setWritingReview] = useState(false);
const handleStartReview = () => {
setWritingReview(true);
};

if (writingReview) {
return <ReviewWriteArtist item={item} />;
}

const truncateText = (text, limit) =>
text.length > limit ? `${text.substring(0, limit)}...` : text;

Expand Down Expand Up @@ -57,7 +67,8 @@ const ReviewArtistDetailed = ({ item }) => {

{/* Button Create Review */}
<div className="w-full mt-4 flex justify-center" id="createArtistReview">
<ButtonCreateReview buttonName={`Write a review about ${truncateText(name, 20)}`} />
<ButtonCreateReview buttonName={`Write a review about ${truncateText(name, 20)}`}
onClick={handleStartReview}/>
</div>

{/* Text block */}
Expand Down
2 changes: 1 addition & 1 deletion src/components/review/reviewCardComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const ReviewCardComponent = ({ review }) => {
text.length > limit ? `${text.substring(0, limit)}...` : text;

return (
<div className="w-full lg:w-72 shadow m-0">
<div className="w-full lg:w-72 shadow m-0 hover:opacity-60">
<div className="w-full">
<img src={coverImage} alt={reviewTitle} className="w-full lg:h-72 object-cover block"/>
</div>
Expand Down
45 changes: 45 additions & 0 deletions src/hooks/useCreateReview.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {useDispatch} from "react-redux";
import {useCallback, useState} from "react";
import {storeReviewArtistData} from "../store/slices/reviewArtistReducer.js";
import {storeReviewAlbumData} from "../store/slices/reviewAlbumReducer.js";
import {storeReviewTrackData} from "../store/slices/reviewTrackReducer.js";
import {Create} from "../axios/reviewAxios.js";

const useCreateReview = () => {
const dispatch = useDispatch();
const [error, setError] = useState(null);

const createReview = useCallback(async (data) => {
setError(null);
try {
const reviewResponse = await Create(data);
const payload = {
items: [reviewResponse.data],
totalCount: 1, // Increment total count
};

switch (data.reviewType) {
case 0:
dispatch(storeReviewArtistData(payload));
break;
case 1:
dispatch(storeReviewAlbumData(payload));
break;
case 2:
dispatch(storeReviewTrackData(payload));
break;
default:
setError("Invalid review type provided.");
return;
}

return reviewResponse.status;
} catch (error) {
setError(error.message || "An error occurred during login.");
throw error;
}
}, [dispatch]);

return { createReview, error };
};
export default useCreateReview;
Loading

0 comments on commit 39c1629

Please sign in to comment.