Changeset b071fb4 for frontend


Ignore:
Timestamp:
02/06/26 20:05:09 (5 months ago)
Author:
Filip Gavrilovski <filipgavrilovski28@…>
Branches:
main
Children:
591919d
Parents:
2ce7c1e
Message:

replace mock data in sidebar with real user data

Location:
frontend/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • frontend/src/components/Sidebar.tsx

    r2ce7c1e rb071fb4  
    1 interface SidebarProps {
    2         isOpen: boolean;
    3         onClose: () => void;
    4 }
     1import { useEffect, useState } from "react";
     2import axiosInstance from "../api/axiosInstance";
     3import type { BasicPlaylist, BasicSong, SidebarProps } from "../utils/types";
    54
    65const Sidebar = ({ isOpen, onClose }: SidebarProps) => {
    7         // mock data for recently listened songs
    8         const recentlyListened = [
    9                 { id: 1, title: "Song One", artist: "Artist A", cover: "/favicon.png" },
    10                 { id: 2, title: "Song Two", artist: "Artist B", cover: "/favicon.png" },
    11                 { id: 3, title: "Song Three", artist: "Artist C", cover: "/favicon.png" },
    12                 { id: 4, title: "Song Four", artist: "Artist D", cover: "/favicon.png" },
    13                 { id: 5, title: "Song Five", artist: "Artist E", cover: "/favicon.png" },
    14         ];
     6        const [recentlyListened, setRecentlyListened] = useState<BasicSong[]>([]);
     7        const [playlists, setPlaylists] = useState<BasicPlaylist[]>([]);
    158
    16         // mock data for my playlists
    17         const playlists = [
    18                 { id: 1, name: "My Favorites", songCount: 25 },
    19                 { id: 2, name: "Workout Mix", songCount: 18 },
    20                 { id: 3, name: "Chill Vibes", songCount: 32 },
    21                 { id: 4, name: "Party Hits", songCount: 45 },
    22         ];
    23 
     9        useEffect(() => {
     10                const fetchData = async () => {
     11                        try {
     12                                const data = await axiosInstance.get<BasicSong[]>("/songs/recent");
     13                                setRecentlyListened(data.data);
     14                        } catch (error) {
     15                                console.error("Error fetching recently listened songs:", error);
     16                                // todo: show toast
     17                        }
     18                        try {
     19                                const data =
     20                                        await axiosInstance.get<BasicPlaylist[]>("/playlists/user");
     21                                setPlaylists(data.data);
     22                        } catch (error) {
     23                                console.error("Error fetching playlists:", error);
     24                                // todo: show toast
     25                        }
     26                };
     27                fetchData();
     28        }, []);
    2429        return (
    2530                <div
     
    6570                                                        >
    6671                                                                <img
    67                                                                         src={song.cover}
     72                                                                        src={song.cover || "/favicon.png"}
    6873                                                                        alt={song.title}
    6974                                                                        className="w-10 h-10 rounded object-cover"
  • frontend/src/pages/LandingPage.tsx

    r2ce7c1e rb071fb4  
    1 import { useEffect, useState } from "react";
     1import { useEffect, useRef, useState } from "react";
    22import axiosInstance from "../api/axiosInstance";
    33import AlbumResult from "../components/search/AlbumResult";
     
    2929        const [searchLoading, setSearchLoading] = useState(false);
    3030        const [hasSearched, setHasSearched] = useState(false);
     31
     32        // playlist dropdown state
     33        const [openPlaylistDropdown, setOpenPlaylistDropdown] = useState<
     34                number | null
     35        >(null);
     36        const playlistDropdownRefs = useRef<{ [key: number]: HTMLDivElement | null }>(
     37                {},
     38        );
    3139
    3240        useEffect(() => {
     
    4351                fetchSongs();
    4452        }, []);
     53
     54        // Handle click outside for playlist dropdown
     55        useEffect(() => {
     56                const handleClickOutside = (event: MouseEvent) => {
     57                        if (openPlaylistDropdown !== null) {
     58                                const ref = playlistDropdownRefs.current[openPlaylistDropdown];
     59                                if (ref && !ref.contains(event.target as Node)) {
     60                                        setOpenPlaylistDropdown(null);
     61                                }
     62                        }
     63                };
     64
     65                document.addEventListener("mousedown", handleClickOutside);
     66                return () => {
     67                        document.removeEventListener("mousedown", handleClickOutside);
     68                };
     69        }, [openPlaylistDropdown]);
     70
     71        const toggleLike = async (songId: number) => {
     72                try {
     73                        await axiosInstance.post(`/musical-entity/${songId}/like`);
     74                        setSongs((prevSongs) =>
     75                                prevSongs.map((song) =>
     76                                        song.id === songId
     77                                                ? { ...song, isLikedByCurrentUser: !song.isLikedByCurrentUser }
     78                                                : song,
     79                                ),
     80                        );
     81                } catch (error) {
     82                        console.error("Error toggling like:", error);
     83                }
     84        };
     85
     86        const togglePlaylistDropdown = (songId: number) => {
     87                setOpenPlaylistDropdown((prev) => (prev === songId ? null : songId));
     88        };
     89
     90        const handleAddToPlaylist = (songId: number, playlistName: string) => {
     91                console.log(`Adding song ${songId} to ${playlistName}`);
     92                // TODO: Implement actual API call
     93                setOpenPlaylistDropdown(null);
     94        };
     95
     96        const handleCreateNewPlaylist = (songId: number) => {
     97                console.log(`Creating new playlist for song ${songId}`);
     98                // TODO: Implement actual playlist creation
     99                setOpenPlaylistDropdown(null);
     100        };
    45101
    46102        const performSearch = async (query: string, category: SearchCategory) => {
     
    289345                                                                                                        </div>
    290346                                                                                                </div>
    291                                                                                                 <div className="p-4 flex flex-col items-center">
     347                                                                                                <div className="p-4">
    292348                                                                                                        <h3 className="text-lg font-semibold mb-2 text-white overflow-hidden text-ellipsis whitespace-nowrap">
    293349                                                                                                                {song.title}
     
    299355                                                                                                                {song.releasedBy}
    300356                                                                                                        </p>
     357                                                                                                        <div className="flex items-center justify-between mt-4 pt-3 border-t border-white/10">
     358                                                                                                                {/* Like button */}
     359                                                                                                                <button
     360                                                                                                                        onClick={(e) => {
     361                                                                                                                                e.stopPropagation();
     362                                                                                                                                toggleLike(song.id);
     363                                                                                                                        }}
     364                                                                                                                        className="text-gray-400 hover:text-[#1db954] transition-colors cursor-pointer"
     365                                                                                                                        aria-label={
     366                                                                                                                                song.isLikedByCurrentUser
     367                                                                                                                                        ? "Unlike song"
     368                                                                                                                                        : "Like song"
     369                                                                                                                        }
     370                                                                                                                >
     371                                                                                                                        {song.isLikedByCurrentUser ? (
     372                                                                                                                                <svg
     373                                                                                                                                        className="w-6 h-6 fill-[#1db954]"
     374                                                                                                                                        viewBox="0 0 24 24"
     375                                                                                                                                >
     376                                                                                                                                        <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" />
     377                                                                                                                                </svg>
     378                                                                                                                        ) : (
     379                                                                                                                                <svg
     380                                                                                                                                        className="w-6 h-6"
     381                                                                                                                                        fill="none"
     382                                                                                                                                        stroke="currentColor"
     383                                                                                                                                        viewBox="0 0 24 24"
     384                                                                                                                                >
     385                                                                                                                                        <path
     386                                                                                                                                                strokeLinecap="round"
     387                                                                                                                                                strokeLinejoin="round"
     388                                                                                                                                                strokeWidth={2}
     389                                                                                                                                                d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
     390                                                                                                                                        />
     391                                                                                                                                </svg>
     392                                                                                                                        )}
     393                                                                                                                </button>
     394
     395                                                                                                                {/* Add to playlist button */}
     396                                                                                                                <div
     397                                                                                                                        className="relative"
     398                                                                                                                        ref={(el) => {
     399                                                                                                                                if (el)
     400                                                                                                                                        playlistDropdownRefs.current[song.id] = el;
     401                                                                                                                        }}
     402                                                                                                                >
     403                                                                                                                        <button
     404                                                                                                                                onClick={(e) => {
     405                                                                                                                                        e.stopPropagation();
     406                                                                                                                                        togglePlaylistDropdown(song.id);
     407                                                                                                                                }}
     408                                                                                                                                className="text-gray-400 hover:text-[#1db954] transition-colors cursor-pointer"
     409                                                                                                                                aria-label="Add to playlist"
     410                                                                                                                        >
     411                                                                                                                                <svg
     412                                                                                                                                        className="w-6 h-6"
     413                                                                                                                                        fill="none"
     414                                                                                                                                        stroke="currentColor"
     415                                                                                                                                        viewBox="0 0 24 24"
     416                                                                                                                                >
     417                                                                                                                                        <path
     418                                                                                                                                                strokeLinecap="round"
     419                                                                                                                                                strokeLinejoin="round"
     420                                                                                                                                                strokeWidth={2}
     421                                                                                                                                                d="M12 4v16m8-8H4"
     422                                                                                                                                        />
     423                                                                                                                                </svg>
     424                                                                                                                        </button>
     425
     426                                                                                                                        {/* Playlist dropdown */}
     427                                                                                                                        {openPlaylistDropdown === song.id && (
     428                                                                                                                                <div className="absolute right-0 bottom-full mb-2 w-48 bg-gray-700 rounded-lg shadow-lg py-1 z-50">
     429                                                                                                                                        <div className="px-3 py-2 text-xs text-gray-400 border-b border-white/10">
     430                                                                                                                                                Add to playlist
     431                                                                                                                                        </div>
     432                                                                                                                                        <button
     433                                                                                                                                                onClick={(e) => {
     434                                                                                                                                                        e.stopPropagation();
     435                                                                                                                                                        handleAddToPlaylist(
     436                                                                                                                                                                song.id,
     437                                                                                                                                                                "Playlist 1",
     438                                                                                                                                                        );
     439                                                                                                                                                }}
     440                                                                                                                                                className="w-full text-left px-4 py-2 text-sm text-white hover:bg-gray-600 transition-colors"
     441                                                                                                                                        >
     442                                                                                                                                                Playlist 1
     443                                                                                                                                        </button>
     444                                                                                                                                        <button
     445                                                                                                                                                onClick={(e) => {
     446                                                                                                                                                        e.stopPropagation();
     447                                                                                                                                                        handleAddToPlaylist(
     448                                                                                                                                                                song.id,
     449                                                                                                                                                                "Playlist 2",
     450                                                                                                                                                        );
     451                                                                                                                                                }}
     452                                                                                                                                                className="w-full text-left px-4 py-2 text-sm text-white hover:bg-gray-600 transition-colors"
     453                                                                                                                                        >
     454                                                                                                                                                Playlist 2
     455                                                                                                                                        </button>
     456                                                                                                                                        <button
     457                                                                                                                                                onClick={(e) => {
     458                                                                                                                                                        e.stopPropagation();
     459                                                                                                                                                        handleCreateNewPlaylist(song.id);
     460                                                                                                                                                }}
     461                                                                                                                                                className="w-full text-left px-4 py-2 text-sm text-[#1db954] hover:bg-gray-600 transition-colors border-t border-white/10 flex items-center gap-2"
     462                                                                                                                                        >
     463                                                                                                                                                <svg
     464                                                                                                                                                        className="w-4 h-4"
     465                                                                                                                                                        fill="none"
     466                                                                                                                                                        stroke="currentColor"
     467                                                                                                                                                        viewBox="0 0 24 24"
     468                                                                                                                                                >
     469                                                                                                                                                        <path
     470                                                                                                                                                                strokeLinecap="round"
     471                                                                                                                                                                strokeLinejoin="round"
     472                                                                                                                                                                strokeWidth={2}
     473                                                                                                                                                                d="M12 4v16m8-8H4"
     474                                                                                                                                                        />
     475                                                                                                                                                </svg>
     476                                                                                                                                                Create new playlist
     477                                                                                                                                        </button>
     478                                                                                                                                </div>
     479                                                                                                                        )}
     480                                                                                                                </div>
     481                                                                                                        </div>
    301482                                                                                                </div>
    302483                                                                                        </div>
  • frontend/src/utils/types.ts

    r2ce7c1e rb071fb4  
    5757
    5858export type SearchCategory = "songs" | "albums" | "artists" | "users";
     59
     60export interface SidebarProps {
     61        isOpen: boolean;
     62        onClose: () => void;
     63}
     64
     65export interface BasicSong {
     66        id: number;
     67        title: string;
     68        artist: string;
     69        cover?: string;
     70}
     71
     72export interface BasicPlaylist {
     73        id: number;
     74        name: string;
     75        songCount: number;
     76}
Note: See TracChangeset for help on using the changeset viewer.