Ignore:
Timestamp:
02/14/26 18:21:18 (5 months ago)
Author:
Dimitar Arsov <dimitararsov04@…>
Branches:
main
Children:
ce45c7a
Parents:
f5bc95e
Message:

save playlist

File:
1 edited

Legend:

Unmodified
Added
Removed
  • frontend/src/components/userProfile/ListenerView.tsx

    rf5bc95e r85512ff  
    11import { Album, Bookmark, Heart, ListMusic, Music } from "lucide-react";
    22import { useState } from "react";
    3 import { useNavigate } from "react-router-dom";
     3import { useNavigate, useParams } from "react-router-dom";
    44import { toast } from "react-toastify";
    55import axiosInstance, { baseURL } from "../../api/axiosInstance";
    66import type { MusicalEntity, Playlist } from "../../utils/types";
    77import SongItem from "../SongItem";
     8import { useAuth } from "../../context/authContext";
    89
    910interface ListenerViewProps {
    10         likedEntities: MusicalEntity[] | [];
    11         createdPlaylists: Playlist[] | [];
    12         savedPlaylists: Playlist[] | [];
     11  likedEntities: MusicalEntity[] | [];
     12  createdPlaylists: Playlist[] | [];
     13  savedPlaylists: Playlist[] | [];
    1314}
    1415
    1516const ListenerView = ({
    16         likedEntities,
    17         createdPlaylists,
    18         savedPlaylists,
     17  likedEntities,
     18  createdPlaylists,
     19  savedPlaylists,
    1920}: ListenerViewProps) => {
    20         const navigate = useNavigate();
    21         const [items, setItems] = useState(likedEntities);
    22         const [savedItems, setSavedItems] = useState(savedPlaylists);
    23 
    24         const likedSongs = items.filter((e) => e.type === "SONG");
    25         const likedAlbums = items.filter((e) => e.type === "ALBUM");
    26 
    27         const handleSavePlaylist = async (
    28                 e: React.MouseEvent,
    29                 playlistId: number,
    30                 playlistName: string,
    31         ) => {
    32                 e.stopPropagation();
    33 
    34                 try {
    35                         const response = await axiosInstance.post(`/playlist/${playlistId}/save`);
    36                         const data = response.data;
    37 
    38                         setSavedItems((prevItems) =>
    39                                 data.isSaved
    40                                         ? [...prevItems, prevItems.find((p) => p.id === playlistId)!]
    41                                         : prevItems.filter((p) => p.id !== playlistId),
    42                         );
    43 
    44                         toast.success(
    45                                 data.isSaved
    46                                         ? `Saved "${playlistName}" to your library`
    47                                         : `Removed "${playlistName}" from your library`,
    48                         );
    49                 } catch (err: any) {
    50                         toast.error(err.response?.data?.error || "Failed to save the playlist");
    51                 }
    52         };
    53 
    54         const handleLike = async (id: number, title: string) => {
    55                 try {
    56                         const response = await axiosInstance.post(`/musical-entity/${id}/like`);
    57                         const data = response.data;
    58 
    59                         setItems((prevItems) =>
    60                                 prevItems.map((item) =>
    61                                         item.id === data.entityId
    62                                                 ? { ...item, isLikedByCurrentUser: data.isLiked }
    63                                                 : item,
    64                                 ),
    65                         );
    66 
    67                         toast.success(
    68                                 data.isLiked ? `Liked "${title}"` : `Removed "${title}" from likes`,
    69                         );
    70                 } catch (err: any) {
    71                         toast.error(err.response?.data?.error || "Failed to like the item");
    72                 }
    73         };
    74 
    75         return (
    76                 <div className="mt-8 space-y-12">
    77                         {createdPlaylists && createdPlaylists.length > 0 && (
    78                                 <section>
    79                                         <div className="flex items-center gap-3 mb-6">
    80                                                 <ListMusic className="w-6 h-6 text-[#1db954]" />
    81                                                 <h3 className="text-2xl font-bold text-white">Created Playlists</h3>
    82                                                 <span className="text-sm text-gray-500">
    83                                                         ({createdPlaylists.length})
    84                                                 </span>
    85                                         </div>
    86 
    87                                         <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
    88                                                 {createdPlaylists.map((playlist) => (
    89                                                         <div
    90                                                                 key={playlist.id}
    91                                                                 className="group cursor-pointer"
    92                                                                 onClick={() => navigate(`/collection/playlist/${playlist.id}`)}
    93                                                         >
    94                                                                 <div className="relative aspect-square rounded-lg overflow-hidden bg-[#181818] mb-3 shadow-md group-hover:shadow-xl transition-all">
    95                                                                         <img
    96                                                                                 src={
    97                                                                                         playlist.cover
    98                                                                                                 ? `${baseURL}/${playlist.cover}`
    99                                                                                                 : "/favicon.png"
    100                                                                                 }
    101                                                                                 alt={playlist.name}
    102                                                                                 className="w-full h-full object-cover"
    103                                                                                 onError={(e) => {
    104                                                                                         (e.target as HTMLImageElement).src = "/favicon.png";
    105                                                                                 }}
    106                                                                         />
    107 
    108                                                                         <button
    109                                                                                 onClick={(e) =>
    110                                                                                         handleSavePlaylist(e, playlist.id, playlist.name)
    111                                                                                 }
    112                                                                                 className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-black/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100"
    113                                                                                 title={playlist.isSavedByCurrentUser ? "Unsave" : "Save"}
    114                                                                         >
    115                                                                                 <Bookmark
    116                                                                                         className={`w-5 h-5 ${
    117                                                                                                 playlist.isSavedByCurrentUser
    118                                                                                                         ? "fill-[#1db954] text-[#1db954]"
    119                                                                                                         : "text-gray-400"
    120                                                                                         }`}
    121                                                                                 />
    122                                                                         </button>
    123                                                                 </div>
    124                                                                 <p className="text-sm font-semibold text-white truncate group-hover:text-[#1db954] transition-colors">
    125                                                                         {playlist.name}
    126                                                                 </p>
    127                                                                 <p className="text-xs text-gray-400 truncate">
    128                                                                         {playlist.creatorName}
    129                                                                 </p>
    130                                                         </div>
    131                                                 ))}
    132                                         </div>
    133                                 </section>
    134                         )}
    135 
    136                         {savedItems && savedItems.length > 0 && (
    137                                 <section>
    138                                         <div className="flex items-center gap-3 mb-6">
    139                                                 <Bookmark className="w-6 h-6 text-[#1db954] fill-[#1db954]" />
    140                                                 <h3 className="text-2xl font-bold text-white">Saved Playlists</h3>
    141                                                 <span className="text-sm text-gray-500">({savedItems.length})</span>
    142                                         </div>
    143 
    144                                         <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
    145                                                 {savedItems.map((playlist) => (
    146                                                         <div
    147                                                                 key={playlist.id}
    148                                                                 className="group cursor-pointer"
    149                                                                 onClick={() => navigate(`/collection/playlist/${playlist.id}`)}
    150                                                         >
    151                                                                 <div className="relative aspect-square rounded-lg overflow-hidden bg-[#181818] mb-3 shadow-md group-hover:shadow-xl transition-all">
    152                                                                         <img
    153                                                                                 src={
    154                                                                                         playlist.cover
    155                                                                                                 ? `${baseURL}/${playlist.cover}`
    156                                                                                                 : "/favicon.png"
    157                                                                                 }
    158                                                                                 alt={playlist.name}
    159                                                                                 className="w-full h-full object-cover"
    160                                                                                 onError={(e) => {
    161                                                                                         (e.target as HTMLImageElement).src = "/favicon.png";
    162                                                                                 }}
    163                                                                         />
    164 
    165                                                                         <button
    166                                                                                 onClick={(e) =>
    167                                                                                         handleSavePlaylist(e, playlist.id, playlist.name)
    168                                                                                 }
    169                                                                                 className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-black/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100"
    170                                                                                 title="Unsave"
    171                                                                         >
    172                                                                                 <Bookmark className="w-5 h-5 fill-[#1db954] text-[#1db954]" />
    173                                                                         </button>
    174                                                                 </div>
    175                                                                 <p className="text-sm font-semibold text-white truncate group-hover:text-[#1db954] transition-colors">
    176                                                                         {playlist.name}
    177                                                                 </p>
    178                                                                 <p className="text-xs text-gray-400 truncate">
    179                                                                         {playlist.creatorName}
    180                                                                 </p>
    181                                                         </div>
    182                                                 ))}
    183                                         </div>
    184                                 </section>
    185                         )}
    186 
    187                         {likedSongs && likedSongs.length > 0 && (
    188                                 <section>
    189                                         <div className="flex items-center gap-3 mb-6">
    190                                                 <Heart className="w-6 h-6 text-red-500 fill-red-500" />
    191                                                 <h3 className="text-2xl font-bold text-white">Liked Songs</h3>
    192                                                 <span className="text-sm text-gray-500">
    193                                                         ({likedSongs?.length})
    194                                                 </span>
    195                                         </div>
    196 
    197                                         <div className="space-y-1">
    198                                                 {likedSongs.map((song, index) => (
    199                                                         <SongItem
    200                                                                 key={song.id}
    201                                                                 song={{
    202                                                                         id: song.id,
    203                                                                         title: song.title,
    204                                                                         cover: song.cover
    205                                                                                 ? `${baseURL}/${song.cover}`
    206                                                                                 : "/favicon.png",
    207                                                                         genre: song.genre,
    208                                                                         link: (song as any).link,
    209                                                                         releasedBy: song.releasedBy,
    210                                                                         isLikedByCurrentUser: song.isLikedByCurrentUser,
    211                                                                 }}
    212                                                                 index={index + 1}
    213                                                                 onLikeToggle={() => handleLike(song.id, song.title)}
    214                                                         />
    215                                                 ))}
    216                                         </div>
    217                                 </section>
    218                         )}
    219 
    220                         {likedAlbums && likedAlbums.length > 0 && (
    221                                 <section>
    222                                         <div className="flex items-center gap-3 mb-6">
    223                                                 <Album className="w-6 h-6 text-[#1db954]" />
    224                                                 <h3 className="text-2xl font-bold text-white">Liked Albums</h3>
    225                                                 <span className="text-sm text-gray-500">
    226                                                         ({likedAlbums.length})
    227                                                 </span>
    228                                         </div>
    229 
    230                                         <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
    231                                                 {likedAlbums.map((album) => (
    232                                                         <div
    233                                                                 key={album.id}
    234                                                                 className="group cursor-pointer"
    235                                                                 onClick={() => navigate(`/collection/album/${album.id}`)}
    236                                                         >
    237                                                                 <div className="relative aspect-square rounded-lg overflow-hidden bg-[#181818] mb-3 shadow-md group-hover:shadow-xl transition-all">
    238                                                                         <img
    239                                                                                 src={
    240                                                                                         album.cover ? `${baseURL}/${album.cover}` : "/favicon.png"
    241                                                                                 }
    242                                                                                 alt={album.title}
    243                                                                                 className="w-full h-full object-cover"
    244                                                                                 onError={(e) => {
    245                                                                                         (e.target as HTMLImageElement).src = "/favicon.png";
    246                                                                                 }}
    247                                                                         />
    248 
    249                                                                         <button
    250                                                                                 onClick={(e) => {
    251                                                                                         e.stopPropagation();
    252                                                                                         handleLike(album.id, album.title);
    253                                                                                 }}
    254                                                                                 className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-black/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100 cursor-pointer"
    255                                                                                 title={album.isLikedByCurrentUser ? "Unlike" : "Like"}
    256                                                                         >
    257                                                                                 <svg
    258                                                                                         className="w-5 h-5"
    259                                                                                         fill={album.isLikedByCurrentUser ? "#ef4444" : "none"}
    260                                                                                         stroke={
    261                                                                                                 album.isLikedByCurrentUser ? "#ef4444" : "#9ca3af"
    262                                                                                         }
    263                                                                                         strokeWidth="2"
    264                                                                                         viewBox="0 0 24 24"
    265                                                                                 >
    266                                                                                         <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
    267                                                                                 </svg>
    268                                                                         </button>
    269                                                                 </div>
    270                                                                 <p className="font-semibold text-sm text-white truncate group-hover:text-[#1db954] transition-colors">
    271                                                                         {album.title}
    272                                                                 </p>
    273                                                                 <p className="text-xs text-gray-400 truncate mt-1">
    274                                                                         {album.releasedBy}
    275                                                                 </p>
    276                                                         </div>
    277                                                 ))}
    278                                         </div>
    279                                 </section>
    280                         )}
    281 
    282                         {likedEntities &&
    283                                 likedEntities.length === 0 &&
    284                                 (!createdPlaylists || createdPlaylists.length === 0) &&
    285                                 (!savedItems || savedItems.length === 0) && (
    286                                         <div className="flex flex-col items-center justify-center py-16 text-gray-500">
    287                                                 <Music className="w-20 h-20 mb-4 opacity-20" />
    288                                                 <p className="text-lg font-medium">Nothing here yet</p>
    289                                                 <p className="text-sm mt-2">
    290                                                         Start exploring music to build your collection
    291                                                 </p>
    292                                         </div>
    293                                 )}
    294                 </div>
    295         );
     21  const navigate = useNavigate();
     22  const { username: usernameParam } = useParams();
     23  const { user: currentUser } = useAuth();
     24  const [items, setItems] = useState(likedEntities);
     25  const [createdItems, setCreatedItems] = useState(createdPlaylists);
     26  const [savedItems, setSavedItems] = useState(savedPlaylists);
     27
     28  const likedSongs = items.filter((e) => e.type === "SONG");
     29  const likedAlbums = items.filter((e) => e.type === "ALBUM");
     30  const username = usernameParam || currentUser?.username;
     31  const isOwnProfile = currentUser?.username === username;
     32
     33  const handleSavePlaylist = async (
     34    e: React.MouseEvent,
     35    playlistId: number,
     36    playlistName: string,
     37  ) => {
     38    e.stopPropagation();
     39
     40    try {
     41      const response = await axiosInstance.post(
     42        `/playlists/${playlistId}/save`,
     43      );
     44      const data = response.data;
     45
     46      setCreatedItems((prevItems) =>
     47        prevItems.map((p) =>
     48          p.id === playlistId
     49            ? { ...p, isSavedByCurrentUser: data.isSavedByCurrentUser }
     50            : p,
     51        ),
     52      );
     53
     54      setSavedItems((prevItems) =>
     55        prevItems.map((p) =>
     56          p.id === playlistId
     57            ? { ...p, isSavedByCurrentUser: data.isSavedByCurrentUser }
     58            : p,
     59        ),
     60      );
     61
     62      if (isOwnProfile) {
     63        if (data.isSavedByCurrentUser) {
     64          const playlistToAdd = createdItems.find((p) => p.id === playlistId);
     65          if (playlistToAdd && !savedItems.find((p) => p.id === playlistId)) {
     66            setSavedItems((prevItems) => [
     67              ...prevItems,
     68              { ...playlistToAdd, isSavedByCurrentUser: true },
     69            ]);
     70          }
     71        } else {
     72          setSavedItems((prevItems) =>
     73            prevItems.filter((p) => p.id !== playlistId),
     74          );
     75        }
     76      }
     77
     78      toast.success(
     79        data.isSavedByCurrentUser
     80          ? `Saved "${playlistName}" to your library`
     81          : `Removed "${playlistName}" from your library`,
     82      );
     83    } catch (err: any) {
     84      toast.error(err.response?.data?.error || "Failed to save the playlist");
     85    }
     86  };
     87
     88  const handleLike = async (id: number, title: string) => {
     89    try {
     90      const response = await axiosInstance.post(`/musical-entity/${id}/like`);
     91      const data = response.data;
     92
     93      setItems((prevItems) =>
     94        prevItems.map((item) =>
     95          item.id === data.entityId
     96            ? { ...item, isLikedByCurrentUser: data.isLiked }
     97            : item,
     98        ),
     99      );
     100
     101      toast.success(
     102        data.isLiked ? `Liked "${title}"` : `Removed "${title}" from likes`,
     103      );
     104    } catch (err: any) {
     105      toast.error(err.response?.data?.error || "Failed to like the item");
     106    }
     107  };
     108
     109  return (
     110    <div className="mt-8 space-y-12">
     111      {createdItems && createdItems.length > 0 && (
     112        <section>
     113          <div className="flex items-center gap-3 mb-6">
     114            <ListMusic className="w-6 h-6 text-[#1db954]" />
     115            <h3 className="text-2xl font-bold text-white">Created Playlists</h3>
     116            <span className="text-sm text-gray-500">
     117              ({createdItems.length})
     118            </span>
     119          </div>
     120
     121          <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
     122            {createdItems.map((playlist) => (
     123              <div
     124                key={playlist.id}
     125                className="group cursor-pointer"
     126                onClick={() => navigate(`/collection/playlist/${playlist.id}`)}
     127              >
     128                <div className="relative aspect-square rounded-lg overflow-hidden bg-[#181818] mb-3 shadow-md group-hover:shadow-xl transition-all">
     129                  <img
     130                    src={
     131                      playlist.cover
     132                        ? `${baseURL}/${playlist.cover}`
     133                        : "/favicon.png"
     134                    }
     135                    alt={playlist.name}
     136                    className="w-full h-full object-cover"
     137                    onError={(e) => {
     138                      (e.target as HTMLImageElement).src = "/favicon.png";
     139                    }}
     140                  />
     141                  {!isOwnProfile &&
     142                    currentUser?.username != playlist.creatorUsername && (
     143                      <button
     144                        onClick={(e) =>
     145                          handleSavePlaylist(e, playlist.id, playlist.name)
     146                        }
     147                        className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-black/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100 cursor-pointer"
     148                        title={
     149                          playlist.isSavedByCurrentUser ? "Unsave" : "Save"
     150                        }
     151                      >
     152                        <Bookmark
     153                          className={`w-5 h-5 ${
     154                            playlist.isSavedByCurrentUser
     155                              ? "fill-[#1db954] text-[#1db954]"
     156                              : "text-gray-400"
     157                          }`}
     158                        />
     159                      </button>
     160                    )}
     161                </div>
     162                <p className="text-sm font-semibold text-white truncate group-hover:text-[#1db954] transition-colors">
     163                  {playlist.name}
     164                </p>
     165                <p className="text-xs text-gray-400 truncate">
     166                  {playlist.creatorName}
     167                </p>
     168              </div>
     169            ))}
     170          </div>
     171        </section>
     172      )}
     173
     174      {savedItems && savedItems.length > 0 && (
     175        <section>
     176          <div className="flex items-center gap-3 mb-6">
     177            <Bookmark className="w-6 h-6 text-[#1db954] fill-[#1db954]" />
     178            <h3 className="text-2xl font-bold text-white">Saved Playlists</h3>
     179            <span className="text-sm text-gray-500">({savedItems.length})</span>
     180          </div>
     181
     182          <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
     183            {savedItems.map((playlist) => (
     184              <div
     185                key={playlist.id}
     186                className="group cursor-pointer"
     187                onClick={() => navigate(`/collection/playlist/${playlist.id}`)}
     188              >
     189                <div className="relative aspect-square rounded-lg overflow-hidden bg-[#181818] mb-3 shadow-md group-hover:shadow-xl transition-all">
     190                  <img
     191                    src={
     192                      playlist.cover
     193                        ? `${baseURL}/${playlist.cover}`
     194                        : "/favicon.png"
     195                    }
     196                    alt={playlist.name}
     197                    className="w-full h-full object-cover"
     198                    onError={(e) => {
     199                      (e.target as HTMLImageElement).src = "/favicon.png";
     200                    }}
     201                  />
     202
     203                  {currentUser?.username != playlist.creatorUsername && (
     204                    <button
     205                      onClick={(e) =>
     206                        handleSavePlaylist(e, playlist.id, playlist.name)
     207                      }
     208                      className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-black/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100 cursor-pointer"
     209                      title={playlist.isSavedByCurrentUser ? "Unsave" : "Save"}
     210                    >
     211                      <Bookmark
     212                        className={`w-5 h-5 ${
     213                          playlist.isSavedByCurrentUser
     214                            ? "fill-[#1db954] text-[#1db954]"
     215                            : "text-gray-400"
     216                        }`}
     217                      />
     218                    </button>
     219                  )}
     220                </div>
     221                <p className="text-sm font-semibold text-white truncate group-hover:text-[#1db954] transition-colors">
     222                  {playlist.name}
     223                </p>
     224                <p className="text-xs text-gray-400 truncate">
     225                  {playlist.creatorName}
     226                </p>
     227              </div>
     228            ))}
     229          </div>
     230        </section>
     231      )}
     232
     233      {likedSongs && likedSongs.length > 0 && (
     234        <section>
     235          <div className="flex items-center gap-3 mb-6">
     236            <Heart className="w-6 h-6 text-red-500 fill-red-500" />
     237            <h3 className="text-2xl font-bold text-white">Liked Songs</h3>
     238            <span className="text-sm text-gray-500">
     239              ({likedSongs?.length})
     240            </span>
     241          </div>
     242
     243          <div className="space-y-1">
     244            {likedSongs.map((song, index) => (
     245              <SongItem
     246                key={song.id}
     247                song={{
     248                  id: song.id,
     249                  title: song.title,
     250                  cover: song.cover
     251                    ? `${baseURL}/${song.cover}`
     252                    : "/favicon.png",
     253                  genre: song.genre,
     254                  link: (song as any).link,
     255                  releasedBy: song.releasedBy,
     256                  isLikedByCurrentUser: song.isLikedByCurrentUser,
     257                }}
     258                index={index + 1}
     259                onLikeToggle={() => handleLike(song.id, song.title)}
     260              />
     261            ))}
     262          </div>
     263        </section>
     264      )}
     265
     266      {likedAlbums && likedAlbums.length > 0 && (
     267        <section>
     268          <div className="flex items-center gap-3 mb-6">
     269            <Album className="w-6 h-6 text-[#1db954]" />
     270            <h3 className="text-2xl font-bold text-white">Liked Albums</h3>
     271            <span className="text-sm text-gray-500">
     272              ({likedAlbums.length})
     273            </span>
     274          </div>
     275
     276          <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
     277            {likedAlbums.map((album) => (
     278              <div
     279                key={album.id}
     280                className="group cursor-pointer"
     281                onClick={() => navigate(`/collection/album/${album.id}`)}
     282              >
     283                <div className="relative aspect-square rounded-lg overflow-hidden bg-[#181818] mb-3 shadow-md group-hover:shadow-xl transition-all">
     284                  <img
     285                    src={
     286                      album.cover ? `${baseURL}/${album.cover}` : "/favicon.png"
     287                    }
     288                    alt={album.title}
     289                    className="w-full h-full object-cover"
     290                    onError={(e) => {
     291                      (e.target as HTMLImageElement).src = "/favicon.png";
     292                    }}
     293                  />
     294
     295                  <button
     296                    onClick={(e) => {
     297                      e.stopPropagation();
     298                      handleLike(album.id, album.title);
     299                    }}
     300                    className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-black/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100 cursor-pointer"
     301                    title={album.isLikedByCurrentUser ? "Unlike" : "Like"}
     302                  >
     303                    <svg
     304                      className="w-5 h-5"
     305                      fill={album.isLikedByCurrentUser ? "#ef4444" : "none"}
     306                      stroke={
     307                        album.isLikedByCurrentUser ? "#ef4444" : "#9ca3af"
     308                      }
     309                      strokeWidth="2"
     310                      viewBox="0 0 24 24"
     311                    >
     312                      <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
     313                    </svg>
     314                  </button>
     315                </div>
     316                <p className="font-semibold text-sm text-white truncate group-hover:text-[#1db954] transition-colors">
     317                  {album.title}
     318                </p>
     319                <p className="text-xs text-gray-400 truncate mt-1">
     320                  {album.releasedBy}
     321                </p>
     322              </div>
     323            ))}
     324          </div>
     325        </section>
     326      )}
     327
     328      {likedEntities &&
     329        likedEntities.length === 0 &&
     330        (!createdItems || createdItems.length === 0) &&
     331        (!savedItems || savedItems.length === 0) && (
     332          <div className="flex flex-col items-center justify-center py-16 text-gray-500">
     333            <Music className="w-20 h-20 mb-4 opacity-20" />
     334            <p className="text-lg font-medium">Nothing here yet</p>
     335            <p className="text-sm mt-2">
     336              Start exploring music to build your collection
     337            </p>
     338          </div>
     339        )}
     340    </div>
     341  );
    296342};
    297343
Note: See TracChangeset for help on using the changeset viewer.