Skip to content

Commit 0a9f7c7

Browse files
committed
Improving Create Review Artist
1 parent 9e03ffa commit 0a9f7c7

File tree

4 files changed

+146
-17
lines changed

4 files changed

+146
-17
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const ButtonCreateReview = ({ buttonName, onClick, isActive }) => {
2+
return (
3+
<button
4+
onClick={onClick}
5+
className={`w-full md:px-12 py-3 text-white cursor-pointer ${
6+
isActive ? "bg-blue-500" : "bg-gray-500"
7+
} hover:bg-blue-400`}
8+
>
9+
{buttonName}
10+
</button>
11+
);
12+
};
13+
14+
export default ButtonCreateReview;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import ButtonReviewType from "../Buttons/ButtonReviewType.jsx";
2+
import ButtonCreateReview from "../Buttons/ButtonCreateReview.jsx";
3+
4+
const ReviewArtistDetailed = ({ item }) => {
5+
const { id, name, uri, href, genres, popularity } = item;
6+
const image = item.images?.[0];
7+
const imageUrl = image?.url;
8+
const followers = new Intl.NumberFormat('de-DE').format(item.followers.total);
9+
10+
const externalUrl = item.externalUrls.spotify;
11+
const radio = `${externalUrl.substring(0, 25)}embed/${externalUrl.substring(25, externalUrl.length)}`;
12+
console.log(radio)
13+
14+
const truncateText = (text, limit) =>
15+
text.length > limit ? `${text.substring(0, limit)}...` : text;
16+
17+
const TitleText = (text) =>
18+
`${text.substring(0, 1).toUpperCase() + text.substring(1, text.length).toLowerCase()}`
19+
20+
const ListGenres = (genres) => {
21+
const preparedList = genres.map((genre) => `${TitleText(genre)}`)
22+
return preparedList.toString().replaceAll(',', ', ');
23+
}
24+
25+
26+
27+
return (
28+
<div className="h-full w-full flex flex-col justify-between">
29+
30+
{/* Artist */}
31+
<div className="py-3 flex justify-center">
32+
<span className="text-xl md:text-3xl font-bold pl-1">{truncateText(name, 45)}</span>
33+
</div>
34+
35+
{/* Image block */}
36+
<div className="w-full flex justify-center">
37+
<img src={imageUrl} alt={name} className="w-full h-full"/>
38+
</div>
39+
40+
{/* Button Create Review */}
41+
<div className="w-full mt-4 flex justify-center">
42+
<ButtonCreateReview buttonName={`Write a review about ${truncateText(name, 20)}`} />
43+
</div>
44+
45+
{/* Text block */}
46+
<article
47+
className="flex flex-col w-full pt-4 px-2 h-auto bg-gradient-to-b from-[#fafafa] to-[#f5faff]">
48+
<div className="flex flex-col justify-between text-sm text-gray-600 pb-6">
49+
50+
{/* Genres */}
51+
<div className="pb-4">
52+
<span className="font-bold">Genres: </span>
53+
{genres.length > 0 ? (
54+
<span className="w-full text-sm pl-1">
55+
{truncateText(ListGenres(genres), 500)}</span>
56+
) :
57+
(
58+
<span className="text-sm text-gray-500 pl-1">Not defined</span>
59+
)
60+
}
61+
</div>
62+
63+
{/* Followers */}
64+
<div className="pb-4">
65+
<span className="font-bold">Spotify followers:</span>
66+
<span className="text-sm md:text-base font-bold pl-1">{followers}</span>
67+
</div>
68+
69+
{/* Popularity */}
70+
<div className="flex items-center">
71+
<span className="font-bold mr-2">Popularity:</span>
72+
<div className="flex-1 bg-gray-300 rounded-lg h-4 relative">
73+
<div
74+
className="bg-green-500 h-4 rounded-lg"
75+
style={{width: `${popularity}%`}}
76+
></div>
77+
</div>
78+
<span className="text-sm md:text-base font-bold pl-2">{popularity}%</span>
79+
</div>
80+
</div>
81+
</article>
82+
83+
{/* Embedded Radio */}
84+
<div className="w-full flex justify-center items-center">
85+
<iframe src={radio} width="1024" height="600" allowTransparency="false" allow="encrypted-media"></iframe>
86+
</div>
87+
88+
</div>
89+
)
90+
}
91+
export default ReviewArtistDetailed;

src/components/review/reviewCardFindArtistComponent.jsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
const ReviewCardFindArtistComponent = ({ item }) => {
3-
const { id, name, uri, href, genres } = item;
3+
const { name, genres } = item;
44
const image = item.images?.[0];
55
const imageUrl = image?.url;
66
const truncateText = (text, limit) =>
@@ -16,15 +16,15 @@ const ReviewCardFindArtistComponent = ({ item }) => {
1616

1717

1818
return (
19-
<div className="w-[90%] md:w-[95%] shadow mb-4 pb-4">
19+
<div className="w-[90%] md:w-full cursor-pointer shadow-md mb-6 hover:opacity-60">
2020

2121
{/* Image block */}
2222
<div className="w-42">
2323
<img src={imageUrl} alt={name} className="w-full h-40 md:h-64 object-cover block"/>
2424
</div>
2525

2626
{/* Text block */}
27-
<article className="flex flex-col w-full h-16 md:h-24 p-4 bg-white pb-3 overflow-hidden">
27+
<article className="flex flex-col w-full h-16 md:h-24 p-4 bg-gradient-to-b from-[#fafafa] to-[#f5faff] pb-3 overflow-hidden"> {/* [#edf5fd] */}
2828
<div className="flex flex-col justify-between text-sm text-gray-600 overflow-hidden">
2929
<div>
3030
<span>Artist:</span>

src/components/review/reviewFindArtistComponent.jsx

+38-14
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useState, useRef } from "react";
22
import { SearchArtistByName } from "../../axios/spotifyAxios.js";
33
import LoaderComponent from "../Common/LoaderComponent.jsx";
44
import ReviewCardFindArtistComponent from "./reviewCardFindArtistComponent.jsx";
5+
import ReviewArtistDetailed from "./reviewArtistDetailed.jsx";
56

67
const ReviewFindArtistComponent = () => {
78
const [search, setSearch] = useState("");
@@ -10,12 +11,14 @@ const ReviewFindArtistComponent = () => {
1011
const [searchResult, setSearchResult] = useState([]);
1112
const [isLoading, setIsLoading] = useState(false);
1213
const [isResultNull, setIsResultNull] = useState(false);
14+
const [selectedArtist, setSelectedArtist] = useState(null); // Track the selected artist
1315
const elementRef = useRef(null); // Reference for the element to scroll to
1416

1517
const getSubmitData = async (limit, offset) => {
1618
setIsLoading(true);
1719
try {
1820
const res = await SearchArtistByName(search, limit, offset);
21+
console.log(res)
1922
if (res?.length === 0) {
2023
setIsResultNull(true);
2124
} else {
@@ -55,8 +58,17 @@ const ReviewFindArtistComponent = () => {
5558
}
5659
};
5760

61+
const handleCardClick = (artist) => {
62+
setSelectedArtist(artist); // Set the selected artist
63+
console.log(artist);
64+
};
65+
66+
const closeDetailedView = () => {
67+
setSelectedArtist(null); // Close the detailed view
68+
};
69+
5870
return (
59-
<div className="w-full md:w-4/5 flex flex-col items-center">
71+
<div className="w-full md:w-4/5 flex flex-col items-center relative">
6072
{/* Search Bar */}
6173
<div className="w-[95vw] md:w-full h-10 flex items-center bg-gray-300 rounded-2xl pl-3 md:m-5">
6274
<span className="w-auto text-xs md:text-sm text-gray-500 text-nowrap">Search for an artist:</span>
@@ -82,34 +94,46 @@ const ReviewFindArtistComponent = () => {
8294
<div className="text-gray-500 pl-2 md:pl-0 pt-4 md:pt-0 pb-4">
8395
Results of your search:
8496
</div>
85-
<div className="w-full flex flex-wrap justify-start md:gap-1 pl-2 md:pl-0">
97+
<div className="w-full flex flex-wrap justify-start md:justify-around md:gap-1 pl-2 md:pl-0">
8698
{searchResult
8799
.filter((item) => item.images.length > 0)
88100
.map((item, index) => (
89101
<div
90102
key={item.id}
91-
className="w-1/2 md:w-1/6"
103+
className="w-1/2 md:w-1/6 cursor-pointer"
92104
ref={index === 5 ? elementRef : null} // Add ref to the 6th element
105+
onClick={() => handleCardClick(item)} // Handle card click
93106
>
94107
<ReviewCardFindArtistComponent item={item} />
95108
</div>
96109
))}
97110
</div>
98111
{searchResult.length < 15 && (
99-
<div className="w-full flex items-center justify-center mt-4 mb-0 md:mb-6">
100-
<div className="w-full flex items-center gap-4 px-2">
101-
<div className="flex-1 border-t border-gray-400"></div>
102-
<button onClick={loadMore} className="px-4 py-2 bg-gray-400 text-white rounded">
103-
Load More
104-
</button>
105-
<div className="flex-1 border-t border-gray-400"></div>
106-
</div>
107-
</div>
108-
)}
112+
<div className="w-full flex items-center justify-center m-4">
113+
<button onClick={loadMore} className="px-4 py-2 bg-gray-400 text-white rounded">
114+
Load More
115+
</button>
109116
</div>
110-
) : isResultNull ? (
117+
)}
118+
</div>
119+
) : isResultNull ? (
111120
<p className="text-center mt-4 text-gray-500">No results found.</p>
112121
) : null}
122+
123+
{/* Overlay Component */}
124+
{selectedArtist && (
125+
<div
126+
className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"
127+
onClick={closeDetailedView} // Close when clicking outside
128+
>
129+
<div
130+
className="bg-white rounded-lg shadow-lg w-4/5 md:w-2/5 h-4/5 scroll-auto overflow-y-auto"
131+
onClick={(e) => e.stopPropagation()} // Prevent closing when clicking inside
132+
>
133+
<ReviewArtistDetailed item={selectedArtist} onClose={closeDetailedView} />
134+
</div>
135+
</div>
136+
)}
113137
</div>
114138
);
115139
};

0 commit comments

Comments
 (0)