From 95e3694af1463b94789d5102e92082213c77d491 Mon Sep 17 00:00:00 2001 From: k0 Date: Tue, 16 Sep 2025 10:22:07 -0500 Subject: [PATCH 01/22] fix npm install error --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5cb4f8f..2e5379d 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "build": "node scripts/build.js", "build:server": "cd server && npm run build", "build:client": "cd client && npm run build", - "install-all": "npm install && cd client && npm install && cd ../server && npm install", + "install-all": "npm install && cd client && npm install --legacy-peer-deps && cd ../server && npm install", "clean": "rm -rf client/dist server/dist client/node_modules server/node_modules node_modules", "clean-all": "rm -rf client/dist server/dist" }, From 77d573996fe11135268af6eb56447312d9574457 Mon Sep 17 00:00:00 2001 From: k0 Date: Tue, 23 Sep 2025 00:17:44 -0500 Subject: [PATCH 02/22] Add requirement doc --- docs/Requirement-Document.md | 247 ------------------- docs/coog-music-schema.png | Bin 0 -> 427394 bytes docs/cosc-3380-doc.pdf | Bin 0 -> 241131 bytes docs/cosc-3380-doc.typ | 462 +++++++++++++++++++++++++++++++++++ 4 files changed, 462 insertions(+), 247 deletions(-) delete mode 100644 docs/Requirement-Document.md create mode 100644 docs/coog-music-schema.png create mode 100644 docs/cosc-3380-doc.pdf create mode 100644 docs/cosc-3380-doc.typ diff --git a/docs/Requirement-Document.md b/docs/Requirement-Document.md deleted file mode 100644 index dd992fd..0000000 --- a/docs/Requirement-Document.md +++ /dev/null @@ -1,247 +0,0 @@ -# CoogMusic - -**Team 8**: _Koren Stalnaker, Ron Alex, Joshua Nguyen, Santiago Reyes, Sharmake Mohamud_ - ---- - -**CoogMusic** is an online music library, where users (primarily UH students and alumni) can upload tracks and listen to tracks by other artists. Users can choose to browse and listen to music without an account, however users must be registered (as artists) to post songs. The application has a community aspect as well — users can follow artists, “like” uploads, comment on uploads, and create playlists of songs that can be shared with other users. - -## Entities - -### Core Entities - -#### Users - -Represents a authenticated CoogMusic user with role-based permissions. - -##### Attributes - -- `id` - Unique, auto-generated identifier -- `username` - Unique username -- `email` - Unique email address -- `password_hash` - Encrypted password -- `authenticated_with` - Authentication provider (default: “CoogMusic”) -- `role` - User permission level -- `profile_picture_url` - Profile image URL -- `artist_id` - Associated artist profile (nullable) -- `created_at` - Account creation timestamp -- `updated_at` - Last profile update - -#### Artists - -Represents a CoogMusic artist. - -##### Attributes - -- `id` - Unique, auto-generated identifier -- `display_name` - Optional display name for artists -- `bio` - Artist profile bio (optional) -- `user_id` - Associated user account -- `created_at` - Artist profile creation timestamp -- `updated_at` - Last profile update - -#### Songs - -Represents individual music tracks uploaded by artists. - -##### Attributes - -- `id` - Unique, auto-generated identifier -- `title` - Song title -- `album_id` - Associated album (optional) -- `genre` - User-entered genre -- `audio_url` - Audio file storage URL -- `duration` - Song length in seconds -- `image_url` - Cover art URL -- `created_at` - Upload timestamp -- `updated_at` - Last updated timestamp - -#### Albums - -Represents albums created by artists. - -##### Attributes - -- `id` - Unique, auto-generated identifier -- `title` - Album title -- `image_url` - Album cover art URL -- `created_by` - Artist who created the album -- `created_at` - Creation timestamp -- `updated_at` - Last updated timestamp - -#### Playlists - -Represents user-created song collections. - -##### Attributes - -- `id` - Unique, auto-generated identifier -- `title` - Playlist title -- `description` - Playlist description -- `created_by` - Playlist creator -- `created_at` - Creation timestamp -- `updated_at` - Last updated timestamp - -### Relational Entities - -#### User Likes - -Tracks user likes on songs. - -##### Attributes - -- `user_id` - User that liked the song -- `song_id` - Song the user liked -- `liked_at` - When the song was liked - -#### User History - -Tracks user listening history. - -##### Attributes - -- `user_id` - User that played the song -- `song_id` - Song the user played -- `played_at` - When the song was played - -#### User Followers - -Tracks artist-follower relationships. - -##### Attributes - -- `follower_id` - Follower user -- `following_id` - Artist the user follows -- `followed_at` - When the artist was followed - -#### Song Artists - -Handles many-to-many relationship between songs and artists. - -##### Attributes - -- `song_id` - ID of the song -- `artist_id` - ID of the artist -- `role_at` - Role of song’s artist (default: “Main”) - -#### Playlist Songs - -Associates songs with playlists. - -##### Attributes - -- `playlist_id` - Playlist the song is on -- `song_id` - Song that is on a playlist -- `added_at` - When the song was added to the playlist - -#### Song Comments - -Stores user comments on songs. - -##### Attributes - -- `user_id` - Commenter ID -- `song_id` - Song the user played -- `comment_text` - The text body of the comment -- `commented_at` - When the user commented on the song - -### User Authentication & Roles - -#### User Roles - -- **Unauthenticated User** - Can browse the site, view songs, artist profiles, and playlists. -- **User** - Basic authenticated user. Can browse the site, like songs, comment on songs, follow artists, create playlists, and save tracks and playlists to their library. -- **Artist** - Authenticated user that has registered as an artist. Has all the privileges of the basic authenticated user, but can also upload songs, update and delete their own songs, and upload and create albums. -- **Admin** - Has all the privileges of an authenticated user, but can update and delete songs, albums, and playlists, as well as update and ban users. - -#### Authentication System - -- The CoogMusic authentication system implements server authentication with site-based sign-up, and Google OAuth authentication, allowing users to sign up with their Google account. - -##### Primary Authentication - -- Email/password with `bcrypt` hashing - -##### OAuth Integration - -- Authentication providers, including Google OAuth - -##### Security - -- JWT refresh and access tokens and CSRF protection - -##### Session Management - -- Token blacklisting for secure logout - -### Data Entry Forms - -#### Song Upload - -- Song metadata (title, genre, album) -- Audio file upload with format validation -- Cover art image upload - -#### Album Creation - -- Album information (title, description, release date) -- Cover art upload -- Song selection - -#### Playlist Management - -- Playlist metadata (title, description) -- Song addition/removal interface -- Playlist sharing options - -#### User Profiles - -- Profile information (bio, profile picture) -- Account settings and preferences -- Authentication method management - -#### Admin Management - -- Content moderation tools -- User management interface -- System configuration options - -### Data Queries - -#### General Site Queries - -- Song page (song, artist, album, comments, related songs) -- Album page (songs, artist, related albums) -- Playlist page (profile information, followers/following, uploaded songs) - -#### Statistics/Insights - -- Site-wide statistics page -- Artist’s 10 ten most played/liked songs -- User’s most streamed songs - -### Data Reports - -#### Monthly Site Analytics - -- Total new user registrations -- Song upload statistics by genre -- Most active users and artists - -#### Realtime Analytics - -- Trending songs and albums -- Artist growth metrics (followers, plays) -- Genre popularity statistics - -### Triggers - -#### Update Timestamp - -- Automatically update `updated_at` when a record in `songs`, `albums`, or `playlists` is modified. - -#### History Cleanup - -- Automatically delete rows from `user_history` older than 30 days whenever the table is updated. - -### Schema diff --git a/docs/coog-music-schema.png b/docs/coog-music-schema.png new file mode 100644 index 0000000000000000000000000000000000000000..6b49ca3bedddd9d7979691eafca8f779188ec097 GIT binary patch literal 427394 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⪙_Sv>jTU%!|2cGyM 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

oI^`5)2uvx27{EK(O_5$}imO|6H(tH{#xqOY? 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 B4h#SQ literal 0 HcmV?d00001 diff --git a/docs/cosc-3380-doc.pdf b/docs/cosc-3380-doc.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4509f2f8e1bec94380bf1b01ed5b9f5e0a5558e9 GIT binary patch literal 241131 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 c{0O#xg=G>#T2WC3LC?>xWvKl>0Es*{jQ{`u literal 0 HcmV?d00001 diff --git a/docs/cosc-3380-doc.typ b/docs/cosc-3380-doc.typ new file mode 100644 index 0000000..ce4ed62 --- /dev/null +++ b/docs/cosc-3380-doc.typ @@ -0,0 +1,462 @@ +#set text( + font: "Noto Sans", + size: 10.5pt, +) + +#set page( + columns: 2, + paper: "us-letter", + margin: (x: 0.5in, y: 0.5in), +) + +#set heading(numbering: "1.") + +#let mono_font = "NotoMono NFP" + +#show raw: set text(font: mono_font, size: 10pt) + += CoogMusic +#v(0.5em) + +CoogMusic is an online music library, where users (primarily UH students and alumni) can upload tracks and listen to tracks by other artists. Users can choose to browse and listen to music without an account, however users must be registered (as artists) to post songs. The application has a community aspect as well — users can follow artists, “like” uploads, comment on uploads, and create playlists of songs. + +== Data Model + +=== Users + +The `User` entity represents an authenticated CoogMusic user. Each user has role-based permissions and may optionally be associated with an artist profile. + +*Attributes*: + +#rect( + fill: blue.lighten(80%), + stroke: 0.5pt, + radius: 2pt, + inset: 6pt, + width: 100%, + [ + #set text(font: mono_font, size: 10pt) + #grid( + columns: (1fr, 1fr), + column-gutter: 2em, + [ + - #underline[id] + - username + - email + - password_hash + - authenticated_with + ], + [ + - role + - pfp_image_url + - artist_id + - created_at + - updated_at + ] + ) + ] +) + +=== Artists + +The `Artist` entity represents a musical artist within the platform. Each artist is associated with a user account. + +*Attributes*: + +#rect( + fill: blue.lighten(80%), + stroke: 0.5pt, + radius: 2pt, + inset: 6pt, + width: 100%, + [ + #set text(font: mono_font, size: 10pt) + #grid( + columns: (1fr, 1fr), + column-gutter: 2em, + [ + - #underline[id] + - display_name + - bio + ], + [ + - user_id + - created_at + - updated_at + ] + ) + ] +) + +=== Songs + +The `Song` entity represents individual music tracks uploaded by artists. + +*Attributes*: + +#rect( + fill: blue.lighten(80%), + stroke: 0.5pt, + radius: 2pt, + inset: 6pt, + width: 100%, + [ + #set text(font: mono_font, size: 10pt) + #grid( + columns: (1fr, 1fr), + column-gutter: 2em, + [ + - #underline[id] + - title + - album_id + - genre + - duration + ], + [ + - audio_url + - image_url + - created_at + - updated_at + ] + ) + ] +) + +=== Albums + +The `Album` entity represents collections of songs created by artists. + +*Attributes*: + +#rect( + fill: blue.lighten(80%), + stroke: 0.5pt, + radius: 2pt, + inset: 6pt, + width: 100%, + [ + #set text(font: mono_font, size: 10pt) + #grid( + columns: (1fr, 1fr), + column-gutter: 2em, + [ + - #underline[id] + - title + - image_url + ], + [ + - created_by + - created_at + - updated_at + ] + ) + ] +) + +=== Playlists + +The `Playlist` entity represents user-created collections of songs. + +*Attributes*: + +#rect( + fill: blue.lighten(80%), + stroke: 0.5pt, + radius: 2pt, + inset: 6pt, + width: 100%, + [ + #set text(font: mono_font, size: 10pt) + #grid( + columns: (1fr, 1fr), + column-gutter: 2em, + [ + - #underline[id] + - title + - description + ], + [ + - created_by + - created_at + - updated_at + ] + ) + ] +) + +== Entity Relationships + +- Users can like songs, albums, and playlists +- Users have listening history and can follow artists +- Songs are performed by artists (many-to-many) +- Playlists contain songs and belong to users +- Users can comment on songs + +#grid( + columns: (1fr, 1fr), + column-gutter: 1em, + [ + *Song Likes* + #v(-0.2em) + #rect( + fill: gray.lighten(80%), + stroke: 0.5pt, + radius: 2pt, + inset: 6pt, + width: 100%, + [ + #set text(font: mono_font, size: 10pt) + #align(left)[ + user_id \ + song_id \ + liked_at + ] + ] + ) + ], + [ + *Album Likes* + #v(-0.2em) + #rect( + fill: gray.lighten(80%), + stroke: 0.5pt, + radius: 2pt, + inset: 6pt, + width: 100%, + [ + #set text(font: mono_font, size: 10pt) + #align(left)[ + user_id \ + album_id \ + liked_at + ] + ] + ) + ] +) + +#grid( + columns: (1fr, 1fr), + column-gutter: 1em, + [ + *Playlist Likes* + #v(-0.2em) + #rect( + fill: gray.lighten(80%), + stroke: 0.5pt, + radius: 2pt, + inset: 6pt, + width: 100%, + [ + #set text(font: mono_font, size: 10pt) + #align(left)[ + user_id \ + playlist_id \ + liked_at + ] + ] + ) + ], + [ + *User History* + #v(-0.2em) + #rect( + fill: gray.lighten(80%), + stroke: 0.5pt, + radius: 2pt, + inset: 6pt, + width: 100%, + [ + #set text(font: mono_font, size: 10pt) + #align(left)[ + user_id \ + song_id \ + played_at + ] + ] + ) + ] +) + +#grid( + columns: (1fr, 1fr), + column-gutter: 1em, + [ + *User Followers* + #v(-0.2em) + #rect( + fill: gray.lighten(80%), + stroke: 0.5pt, + radius: 2pt, + inset: 6pt, + width: 100%, + [ + #set text(font: mono_font, size: 10pt) + #align(left)[ + follower_id \ + following_id \ + followed_at + ] + ] + ) + ], + [ + *Song Artists* + #v(-0.2em) + #rect( + fill: gray.lighten(80%), + stroke: 0.5pt, + radius: 2pt, + inset: 6pt, + width: 100%, + [ + #set text(font: mono_font, size: 10pt) + #align(left)[ + song_id \ + artist_id \ + role + ] + ] + ) + ] +) + +#grid( + columns: (1fr, 1fr), + column-gutter: 1em, + [ + *Playlist Songs* + #v(-0.2em) + #rect( + fill: gray.lighten(80%), + stroke: 0.5pt, + radius: 2pt, + inset: 6pt, + width: 100%, + [ + #set text(font: mono_font, size: 10pt) + #align(left)[ + playlist_id \ + song_id \ + added_at + ] + ] + ) + ], + [ + *Song Comments* + #v(-0.2em) + #rect( + fill: gray.lighten(80%), + stroke: 0.5pt, + radius: 2pt, + inset: 6pt, + width: 100%, + [ + #set text(font: mono_font, size: 10pt) + #align(left)[ + user_id \ + song_id \ + comment_text + ] + ] + ) + ] +) + +== User Authentication & Roles + +User roles define the levels of access and permissions of different types of users within CoogMusic. Each role builds upon the previous, which creates a hierarchy that ranges from casual browsing to full administrative control. + +=== Roles + ++ *Unauthenticated User* - Can browse the site, view songs, artist profiles, and playlists. These users have limited access and cannot interact with the site beyond causal browsing. ++ *User* - Basic authenticated user. Can browse the site, like songs, comment on songs, follow artists, create playlists, and save tracks and playlists to their library. ++ *Artist* - Authenticated user that has registered as an artist. Has all the privileges of the basic authenticated user, but can also upload songs, update and delete their own songs, and upload and create albums. ++ *Admin* - Admins moderate content and manage user behavior. Has all the privileges of an authenticated user, but can update and delete songs, albums, and playlists, as well as update and ban users. + +=== Authentication System + +The CoogMusic authentication system implements server authentication with site-based sign-up and Google OAuth authentication, allowing users to sign up with their Google account. + ++ *Primary Authentication* - Email/password with `bcrypt` hashing. ++ *OAuth Integration* - OAuth allows users to sign up or log in using third-party authentication providers, including Google OAuth. ++ *Security* - JWT refresh and access tokens provide stateless authentication, allowing sessions to be maintained securely. CSRF protection prevents cross-site request forgery attacks. + +== Data Entry Forms + +Data entry forms provide a method for users and artists generate content for the platform. + ++ *Song Upload* + - Song metadata (title, genre, album) + - Audio file upload with format validation + - Cover art image upload + ++ *Album Creation* + - Album information (title, description, release date) + - Cover art upload + - Song selection + ++ *Playlist Management* + - Playlist metadata (title, description) + - Song addition/removal interface + - Playlist sharing options + ++ *User Profiles* + - Profile information (bio, profile picture) + - Account settings and preferences + ++ *Admin Management* + - Content moderation tools + - User management interface + - System configuration options + +== Data Queries + +Data queries are used to retrieve and serve relevant content to users, and to provide statistics and analytics to artists and admins. + ++ *General Site Queries* + - Song page (song, artist, album, comments, related songs) + - Album page (songs, artist, related albums) + - Playlist page (profile information, followers/following, uploaded songs) + ++ *Statistics/Insights* + - Site-wide statistics page + - Artist's 10 ten most played/liked songs + - User's most streamed songs + +== Data Reports + +Data reports consolidate information to create periodic and real-time analytics. + ++ *Monthly Site Analytics* + - Total new user registrations + - Song upload statistics by genre + - Most active users and artists + ++ *Realtime Analytics* + - Trending songs and albums + - Artist growth metrics (followers, plays) + - Genre popularity statistics + +== Triggers + +Database triggers are used to automate routine data operations. + ++ *Update Timestamp* + - Automatically update `updated_at` when a record in `Songs`, `Albums`, or `Playlists` is modified. + ++ *History Cleanup* + - Automatically delete rows from `user_history` older than 30 days whenever the table is updated. + +#set page( + columns: 1, +) + +== Schema Diagram + +#v(0.5em) + +#figure( + image("coog-music-schema.png", width: 100%), +) \ No newline at end of file From 28df5fe009f1c6322e96c31c548b3fbbb4466295 Mon Sep 17 00:00:00 2001 From: SHarmake Mohamud Date: Mon, 13 Oct 2025 19:11:26 -0500 Subject: [PATCH 03/22] Created Home Page and its Components --- client/public/PlayerBar/BackSong.svg | 3 + client/public/PlayerBar/Like.svg | 3 + client/public/PlayerBar/Mask group.png | Bin 0 -> 146150 bytes client/public/PlayerBar/MixSong.svg | 3 + client/public/PlayerBar/NextSong.svg | 3 + client/public/PlayerBar/Pause.svg | 3 + client/public/PlayerBar/Play.svg | 3 + client/public/PlayerBar/Playlist.svg | 3 + client/public/PlayerBar/Replay.svg | 3 + client/public/PlayerBar/Volume.svg | 3 + client/public/SideBar/Expand.svg | 4 + client/public/SideBar/Logo.svg | 6 + client/public/SideBar/LogoutButton.svg | 4 + client/public/SideBar/SongOrder.svg | 3 + client/public/SideBar/Vector-2.svg | 3 + client/public/SideBar/Vector-3.svg | 3 + client/public/SideBar/Vector-4.svg | 3 + client/public/TopBar/FeedButton.svg | 4 + client/public/TopBar/HomeButton.svg | 3 + client/public/TopBar/NotificationButton.svg | 3 + client/public/TopBar/ProfileButton.svg | 3 + client/public/TopBar/SettingButton.svg | 3 + client/src/Routes.tsx | 4 +- .../components/PlayerBar/playerBar.module.css | 138 +++++++++++++++ client/src/components/PlayerBar/playerBar.tsx | 57 +++++++ .../src/components/SideBar/sideBar.module.css | 70 ++++++++ client/src/components/SideBar/sidebar.tsx | 42 +++++ .../components/SongCard/SongCard.module.css | 105 ++++++++++++ client/src/components/SongCard/SongCard.tsx | 51 ++++++ .../src/components/TopBar/topBar.module.css | 89 ++++++++++ client/src/components/TopBar/topBar.tsx | 53 ++++++ client/src/pages/HomePage/HomePage.module.css | 158 ++++++++++++++++++ client/src/pages/HomePage/HomePage.tsx | 87 ++++++++++ .../HomePage/sections/FeaturedSection.tsx | 45 +++++ .../HomePage/sections/NewSongSection.tsx | 27 +++ .../pages/HomePage/sections/RecentSection.tsx | 34 ++++ .../HomePage/sections/Sections.module.css | 150 +++++++++++++++++ client/src/pages/TestPage/TestPage.tsx | 4 +- 38 files changed, 1180 insertions(+), 3 deletions(-) create mode 100644 client/public/PlayerBar/BackSong.svg create mode 100644 client/public/PlayerBar/Like.svg create mode 100644 client/public/PlayerBar/Mask group.png create mode 100644 client/public/PlayerBar/MixSong.svg create mode 100644 client/public/PlayerBar/NextSong.svg create mode 100644 client/public/PlayerBar/Pause.svg create mode 100644 client/public/PlayerBar/Play.svg create mode 100644 client/public/PlayerBar/Playlist.svg create mode 100644 client/public/PlayerBar/Replay.svg create mode 100644 client/public/PlayerBar/Volume.svg create mode 100644 client/public/SideBar/Expand.svg create mode 100644 client/public/SideBar/Logo.svg create mode 100644 client/public/SideBar/LogoutButton.svg create mode 100644 client/public/SideBar/SongOrder.svg create mode 100644 client/public/SideBar/Vector-2.svg create mode 100644 client/public/SideBar/Vector-3.svg create mode 100644 client/public/SideBar/Vector-4.svg create mode 100644 client/public/TopBar/FeedButton.svg create mode 100644 client/public/TopBar/HomeButton.svg create mode 100644 client/public/TopBar/NotificationButton.svg create mode 100644 client/public/TopBar/ProfileButton.svg create mode 100644 client/public/TopBar/SettingButton.svg create mode 100644 client/src/components/PlayerBar/playerBar.module.css create mode 100644 client/src/components/PlayerBar/playerBar.tsx create mode 100644 client/src/components/SideBar/sideBar.module.css create mode 100644 client/src/components/SideBar/sidebar.tsx create mode 100644 client/src/components/SongCard/SongCard.module.css create mode 100644 client/src/components/SongCard/SongCard.tsx create mode 100644 client/src/components/TopBar/topBar.module.css create mode 100644 client/src/components/TopBar/topBar.tsx create mode 100644 client/src/pages/HomePage/HomePage.module.css create mode 100644 client/src/pages/HomePage/HomePage.tsx create mode 100644 client/src/pages/HomePage/sections/FeaturedSection.tsx create mode 100644 client/src/pages/HomePage/sections/NewSongSection.tsx create mode 100644 client/src/pages/HomePage/sections/RecentSection.tsx create mode 100644 client/src/pages/HomePage/sections/Sections.module.css diff --git a/client/public/PlayerBar/BackSong.svg b/client/public/PlayerBar/BackSong.svg new file mode 100644 index 0000000..cf0d12c --- /dev/null +++ b/client/public/PlayerBar/BackSong.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/PlayerBar/Like.svg b/client/public/PlayerBar/Like.svg new file mode 100644 index 0000000..19d7b5e --- /dev/null +++ b/client/public/PlayerBar/Like.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/PlayerBar/Mask group.png b/client/public/PlayerBar/Mask group.png new file mode 100644 index 0000000000000000000000000000000000000000..cda21bd6c58169d48dbe436fcd0d971b14a802e7 GIT binary patch literal 146150 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≦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

lQ+) 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 + + diff --git a/client/public/PlayerBar/NextSong.svg b/client/public/PlayerBar/NextSong.svg new file mode 100644 index 0000000..54fcad3 --- /dev/null +++ b/client/public/PlayerBar/NextSong.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/PlayerBar/Pause.svg b/client/public/PlayerBar/Pause.svg new file mode 100644 index 0000000..931bb96 --- /dev/null +++ b/client/public/PlayerBar/Pause.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/PlayerBar/Play.svg b/client/public/PlayerBar/Play.svg new file mode 100644 index 0000000..b668cf4 --- /dev/null +++ b/client/public/PlayerBar/Play.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/PlayerBar/Playlist.svg b/client/public/PlayerBar/Playlist.svg new file mode 100644 index 0000000..eabc19f --- /dev/null +++ b/client/public/PlayerBar/Playlist.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/PlayerBar/Replay.svg b/client/public/PlayerBar/Replay.svg new file mode 100644 index 0000000..9435723 --- /dev/null +++ b/client/public/PlayerBar/Replay.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/PlayerBar/Volume.svg b/client/public/PlayerBar/Volume.svg new file mode 100644 index 0000000..81c5357 --- /dev/null +++ b/client/public/PlayerBar/Volume.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/SideBar/Expand.svg b/client/public/SideBar/Expand.svg new file mode 100644 index 0000000..76d9eed --- /dev/null +++ b/client/public/SideBar/Expand.svg @@ -0,0 +1,4 @@ + + + + diff --git a/client/public/SideBar/Logo.svg b/client/public/SideBar/Logo.svg new file mode 100644 index 0000000..a0bb7a3 --- /dev/null +++ b/client/public/SideBar/Logo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/client/public/SideBar/LogoutButton.svg b/client/public/SideBar/LogoutButton.svg new file mode 100644 index 0000000..0a8f9b6 --- /dev/null +++ b/client/public/SideBar/LogoutButton.svg @@ -0,0 +1,4 @@ + + + + diff --git a/client/public/SideBar/SongOrder.svg b/client/public/SideBar/SongOrder.svg new file mode 100644 index 0000000..761bdc5 --- /dev/null +++ b/client/public/SideBar/SongOrder.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/SideBar/Vector-2.svg b/client/public/SideBar/Vector-2.svg new file mode 100644 index 0000000..5ad6792 --- /dev/null +++ b/client/public/SideBar/Vector-2.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/SideBar/Vector-3.svg b/client/public/SideBar/Vector-3.svg new file mode 100644 index 0000000..e113f6b --- /dev/null +++ b/client/public/SideBar/Vector-3.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/SideBar/Vector-4.svg b/client/public/SideBar/Vector-4.svg new file mode 100644 index 0000000..9f05bef --- /dev/null +++ b/client/public/SideBar/Vector-4.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/TopBar/FeedButton.svg b/client/public/TopBar/FeedButton.svg new file mode 100644 index 0000000..c35f6c1 --- /dev/null +++ b/client/public/TopBar/FeedButton.svg @@ -0,0 +1,4 @@ + + + + diff --git a/client/public/TopBar/HomeButton.svg b/client/public/TopBar/HomeButton.svg new file mode 100644 index 0000000..6ff90a9 --- /dev/null +++ b/client/public/TopBar/HomeButton.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/TopBar/NotificationButton.svg b/client/public/TopBar/NotificationButton.svg new file mode 100644 index 0000000..7f8e8d3 --- /dev/null +++ b/client/public/TopBar/NotificationButton.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/TopBar/ProfileButton.svg b/client/public/TopBar/ProfileButton.svg new file mode 100644 index 0000000..b016a05 --- /dev/null +++ b/client/public/TopBar/ProfileButton.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/TopBar/SettingButton.svg b/client/public/TopBar/SettingButton.svg new file mode 100644 index 0000000..23ddf9b --- /dev/null +++ b/client/public/TopBar/SettingButton.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/src/Routes.tsx b/client/src/Routes.tsx index 1d02c9c..31021fa 100644 --- a/client/src/Routes.tsx +++ b/client/src/Routes.tsx @@ -1,10 +1,12 @@ import { Routes, Route } from "react-router-dom"; import * as Pages from "./pages"; +import HomePage from "./pages/HomePage/HomePage" export default function AppRoutes() { return ( - } /> + } /> + } /> ); } diff --git a/client/src/components/PlayerBar/playerBar.module.css b/client/src/components/PlayerBar/playerBar.module.css new file mode 100644 index 0000000..0597c5f --- /dev/null +++ b/client/src/components/PlayerBar/playerBar.module.css @@ -0,0 +1,138 @@ +.PlayerBar { + position: fixed; + bottom: 0; + left: 80px; /* Match sidebar width */ + right: 0; + height: 90px; + background-color: #121212; + border-top: 1px solid #222; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 16px; + z-index: 900; +} + +/* Left section - Song info */ +.playerInfo { + display: flex; + align-items: center; + gap: 12px; + min-width: 180px; + width: 30%; +} + +.playerImage { + width: 56px; + height: 56px; + border-radius: 4px; + object-fit: cover; +} + +.playerSong { + display: flex; + flex-direction: column; + gap: 4px; +} + +.playerSong p { + color: #fff; + margin: 0; + font-size: 14px; +} + +.playerSong span { + color: #a7a7a7; + font-size: 12px; +} + +/* Center section - Controls */ +.playerControls { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + flex: 1; + max-width: 722px; +} + +.playButtons { + display: flex; + align-items: center; + gap: 16px; + margin-bottom: 8px; +} + +.playButtons button { + background: none; + border: none; + padding: 8px; + cursor: pointer; + border-radius: 50%; + transition: all 0.2s ease; +} + +.playButtons button:hover { + background-color: rgba(255, 255, 255, 0.1); +} + +.playButton { + width: 32px; + height: 32px; +} + +/* Progress bar */ +.progressContainer { + width: 100%; + height: 4px; + background-color: #4d4d4d; + border-radius: 2px; + cursor: pointer; +} + +.progressBar { + height: 100%; + background-color: #fff; + border-radius: 2px; + width: 30%; /* Update dynamically with JS */ +} + +/* Right section - Volume */ +.playerExtra { + display: flex; + align-items: center; + gap: 16px; + min-width: 180px; + width: 30%; + justify-content: flex-end; +} + +.volumeControl { + display: flex; + align-items: center; + gap: 8px; +} + +.iconButton { + background: none; + border: none; + padding: 8px; + cursor: pointer; + border-radius: 50%; + transition: all 0.2s ease; +} + +.iconButton:hover { + background-color: rgba(255, 255, 255, 0.1); +} + +.iconButton img { + width: 20px; + height: 20px; + opacity: 0.7; + transition: opacity 0.2s ease; +} + +.iconButton:hover img { + opacity: 1; +} \ No newline at end of file diff --git a/client/src/components/PlayerBar/playerBar.tsx b/client/src/components/PlayerBar/playerBar.tsx new file mode 100644 index 0000000..19282c9 --- /dev/null +++ b/client/src/components/PlayerBar/playerBar.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import styles from './playerBar.module.css'; + +const PlayerBar: React.FC = () => { + return ( +

+ ); +}; + +export default PlayerBar; \ No newline at end of file diff --git a/client/src/components/SideBar/sideBar.module.css b/client/src/components/SideBar/sideBar.module.css new file mode 100644 index 0000000..f69e40d --- /dev/null +++ b/client/src/components/SideBar/sideBar.module.css @@ -0,0 +1,70 @@ +.sideBarContainer { + position: fixed; + top: 0; + left: 0; + width: 80px; + height: 100vh; + background-color: #111; + display: flex; + flex-direction: column; + align-items: center; + padding: 24px 0; + z-index: 1000; +} + +.sidebar-icons { + display: flex; + flex-direction: column; + align-items: center; + gap: 32px; + width: 100%; +} + +.sidebar-icon { + position: relative; + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; + border-radius: 8px; +} + +.sidebar-icon:hover { + transform: scale(1.1); + background-color: rgba(255, 59, 48, 0.1); +} + +.sidebar-icon img { + width: 24px; + height: 24px; + transition: all 0.2s ease; +} + +.sidebar-icon:hover img { + filter: brightness(1.2) sepia(1) saturate(3) hue-rotate(315deg); +} + +.logoContainer { + margin-bottom: 48px; +} + +.logoIcon { + width: 48px; + height: 48px; +} + +.active { + background-color: rgba(255, 59, 48, 0.15); +} + +.active img { + filter: brightness(1.2) sepia(1) saturate(3) hue-rotate(315deg); +} + +/* Push logout button to bottom */ +.sidebarBottom { + margin-top: auto; + padding-top: 32px; +} \ No newline at end of file diff --git a/client/src/components/SideBar/sidebar.tsx b/client/src/components/SideBar/sidebar.tsx new file mode 100644 index 0000000..90e82d8 --- /dev/null +++ b/client/src/components/SideBar/sidebar.tsx @@ -0,0 +1,42 @@ +import React, { useState } from 'react'; +import styles from './sideBar.module.css'; + +const Sidebar: React.FC = () => { + const [activeIcon, setActiveIcon] = useState('home'); + + const icons = [ + { id: 'expand', src: '/SideBar/Expand.svg', alt: 'Expand' }, + { id: 'songs', src: '/SideBar/SongOrder.svg', alt: 'Songs' }, + { id: 'playlists', src: '/SideBar/Vector-2.svg', alt: 'Playlists' }, + { id: 'artists', src: '/SideBar/Vector-3.svg', alt: 'Artists' }, + { id: 'albums', src: '/SideBar/Vector-4.svg', alt: 'Albums' }, + ]; + + return ( +
+
+
+ Logo +
+ + {icons.map(icon => ( +
setActiveIcon(icon.id)} + > + {icon.alt} +
+ ))} + +
+
+ Logout +
+
+
+
+ ); +}; + +export default Sidebar; \ No newline at end of file diff --git a/client/src/components/SongCard/SongCard.module.css b/client/src/components/SongCard/SongCard.module.css new file mode 100644 index 0000000..a63d038 --- /dev/null +++ b/client/src/components/SongCard/SongCard.module.css @@ -0,0 +1,105 @@ +.songCard { + background-color: #181818; + border-radius: 12px; + padding: 12px; + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + transition: background-color 0.2s ease, transform 0.2s ease; + cursor: pointer; +} + +.songCard:hover { + background-color: #202020; + transform: translateY(-4px); +} + +.imageContainer { + position: relative; + width: 100%; + aspect-ratio: 1 / 1; + border-radius: 8px; + overflow: hidden; +} + +.songImage { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: 8px; +} + +.overlay { + position: absolute; + inset: 0; + background-color: rgba(0, 0, 0, 0.4); + opacity: 0; + display: flex; + justify-content: center; + align-items: center; + transition: opacity 0.2s ease; +} + +.imageContainer:hover .overlay { + opacity: 1; +} + +.playButton { + width: 48px; + height: 48px; + background-color: #e63946; + border: none; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + transition: transform 0.2s ease, background-color 0.2s ease; +} + +.playButton:hover { + transform: scale(1.1); + background-color: #ff4d5a; +} + +.songInfo { + text-align: center; +} + +.songTitle { + font-weight: 600; + color: #ffffff; + margin-bottom: 4px; + font-size: 0.95rem; +} + +.songArtist { + font-size: 0.8rem; + color: #aaa; +} + +.songStats { + display: flex; + justify-content: space-around; + width: 100%; + margin-top: 8px; +} + +.statItem { + display: flex; + align-items: center; + gap: 6px; + color: #aaa; + font-size: 0.8rem; + transition: color 0.2s ease; +} + +.statItem:hover { + color: #fff; +} + +.statIcon { + width: 14px; + height: 14px; + fill: currentColor; +} \ No newline at end of file diff --git a/client/src/components/SongCard/SongCard.tsx b/client/src/components/SongCard/SongCard.tsx new file mode 100644 index 0000000..10925b1 --- /dev/null +++ b/client/src/components/SongCard/SongCard.tsx @@ -0,0 +1,51 @@ +import React from "react"; +import styles from "./SongCard.module.css"; + +export interface SongCardProps { + image: string; + title: string; + artist: string; + plays: number; + likes: number; + comments: number; +} + +const SongCard: React.FC = ({ + image, + title, + artist, + plays, + likes, + comments, +}) => { + return ( +
+
+ {title} +
+ +
+
+ +
+

{title}

+ {artist} +
+ +
+
+ {plays} +
+
+ {likes} +
+
+ {comments} +
+
+
+ ); +}; + +export default SongCard; \ No newline at end of file diff --git a/client/src/components/TopBar/topBar.module.css b/client/src/components/TopBar/topBar.module.css new file mode 100644 index 0000000..ead8427 --- /dev/null +++ b/client/src/components/TopBar/topBar.module.css @@ -0,0 +1,89 @@ +.topBarContainer { + position: fixed; + top: 0; + left: 80px; /* Match sidebar width */ + right: 0; + height: 64px; + background-color: #181818; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 24px; + z-index: 900; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + +.topBarNav { + display: flex; + align-items: center; + gap: 16px; +} + +.navButton { + background: none; + border: none; + padding: 8px; + cursor: pointer; + transition: all 0.2s ease; + border-radius: 8px; +} + +.navButton:hover { + background-color: rgba(255, 255, 255, 0.1); +} + +.navIcon { + width: 24px; + height: 24px; + opacity: 0.8; + transition: opacity 0.2s ease; +} + +.navButton:hover .navIcon { + opacity: 1; +} + +.searchContainer { + flex: 1; + max-width: 600px; + margin: 0 32px; +} + +.searchInput { + width: 100%; + height: 40px; + background-color: rgba(255, 255, 255, 0.1); + border: none; + border-radius: 20px; + padding: 0 16px; + color: white; + font-size: 14px; +} + +.searchInput::placeholder { + color: rgba(255, 255, 255, 0.5); +} + +.searchInput:focus { + outline: none; + background-color: rgba(255, 255, 255, 0.15); +} + +.rightSection { + display: flex; + align-items: center; + gap: 16px; +} + +.iconButton { + background: none; + border: none; + padding: 8px; + cursor: pointer; + transition: all 0.2s ease; + border-radius: 50%; +} + +.iconButton:hover { + background-color: rgba(255, 255, 255, 0.1); +} \ No newline at end of file diff --git a/client/src/components/TopBar/topBar.tsx b/client/src/components/TopBar/topBar.tsx new file mode 100644 index 0000000..559d938 --- /dev/null +++ b/client/src/components/TopBar/topBar.tsx @@ -0,0 +1,53 @@ +import React from "react"; +import styles from "./topBar.module.css" +; +const HomeButton = "../../../public/TopBar/HomeButton.svg"; +const FeedButton = "../../../public/TopBar/FeedButton.svg"; +const NotificationButton = "../../../public/TopBar/NotificationButton.svg"; +const SettingButton = "../../../public/TopBar/SettingButton.svg"; +const ProfileButton = "../../../public/TopBar/ProfileButton.svg"; + + +const TopBar: React.FC = () => { + return ( +
+ {/* Navigation Buttons */} +
+ + + +
+ + {/* Search Bar */} +
+ +
+ + {/* Profile, Settings, Notifications */} +
+ + + + + +
+
+ ); +}; +export default TopBar; \ No newline at end of file diff --git a/client/src/pages/HomePage/HomePage.module.css b/client/src/pages/HomePage/HomePage.module.css new file mode 100644 index 0000000..d76c750 --- /dev/null +++ b/client/src/pages/HomePage/HomePage.module.css @@ -0,0 +1,158 @@ +/* Reset and variables */ +:root { + --sidebar-width: 80px; + --topbar-height: 64px; + --player-height: 90px; + --content-padding: 32px; + --background-dark: #0d0d0d; + --text-primary: #ffffff; + --text-secondary: #b3b3b3; +} + +/* Main content area */ +.contentArea { + position: fixed; + top: var(--topbar-height); + left: var(--sidebar-width); + right: 0; + bottom: var(--player-height); + overflow-y: auto; + background: var(--background-dark); + color: var(--text-primary); +} + +/* Content wrapper with padding */ +.contentWrapper { + padding: var(--content-padding); + display: flex; + flex-direction: column; + gap: 48px; + max-width: 1800px; + margin: 0 auto; +} + +/* Section styling */ +.section { + display: flex; + flex-direction: column; + gap: 24px; +} + +/* Section header row */ +.sectionHeader { + display: flex; + justify-content: space-between; + align-items: center; + padding-right: 8px; +} + +.sectionTitle { + font-size: 24px; + font-weight: 700; + margin: 0; +} + +.viewMore { + color: var(--text-secondary); + text-decoration: none; + font-size: 14px; + transition: color 0.2s ease; +} + +.viewMore:hover { + color: var(--text-primary); +} + +/* Horizontal scrollable container */ +.cardsContainer { + display: flex; + gap: 24px; + overflow-x: auto; + padding: 4px 0; + /* Hide scrollbar but keep functionality */ + scrollbar-width: none; + -ms-overflow-style: none; +} + +.cardsContainer::-webkit-scrollbar { + display: none; +} + +.topGrid { + display: grid; + grid-template-columns: 65% 35%; + gap: 40px; + margin-bottom: 48px; +} + +/* Featured section adjustments */ +.featuredSection { + height: 100%; + min-height: 400px; + padding: 40px; + background: linear-gradient(90deg, #ff3b30 0%, #ff6a4a 100%); + border-radius: 16px; + display: flex; + flex-direction: column; + justify-content: center; +} + +/* Recently played column */ +.recentlyPlayedColumn { + display: flex; + flex-direction: column; + gap: 24px; + height: 100%; +} + +/* Vertical scrollable list for recently played */ +.verticalCardsList { + display: flex; + flex-direction: column; + gap: 16px; + overflow-y: auto; + height: calc(400px - 48px); /* Match featured height minus header */ + padding-right: 16px; +} + +/* Compact song card style for sidebar */ +.compactCard { + background: rgba(255, 255, 255, 0.05); + border-radius: 8px; + padding: 12px; + display: flex; + align-items: center; + gap: 12px; + transition: background-color 0.2s ease; +} + +.compactCard:hover { + background: rgba(255, 255, 255, 0.1); +} + +.compactCard img { + width: 48px; + height: 48px; + border-radius: 4px; + object-fit: cover; +} + +.compactCard .songInfo { + flex: 1; + min-width: 0; +} + +.compactCard .songTitle { + font-size: 14px; + font-weight: 600; + margin: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.compactCard .artistName { + font-size: 12px; + color: var(--text-secondary); + margin: 4px 0 0; +} \ No newline at end of file diff --git a/client/src/pages/HomePage/HomePage.tsx b/client/src/pages/HomePage/HomePage.tsx new file mode 100644 index 0000000..d3d116f --- /dev/null +++ b/client/src/pages/HomePage/HomePage.tsx @@ -0,0 +1,87 @@ +import React from "react"; +import styles from "./HomePage.module.css"; +import Sidebar from "../../components/SideBar/sidebar"; +import Topbar from "../../components/TopBar/topBar"; +import PlayerBar from "../../components/PlayerBar/playerBar"; +import FeaturedSection from "./sections/FeaturedSection"; +import SongCard from "../../components/SongCard/SongCard"; + +const HomePage: React.FC = () => { + // Mock data + const recentSongs = Array(8).fill({ + title: "Song Title", + artist: "Artist Name", + image: "/PlayerBar/Mask group.png", + plays: 1234, + likes: 234, + comments: 12, + }); + + const newSongs = Array(5).fill({ + title: "New Release", + artist: "Artist Name", + image: "/PlayerBar/Mask group.png", + }); + + return ( + <> + + + +
+ + + + ); +}; + +export default HomePage; \ No newline at end of file diff --git a/client/src/pages/HomePage/sections/FeaturedSection.tsx b/client/src/pages/HomePage/sections/FeaturedSection.tsx new file mode 100644 index 0000000..3d71e43 --- /dev/null +++ b/client/src/pages/HomePage/sections/FeaturedSection.tsx @@ -0,0 +1,45 @@ +import React from "react"; +import styles from "./Sections.module.css"; + + +interface FeaturedSectionProps { + title: string; + description: string; + image: string; + likes: number; + tracks: number; + duration: string; +} + +const FeaturedSection: React.FC = ({ + title, + description, + image, + likes, + tracks, + duration, +}) => ( +
+
+

Featured Playlist

+

{title}

+

{description}

+
+ + {likes.toLocaleString()} likes + • {tracks} tracks + • {duration} +
+
+ +
+
+ {title} + +
+
+
+); + +export default FeaturedSection; \ No newline at end of file diff --git a/client/src/pages/HomePage/sections/NewSongSection.tsx b/client/src/pages/HomePage/sections/NewSongSection.tsx new file mode 100644 index 0000000..0ad24a2 --- /dev/null +++ b/client/src/pages/HomePage/sections/NewSongSection.tsx @@ -0,0 +1,27 @@ +import React from "react"; +import styles from "./Sections.module.css"; + +interface NewSongsSectionProps { + title: string; + songs: { image: string; title: string }[]; +} + +const NewSongsSection: React.FC = ({ title, songs }) => ( +
+
+

{title}

+ +
+ +
+ {songs.map((song, index) => ( +
+ {song.title} +

{song.title}

+
+ ))} +
+
+); + +export default NewSongsSection; \ No newline at end of file diff --git a/client/src/pages/HomePage/sections/RecentSection.tsx b/client/src/pages/HomePage/sections/RecentSection.tsx new file mode 100644 index 0000000..c6a4948 --- /dev/null +++ b/client/src/pages/HomePage/sections/RecentSection.tsx @@ -0,0 +1,34 @@ +import React from "react"; +import styles from "./Sections.module.css"; +import SongCard from "../../../components/SongCard/SongCard"; + +interface Song { + image: string; + title: string; + artist: string; + plays: number; + likes: number; + comments: number; +} + +interface RecentSongsSectionProps { + title: string; + songs: Song[]; +} + +const RecentSongsSection: React.FC = ({ title, songs }) => ( +
+
+

{title}

+ +
+ +
+ {songs.map((song, index) => ( + + ))} +
+
+); + +export default RecentSongsSection; \ No newline at end of file diff --git a/client/src/pages/HomePage/sections/Sections.module.css b/client/src/pages/HomePage/sections/Sections.module.css new file mode 100644 index 0000000..0e4f1a1 --- /dev/null +++ b/client/src/pages/HomePage/sections/Sections.module.css @@ -0,0 +1,150 @@ +.homeGrid { + display: grid; + grid-template-columns: 1fr; + gap: 40px; + padding: 24px; +} + +.section { + display: flex; + flex-direction: column; + gap: 20px; +} + +.sectionHeader { + display: flex; + justify-content: space-between; + align-items: center; +} + +.sectionHeader h2 { + font-size: 1.4rem; + font-weight: 600; +} + +.viewMore { + background: none; + border: none; + color: #aaa; + cursor: pointer; + transition: color 0.2s; +} + +.viewMore:hover { + color: #fff; +} + +.featuredSection { + display: flex; + background: linear-gradient(to right, #7a1c1c, #c42b2b); + padding: 24px; + border-radius: 12px; + height: 400px; + color: #fff; + align-items: center; +} + +.featuredLeft { + flex: 1; +} + +.featuredSubtitle { + font-size: 0.8rem; + color: #eee; + text-transform: uppercase; +} + +.featuredTitle { + font-size: 2rem; + font-weight: 700; + margin: 8px 0; +} + +.featuredDescription { + color: #ddd; + margin-bottom: 12px; + line-height: 1.5; +} + +.featuredMeta { + display: flex; + align-items: center; + gap: 10px; + font-size: 0.9rem; + color: #eee; +} + +.featuredRight { + display: flex; + justify-content: center; + align-items: center; +} + +.featuredImageContainer { + position: relative; +} + +.featuredImage { + width: 320px; + max-width: 40%; + height: auto; + border-radius: 8px; + object-fit: cover; +} + +.playButton { + position: absolute; + inset: 0; + background-color: rgba(0, 0, 0, 0.4); + display: flex; + align-items: center; + justify-content: center; + border: none; + border-radius: 8px; + opacity: 0; + transition: opacity 0.2s ease; + cursor: pointer; +} + +.featuredImageContainer:hover .playButton { + opacity: 1; +} + +.songGrid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); + gap: 16px; +} + +.newSongsRow { + display: flex; + gap: 16px; + overflow-x: auto; + padding-bottom: 8px; +} + +.newSongCard { + flex-shrink: 0; + width: 180px; + display: flex; + flex-direction: column; + align-items: center; +} + +.newSongImage { + width: 100%; + height: 180px; + border-radius: 8px; + object-fit: cover; + transition: opacity 0.2s; +} + +.newSongImage:hover { + opacity: 0.8; +} + +.newSongTitle { + margin-top: 8px; + color: #ccc; + font-size: 0.9rem; +} \ No newline at end of file diff --git a/client/src/pages/TestPage/TestPage.tsx b/client/src/pages/TestPage/TestPage.tsx index f45f713..8d87d0e 100644 --- a/client/src/pages/TestPage/TestPage.tsx +++ b/client/src/pages/TestPage/TestPage.tsx @@ -33,12 +33,12 @@ const TestPage: React.FC = () => { Test Page - +

Test Page

- +
diff --git a/client/src/components/index.ts b/client/src/components/index.ts index e69de29..1c35700 100644 --- a/client/src/components/index.ts +++ b/client/src/components/index.ts @@ -0,0 +1 @@ +export { default as SongCard } from './SongCard/SongCard'; \ No newline at end of file diff --git a/client/src/pages/SearchResultsPage/SearchResultsPage.module.css b/client/src/pages/SearchResultsPage/SearchResultsPage.module.css index e69de29..981bc72 100644 --- a/client/src/pages/SearchResultsPage/SearchResultsPage.module.css +++ b/client/src/pages/SearchResultsPage/SearchResultsPage.module.css @@ -0,0 +1,42 @@ +.container { + padding: 20px; + max-width: 1200px; + margin: 0 auto; +} + +.header { + margin-bottom: 24px; +} + +.filters { + display: flex; + gap: 16px; + margin-bottom: 24px; +} + +.results { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: 24px; +} + +.noResults { + text-align: center; + padding: 48px 0; + color: #666; +} + +.filterButton { + padding: 8px 16px; + border: 1px solid #ddd; + border-radius: 20px; + background: transparent; + cursor: pointer; + transition: all 0.2s ease; +} + +.filterButton.active { + background: #1db954; + color: white; + border-color: #1db954; +} diff --git a/client/src/pages/SearchResultsPage/SearchResultsPage.tsx b/client/src/pages/SearchResultsPage/SearchResultsPage.tsx index e69de29..2bf365c 100644 --- a/client/src/pages/SearchResultsPage/SearchResultsPage.tsx +++ b/client/src/pages/SearchResultsPage/SearchResultsPage.tsx @@ -0,0 +1,161 @@ +import { useState } from 'react'; +import { useSearchParams } from 'react-router-dom'; +import styles from './SearchResultsPage.module.css'; +import homeStyles from "../HomePage/HomePage.module.css"; +import Sidebar from "../../components/SideBar/sidebar"; +import Topbar from "../../components/TopBar/topBar"; +import PlayerBar from "../../components/PlayerBar/playerBar"; +import { SongCard } from '../../components'; + +// Mock data types +interface Song { + id: string; + title: string; + artist: string; + image: string; + plays: number; + likes: number; + comments: number; +} + +interface Artist { + id: string; + name: string; + image: string; + plays: number; + likes: number; + comments: number; +} + +interface Album { + id: string; + title: string; + artist: string; + image: string; + plays: number; + likes: number; + comments: number; +} + +// Mock data for development +const mockData = { + songs: [ + { id: '1', title: 'Shape of You', artist: 'Ed Sheeran', image: 'https://via.placeholder.com/150', plays: 1000000, likes: 50000, comments: 2500 }, + { id: '2', title: 'Blinding Lights', artist: 'The Weeknd', image: 'https://via.placeholder.com/150', plays: 800000, likes: 45000, comments: 2000 }, + { id: '3', title: 'Stay', artist: 'Kid Laroi & Justin Bieber', image: 'https://via.placeholder.com/150', plays: 600000, likes: 35000, comments: 1500 }, + ], + artists: [ + { id: '1', name: 'Ed Sheeran', image: 'https://via.placeholder.com/150', plays: 5000000, likes: 200000, comments: 15000 }, + { id: '2', name: 'The Weeknd', image: 'https://via.placeholder.com/150', plays: 4500000, likes: 180000, comments: 12000 }, + { id: '3', name: 'Justin Bieber', image: 'https://via.placeholder.com/150', plays: 4000000, likes: 160000, comments: 10000 }, + ], + albums: [ + { id: '1', title: '÷ (Divide)', artist: 'Ed Sheeran', image: 'https://via.placeholder.com/150', plays: 3000000, likes: 150000, comments: 8000 }, + { id: '2', title: 'After Hours', artist: 'The Weeknd', image: 'https://via.placeholder.com/150', plays: 2500000, likes: 120000, comments: 6000 }, + { id: '3', title: 'Justice', artist: 'Justin Bieber', image: 'https://via.placeholder.com/150', plays: 2000000, likes: 100000, comments: 5000 }, + ], +}; + +type ResultType = 'all' | 'songs' | 'artists' | 'albums'; + +export default function SearchResultsPage() { + const [searchParams] = useSearchParams(); + const query = searchParams.get('q') || ''; + const [activeFilter, setActiveFilter] = useState('all'); + + // Filter results based on search query and active filter + const getFilteredResults = () => { + const filterMap: Record> = { + songs: mockData.songs.filter(song => + song.title.toLowerCase().includes(query.toLowerCase()) || + song.artist.toLowerCase().includes(query.toLowerCase()) + ), + artists: mockData.artists.filter(artist => + artist.name.toLowerCase().includes(query.toLowerCase()) + ), + albums: mockData.albums.filter(album => + album.title.toLowerCase().includes(query.toLowerCase()) || + album.artist.toLowerCase().includes(query.toLowerCase()) + ), + }; + + if (activeFilter === 'all') { + return { + songs: filterMap.songs, + artists: filterMap.artists, + albums: filterMap.albums, + }; + } + + return { + [activeFilter]: filterMap[activeFilter], + }; + }; + + const filteredResults = getFilteredResults(); + + return ( + <> + + + +
+
+
+
+
+

Search Results for "{query}"

+
+ +
+ {(['all', 'songs', 'artists', 'albums'] as ResultType[]).map((filter) => ( + + ))} +
+ +
+ {Object.entries(filteredResults).map(([type, items]) => ( + items.length > 0 && ( +
+

{type.charAt(0).toUpperCase() + type.slice(1)}

+
+ {items.map((item) => { + const isArtist = (item: any): item is Artist => 'name' in item; + return ( + + ); + })} +
+
+ ) + ))} + + {Object.values(filteredResults).every((items: any) => items.length === 0) && ( +
+ No results found for "{query}" +
+ )} +
+
+
+
+
+ + + + ); +} diff --git a/client/src/pages/index.ts b/client/src/pages/index.ts index 4a389c3..e5ede7d 100644 --- a/client/src/pages/index.ts +++ b/client/src/pages/index.ts @@ -1 +1,2 @@ export { default as TestPage } from "./TestPage/TestPage.js"; +export { default as SearchResultsPage } from "./SearchResultsPage/SearchResultsPage"; diff --git a/server/src/server.ts b/server/src/server.ts index 62e3979..562e981 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -1,9 +1,11 @@ import express from "express"; import cookieParser from "cookie-parser"; import cors from "cors"; +import helmet from "helmet"; import path from "path"; import dotenv from "dotenv"; import { testConnection } from "config/database"; +import { generalRateLimit } from "./middleware/rateLimiting.middleware.js"; import * as Routes from "@routes"; @@ -25,11 +27,30 @@ const corsOptions = { : process.env.CLIENT_URL || "http://localhost:5173", credentials: true, methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], - allowedHeaders: ["Content-Type", "Authorization"], + allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With"], }; app.use(cors(corsOptions)); +// Security middleware +app.use( + helmet({ + contentSecurityPolicy: { + directives: { + defaultSrc: ["'self'"], + styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"], + fontSrc: ["'self'", "https://fonts.gstatic.com"], + imgSrc: ["'self'", "data:", "https:"], + scriptSrc: ["'self'"], + }, + }, + crossOriginEmbedderPolicy: false, + }) +); + +// General rate limiting +// app.use(generalRateLimit); + // Body parsing middleware app.use(express.json({ limit: "10mb" })); app.use(express.urlencoded({ extended: true, limit: "10mb" })); @@ -51,7 +72,13 @@ const clientDistPath = path.join(__dirname, "public"); app.use(express.static(clientDistPath)); // Routes -app.use("/api/songs", Routes.songRoutes); +app.use("/api/auth", Routes.authRoutes); +// app.use("/api/songs", Routes.songRoutes); // temporarily disabled for local dev without Azure +app.use("/api/albums", Routes.albumRoutes); +app.use("/api/artists", Routes.artistRoutes); +app.use("/api/playlists", Routes.playlistRoutes); +app.use("/api/users", Routes.userRoutes); +app.use("/api/search", Routes.searchRoutes); // React SPA routes app.get("/", (req, res) => { @@ -79,4 +106,4 @@ async function startServer() { } } -startServer(); +startServer(); \ No newline at end of file From daae206fa863a73982930b392dd855d8e9dc5158 Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Sun, 26 Oct 2025 22:24:14 -0500 Subject: [PATCH 07/22] Update SearchResultsPage.tsx --- .../SearchResultsPage/SearchResultsPage.tsx | 142 +----------------- 1 file changed, 1 insertion(+), 141 deletions(-) diff --git a/client/src/pages/SearchResultsPage/SearchResultsPage.tsx b/client/src/pages/SearchResultsPage/SearchResultsPage.tsx index 2bf365c..e4c8ee8 100644 --- a/client/src/pages/SearchResultsPage/SearchResultsPage.tsx +++ b/client/src/pages/SearchResultsPage/SearchResultsPage.tsx @@ -1,99 +1,9 @@ -import { useState } from 'react'; -import { useSearchParams } from 'react-router-dom'; -import styles from './SearchResultsPage.module.css'; import homeStyles from "../HomePage/HomePage.module.css"; import Sidebar from "../../components/SideBar/sidebar"; import Topbar from "../../components/TopBar/topBar"; import PlayerBar from "../../components/PlayerBar/playerBar"; -import { SongCard } from '../../components'; - -// Mock data types -interface Song { - id: string; - title: string; - artist: string; - image: string; - plays: number; - likes: number; - comments: number; -} - -interface Artist { - id: string; - name: string; - image: string; - plays: number; - likes: number; - comments: number; -} - -interface Album { - id: string; - title: string; - artist: string; - image: string; - plays: number; - likes: number; - comments: number; -} - -// Mock data for development -const mockData = { - songs: [ - { id: '1', title: 'Shape of You', artist: 'Ed Sheeran', image: 'https://via.placeholder.com/150', plays: 1000000, likes: 50000, comments: 2500 }, - { id: '2', title: 'Blinding Lights', artist: 'The Weeknd', image: 'https://via.placeholder.com/150', plays: 800000, likes: 45000, comments: 2000 }, - { id: '3', title: 'Stay', artist: 'Kid Laroi & Justin Bieber', image: 'https://via.placeholder.com/150', plays: 600000, likes: 35000, comments: 1500 }, - ], - artists: [ - { id: '1', name: 'Ed Sheeran', image: 'https://via.placeholder.com/150', plays: 5000000, likes: 200000, comments: 15000 }, - { id: '2', name: 'The Weeknd', image: 'https://via.placeholder.com/150', plays: 4500000, likes: 180000, comments: 12000 }, - { id: '3', name: 'Justin Bieber', image: 'https://via.placeholder.com/150', plays: 4000000, likes: 160000, comments: 10000 }, - ], - albums: [ - { id: '1', title: '÷ (Divide)', artist: 'Ed Sheeran', image: 'https://via.placeholder.com/150', plays: 3000000, likes: 150000, comments: 8000 }, - { id: '2', title: 'After Hours', artist: 'The Weeknd', image: 'https://via.placeholder.com/150', plays: 2500000, likes: 120000, comments: 6000 }, - { id: '3', title: 'Justice', artist: 'Justin Bieber', image: 'https://via.placeholder.com/150', plays: 2000000, likes: 100000, comments: 5000 }, - ], -}; - -type ResultType = 'all' | 'songs' | 'artists' | 'albums'; export default function SearchResultsPage() { - const [searchParams] = useSearchParams(); - const query = searchParams.get('q') || ''; - const [activeFilter, setActiveFilter] = useState('all'); - - // Filter results based on search query and active filter - const getFilteredResults = () => { - const filterMap: Record> = { - songs: mockData.songs.filter(song => - song.title.toLowerCase().includes(query.toLowerCase()) || - song.artist.toLowerCase().includes(query.toLowerCase()) - ), - artists: mockData.artists.filter(artist => - artist.name.toLowerCase().includes(query.toLowerCase()) - ), - albums: mockData.albums.filter(album => - album.title.toLowerCase().includes(query.toLowerCase()) || - album.artist.toLowerCase().includes(query.toLowerCase()) - ), - }; - - if (activeFilter === 'all') { - return { - songs: filterMap.songs, - artists: filterMap.artists, - albums: filterMap.albums, - }; - } - - return { - [activeFilter]: filterMap[activeFilter], - }; - }; - - const filteredResults = getFilteredResults(); - return ( <> @@ -101,57 +11,7 @@ export default function SearchResultsPage() {
-
-
-
-

Search Results for "{query}"

-
- -
- {(['all', 'songs', 'artists', 'albums'] as ResultType[]).map((filter) => ( - - ))} -
- -
- {Object.entries(filteredResults).map(([type, items]) => ( - items.length > 0 && ( -
-

{type.charAt(0).toUpperCase() + type.slice(1)}

-
- {items.map((item) => { - const isArtist = (item: any): item is Artist => 'name' in item; - return ( - - ); - })} -
-
- ) - ))} - - {Object.values(filteredResults).every((items: any) => items.length === 0) && ( -
- No results found for "{query}" -
- )} -
-
-
+ {/* Intentionally left blank for now. Search bar in TopBar remains active. */}
From ce8c7389f4a6aa5d80728a128cce006c25d5383c Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Mon, 27 Oct 2025 00:33:58 -0500 Subject: [PATCH 08/22] added songs, albums, playlists, and artists rows --- client/src/components/SongCard/SongCard.tsx | 25 ++-- .../SearchResultsPage/SearchResultsPage.tsx | 122 +++++++++++++++++- 2 files changed, 135 insertions(+), 12 deletions(-) diff --git a/client/src/components/SongCard/SongCard.tsx b/client/src/components/SongCard/SongCard.tsx index 10925b1..844b79b 100644 --- a/client/src/components/SongCard/SongCard.tsx +++ b/client/src/components/SongCard/SongCard.tsx @@ -8,6 +8,7 @@ export interface SongCardProps { plays: number; likes: number; comments: number; + showStats?: boolean; } const SongCard: React.FC = ({ @@ -17,6 +18,7 @@ const SongCard: React.FC = ({ plays, likes, comments, + showStats = true, }) => { return (
@@ -32,18 +34,19 @@ const SongCard: React.FC = ({

{title}

{artist}
- -
-
- {plays} -
-
- {likes} + {showStats && ( +
+
+ {plays} +
+
+ {likes} +
+
+ {comments} +
-
- {comments} -
-
+ )}
); }; diff --git a/client/src/pages/SearchResultsPage/SearchResultsPage.tsx b/client/src/pages/SearchResultsPage/SearchResultsPage.tsx index e4c8ee8..7779d0e 100644 --- a/client/src/pages/SearchResultsPage/SearchResultsPage.tsx +++ b/client/src/pages/SearchResultsPage/SearchResultsPage.tsx @@ -2,16 +2,136 @@ import homeStyles from "../HomePage/HomePage.module.css"; import Sidebar from "../../components/SideBar/sidebar"; import Topbar from "../../components/TopBar/topBar"; import PlayerBar from "../../components/PlayerBar/playerBar"; +import SongCard from "../../components/SongCard/SongCard"; export default function SearchResultsPage() { + // Mock data for recently played + const recentSongs = Array(4).fill({ + title: "Song Title", + artist: "Artist Name", + image: "/PlayerBar/Mask group.png", + plays: 1234, + likes: 234, + comments: 12, + }); + + // Mock data for artists, albums, playlists + const newArtists = Array(8).fill({ + name: "Artist Name", + image: "/PlayerBar/Mask group.png", + plays: 321000, + likes: 12345, + comments: 456, + }); + + const newAlbums = Array(8).fill({ + title: "Album Title", + artist: "Artist Name", + image: "/PlayerBar/Mask group.png", + plays: 210000, + likes: 9876, + comments: 321, + }); + + const newPlaylists = Array(8).fill({ + title: "Playlist Name", + artist: "User Name", + image: "/PlayerBar/Mask group.png", + plays: 150000, + likes: 5432, + comments: 210, + }); return ( <> +
- {/* Intentionally left blank for now. Search bar in TopBar remains active. */} +
+
+

Songs

+ View More +
+
+ {recentSongs.map((song, index) => ( +
+ {song.title} +
+

{song.title}

+

{song.artist}

+
+
+ ))} +
+
+ + {/* Artists Section */} +
+
+

Artists

+ View More +
+
+ {newArtists.map((artist, index) => ( + + ))} +
+
+ + {/* Albums Section */} +
+
+

Albums

+ View More +
+
+ {newAlbums.map((album, index) => ( + + ))} +
+
+ + {/* Playlists Section */} +
+
+

Playlists

+ View More +
+
+ {newPlaylists.map((pl, index) => ( + + ))} +
+
From 474897e6be92b9a3642d48a4c4cc2e0f574c67bf Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Mon, 27 Oct 2025 02:21:27 -0500 Subject: [PATCH 09/22] Need to verify database connection --- client/src/api/api.ts | 9 +- client/src/api/search.api.ts | 62 +++++ .../SearchResultsPage/SearchResultsPage.tsx | 230 +++++++++--------- client/vite.config.ts | 2 +- server/src/config/blobStorage.ts | 46 +++- server/src/config/database.ts | 33 ++- server/src/routes/search.routes.ts | 112 +++++++++ server/src/server.ts | 35 ++- 8 files changed, 390 insertions(+), 139 deletions(-) create mode 100644 client/src/api/search.api.ts diff --git a/client/src/api/api.ts b/client/src/api/api.ts index 1da052d..1c96857 100644 --- a/client/src/api/api.ts +++ b/client/src/api/api.ts @@ -2,8 +2,15 @@ import axios from "axios"; const API_BASE_URL = import.meta.env.VITE_API_URL; +// Ensure the baseURL always points to the API root. If a full server URL is +// provided (e.g., http://localhost:8080), append "/api". Otherwise, default +// to the Vite dev proxy on "/api" so requests are proxied during development. +const resolvedBaseUrl = API_BASE_URL + ? `${API_BASE_URL.replace(/\/$/, "")}/api` + : "/api"; + const api = axios.create({ - baseURL: API_BASE_URL || "/api", + baseURL: resolvedBaseUrl, timeout: 30000, headers: { "Content-Type": "application/json", diff --git a/client/src/api/search.api.ts b/client/src/api/search.api.ts new file mode 100644 index 0000000..fd0a8fa --- /dev/null +++ b/client/src/api/search.api.ts @@ -0,0 +1,62 @@ +import api from "./api"; + +export type SearchType = "all" | "songs" | "artists" | "albums" | "playlists"; + +export interface SearchSong { + id: string | number; + title: string; + artist: string; + image: string; + plays: number; + likes: number; + comments: number; + duration?: number; +} + +export interface SearchArtist { + id: string | number; + name: string; + image: string; + plays: number; + likes?: number; + comments?: number; +} + +export interface SearchAlbum { + id: string | number; + title: string; + artist: string; + image: string; + release_date?: string; + plays?: number; + likes?: number; + comments?: number; +} + +export interface SearchPlaylist { + id: string | number; + title: string; + artist: string; + image: string; + plays?: number; + likes?: number; + comments?: number; +} + +export interface SearchResponse { + songs?: SearchSong[]; + artists?: SearchArtist[]; + albums?: SearchAlbum[]; + playlists?: SearchPlaylist[]; +} + +export async function fetchSearch( + q: string, + type: SearchType = "all", + limit = 20, + offset = 0 +): Promise { + const params = { q, type, limit, offset }; + const { data } = await api.get(`/search`, { params }); + return data; +} diff --git a/client/src/pages/SearchResultsPage/SearchResultsPage.tsx b/client/src/pages/SearchResultsPage/SearchResultsPage.tsx index 7779d0e..7333bd6 100644 --- a/client/src/pages/SearchResultsPage/SearchResultsPage.tsx +++ b/client/src/pages/SearchResultsPage/SearchResultsPage.tsx @@ -1,46 +1,45 @@ +import { useEffect, useState } from "react"; +import { useSearchParams } from "react-router-dom"; import homeStyles from "../HomePage/HomePage.module.css"; import Sidebar from "../../components/SideBar/sidebar"; import Topbar from "../../components/TopBar/topBar"; import PlayerBar from "../../components/PlayerBar/playerBar"; import SongCard from "../../components/SongCard/SongCard"; +import { fetchSearch, type SearchResponse } from "../../api/search.api"; export default function SearchResultsPage() { - // Mock data for recently played - const recentSongs = Array(4).fill({ - title: "Song Title", - artist: "Artist Name", - image: "/PlayerBar/Mask group.png", - plays: 1234, - likes: 234, - comments: 12, - }); + const [searchParams] = useSearchParams(); + const query = searchParams.get("q") ?? ""; - // Mock data for artists, albums, playlists - const newArtists = Array(8).fill({ - name: "Artist Name", - image: "/PlayerBar/Mask group.png", - plays: 321000, - likes: 12345, - comments: 456, - }); + const [results, setResults] = useState({}); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); - const newAlbums = Array(8).fill({ - title: "Album Title", - artist: "Artist Name", - image: "/PlayerBar/Mask group.png", - plays: 210000, - likes: 9876, - comments: 321, - }); + useEffect(() => { + if (!query.trim()) return; + + const loadResults = async () => { + setLoading(true); + setError(null); + try { + const data = await fetchSearch(query, "all", 20, 0); + setResults(data); + } catch (err) { + console.error("Search failed:", err); + setError("Failed to load search results. Please try again."); + } finally { + setLoading(false); + } + }; + + loadResults(); + }, [query]); + + const songs = results.songs ?? []; + const artists = results.artists ?? []; + const albums = results.albums ?? []; + const playlists = results.playlists ?? []; - const newPlaylists = Array(8).fill({ - title: "Playlist Name", - artist: "User Name", - image: "/PlayerBar/Mask group.png", - plays: 150000, - likes: 5432, - comments: 210, - }); return ( <> @@ -49,89 +48,96 @@ export default function SearchResultsPage() {
-
-
-

Songs

- View More -
-
- {recentSongs.map((song, index) => ( -
- {song.title} -
-

{song.title}

-

{song.artist}

-
+ {loading &&

Loading...

} + {error &&

{error}

} + + {!loading && !error && ( + <> +
+
+

Songs

+ View More +
+
+ {songs.map((song, index) => ( +
+ {song.title} +
+

{song.title}

+

{song.artist}

+
+
+ ))}
- ))} -
-
+ - {/* Artists Section */} -
-
-

Artists

- View More -
-
- {newArtists.map((artist, index) => ( - - ))} -
-
+ {/* Artists Section */} +
+
+

Artists

+ View More +
+
+ {artists.map((artist, index) => ( + + ))} +
+
- {/* Albums Section */} -
-
-

Albums

- View More -
-
- {newAlbums.map((album, index) => ( - - ))} -
-
+ {/* Albums Section */} +
+
+

Albums

+ View More +
+
+ {albums.map((album, index) => ( + + ))} +
+
- {/* Playlists Section */} -
-
-

Playlists

- View More -
-
- {newPlaylists.map((pl, index) => ( - - ))} -
-
+ {/* Playlists Section */} +
+
+

Playlists

+ View More +
+
+ {playlists.map((pl, index) => ( + + ))} +
+
+ + )}
diff --git a/client/vite.config.ts b/client/vite.config.ts index a9789fb..a4193fb 100644 --- a/client/vite.config.ts +++ b/client/vite.config.ts @@ -12,7 +12,7 @@ export default defineConfig({ open: true, proxy: { "/api": { - target: process.env.VITE_API_URL, + target: process.env.VITE_API_URL || "http://localhost:8080", changeOrigin: true, secure: false, }, diff --git a/server/src/config/blobStorage.ts b/server/src/config/blobStorage.ts index 0f4cb52..ce36e93 100644 --- a/server/src/config/blobStorage.ts +++ b/server/src/config/blobStorage.ts @@ -12,19 +12,33 @@ dotenv.config(); const connectionString = process.env.AZURE_STORAGE_CONNECTION_STRING; const containerName = process.env.AZURE_STORAGE_CONTAINER || "uploads"; -const accountName = process.env.AZURE_STORAGE_ACCOUNT!; -const accountKey = process.env.AZURE_STORAGE_ACCOUNT_KEY!; +const accountName = process.env.AZURE_STORAGE_ACCOUNT; +const accountKey = process.env.AZURE_STORAGE_ACCOUNT_KEY; +const sasTokenDuration = Number(process.env.SAS_TOKEN_DURATION) || 3600; -if (!connectionString) { - throw new Error("Missing Azure Storage connection string"); +// Make Azure blob storage optional for local development +const isAzureConfigured = !!(connectionString && accountName && accountKey); + +let blobServiceClient: BlobServiceClient | null = null; +let containerClient: ContainerClient | null = null; + +if (isAzureConfigured && connectionString) { + blobServiceClient = BlobServiceClient.fromConnectionString(connectionString); + containerClient = blobServiceClient.getContainerClient(containerName); + console.log("✓ Azure Blob Storage configured"); +} else { + console.warn("⚠ Azure Blob Storage not configured - blob URLs will return placeholder paths"); } -const blobServiceClient = - BlobServiceClient.fromConnectionString(connectionString); -const containerClient: ContainerClient = - blobServiceClient.getContainerClient(containerName); +export function getBlobUrl( + filename: string, + expiresInSeconds = sasTokenDuration +): string { + if (!isAzureConfigured || !containerClient || !accountName || !accountKey) { + // Return placeholder URL when Azure is not configured + return `/placeholder/${filename}`; + } -export function getBlobUrl(filename: string, expiresInSeconds = 3600): string { const blobClient = containerClient.getBlobClient(filename); try { const sasToken = generateBlobSASQueryParameters( @@ -40,7 +54,7 @@ export function getBlobUrl(filename: string, expiresInSeconds = 3600): string { return `${blobClient.url}?${sasToken}`; } catch (error) { console.error("Could not generate SAS token:", error); - return blobClient.url; + throw new Error("Could not generate SAS token"); } } @@ -48,6 +62,11 @@ export async function uploadBlob( filename: string, data: Buffer | Readable ): Promise { + if (!isAzureConfigured || !containerClient) { + console.warn("Azure Blob Storage not configured - skipping upload"); + return; + } + try { const blockBlobClient = containerClient.getBlockBlobClient(filename); @@ -63,6 +82,11 @@ export async function uploadBlob( } export async function deleteBlob(filename: string): Promise { + if (!isAzureConfigured || !containerClient) { + console.warn("Azure Blob Storage not configured - skipping delete"); + return; + } + try { const blobClient = containerClient.getBlobClient(filename); await blobClient.deleteIfExists(); @@ -72,4 +96,4 @@ export async function deleteBlob(filename: string): Promise { } } -export { containerClient }; +export { containerClient }; \ No newline at end of file diff --git a/server/src/config/database.ts b/server/src/config/database.ts index bead346..5e09d5c 100644 --- a/server/src/config/database.ts +++ b/server/src/config/database.ts @@ -1,4 +1,4 @@ -import { Pool } from "pg"; +import { Pool, PoolClient } from "pg"; import dotenv from "dotenv"; dotenv.config(); @@ -13,10 +13,18 @@ const { PGSSLMODE, } = process.env; +console.log("Database config:", { + PGHOST, + PGDATABASE, + PGUSER, + PGPORT, +}); + if (!PGHOST || !PGUSER || !PGPASSWORD || !PGDATABASE) { throw new Error("Missing required Postgres environment variables."); } +// ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: true } : { rejectUnauthorized: false }, not working idek fix later const pool = new Pool({ host: PGHOST, port: PGPORT ? parseInt(PGPORT, 10) : 5432, @@ -25,8 +33,8 @@ const pool = new Pool({ database: PGDATABASE, max: PGPOOLSIZE ? parseInt(PGPOOLSIZE, 10) : undefined, ssl: { - rejectUnauthorized: false - } + rejectUnauthorized: false, + }, }); export async function query( @@ -37,6 +45,23 @@ export async function query( return res.rows as T[]; } +export async function withTransaction( + callback: (client: PoolClient) => Promise +): Promise { + const client = await pool.connect(); + try { + await client.query("BEGIN"); + const result = await callback(client); + await client.query("COMMIT"); + return result; + } catch (error) { + await client.query("ROLLBACK"); + throw error; + } finally { + client.release(); + } +} + export async function testConnection() { try { console.log("Testing database connection..."); @@ -53,3 +78,5 @@ export async function testConnection() { export async function closePool(): Promise { await pool.end(); } + +export { pool }; \ No newline at end of file diff --git a/server/src/routes/search.routes.ts b/server/src/routes/search.routes.ts index e69de29..f7ba075 100644 --- a/server/src/routes/search.routes.ts +++ b/server/src/routes/search.routes.ts @@ -0,0 +1,112 @@ +import express, { Request, Response } from "express"; +import { getBlobUrl } from "../config/blobStorage.js"; + +const router = express.Router(); + +// GET /api/search?q=query&type=all|songs|artists|albums|playlists&limit=20&offset=0 +router.get("/", async (req: Request, res: Response): Promise => { + const { q, type = "all", limit = "20", offset = "0" } = req.query; + + if (!q || typeof q !== "string") { + res.status(400).json({ error: "Search query (q) is required" }); + return; + } + + try { + // Dynamically import pool to avoid import-time errors + const { pool } = await import("../config/database.js"); + + const searchTerm = `%${q.toLowerCase()}%`; + const limitNum = parseInt(limit as string, 10); + const offsetNum = parseInt(offset as string, 10); + + const results: any = {}; + + // Search songs + if (type === "all" || type === "songs") { + const songsQuery = ` + SELECT s.song_id as id, s.title, s.duration, s.play_count as plays, + s.likes, s.comments, s.cover_image_url as image, + a.name as artist + FROM songs s + LEFT JOIN artists a ON s.artist_id = a.artist_id + WHERE LOWER(s.title) LIKE $1 OR LOWER(a.name) LIKE $1 + ORDER BY s.play_count DESC + LIMIT $2 OFFSET $3 + `; + const songsResult = await pool.query(songsQuery, [searchTerm, limitNum, offsetNum]); + results.songs = songsResult.rows.map((row: any) => ({ + ...row, + image: row.image ? getBlobUrl(row.image) : "/PlayerBar/Mask group.png", + })); + } + + // Search artists + if (type === "all" || type === "artists") { + const artistsQuery = ` + SELECT artist_id as id, name, profile_image_url as image, + bio, monthly_listeners as plays + FROM artists + WHERE LOWER(name) LIKE $1 + ORDER BY monthly_listeners DESC + LIMIT $2 OFFSET $3 + `; + const artistsResult = await pool.query(artistsQuery, [searchTerm, limitNum, offsetNum]); + results.artists = artistsResult.rows.map((row: any) => ({ + ...row, + image: row.image ? getBlobUrl(row.image) : "/PlayerBar/Mask group.png", + likes: 0, + comments: 0, + })); + } + + // Search albums + if (type === "all" || type === "albums") { + const albumsQuery = ` + SELECT al.album_id as id, al.title, al.cover_image_url as image, + al.release_date, a.name as artist + FROM albums al + LEFT JOIN artists a ON al.artist_id = a.artist_id + WHERE LOWER(al.title) LIKE $1 OR LOWER(a.name) LIKE $1 + ORDER BY al.release_date DESC + LIMIT $2 OFFSET $3 + `; + const albumsResult = await pool.query(albumsQuery, [searchTerm, limitNum, offsetNum]); + results.albums = albumsResult.rows.map((row: any) => ({ + ...row, + image: row.image ? getBlobUrl(row.image) : "/PlayerBar/Mask group.png", + plays: 0, + likes: 0, + comments: 0, + })); + } + + // Search playlists + if (type === "all" || type === "playlists") { + const playlistsQuery = ` + SELECT p.playlist_id as id, p.name as title, p.cover_image_url as image, + p.description, u.username as artist + FROM playlists p + LEFT JOIN users u ON p.user_id = u.user_id + WHERE LOWER(p.name) LIKE $1 OR LOWER(p.description) LIKE $1 + ORDER BY p.created_at DESC + LIMIT $2 OFFSET $3 + `; + const playlistsResult = await pool.query(playlistsQuery, [searchTerm, limitNum, offsetNum]); + results.playlists = playlistsResult.rows.map((row: any) => ({ + ...row, + image: row.image ? getBlobUrl(row.image) : "/PlayerBar/Mask group.png", + plays: 0, + likes: 0, + comments: 0, + })); + } + + res.status(200).json(results); + } catch (error) { + console.error("Error in /api/search:", error); + res.status(500).json({ error: "Internal server error" }); + } +}); + +export default router; \ No newline at end of file diff --git a/server/src/server.ts b/server/src/server.ts index 562e981..6decde5 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -13,6 +13,8 @@ const __dirname = path.resolve(); dotenv.config(); +console.log("Imported routes:", Object.keys(Routes)); + const app = express(); const PORT = Number(process.env.PORT) || 8080; const NODE_ENV = process.env.NODE_ENV || "development"; @@ -24,7 +26,7 @@ const corsOptions = { ? process.env.ALLOWED_ORIGINS ? process.env.ALLOWED_ORIGINS.split(",") : true - : process.env.CLIENT_URL || "http://localhost:5173", + : process.env.CLIENT_URL || ["http://localhost:5173", "http://localhost:5174", "http://localhost:5175", "http://localhost:5176", "http://localhost:5177", "http://localhost:5178", "http://localhost:5179", "http://localhost:5180"], credentials: true, methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With"], @@ -71,14 +73,20 @@ app.get("/api/health", (req, res) => { const clientDistPath = path.join(__dirname, "public"); app.use(express.static(clientDistPath)); -// Routes -app.use("/api/auth", Routes.authRoutes); -// app.use("/api/songs", Routes.songRoutes); // temporarily disabled for local dev without Azure -app.use("/api/albums", Routes.albumRoutes); -app.use("/api/artists", Routes.artistRoutes); -app.use("/api/playlists", Routes.playlistRoutes); -app.use("/api/users", Routes.userRoutes); -app.use("/api/search", Routes.searchRoutes); +// Routes (guard against undefined handlers) +// if (Routes.authRoutes) app.use("/api/auth", Routes.authRoutes); +if (Routes.songRoutes) { + console.log("✓ Registering song routes at /api/songs"); + app.use("/api/songs", Routes.songRoutes); +} +// if (Routes.albumRoutes) app.use("/api/albums", Routes.albumRoutes); +// if (Routes.artistRoutes) app.use("/api/artists", Routes.artistRoutes); +// if (Routes.playlistRoutes) app.use("/api/playlists", Routes.playlistRoutes); +// if (Routes.userRoutes) app.use("/api/users", Routes.userRoutes); +if (Routes.searchRoutes) { + console.log("✓ Registering search routes at /api/search"); + app.use("/api/search", Routes.searchRoutes); +} // React SPA routes app.get("/", (req, res) => { @@ -92,7 +100,11 @@ app.use((req, res) => { async function startServer() { try { - await testConnection(); + try { + await testConnection(); + } catch (err) { + console.warn("⚠ Database connection failed at startup. Continuing to start server.", err); + } app.listen(PORT, "0.0.0.0", () => { console.log(`⚡ Server running on port: ${PORT}`); console.log("Environment: ", NODE_ENV); @@ -106,4 +118,5 @@ async function startServer() { } } -startServer(); \ No newline at end of file +startServer(); +Monday, October 27, 2025 2:17:15 AM \ No newline at end of file From 49ca462c602d3717cfa3bc9f68065752c7e5d7d3 Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Mon, 27 Oct 2025 12:05:36 -0500 Subject: [PATCH 10/22] fixed db connection --- server/src/routes/search.routes.ts | 3 +- server/src/server.ts | 67 ++++++++++++++++++++---------- 2 files changed, 45 insertions(+), 25 deletions(-) diff --git a/server/src/routes/search.routes.ts b/server/src/routes/search.routes.ts index f7ba075..3c4f381 100644 --- a/server/src/routes/search.routes.ts +++ b/server/src/routes/search.routes.ts @@ -1,5 +1,6 @@ import express, { Request, Response } from "express"; import { getBlobUrl } from "../config/blobStorage.js"; +import { pool } from "../config/database.js"; const router = express.Router(); @@ -13,8 +14,6 @@ router.get("/", async (req: Request, res: Response): Promise => { } try { - // Dynamically import pool to avoid import-time errors - const { pool } = await import("../config/database.js"); const searchTerm = `%${q.toLowerCase()}%`; const limitNum = parseInt(limit as string, 10); diff --git a/server/src/server.ts b/server/src/server.ts index 6decde5..f2c0358 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -5,16 +5,13 @@ import helmet from "helmet"; import path from "path"; import dotenv from "dotenv"; import { testConnection } from "config/database"; -import { generalRateLimit } from "./middleware/rateLimiting.middleware.js"; - +import searchRoutes from "./routes/search.routes.js"; import * as Routes from "@routes"; const __dirname = path.resolve(); dotenv.config(); -console.log("Imported routes:", Object.keys(Routes)); - const app = express(); const PORT = Number(process.env.PORT) || 8080; const NODE_ENV = process.env.NODE_ENV || "development"; @@ -80,12 +77,14 @@ if (Routes.songRoutes) { app.use("/api/songs", Routes.songRoutes); } // if (Routes.albumRoutes) app.use("/api/albums", Routes.albumRoutes); -// if (Routes.artistRoutes) app.use("/api/artists", Routes.artistRoutes); +// if (Routes.artistRoutes) app.use("/api/artists", Routes.artistRoutes"); // if (Routes.playlistRoutes) app.use("/api/playlists", Routes.playlistRoutes); // if (Routes.userRoutes) app.use("/api/users", Routes.userRoutes); -if (Routes.searchRoutes) { + +// Register search routes using direct import (tsconfig-paths issue with re-exports) +if (searchRoutes) { console.log("✓ Registering search routes at /api/search"); - app.use("/api/search", Routes.searchRoutes); + app.use("/api/search", searchRoutes); } // React SPA routes @@ -98,25 +97,47 @@ app.use((req, res) => { res.status(404).send("Not found"); }); -async function startServer() { - try { - try { - await testConnection(); - } catch (err) { - console.warn("⚠ Database connection failed at startup. Continuing to start server.", err); - } - app.listen(PORT, "0.0.0.0", () => { +// Test connection then start server +testConnection() + .then(() => { + console.log("✅ Database connection verified"); + }) + .catch((err) => { + console.warn("⚠ Database connection failed. Server will start anyway.", err.message); + }) + .finally(() => { + const server = app.listen(PORT, "0.0.0.0", () => { console.log(`⚡ Server running on port: ${PORT}`); console.log("Environment: ", NODE_ENV); if (NODE_ENV !== "production") { console.log("CORS Origin:", corsOptions.origin); } }); - } catch (error) { - console.error("Failed to start server:", error); - process.exit(1); - } -} - -startServer(); -Monday, October 27, 2025 2:17:15 AM \ No newline at end of file + + // Explicitly keep the process alive + server.on('listening', () => { + console.log('✅ Server is now accepting connections'); + }); + + server.on('error', (err) => { + console.error('❌ Server error:', err); + process.exit(1); + }); + + // Keep process alive + process.on('SIGTERM', () => { + console.log('SIGTERM received, closing server'); + server.close(() => { + console.log('Server closed'); + process.exit(0); + }); + }); + + process.on('SIGINT', () => { + console.log('SIGINT received, closing server'); + server.close(() => { + console.log('Server closed'); + process.exit(0); + }); + }); + }); From f6f66ae8e69f89617d55b58b0226380a31c23b5c Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Mon, 27 Oct 2025 19:25:20 -0500 Subject: [PATCH 11/22] Refactor dev script for improved clarity and output Split the 'dev' script into 'dev:server' and 'dev:client' for better separation of concerns. Added named and color-prefixed output to concurrently for easier log identification. --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index a5a90df..f00da50 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,9 @@ "version": "0.0.1", "type": "module", "scripts": { - "dev": "concurrently \"npm run server\" \"npm run client\"", + "dev": "concurrently \"npm run dev:server\" \"npm run dev:client\" --names \"SERVER,CLIENT\" --prefix-colors \"blue,green\"", + "dev:server": "cd server && npm run dev", + "dev:client": "cd client && npm run dev", "client": "cd client && npm run dev", "server": "cd server && npm run dev", "build": "node scripts/build.js", From ca24050a2d36a0374fa4e967b9d43276c765ecb6 Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Tue, 28 Oct 2025 00:08:21 -0500 Subject: [PATCH 12/22] Refactor search queries for songs, artists, albums, playlists Updated search logic to query songs, artists, albums, and playlists using new table structures and fields. Expanded search to include additional fields (e.g., genre for songs, bio for artists, created_by for albums and playlists). Added error handling for each search type and standardized default values for missing images and metadata. --- server/src/routes/search.routes.ts | 157 ++++++++++++++++------------- 1 file changed, 89 insertions(+), 68 deletions(-) diff --git a/server/src/routes/search.routes.ts b/server/src/routes/search.routes.ts index 3c4f381..9088a75 100644 --- a/server/src/routes/search.routes.ts +++ b/server/src/routes/search.routes.ts @@ -21,84 +21,105 @@ router.get("/", async (req: Request, res: Response): Promise => { const results: any = {}; - // Search songs + // Search songs - search in title and genre if (type === "all" || type === "songs") { - const songsQuery = ` - SELECT s.song_id as id, s.title, s.duration, s.play_count as plays, - s.likes, s.comments, s.cover_image_url as image, - a.name as artist - FROM songs s - LEFT JOIN artists a ON s.artist_id = a.artist_id - WHERE LOWER(s.title) LIKE $1 OR LOWER(a.name) LIKE $1 - ORDER BY s.play_count DESC - LIMIT $2 OFFSET $3 - `; - const songsResult = await pool.query(songsQuery, [searchTerm, limitNum, offsetNum]); - results.songs = songsResult.rows.map((row: any) => ({ - ...row, - image: row.image ? getBlobUrl(row.image) : "/PlayerBar/Mask group.png", - })); + try { + const songsQuery = ` + SELECT id, title, image_url as image, genre + FROM "songs" + WHERE LOWER(title) LIKE $1 OR LOWER(COALESCE(genre, '')) LIKE $1 + ORDER BY title + LIMIT $2 OFFSET $3 + `; + const songsResult = await pool.query(songsQuery, [searchTerm, limitNum, offsetNum]); + results.songs = songsResult.rows.map((row: any) => ({ + ...row, + image: row.image || "/PlayerBar/Mask group.png", + artist: row.genre || "Unknown", + plays: 0, + likes: 0, + comments: 0, + })); + } catch (err) { + console.error("Error searching songs:", err); + results.songs = []; + } } - // Search artists + // Search artists - search in display_name and bio if (type === "all" || type === "artists") { - const artistsQuery = ` - SELECT artist_id as id, name, profile_image_url as image, - bio, monthly_listeners as plays - FROM artists - WHERE LOWER(name) LIKE $1 - ORDER BY monthly_listeners DESC - LIMIT $2 OFFSET $3 - `; - const artistsResult = await pool.query(artistsQuery, [searchTerm, limitNum, offsetNum]); - results.artists = artistsResult.rows.map((row: any) => ({ - ...row, - image: row.image ? getBlobUrl(row.image) : "/PlayerBar/Mask group.png", - likes: 0, - comments: 0, - })); + try { + const artistsQuery = ` + SELECT id, display_name as name, bio + FROM "artists" + WHERE LOWER(display_name) LIKE $1 OR LOWER(COALESCE(bio, '')) LIKE $1 + ORDER BY display_name + LIMIT $2 OFFSET $3 + `; + const artistsResult = await pool.query(artistsQuery, [searchTerm, limitNum, offsetNum]); + results.artists = artistsResult.rows.map((row: any) => ({ + ...row, + image: "/PlayerBar/Mask group.png", + plays: 0, + likes: 0, + comments: 0, + })); + } catch (err) { + console.error("Error searching artists:", err); + results.artists = []; + } } - // Search albums + // Search albums - search in title and created_by if (type === "all" || type === "albums") { - const albumsQuery = ` - SELECT al.album_id as id, al.title, al.cover_image_url as image, - al.release_date, a.name as artist - FROM albums al - LEFT JOIN artists a ON al.artist_id = a.artist_id - WHERE LOWER(al.title) LIKE $1 OR LOWER(a.name) LIKE $1 - ORDER BY al.release_date DESC - LIMIT $2 OFFSET $3 - `; - const albumsResult = await pool.query(albumsQuery, [searchTerm, limitNum, offsetNum]); - results.albums = albumsResult.rows.map((row: any) => ({ - ...row, - image: row.image ? getBlobUrl(row.image) : "/PlayerBar/Mask group.png", - plays: 0, - likes: 0, - comments: 0, - })); + try { + const albumsQuery = ` + SELECT id, title, image_url as image, created_by + FROM "albums" + WHERE LOWER(title) LIKE $1 OR LOWER(COALESCE(created_by, '')) LIKE $1 + ORDER BY title + LIMIT $2 OFFSET $3 + `; + const albumsResult = await pool.query(albumsQuery, [searchTerm, limitNum, offsetNum]); + results.albums = albumsResult.rows.map((row: any) => ({ + ...row, + image: row.image || "/PlayerBar/Mask group.png", + artist: row.created_by || "Unknown", + plays: 0, + likes: 0, + comments: 0, + })); + } catch (err) { + console.error("Error searching albums:", err); + results.albums = []; + } } - // Search playlists + // Search playlists - search in title, description, and created_by if (type === "all" || type === "playlists") { - const playlistsQuery = ` - SELECT p.playlist_id as id, p.name as title, p.cover_image_url as image, - p.description, u.username as artist - FROM playlists p - LEFT JOIN users u ON p.user_id = u.user_id - WHERE LOWER(p.name) LIKE $1 OR LOWER(p.description) LIKE $1 - ORDER BY p.created_at DESC - LIMIT $2 OFFSET $3 - `; - const playlistsResult = await pool.query(playlistsQuery, [searchTerm, limitNum, offsetNum]); - results.playlists = playlistsResult.rows.map((row: any) => ({ - ...row, - image: row.image ? getBlobUrl(row.image) : "/PlayerBar/Mask group.png", - plays: 0, - likes: 0, - comments: 0, - })); + try { + const playlistsQuery = ` + SELECT id, title, description, created_by + FROM "playlists" + WHERE LOWER(title) LIKE $1 + OR LOWER(COALESCE(description, '')) LIKE $1 + OR LOWER(COALESCE(created_by, '')) LIKE $1 + ORDER BY title + LIMIT $2 OFFSET $3 + `; + const playlistsResult = await pool.query(playlistsQuery, [searchTerm, limitNum, offsetNum]); + results.playlists = playlistsResult.rows.map((row: any) => ({ + ...row, + image: "/PlayerBar/Mask group.png", + artist: row.created_by || "Playlist", + plays: 0, + likes: 0, + comments: 0, + })); + } catch (err) { + console.error("Error searching playlists:", err); + results.playlists = []; + } } res.status(200).json(results); From 2441a19102c6f61da8d05e4a9e22c556d37b72b8 Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Tue, 28 Oct 2025 00:10:43 -0500 Subject: [PATCH 13/22] Home button now directs to home page --- client/src/components/TopBar/topBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/TopBar/topBar.tsx b/client/src/components/TopBar/topBar.tsx index 350579e..aff2f87 100644 --- a/client/src/components/TopBar/topBar.tsx +++ b/client/src/components/TopBar/topBar.tsx @@ -35,7 +35,7 @@ const TopBar: React.FC = () => {
{/* Navigation Buttons */}
- From fe2574589a876022c6737f70fecd3d259803a195 Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Tue, 28 Oct 2025 00:55:30 -0500 Subject: [PATCH 14/22] Add logging to search route for debugging Added console.log statements to the search route to log incoming query parameters and the number of matched results for songs, artists, albums, and playlists. This will help with debugging and monitoring search activity. --- server/src/routes/search.routes.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/src/routes/search.routes.ts b/server/src/routes/search.routes.ts index 9088a75..0bb6266 100644 --- a/server/src/routes/search.routes.ts +++ b/server/src/routes/search.routes.ts @@ -14,6 +14,7 @@ router.get("/", async (req: Request, res: Response): Promise => { } try { + console.log(`[search] request q="${q}" type=${type} limit=${limit} offset=${offset}`); const searchTerm = `%${q.toLowerCase()}%`; const limitNum = parseInt(limit as string, 10); @@ -32,6 +33,7 @@ router.get("/", async (req: Request, res: Response): Promise => { LIMIT $2 OFFSET $3 `; const songsResult = await pool.query(songsQuery, [searchTerm, limitNum, offsetNum]); + console.log(`[search] songs matched=${songsResult.rowCount}`); results.songs = songsResult.rows.map((row: any) => ({ ...row, image: row.image || "/PlayerBar/Mask group.png", @@ -57,6 +59,7 @@ router.get("/", async (req: Request, res: Response): Promise => { LIMIT $2 OFFSET $3 `; const artistsResult = await pool.query(artistsQuery, [searchTerm, limitNum, offsetNum]); + console.log(`[search] artists matched=${artistsResult.rowCount}`); results.artists = artistsResult.rows.map((row: any) => ({ ...row, image: "/PlayerBar/Mask group.png", @@ -81,6 +84,7 @@ router.get("/", async (req: Request, res: Response): Promise => { LIMIT $2 OFFSET $3 `; const albumsResult = await pool.query(albumsQuery, [searchTerm, limitNum, offsetNum]); + console.log(`[search] albums matched=${albumsResult.rowCount}`); results.albums = albumsResult.rows.map((row: any) => ({ ...row, image: row.image || "/PlayerBar/Mask group.png", @@ -108,6 +112,7 @@ router.get("/", async (req: Request, res: Response): Promise => { LIMIT $2 OFFSET $3 `; const playlistsResult = await pool.query(playlistsQuery, [searchTerm, limitNum, offsetNum]); + console.log(`[search] playlists matched=${playlistsResult.rowCount}`); results.playlists = playlistsResult.rows.map((row: any) => ({ ...row, image: "/PlayerBar/Mask group.png", From 711bd902a0c47074f195652fd5d1d395e5096ebd Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Wed, 29 Oct 2025 18:05:34 -0500 Subject: [PATCH 15/22] Refactor server config and search, add new client deps Improved environment variable loading and CORS handling in server startup, made database connection checks non-blocking, and enhanced health check endpoint. Refactored search route for safer queries and simplified logic. Added several new dependencies to client/package.json for UI and audio features. --- client/package.json | 12 +- server/src/config/database.ts | 10 +- server/src/routes/search.routes.ts | 205 +++++++++++++---------------- server/src/server.ts | 195 ++++++++++++++++++--------- 4 files changed, 246 insertions(+), 176 deletions(-) diff --git a/client/package.json b/client/package.json index 6298133..70d632c 100644 --- a/client/package.json +++ b/client/package.json @@ -11,6 +11,11 @@ "preview": "vite preview" }, "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@mui/material": "^7.3.4", + "@mui/x-charts": "^8.14.0", + "@wavesurfer/react": "^1.0.11", "axios": "^1.11.0", "classnames": "^2.5.1", "dotenv": "^17.2.2", @@ -19,7 +24,10 @@ "react-helmet": "^6.1.0", "react-helmet-async": "^2.0.5", "react-icons": "^5.5.0", - "react-router-dom": "^7.8.2" + "react-router-dom": "^7.8.2", + "react-spinners": "^0.17.0", + "uuid": "^13.0.0", + "wavesurfer.js": "^7.11.0" }, "devDependencies": { "@eslint/js": "^9.33.0", @@ -36,4 +44,4 @@ "typescript-eslint": "^8.39.1", "vite": "^7.1.4" } -} +} \ No newline at end of file diff --git a/server/src/config/database.ts b/server/src/config/database.ts index 5e09d5c..396579d 100644 --- a/server/src/config/database.ts +++ b/server/src/config/database.ts @@ -1,7 +1,12 @@ -import { Pool, PoolClient } from "pg"; import dotenv from "dotenv"; +import { fileURLToPath } from "url"; +import { dirname, join } from "path"; +import { Pool, PoolClient } from "pg"; -dotenv.config(); +// Resolve server/.env regardless of cwd +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +dotenv.config({ path: join(__dirname, "../../.env") }); const { PGHOST, @@ -35,6 +40,7 @@ const pool = new Pool({ ssl: { rejectUnauthorized: false, }, + connectionTimeoutMillis: Number(process.env.PGCONNECT_TIMEOUT || 3000), }); export async function query( diff --git a/server/src/routes/search.routes.ts b/server/src/routes/search.routes.ts index 0bb6266..d8e88ef 100644 --- a/server/src/routes/search.routes.ts +++ b/server/src/routes/search.routes.ts @@ -4,6 +4,17 @@ import { pool } from "../config/database.js"; const router = express.Router(); +// Safe query helper: returns [] on failure +async function safeQuery(sql: string, params: any[]): Promise { + try { + const r = await pool.query(sql, params); + return r.rows as T[]; + } catch (e) { + console.error("Search query failed:", e); + return []; + } +} + // GET /api/search?q=query&type=all|songs|artists|albums|playlists&limit=20&offset=0 router.get("/", async (req: Request, res: Response): Promise => { const { q, type = "all", limit = "20", offset = "0" } = req.query; @@ -13,125 +24,93 @@ router.get("/", async (req: Request, res: Response): Promise => { return; } - try { - console.log(`[search] request q="${q}" type=${type} limit=${limit} offset=${offset}`); - - const searchTerm = `%${q.toLowerCase()}%`; - const limitNum = parseInt(limit as string, 10); - const offsetNum = parseInt(offset as string, 10); - - const results: any = {}; + const searchTerm = `%${q}%`; + const limitNum = parseInt(limit as string, 10); + const offsetNum = parseInt(offset as string, 10); - // Search songs - search in title and genre - if (type === "all" || type === "songs") { - try { - const songsQuery = ` - SELECT id, title, image_url as image, genre - FROM "songs" - WHERE LOWER(title) LIKE $1 OR LOWER(COALESCE(genre, '')) LIKE $1 - ORDER BY title - LIMIT $2 OFFSET $3 - `; - const songsResult = await pool.query(songsQuery, [searchTerm, limitNum, offsetNum]); - console.log(`[search] songs matched=${songsResult.rowCount}`); - results.songs = songsResult.rows.map((row: any) => ({ - ...row, - image: row.image || "/PlayerBar/Mask group.png", - artist: row.genre || "Unknown", - plays: 0, - likes: 0, - comments: 0, - })); - } catch (err) { - console.error("Error searching songs:", err); - results.songs = []; - } - } + const results: any = {}; - // Search artists - search in display_name and bio - if (type === "all" || type === "artists") { - try { - const artistsQuery = ` - SELECT id, display_name as name, bio - FROM "artists" - WHERE LOWER(display_name) LIKE $1 OR LOWER(COALESCE(bio, '')) LIKE $1 - ORDER BY display_name - LIMIT $2 OFFSET $3 - `; - const artistsResult = await pool.query(artistsQuery, [searchTerm, limitNum, offsetNum]); - console.log(`[search] artists matched=${artistsResult.rowCount}`); - results.artists = artistsResult.rows.map((row: any) => ({ - ...row, - image: "/PlayerBar/Mask group.png", - plays: 0, - likes: 0, - comments: 0, - })); - } catch (err) { - console.error("Error searching artists:", err); - results.artists = []; - } - } + // Songs + if (type === "all" || type === "songs") { + const songsQuery = ` + SELECT + title, + image_url AS image, + genre + FROM songs + WHERE title ILIKE $1 + ORDER BY title ASC + LIMIT $2 OFFSET $3 + `; + const rows = await safeQuery(songsQuery, [searchTerm, limitNum, offsetNum]); + results.songs = rows.map((row: any) => ({ + ...row, + image: row.image ? getBlobUrl(row.image) : "/PlayerBar/Mask group.png", + })); + } - // Search albums - search in title and created_by - if (type === "all" || type === "albums") { - try { - const albumsQuery = ` - SELECT id, title, image_url as image, created_by - FROM "albums" - WHERE LOWER(title) LIKE $1 OR LOWER(COALESCE(created_by, '')) LIKE $1 - ORDER BY title - LIMIT $2 OFFSET $3 - `; - const albumsResult = await pool.query(albumsQuery, [searchTerm, limitNum, offsetNum]); - console.log(`[search] albums matched=${albumsResult.rowCount}`); - results.albums = albumsResult.rows.map((row: any) => ({ - ...row, - image: row.image || "/PlayerBar/Mask group.png", - artist: row.created_by || "Unknown", - plays: 0, - likes: 0, - comments: 0, - })); - } catch (err) { - console.error("Error searching albums:", err); - results.albums = []; - } - } + // Artists (display_name only) + if (type === "all" || type === "artists") { + const artistsQuery = ` + SELECT user_id as id, display_name as name, bio + FROM artists + WHERE display_name ILIKE $1 + LIMIT $2 OFFSET $3 + `; + const rows = await safeQuery(artistsQuery, [searchTerm, limitNum, offsetNum]); + results.artists = rows.map((row: any) => ({ + ...row, + image: row.image ? getBlobUrl(row.image) : "/PlayerBar/Mask group.png", + likes: 0, + comments: 0, + })); + } - // Search playlists - search in title, description, and created_by - if (type === "all" || type === "playlists") { - try { - const playlistsQuery = ` - SELECT id, title, description, created_by - FROM "playlists" - WHERE LOWER(title) LIKE $1 - OR LOWER(COALESCE(description, '')) LIKE $1 - OR LOWER(COALESCE(created_by, '')) LIKE $1 - ORDER BY title - LIMIT $2 OFFSET $3 - `; - const playlistsResult = await pool.query(playlistsQuery, [searchTerm, limitNum, offsetNum]); - console.log(`[search] playlists matched=${playlistsResult.rowCount}`); - results.playlists = playlistsResult.rows.map((row: any) => ({ - ...row, - image: "/PlayerBar/Mask group.png", - artist: row.created_by || "Playlist", - plays: 0, - likes: 0, - comments: 0, - })); - } catch (err) { - console.error("Error searching playlists:", err); - results.playlists = []; - } - } + // Albums (title, image_url, created_by) + if (type === "all" || type === "albums") { + const albumsQuery = ` + SELECT + title, + image_url AS image, + created_by AS artist + FROM albums + WHERE title ILIKE $1 OR created_by ILIKE $1 + ORDER BY title ASC + LIMIT $2 OFFSET $3 + `; + const rows = await safeQuery(albumsQuery, [searchTerm, limitNum, offsetNum]); + results.albums = rows.map((row: any) => ({ + ...row, + image: row.image ? getBlobUrl(row.image) : "/PlayerBar/Mask group.png", + plays: 0, + likes: 0, + comments: 0, + })); + } - res.status(200).json(results); - } catch (error) { - console.error("Error in /api/search:", error); - res.status(500).json({ error: "Internal server error" }); + // Playlists (title, description, created_by) + if (type === "all" || type === "playlists") { + const playlistsQuery = ` + SELECT + title, + description, + created_by AS artist + FROM playlists + WHERE title ILIKE $1 OR description ILIKE $1 OR created_by ILIKE $1 + ORDER BY title ASC + LIMIT $2 OFFSET $3 + `; + const rows = await safeQuery(playlistsQuery, [searchTerm, limitNum, offsetNum]); + results.playlists = rows.map((row: any) => ({ + ...row, + image: row.image ? getBlobUrl(row.image) : "/PlayerBar/Mask group.png", + plays: 0, + likes: 0, + comments: 0, + })); } + + res.status(200).json(results); }); export default router; \ No newline at end of file diff --git a/server/src/server.ts b/server/src/server.ts index f2c0358..0123995 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -1,29 +1,70 @@ +import { fileURLToPath } from "url"; +import { dirname, join } from "path"; +import path from "path"; +import dotenv from "dotenv"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +dotenv.config({ path: join(__dirname, "../.env") }); + +console.log("Environment variables loaded:", { + PGHOST: process.env.PGHOST, + PGUSER: process.env.PGUSER, + PGDATABASE: process.env.PGDATABASE, +}); + import express from "express"; import cookieParser from "cookie-parser"; import cors from "cors"; import helmet from "helmet"; -import path from "path"; -import dotenv from "dotenv"; -import { testConnection } from "config/database"; import searchRoutes from "./routes/search.routes.js"; -import * as Routes from "@routes"; - -const __dirname = path.resolve(); - -dotenv.config(); const app = express(); const PORT = Number(process.env.PORT) || 8080; const NODE_ENV = process.env.NODE_ENV || "development"; // CORS middleware +const devOrigins = new Set([ + process.env.CLIENT_URL || "", + "http://localhost:5173", + "http://localhost:5174", + "http://localhost:5175", + "http://localhost:5176", + "http://localhost:5177", + "http://localhost:5178", + "http://localhost:5179", + "http://localhost:5180", + "http://127.0.0.1:5173", + "http://127.0.0.1:5174", + "http://127.0.0.1:5175", + "http://127.0.0.1:5176", + "http://127.0.0.1:5177", + "http://127.0.0.1:5178", + "http://127.0.0.1:5179", + "http://127.0.0.1:5180", +].filter(Boolean) as string[]); + const corsOptions = { - origin: - NODE_ENV === "production" - ? process.env.ALLOWED_ORIGINS - ? process.env.ALLOWED_ORIGINS.split(",") - : true - : process.env.CLIENT_URL || ["http://localhost:5173", "http://localhost:5174", "http://localhost:5175", "http://localhost:5176", "http://localhost:5177", "http://localhost:5178", "http://localhost:5179", "http://localhost:5180"], + origin: (origin: string | undefined, callback: (err: Error | null, allow?: boolean) => void) => { + // Allow curl/Postman or same-origin (no Origin header) + if (!origin) return callback(null, true); + + if (NODE_ENV !== "production") { + if (devOrigins.has(origin)) return callback(null, true); + console.warn(`CORS blocked (dev): ${origin}`); + return callback(new Error("Not allowed by CORS")); + } + + // Production: allow from ALLOWED_ORIGINS if set; otherwise allow all + const allowed = (process.env.ALLOWED_ORIGINS || "") + .split(",") + .map(s => s.trim()) + .filter(Boolean); + if (allowed.length === 0 || allowed.includes(origin)) return callback(null, true); + + console.warn(`CORS blocked (prod): ${origin}`); + return callback(new Error("Not allowed by CORS")); + }, credentials: true, methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With"], @@ -55,10 +96,34 @@ app.use(express.json({ limit: "10mb" })); app.use(express.urlencoded({ extended: true, limit: "10mb" })); app.use(cookieParser()); -// Health check endpoint -app.get("/api/health", (req, res) => { +// Log incoming requests (method + path) +app.use((req, _res, next) => { + console.log(`[REQ] ${req.method} ${req.originalUrl}`); + next(); +}); + +// Optional alias routes import; don’t block server if alias is missing +let Routes: any = null; +try { + Routes = await import("@routes"); + console.log("✓ Optional '@routes' module loaded"); +} catch { + console.warn("⚠ Optional module '@routes' not found; skipping alias routes"); +} + +// Health check endpoint (includes DB status) +app.get("/api/health", async (_req, res) => { + let db = "down"; + try { + const { pool } = await import("config/database"); + await pool.query("SELECT 1"); + db = "up"; + } catch (e: any) { + console.warn("DB health check failed:", e?.message); + } res.json({ status: "ok", + db, timestamp: new Date().toISOString(), uptime: process.uptime(), environment: NODE_ENV, @@ -72,7 +137,7 @@ app.use(express.static(clientDistPath)); // Routes (guard against undefined handlers) // if (Routes.authRoutes) app.use("/api/auth", Routes.authRoutes); -if (Routes.songRoutes) { +if (Routes?.songRoutes) { console.log("✓ Registering song routes at /api/songs"); app.use("/api/songs", Routes.songRoutes); } @@ -97,47 +162,59 @@ app.use((req, res) => { res.status(404).send("Not found"); }); -// Test connection then start server -testConnection() - .then(() => { +// Global error handler to see proxy failures that hit the server and explode +app.use((err: any, _req: express.Request, res: express.Response, _next: express.NextFunction) => { + console.error("[ERR]", err); + res.status(500).json({ error: "Internal server error" }); +}); + +// Start server immediately (don’t wait on DB) +const server = app.listen(PORT, "0.0.0.0", () => { + console.log(`⚡ Server running on port: ${PORT}`); + console.log("Environment: ", NODE_ENV); + if (NODE_ENV !== "production") { + console.log("CORS Origin:", corsOptions.origin); + } +}); + +// Explicitly keep the process alive +server.on("listening", () => { + console.log("✅ Server is now accepting connections"); +}); + +server.on("error", (err) => { + console.error("❌ Server error:", err); + process.exit(1); +}); + +// Background DB connectivity check with timeout (non-blocking) +(async () => { + try { + const { testConnection } = await import("config/database"); + const timeoutMs = Number(process.env.DB_TEST_TIMEOUT_MS || 3000); + await Promise.race([ + testConnection(), + new Promise((_, reject) => setTimeout(() => reject(new Error("DB test timeout")), timeoutMs)), + ]); console.log("✅ Database connection verified"); - }) - .catch((err) => { - console.warn("⚠ Database connection failed. Server will start anyway.", err.message); - }) - .finally(() => { - const server = app.listen(PORT, "0.0.0.0", () => { - console.log(`⚡ Server running on port: ${PORT}`); - console.log("Environment: ", NODE_ENV); - if (NODE_ENV !== "production") { - console.log("CORS Origin:", corsOptions.origin); - } - }); - - // Explicitly keep the process alive - server.on('listening', () => { - console.log('✅ Server is now accepting connections'); - }); - - server.on('error', (err) => { - console.error('❌ Server error:', err); - process.exit(1); - }); - - // Keep process alive - process.on('SIGTERM', () => { - console.log('SIGTERM received, closing server'); - server.close(() => { - console.log('Server closed'); - process.exit(0); - }); - }); - - process.on('SIGINT', () => { - console.log('SIGINT received, closing server'); - server.close(() => { - console.log('Server closed'); - process.exit(0); - }); - }); + } catch (err: any) { + console.warn("⚠ Database connection failed/timeout. Continuing to serve API.", err?.message); + } +})(); + +// Keep process alive +process.on("SIGTERM", () => { + console.log("SIGTERM received, closing server"); + server.close(() => { + console.log("Server closed"); + process.exit(0); }); +}); + +process.on("SIGINT", () => { + console.log("SIGINT received, closing server"); + server.close(() => { + console.log("Server closed"); + process.exit(0); + }); +}); From ce337ef57c9a388fd2a19394644460f7d00e2c25 Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Mon, 3 Nov 2025 23:44:07 -0600 Subject: [PATCH 16/22] Create playlist.repo.ts --- server/src/repos/playlist.repo.ts | 394 ++++++++++++++++++++++++++++++ 1 file changed, 394 insertions(+) create mode 100644 server/src/repos/playlist.repo.ts diff --git a/server/src/repos/playlist.repo.ts b/server/src/repos/playlist.repo.ts new file mode 100644 index 0000000..f02ed4c --- /dev/null +++ b/server/src/repos/playlist.repo.ts @@ -0,0 +1,394 @@ +import { Playlist, PlaylistSong, UUID } from "@types"; +import { query, withTransaction } from "@config/database"; +import { getBlobUrl } from "@config/blobStorage"; +import { SongRepository } from "@repositories"; + +export default class PlaylistRepository { + /** + * Creates a new playlist. + * @param playlistData - The data for the new playlist. + * @param playlist.title - The title of the playlist. + * @param playlist.description - The description of the playlist. + * @param playlist.created_by - The ID of the user who created the playlist. + * @returns The created playlist, or null if creation fails. + * @throws Error if the operation fails. + */ + static async create({ + title, + description, + created_by, + }: { + title: string; + description: string; + created_by: UUID; + }): Promise { + try { + const res = await query( + `INSERT INTO playlists (title, description, created_by) + VALUES ($1, $2, $3) + RETURNING *`, + [title, description, created_by] + ); + + return res[0] ?? null; + } catch (error) { + console.error("Error creating playlist:", error); + throw error; + } + } + + /** + * Updates a playlist. + * @param id - The ID of the playlist to update. + * @param playlistData - The new data for the playlist. + * @param playlist.title - The new title of the playlist (optional). + * @param playlist.description - The new description of the playlist (optional). + * @param playlist.created_by - The new ID of the user who created the playlist (optional). + * @returns The updated playlist, or null if the update fails. + * @throws Error if the operation fails. + */ + static async update( + id: UUID, + { + title, + description, + created_by, + }: { title?: string; description?: string; created_by?: UUID } + ): Promise { + try { + const fields: string[] = []; + const values: any[] = []; + + if (title !== undefined) { + fields.push(`title = $${values.length + 1}`); + values.push(title); + } + if (description !== undefined) { + fields.push(`description = $${values.length + 1}`); + values.push(description); + } + if (created_by !== undefined) { + fields.push(`created_by = $${values.length + 1}`); + values.push(created_by); + } + if (fields.length === 0) { + throw new Error("No fields to update"); + } + + values.push(id); + + const res = await withTransaction(async (client) => { + const sql = `UPDATE playlists SET ${fields.join(", ")} WHERE id = $${ + values.length + } RETURNING *`; + const res = await client.query(sql, values); + return res.rows[0] ?? null; + }); + + return res; + } catch (error) { + console.error("Error updating playlist:", error); + throw error; + } + } + + /** + * Deletes a playlist. + * @param id - The ID of the playlist to delete. + * @returns The deleted playlist, or null if the deletion fails. + * @throws Error if the operation fails. + */ + static async delete(id: UUID): Promise { + try { + const res = await withTransaction(async (client) => { + const del = await client.query( + `DELETE FROM playlists WHERE id = $1 RETURNING *`, + [id] + ); + return del.rows[0] ?? null; + }); + + return res; + } catch (error) { + console.error("Error deleting playlist:", error); + throw error; + } + } + + /** + * Gets a single playlist by ID. + * @param id - The ID of the playlist to get. + * @param options - Options for including related data. + * @param options.includeUser - Option to include the user who created the playlist. + * @param options.includeLikes - Option to include the like count. + * @param options.includeSongCount - Option to include the total number of songs on the playlist. + * @returns The playlist, or null if not found. + * @throws Error if the operation fails. + */ + static async getOne( + id: UUID, + options?: { + includeUser?: boolean; + includeLikes?: boolean; + includeSongCount?: boolean; + } + ): Promise { + try { + const sql = ` + SELECT p.*, + CASE WHEN $1 THEN row_to_json(u.*) + ELSE NULL END as user, + CASE WHEN $2 THEN (SELECT COUNT(*) FROM playlist_likes pl + WHERE pl.playlist_id = p.id) + ELSE NULL END as likes, + CASE WHEN $3 THEN (SELECT COUNT(*) FROM playlist_songs ps + WHERE ps.playlist_id = p.id) + ELSE NULL END as song_count + FROM playlists p + LEFT JOIN users u ON p.created_by = u.id + WHERE p.id = $4 + LIMIT 1 + `; + + const params = [ + options?.includeUser ?? false, + options?.includeLikes ?? false, + options?.includeSongCount ?? false, + id, + ]; + + const res = await query(sql, params); + if (!res || res.length === 0) { + return null; + } + + const playlist: Playlist = res[0]; + if (playlist.user && playlist.user.profile_picture_url) { + playlist.user.profile_picture_url = getBlobUrl( + playlist.user.profile_picture_url + ); + } + + return playlist; + } catch (error) { + console.error("Error fetching playlist:", error); + throw error; + } + } + + /** + * Gets multiple playlists. + * @param options - Options for pagination and including related data. + * @param options.includeUser - Option to include the user who created each playlist. + * @param options.includeLikes - Option to include the like count for each playlist. + * @param options.includeSongCount - Option to include the total number of songs on each playlist. + * @param options.limit - Maximum number of playlists to return. + * @param options.offset - Number of playlists to skip. + * @returns A list of playlists. + * @throws Error if the operation fails. + */ + static async getMany(options?: { + includeUser?: boolean; + includeLikes?: boolean; + includeSongCount?: boolean; + limit?: number; + offset?: number; + }): Promise { + try { + const limit = options?.limit ?? 50; + const offset = options?.offset ?? 0; + + const sql = ` + SELECT p.*, + CASE WHEN $1 THEN row_to_json(u.*) + ELSE NULL END as user, + CASE WHEN $2 THEN (SELECT COUNT(*) FROM playlist_likes pl + WHERE pl.playlist_id = p.id) + ELSE NULL END as likes, + CASE WHEN $3 THEN (SELECT COUNT(*) FROM playlist_songs ps + WHERE ps.playlist_id = p.id) + ELSE NULL END as song_count + FROM playlists p + LEFT JOIN users u ON p.created_by = u.id + ORDER BY p.created_at DESC + LIMIT $4 OFFSET $5 + `; + + const params = [ + options?.includeUser ?? false, + options?.includeLikes ?? false, + options?.includeSongCount ?? false, + limit, + offset, + ]; + + const playlists = await query(sql, params); + if (!playlists || playlists.length === 0) { + return []; + } + + const processedPlaylists = await Promise.all( + playlists.map(async (playlist: Playlist) => { + if (playlist.user && playlist.user.profile_picture_url) { + playlist.user.profile_picture_url = getBlobUrl( + playlist.user.profile_picture_url + ); + } + return playlist; + }) + ); + + return processedPlaylists; + } catch (error) { + console.error("Error fetching playlists:", error); + throw error; + } + } + + /** + * Fetches all songs in a specific playlist. + * @param playlistId The ID of the playlist. + * @param options - Options for pagination and including related data. + * @param options.includeAlbum - Option to include the album data. + * @param options.includeArtists - Option to include the artists data. + * @param options.includeLikes - Option to include the like count. + * @param options.limit - Maximum number of songs to return. + * @param options.offset - Number of songs to skip. + * @returns An array of songs in the playlist, with added_at timestamp. + * @throws Error if the operation fails + */ + static async getSongs( + playlistId: UUID, + options?: { + includeAlbum?: boolean; + includeArtists?: boolean; + includeLikes?: boolean; + limit?: number; + offset?: number; + } + ): Promise { + try { + const limit = options?.limit ?? 50; + const offset = options?.offset ?? 0; + + const sql = ` + SELECT s.*, ps.added_at, + CASE WHEN $1 THEN row_to_json(a.*) + ELSE NULL END as album, + CASE WHEN $2 THEN + (SELECT json_agg(row_to_json(ar.*)) FROM artists ar + JOIN song_artists sa ON sa.artist_id = ar.id + WHERE sa.song_id = s.id) + ELSE NULL END as artists, + CASE WHEN $3 THEN + (SELECT COUNT(*) FROM song_likes sl + WHERE sl.song_id = s.id) + ELSE NULL END as likes + FROM songs s + LEFT JOIN album_songs als ON als.song_id = s.id + LEFT JOIN albums a ON als.album_id = a.id + LEFT JOIN playlist_songs ps ON s.id = ps.song_id + WHERE ps.playlist_id = $4 + ORDER BY ps.added_at + LIMIT $5 OFFSET $6 + `; + + const params = [ + options?.includeAlbum ?? false, + options?.includeArtists ?? false, + options?.includeLikes ?? false, + playlistId, + limit, + offset, + ]; + + const songs = await query(sql, params); + if (!songs || songs.length === 0) { + return []; + } + + const processedSongs = await Promise.all( + songs.map(async (song: PlaylistSong) => { + if (song.image_url) { + song.image_url = getBlobUrl(song.image_url); + } + if (song.audio_url) { + song.audio_url = getBlobUrl(song.audio_url); + } + if (song.albums?.length && song.albums[0]?.image_url) { + // Type assertions used to satisfy strict null checks + song.albums[0].image_url = getBlobUrl(song.albums[0].image_url as string); + } + return song; + }) + ); + + return processedSongs; + } catch (error) { + console.error("Error fetching playlist songs:", error); + throw error; + } + } + + /** + * Adds songs to a playlist. + * @param playlistId The ID of the playlist. + * @param songIds An array of song IDs to add to the playlist. + * @throws Error if the operation fails. + */ + static async addSongs(playlistId: UUID, songIds: UUID[]) { + try { + await withTransaction(async (client) => { + for (const songId of songIds) { + await client.query( + `INSERT INTO playlist_songs (playlist_id, song_id) + VALUES ($1, $2) + ON CONFLICT (playlist_id, song_id) DO NOTHING`, + [playlistId, songId] + ); + } + }); + } catch (error) { + console.error("Error adding songs to playlist:", error); + throw error; + } + } + + /** + * Removes songs from a playlist. + * @param playlistId The ID of the playlist. + * @param songIds An array of song IDs to remove from the playlist. + * @throws Error if the operation fails. + */ + static async removeSongs(playlistId: UUID, songIds: UUID[]) { + try { + await withTransaction(async (client) => { + for (const songId of songIds) { + await client.query( + `DELETE FROM playlist_songs + WHERE playlist_id = $1 AND song_id = $2`, + [playlistId, songId] + ); + } + }); + } catch (error) { + console.error("Error removing songs from playlist:", error); + throw error; + } + } + + /** + * Counts the total number of playlists. + * @return The total number of playlists. + * @throws Error if the operation fails. + */ + static async count(): Promise { + try { + const res = await query("SELECT COUNT(*) FROM playlists"); + return parseInt(res[0]?.count ?? "0", 10); + } catch (error) { + console.error("Error counting playlists:", error); + throw error; + } + } +} From 9667f85f7e3c75ab4a372d4a05420cac8a1720bc Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Wed, 5 Nov 2025 12:59:31 -0600 Subject: [PATCH 17/22] Add MUI, Emotion, Wavesurfer, and related deps Updated package-lock.json to include @mui/material, @emotion/react, @emotion/styled, @mui/x-charts, @wavesurfer/react, react-spinners, uuid, and wavesurfer.js, along with their dependencies. This prepares the client for new UI and audio features. --- client/package-lock.json | 1038 +++++++++++++++++++++++++++- server/src/routes/search.routes.ts | 19 +- 2 files changed, 1019 insertions(+), 38 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 0daa83c..8680c5f 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -8,6 +8,11 @@ "name": "cosc-3380-project-client", "version": "0.0.0", "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@mui/material": "^7.3.4", + "@mui/x-charts": "^8.14.0", + "@wavesurfer/react": "^1.0.11", "axios": "^1.11.0", "classnames": "^2.5.1", "dotenv": "^17.2.2", @@ -16,7 +21,10 @@ "react-helmet": "^6.1.0", "react-helmet-async": "^2.0.5", "react-icons": "^5.5.0", - "react-router-dom": "^7.8.2" + "react-router-dom": "^7.8.2", + "react-spinners": "^0.17.0", + "uuid": "^13.0.0", + "wavesurfer.js": "^7.11.0" }, "devDependencies": { "@eslint/js": "^9.33.0", @@ -38,7 +46,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", @@ -91,7 +98,6 @@ "version": "7.28.3", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", - "dev": true, "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", @@ -123,7 +129,6 @@ "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -132,7 +137,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" @@ -171,7 +175,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -180,7 +183,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -211,7 +213,6 @@ "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", - "dev": true, "dependencies": { "@babel/types": "^7.28.4" }, @@ -252,11 +253,19 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", @@ -270,7 +279,6 @@ "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -288,7 +296,6 @@ "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", - "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" @@ -297,6 +304,158 @@ "node": ">=6.9.0" } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz", + "integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.14.1", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", + "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.9", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", @@ -908,7 +1067,6 @@ "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" @@ -928,7 +1086,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -936,19 +1093,328 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.30", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", - "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mui/core-downloads-tracker": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.5.tgz", + "integrity": "sha512-kOLwlcDPnVz2QMhiBv0OQ8le8hTCqKM9cRXlfVPL91l3RGeOsxrIhNRsUt3Xb8wb+pTVUolW+JXKym93vRKxCw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/material": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.5.tgz", + "integrity": "sha512-8VVxFmp1GIm9PpmnQoCoYo0UWHoOrdA57tDL62vkpzEgvb/d71Wsbv4FRg7r1Gyx7PuSo0tflH34cdl/NvfHNQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/core-downloads-tracker": "^7.3.5", + "@mui/system": "^7.3.5", + "@mui/types": "^7.4.8", + "@mui/utils": "^7.3.5", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^19.2.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^7.3.5", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.0.tgz", + "integrity": "sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA==", + "license": "MIT" + }, + "node_modules/@mui/private-theming": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.3.5.tgz", + "integrity": "sha512-cTx584W2qrLonwhZLbEN7P5pAUu0nZblg8cLBlTrZQ4sIiw8Fbvg7GvuphQaSHxPxrCpa7FDwJKtXdbl2TSmrA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/utils": "^7.3.5", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.3.5.tgz", + "integrity": "sha512-zbsZ0uYYPndFCCPp2+V3RLcAN6+fv4C8pdwRx6OS3BwDkRCN8WBehqks7hWyF3vj1kdQLIWrpdv/5Y0jHRxYXQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.3.5.tgz", + "integrity": "sha512-yPaf5+gY3v80HNkJcPi6WT+r9ebeM4eJzrREXPxMt7pNTV/1eahyODO4fbH3Qvd8irNxDFYn5RQ3idHW55rA6g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/private-theming": "^7.3.5", + "@mui/styled-engine": "^7.3.5", + "@mui/types": "^7.4.8", + "@mui/utils": "^7.3.5", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.4.8", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.8.tgz", + "integrity": "sha512-ZNXLBjkPV6ftLCmmRCafak3XmSn8YV0tKE/ZOhzKys7TZXUiE0mZxlH8zKDo6j6TTUaDnuij68gIG+0Ucm7Xhw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.3.5.tgz", + "integrity": "sha512-jisvFsEC3sgjUjcPnR4mYfhzjCDIudttSGSbe1o/IXFNu0kZuR+7vqQI0jg8qtcVZBHWrwTfvAZj9MNMumcq1g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/types": "^7.4.8", + "@types/prop-types": "^15.7.15", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.2.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.0.tgz", + "integrity": "sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA==", + "license": "MIT" + }, + "node_modules/@mui/x-charts": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-8.16.0.tgz", + "integrity": "sha512-Gx1kkda2BZWQUAJS5pR3hV/EaUS1cEiSWkQyu6riyeLz9trnkAuhSzOUX3X7vuN7k6JDLm+YUBpiHXFsMPrpfA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/utils": "^7.3.3", + "@mui/x-charts-vendor": "8.15.0", + "@mui/x-internal-gestures": "0.3.4", + "@mui/x-internals": "8.16.0", + "bezier-easing": "^2.1.0", + "clsx": "^2.1.1", + "flatqueue": "^3.0.0", + "prop-types": "^15.8.1", + "reselect": "^5.1.1", + "use-sync-external-store": "^1.6.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14 || ^6.0.0 || ^7.0.0", + "@mui/system": "^5.15.14 || ^6.0.0 || ^7.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/x-charts-vendor": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/@mui/x-charts-vendor/-/x-charts-vendor-8.15.0.tgz", + "integrity": "sha512-0w7Who278kmRFm+5LUZY5MErSJBO75tqBH8abDkTiDNfsCe88vnrImmIT7OGzJGyRJfyrEBht8RLL6bHNEParg==", + "license": "MIT AND ISC", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@types/d3-color": "^3.1.3", + "@types/d3-interpolate": "^3.0.4", + "@types/d3-sankey": "^0.12.4", + "@types/d3-scale": "^4.0.9", + "@types/d3-shape": "^3.1.7", + "@types/d3-time": "^3.0.4", + "@types/d3-timer": "^3.0.2", + "d3-color": "^3.1.0", + "d3-interpolate": "^3.0.1", + "d3-sankey": "^0.12.3", + "d3-scale": "^4.0.2", + "d3-shape": "^3.2.0", + "d3-time": "^3.1.0", + "d3-timer": "^3.0.1" + } + }, + "node_modules/@mui/x-internal-gestures": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@mui/x-internal-gestures/-/x-internal-gestures-0.3.4.tgz", + "integrity": "sha512-7qQuDE7Khks3ujWtKPvGE0PAT2D15TKS6d3PDQYg/NzLyOoXe3AR5uGO4o+dOzHpdFC/qqNvn68wmq1N7UzL6Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4" + } + }, + "node_modules/@mui/x-internals": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-8.16.0.tgz", + "integrity": "sha512-JR53WOFqmQYQzurOpB0H91K7/9uMcte1ooxHxTLGB+97PgB+rKY6siRWvUALGS56XyPV+1a2ALI33hd2E7+Rgg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/utils": "^7.3.3", + "reselect": "^5.1.1", + "use-sync-external-store": "^1.6.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -984,6 +1450,16 @@ "node": ">= 8" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.34", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.34.tgz", @@ -1304,6 +1780,81 @@ "@babel/types": "^7.28.2" } }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-sankey": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/@types/d3-sankey/-/d3-sankey-0.12.4.tgz", + "integrity": "sha512-YTicQNwioitIlvuvlfW2GfO6sKxpohzg2cSQttlXAPjFwoBuN+XpGLhUN3kLutG/dI3GCLC+DUorqiJt7Naetw==", + "license": "MIT", + "dependencies": { + "@types/d3-shape": "^1" + } + }, + "node_modules/@types/d3-sankey/node_modules/@types/d3-path": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.11.tgz", + "integrity": "sha512-4pQMp8ldf7UaB/gR8Fvvy69psNHkTpD/pVw3vmEi8iZAB9EPMBruB1JvHO4BIq9QkUUd2lV1F5YXpMNj7JPBpw==", + "license": "MIT" + }, + "node_modules/@types/d3-sankey/node_modules/@types/d3-shape": { + "version": "1.3.12", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-1.3.12.tgz", + "integrity": "sha512-8oMzcd4+poSLGgV0R1Q1rOlx/xdmozS4Xab7np0eamFFUYq71AU9pOCJEFnkXW2aI/oXdVYJzw6pssbSut7Z9Q==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "^1" + } + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1325,6 +1876,18 @@ "undici-types": "~7.10.0" } }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, "node_modules/@types/react": { "version": "19.1.12", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.12.tgz", @@ -1352,6 +1915,15 @@ "@types/react": "*" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.43.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.43.0.tgz", @@ -1629,6 +2201,16 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, + "node_modules/@wavesurfer/react": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@wavesurfer/react/-/react-1.0.11.tgz", + "integrity": "sha512-DRpaA3MRTKy4Jby12xvoHASa+w31FZtxaqanXcJjfqNqfamkKi8VJfRnz+Uub9LkpdgoAc3g5SuZF75lEcGgzQ==", + "license": "BSD-3-Clause", + "peerDependencies": { + "react": "^18.2.0 || ^19.0.0", + "wavesurfer.js": ">=7.7.14" + } + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -1702,12 +2284,33 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/bezier-easing": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bezier-easing/-/bezier-easing-2.1.0.tgz", + "integrity": "sha512-gbIqZ/eslnUFC1tjEvtz0sgx+xTK20wDnYMIA27VA04R7w6xxXQPZDbibjA9DTWZRA2CXtwHykkVzlCaAJAZig==", + "license": "MIT" + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -1778,7 +2381,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -1824,6 +2426,15 @@ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1873,6 +2484,22 @@ "node": ">=18" } }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1890,14 +2517,146 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } }, "node_modules/debug": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, "dependencies": { "ms": "^2.1.3" }, @@ -1924,6 +2683,16 @@ "node": ">=0.4.0" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/dotenv": { "version": "17.2.2", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", @@ -1954,6 +2723,15 @@ "integrity": "sha512-TIvGp57UpeNetj/wV/xpFNpWGb0b/ROw372lHPx5Aafx02gjTBtWnEEcaSX3W2dLM3OSdGGyHX/cHl01JQsLaQ==", "dev": true }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -2049,7 +2827,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -2304,6 +3081,12 @@ "node": ">=8" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -2333,6 +3116,12 @@ "node": ">=16" } }, + "node_modules/flatqueue": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/flatqueue/-/flatqueue-3.0.0.tgz", + "integrity": "sha512-y1deYaVt+lIc/d2uIcWDNd0CrdQTO5xoCjeFdhX0kSXvm2Acm0o+3bAOiYklTEoRyzwio3sv3/IiBZdusbAe2Q==", + "license": "ISC" + }, "node_modules/flatted": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", @@ -2525,6 +3314,15 @@ "node": ">= 0.4" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -2538,7 +3336,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -2559,6 +3356,12 @@ "node": ">=0.8.19" } }, + "node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -2568,6 +3371,27 @@ "loose-envify": "^1.0.0" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2625,7 +3449,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, "bin": { "jsesc": "bin/jsesc" }, @@ -2639,6 +3462,12 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -2685,6 +3514,12 @@ "node": ">= 0.8.0" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2790,8 +3625,7 @@ "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/nanoid": { "version": "3.3.11", @@ -2882,7 +3716,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, "dependencies": { "callsites": "^3.0.0" }, @@ -2890,6 +3723,24 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -2908,11 +3759,25 @@ "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -3125,11 +3990,62 @@ "react-dom": ">=18" } }, + "node_modules/react-spinners": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-spinners/-/react-spinners-0.17.0.tgz", + "integrity": "sha512-L/8HTylaBmIWwQzIjMq+0vyaRXuoAevzWoD35wKpNTxxtYXWZp+xtgkfD7Y4WItuX0YvdxMPU79+7VhhmbmuTQ==", + "license": "MIT", + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "engines": { "node": ">=4" } @@ -3253,6 +4169,15 @@ "node": ">=8" } }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -3274,6 +4199,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3286,6 +4217,18 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -3448,6 +4391,28 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/uuid": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", + "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, "node_modules/vite": { "version": "7.1.5", "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.5.tgz", @@ -3551,6 +4516,12 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/wavesurfer.js": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/wavesurfer.js/-/wavesurfer.js-7.11.1.tgz", + "integrity": "sha512-8Q+wwItpjJAlhQ7crQLtKwgfbqqczm5/wx+76K4PptP+MBAjB0OA78+A9OuLnULz/8GpAQ+fKM6s81DonEO0Sg==", + "license": "BSD-3-Clause" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3581,6 +4552,15 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/server/src/routes/search.routes.ts b/server/src/routes/search.routes.ts index d8e88ef..6713a8b 100644 --- a/server/src/routes/search.routes.ts +++ b/server/src/routes/search.routes.ts @@ -38,7 +38,7 @@ router.get("/", async (req: Request, res: Response): Promise => { image_url AS image, genre FROM songs - WHERE title ILIKE $1 + WHERE title ILIKE $1 OR genre ILIKE $1 ORDER BY title ASC LIMIT $2 OFFSET $3 `; @@ -49,12 +49,12 @@ router.get("/", async (req: Request, res: Response): Promise => { })); } - // Artists (display_name only) + // Artists (display_name and bio) if (type === "all" || type === "artists") { const artistsQuery = ` - SELECT user_id as id, display_name as name, bio + SELECT user_id as id, display_name as name, bio, image_url AS image FROM artists - WHERE display_name ILIKE $1 + WHERE display_name ILIKE $1 OR bio ILIKE $1 LIMIT $2 OFFSET $3 `; const rows = await safeQuery(artistsQuery, [searchTerm, limitNum, offsetNum]); @@ -66,7 +66,7 @@ router.get("/", async (req: Request, res: Response): Promise => { })); } - // Albums (title, image_url, created_by) + // Albums (title only) if (type === "all" || type === "albums") { const albumsQuery = ` SELECT @@ -74,7 +74,7 @@ router.get("/", async (req: Request, res: Response): Promise => { image_url AS image, created_by AS artist FROM albums - WHERE title ILIKE $1 OR created_by ILIKE $1 + WHERE title ILIKE $1 ORDER BY title ASC LIMIT $2 OFFSET $3 `; @@ -88,15 +88,16 @@ router.get("/", async (req: Request, res: Response): Promise => { })); } - // Playlists (title, description, created_by) + // Playlists (title and description only) if (type === "all" || type === "playlists") { const playlistsQuery = ` SELECT title, description, - created_by AS artist + created_by AS artist, + image_url AS image FROM playlists - WHERE title ILIKE $1 OR description ILIKE $1 OR created_by ILIKE $1 + WHERE title ILIKE $1 OR description ILIKE $1 ORDER BY title ASC LIMIT $2 OFFSET $3 `; From aaca824a18b5eac01a04c77c595a18addd4f8371 Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Wed, 5 Nov 2025 18:00:44 -0600 Subject: [PATCH 18/22] Apply Inter font and clean up SearchResultsPage UI Added Inter font via Google Fonts in index.html and applied it to key UI elements for consistent typography. Updated CSS in SongCard, HomePage, and SearchResultsPage to use Inter and semi-bold weights. Removed unused 'View More' links from SearchResultsPage and styled the loading text. --- client/index.html | 3 +++ client/src/components/SongCard/SongCard.module.css | 3 ++- client/src/pages/HomePage/HomePage.module.css | 10 +++++----- .../SearchResultsPage/SearchResultsPage.module.css | 5 +++++ .../src/pages/SearchResultsPage/SearchResultsPage.tsx | 7 ++----- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/client/index.html b/client/index.html index 2ecbadc..2dd366a 100644 --- a/client/index.html +++ b/client/index.html @@ -4,6 +4,9 @@ + + + COSC 3380 diff --git a/client/src/components/SongCard/SongCard.module.css b/client/src/components/SongCard/SongCard.module.css index a63d038..f1e7ad3 100644 --- a/client/src/components/SongCard/SongCard.module.css +++ b/client/src/components/SongCard/SongCard.module.css @@ -67,10 +67,11 @@ } .songTitle { - font-weight: 600; + font-weight: 600; /* semi-bold */ color: #ffffff; margin-bottom: 4px; font-size: 0.95rem; + font-family: 'Inter', sans-serif; } .songArtist { diff --git a/client/src/pages/HomePage/HomePage.module.css b/client/src/pages/HomePage/HomePage.module.css index d76c750..2f4efc1 100644 --- a/client/src/pages/HomePage/HomePage.module.css +++ b/client/src/pages/HomePage/HomePage.module.css @@ -48,7 +48,8 @@ .sectionTitle { font-size: 24px; - font-weight: 700; + font-weight: 600; /* semi-bold */ + font-family: 'Inter', sans-serif; margin: 0; } @@ -57,10 +58,8 @@ text-decoration: none; font-size: 14px; transition: color 0.2s ease; -} - -.viewMore:hover { - color: var(--text-primary); + font-family: 'Inter', sans-serif; + font-weight: 600; /* semi-bold */ } /* Horizontal scrollable container */ @@ -149,6 +148,7 @@ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; + font-family: 'Inter', sans-serif; /* ensure Inter font */ } .compactCard .artistName { diff --git a/client/src/pages/SearchResultsPage/SearchResultsPage.module.css b/client/src/pages/SearchResultsPage/SearchResultsPage.module.css index 981bc72..b6f9617 100644 --- a/client/src/pages/SearchResultsPage/SearchResultsPage.module.css +++ b/client/src/pages/SearchResultsPage/SearchResultsPage.module.css @@ -40,3 +40,8 @@ color: white; border-color: #1db954; } + +.loading { + font-family: 'Inter', sans-serif; + font-weight: 600; /* semi-bold */ +} diff --git a/client/src/pages/SearchResultsPage/SearchResultsPage.tsx b/client/src/pages/SearchResultsPage/SearchResultsPage.tsx index 7333bd6..1643309 100644 --- a/client/src/pages/SearchResultsPage/SearchResultsPage.tsx +++ b/client/src/pages/SearchResultsPage/SearchResultsPage.tsx @@ -1,6 +1,7 @@ import { useEffect, useState } from "react"; import { useSearchParams } from "react-router-dom"; import homeStyles from "../HomePage/HomePage.module.css"; +import styles from "./SearchResultsPage.module.css"; import Sidebar from "../../components/SideBar/sidebar"; import Topbar from "../../components/TopBar/topBar"; import PlayerBar from "../../components/PlayerBar/playerBar"; @@ -48,7 +49,7 @@ export default function SearchResultsPage() {
- {loading &&

Loading...

} + {loading &&

Loading...

} {error &&

{error}

} {!loading && !error && ( @@ -56,7 +57,6 @@ export default function SearchResultsPage() {

Songs

- View More
{songs.map((song, index) => ( @@ -75,7 +75,6 @@ export default function SearchResultsPage() {

Artists

- View More
{artists.map((artist, index) => ( @@ -97,7 +96,6 @@ export default function SearchResultsPage() {

Albums

- View More
{albums.map((album, index) => ( @@ -119,7 +117,6 @@ export default function SearchResultsPage() {

Playlists

- View More
{playlists.map((pl, index) => ( From 9a1c14c2a1e2f18113239c1e353ae77108efd5d2 Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Wed, 5 Nov 2025 18:19:24 -0600 Subject: [PATCH 19/22] Add EntityItem component for displaying entities Introduces the EntityItem React component and its CSS module for displaying songs, playlists, albums, or artists with action buttons and navigation. This component supports both small and wide layouts, handles play and queue actions, and displays relevant entity information. --- .../EntityItem/EntityItem.module.css | 0 .../src/components/EntityItem/EntityItem.tsx | 193 ++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 client/src/components/EntityItem/EntityItem.module.css create mode 100644 client/src/components/EntityItem/EntityItem.tsx diff --git a/client/src/components/EntityItem/EntityItem.module.css b/client/src/components/EntityItem/EntityItem.module.css new file mode 100644 index 0000000..e69de29 diff --git a/client/src/components/EntityItem/EntityItem.tsx b/client/src/components/EntityItem/EntityItem.tsx new file mode 100644 index 0000000..b847586 --- /dev/null +++ b/client/src/components/EntityItem/EntityItem.tsx @@ -0,0 +1,193 @@ +import { memo, useState, useCallback, useRef, useEffect } from "react"; +import { Link, useNavigate } from "react-router-dom"; +import { useAudioQueue, useAuth } from "@contexts"; +import type { Song, Playlist, Album } from "@types"; +import { QueueMenu } from "@components"; +import styles from "./EntityItem.module.css"; +import musicPlaceholder from "@assets/music-placeholder.png"; +import artistPlaceholder from "@assets/artist-placeholder.png"; +import { LuPlay, LuListEnd } from "react-icons/lu"; + +interface EntityActionButtonsProps { + type: "song" | "list" | "artist"; + entity?: Song | Playlist | Album; + isHovered: boolean; + isSmall: boolean; +} + +const EntityActionButtons: React.FC = memo( + ({ type, entity, isHovered, isSmall }) => { + const { actions } = useAudioQueue(); + const { isAuthenticated } = useAuth(); + const navigate = useNavigate(); + + const [queueMenuOpen, setQueueMenuOpen] = useState(false); + const queueButtonRef = useRef(null); + + useEffect(() => { + if (!isHovered && queueMenuOpen) { + setQueueMenuOpen(false); + } + }, [isHovered, queueMenuOpen]); + + const handlePlay = useCallback(() => { + if (!entity) return; + actions.play(entity); + }, [actions, entity]); + + const handleAddToQueue = useCallback(async () => { + try { + if (isAuthenticated) { + setQueueMenuOpen((prev) => !prev); + } else { + navigate("/login"); + } + } catch (error) { + console.error("Adding to queue failed:", error); + } + }, [isAuthenticated, navigate]); + + if (isSmall) { + return ( +
+ {type === "song" && ( +
+ + setQueueMenuOpen(false)} + song={entity as Song} + buttonRef={queueButtonRef} + justification="right" + /> +
+ )} + {(type === "song" || type === "list") && ( + + )} +
+ ); + } + + return ( +
+ {type === "song" && ( +
+ + setQueueMenuOpen(false)} + song={entity as Song} + buttonRef={queueButtonRef} + justification="right" + /> +
+ )} + {(type === "song" || type === "list") && ( + + )} +
+ ); + } +); + +type EntityItemProps = + | { + type: "artist"; + linkTo: string; + author?: string; + title: string; + subtitle?: string; + imageUrl?: string; + entity?: never; + isSmall?: boolean; + index?: number; + } + | { + type: "song" | "list"; + linkTo: string; + author?: string; + title: string; + subtitle?: string; + imageUrl?: string; + entity: Song | Playlist | Album; + isSmall?: boolean; + index?: number; + }; + +/** + * @param EntityItemProps + * @param entity The entity object to play when clicking play (Song, Playlist, or Album) + * @param imageUrl Image URL for the entity + * @param linkTo Link to navigate to when clicking the title + * @param author Author name to display (text above title) + * @param title Title of the entity + * @param subtitle Subtitle text to display (text below title) + * @param type Type of entity: "song", "list", or "artist" + * @param isSmall Whether to use small layout (default: true). + * @param index Optional index number to display (for non-small layout) + */ +const EntityItem: React.FC = ({ + entity, + imageUrl, + linkTo, + author, + title, + subtitle, + type, + isSmall = true, + index, +}) => { + const [isHovered, setIsHovered] = useState(false); + + return ( +
setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + > + {!isSmall && index !== undefined && ( + {index} + )} + {`${title} +
+ {author && {author}} + + {title} + + {subtitle && {subtitle}} +
+ +
+ ); +}; + +export default memo(EntityItem); \ No newline at end of file From 5a2c96030dd6219667e28c3c676170536b848c8d Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Wed, 5 Nov 2025 18:23:13 -0600 Subject: [PATCH 20/22] Remove HomePage section components and styles Deleted FeaturedSection, NewSongSection, RecentSection components and their associated CSS module. This likely reflects a refactor or redesign of the HomePage structure. --- .../HomePage/sections/FeaturedSection.tsx | 45 ------ .../HomePage/sections/NewSongSection.tsx | 27 ---- .../pages/HomePage/sections/RecentSection.tsx | 34 ---- .../HomePage/sections/Sections.module.css | 150 ------------------ 4 files changed, 256 deletions(-) delete mode 100644 client/src/pages/HomePage/sections/FeaturedSection.tsx delete mode 100644 client/src/pages/HomePage/sections/NewSongSection.tsx delete mode 100644 client/src/pages/HomePage/sections/RecentSection.tsx delete mode 100644 client/src/pages/HomePage/sections/Sections.module.css diff --git a/client/src/pages/HomePage/sections/FeaturedSection.tsx b/client/src/pages/HomePage/sections/FeaturedSection.tsx deleted file mode 100644 index 3d71e43..0000000 --- a/client/src/pages/HomePage/sections/FeaturedSection.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import React from "react"; -import styles from "./Sections.module.css"; - - -interface FeaturedSectionProps { - title: string; - description: string; - image: string; - likes: number; - tracks: number; - duration: string; -} - -const FeaturedSection: React.FC = ({ - title, - description, - image, - likes, - tracks, - duration, -}) => ( -
-
-

Featured Playlist

-

{title}

-

{description}

-
- - {likes.toLocaleString()} likes - • {tracks} tracks - • {duration} -
-
- -
-
- {title} - -
-
-
-); - -export default FeaturedSection; \ No newline at end of file diff --git a/client/src/pages/HomePage/sections/NewSongSection.tsx b/client/src/pages/HomePage/sections/NewSongSection.tsx deleted file mode 100644 index 0ad24a2..0000000 --- a/client/src/pages/HomePage/sections/NewSongSection.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import React from "react"; -import styles from "./Sections.module.css"; - -interface NewSongsSectionProps { - title: string; - songs: { image: string; title: string }[]; -} - -const NewSongsSection: React.FC = ({ title, songs }) => ( -
-
-

{title}

- -
- -
- {songs.map((song, index) => ( -
- {song.title} -

{song.title}

-
- ))} -
-
-); - -export default NewSongsSection; \ No newline at end of file diff --git a/client/src/pages/HomePage/sections/RecentSection.tsx b/client/src/pages/HomePage/sections/RecentSection.tsx deleted file mode 100644 index c6a4948..0000000 --- a/client/src/pages/HomePage/sections/RecentSection.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from "react"; -import styles from "./Sections.module.css"; -import SongCard from "../../../components/SongCard/SongCard"; - -interface Song { - image: string; - title: string; - artist: string; - plays: number; - likes: number; - comments: number; -} - -interface RecentSongsSectionProps { - title: string; - songs: Song[]; -} - -const RecentSongsSection: React.FC = ({ title, songs }) => ( -
-
-

{title}

- -
- -
- {songs.map((song, index) => ( - - ))} -
-
-); - -export default RecentSongsSection; \ No newline at end of file diff --git a/client/src/pages/HomePage/sections/Sections.module.css b/client/src/pages/HomePage/sections/Sections.module.css deleted file mode 100644 index 0e4f1a1..0000000 --- a/client/src/pages/HomePage/sections/Sections.module.css +++ /dev/null @@ -1,150 +0,0 @@ -.homeGrid { - display: grid; - grid-template-columns: 1fr; - gap: 40px; - padding: 24px; -} - -.section { - display: flex; - flex-direction: column; - gap: 20px; -} - -.sectionHeader { - display: flex; - justify-content: space-between; - align-items: center; -} - -.sectionHeader h2 { - font-size: 1.4rem; - font-weight: 600; -} - -.viewMore { - background: none; - border: none; - color: #aaa; - cursor: pointer; - transition: color 0.2s; -} - -.viewMore:hover { - color: #fff; -} - -.featuredSection { - display: flex; - background: linear-gradient(to right, #7a1c1c, #c42b2b); - padding: 24px; - border-radius: 12px; - height: 400px; - color: #fff; - align-items: center; -} - -.featuredLeft { - flex: 1; -} - -.featuredSubtitle { - font-size: 0.8rem; - color: #eee; - text-transform: uppercase; -} - -.featuredTitle { - font-size: 2rem; - font-weight: 700; - margin: 8px 0; -} - -.featuredDescription { - color: #ddd; - margin-bottom: 12px; - line-height: 1.5; -} - -.featuredMeta { - display: flex; - align-items: center; - gap: 10px; - font-size: 0.9rem; - color: #eee; -} - -.featuredRight { - display: flex; - justify-content: center; - align-items: center; -} - -.featuredImageContainer { - position: relative; -} - -.featuredImage { - width: 320px; - max-width: 40%; - height: auto; - border-radius: 8px; - object-fit: cover; -} - -.playButton { - position: absolute; - inset: 0; - background-color: rgba(0, 0, 0, 0.4); - display: flex; - align-items: center; - justify-content: center; - border: none; - border-radius: 8px; - opacity: 0; - transition: opacity 0.2s ease; - cursor: pointer; -} - -.featuredImageContainer:hover .playButton { - opacity: 1; -} - -.songGrid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); - gap: 16px; -} - -.newSongsRow { - display: flex; - gap: 16px; - overflow-x: auto; - padding-bottom: 8px; -} - -.newSongCard { - flex-shrink: 0; - width: 180px; - display: flex; - flex-direction: column; - align-items: center; -} - -.newSongImage { - width: 100%; - height: 180px; - border-radius: 8px; - object-fit: cover; - transition: opacity 0.2s; -} - -.newSongImage:hover { - opacity: 0.8; -} - -.newSongTitle { - margin-top: 8px; - color: #ccc; - font-size: 0.9rem; -} \ No newline at end of file From f17b8e55030f206b61cf2addea9f23037f7b9f6f Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Wed, 5 Nov 2025 18:23:35 -0600 Subject: [PATCH 21/22] Improve styles and key usage in search results Added new styles for EntityItem and updated PlayerBar styles for better font consistency. Changed song list rendering in SearchResultsPage to use song.id as the key instead of the array index. Added clarifying comments in search.routes.ts regarding blob URL resolution. --- .../EntityItem/EntityItem.module.css | 130 ++++++++++++++++++ .../components/PlayerBar/playerBar.module.css | 4 + .../SearchResultsPage/SearchResultsPage.tsx | 4 +- server/src/routes/search.routes.ts | 4 +- 4 files changed, 138 insertions(+), 4 deletions(-) diff --git a/client/src/components/EntityItem/EntityItem.module.css b/client/src/components/EntityItem/EntityItem.module.css index e69de29..025e0d8 100644 --- a/client/src/components/EntityItem/EntityItem.module.css +++ b/client/src/components/EntityItem/EntityItem.module.css @@ -0,0 +1,130 @@ +.entityItem { + display: flex; + gap: var(--spacing-md); + align-items: center; + min-width: 0; + width: 100%; + position: relative; + } + + .entityImage { + width: 8rem; + height: 8rem; + border-radius: var(--border-radius-sm); + object-fit: cover; + aspect-ratio: 1 / 1; + flex-shrink: 0; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); + } + + .entityInfo { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); + min-width: 0; + width: 100%; + } + + .entityAuthor { + font-size: var(--font-size-sm); + color: var(--color-text-gray); + font-weight: 500; + } + + .entityTitle { + font-size: var(--font-size-md); + color: var(--color-white); + font-weight: 500; + transition: color var(--transition-speed) ease-in-out; + } + + .entityTitle:hover { + color: var(--color-red); + } + + .entitySubtitle { + font-size: var(--font-size-sm); + color: var(--color-text-gray); + font-weight: 500; + } + + .entityTitle, + .entityAuthor, + .entitySubtitle, + .entitySubtitle { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + width: 100%; + max-width: 100%; + } + + .entityActionButton { + display: flex; + align-items: center; + justify-content: center; + background: var(--color-panel-gray); + border-radius: var(--border-radius-sm); + border: 2px solid var(--color-panel-border); + color: var(--color-white); + cursor: pointer; + font-size: var(--icon-size-xs); + padding: var(--spacing-sm); + transition: color var(--transition-speed) ease-in-out; + } + + .entityActionButton:hover { + color: var(--color-red); + } + + .queueButtonContainer { + position: relative; + } + + .entityActionButtonContainer { + position: absolute; + right: 0; + top: 50%; + transform: translateY(-50%); + display: flex; + align-items: center; + gap: var(--spacing-sm); + opacity: 0; + visibility: hidden; + transition: all var(--transition-speed) ease; + background: linear-gradient( + to left, + var(--color-black) 0%, + var(--color-black) 75%, + transparent 100% + ); + padding: var(--spacing-sm) var(--spacing-md) var(--spacing-sm) + var(--spacing-xl); + border-radius: var(--border-radius-sm); + } + + .entityItem:hover .entityActionButtonContainer { + opacity: 1; + visibility: visible; + } + + .entityActionButtonContainerWide { + display: flex; + align-items: center; + gap: var(--spacing-sm); + flex-shrink: 0; + } + + .entityIndex { + font-size: var(--font-size-sm); + color: var(--color-white); + font-weight: 500; + width: 2rem; + min-width: 2rem; + max-width: 2rem; + flex-shrink: 0; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + text-align: center; + } \ No newline at end of file diff --git a/client/src/components/PlayerBar/playerBar.module.css b/client/src/components/PlayerBar/playerBar.module.css index 0597c5f..77f8b0e 100644 --- a/client/src/components/PlayerBar/playerBar.module.css +++ b/client/src/components/PlayerBar/playerBar.module.css @@ -39,11 +39,15 @@ color: #fff; margin: 0; font-size: 14px; + font-weight: 600; + font-family: 'Inter', sans-serif; } .playerSong span { color: #a7a7a7; font-size: 12px; + font-weight: 400; + font-family: 'Inter', sans-serif; } /* Center section - Controls */ diff --git a/client/src/pages/SearchResultsPage/SearchResultsPage.tsx b/client/src/pages/SearchResultsPage/SearchResultsPage.tsx index 1643309..2269fc3 100644 --- a/client/src/pages/SearchResultsPage/SearchResultsPage.tsx +++ b/client/src/pages/SearchResultsPage/SearchResultsPage.tsx @@ -59,8 +59,8 @@ export default function SearchResultsPage() {

Songs

- {songs.map((song, index) => ( -
+ {songs.map((song) => ( +
{song.title}

{song.title}

diff --git a/server/src/routes/search.routes.ts b/server/src/routes/search.routes.ts index 6713a8b..03250c4 100644 --- a/server/src/routes/search.routes.ts +++ b/server/src/routes/search.routes.ts @@ -1,5 +1,5 @@ import express, { Request, Response } from "express"; -import { getBlobUrl } from "../config/blobStorage.js"; +import { getBlobUrl } from "../config/blobStorage.js"; // Used to resolve blob URLs import { pool } from "../config/database.js"; const router = express.Router(); @@ -45,7 +45,7 @@ router.get("/", async (req: Request, res: Response): Promise => { const rows = await safeQuery(songsQuery, [searchTerm, limitNum, offsetNum]); results.songs = rows.map((row: any) => ({ ...row, - image: row.image ? getBlobUrl(row.image) : "/PlayerBar/Mask group.png", + image: row.image ? getBlobUrl(row.image) : "/PlayerBar/Mask group.png", // Resolving blob URL })); } From 293c513d5b29bd7fbf823681ce0771114a5020ce Mon Sep 17 00:00:00 2001 From: Joshua Nguyen Date: Thu, 6 Nov 2025 16:35:41 -0600 Subject: [PATCH 22/22] Add artist page components and refactor layout Introduces new components for the artist page, including ArtistBanner, ArtistAbout, ArtistActions, ArtistPlaylists, and RelatedArtists, along with their styles. Removes old PlayerBar, SideBar, and TopBar components, and updates routing to support artist pages. Refactors layout structure with AppLayout and MainLayout, adds utility and test components, and updates API types for artist and search functionality. --- client/src/Routes.tsx | 3 +- client/src/api/artist.api.ts | 0 client/src/api/search.api.ts | 17 +- client/src/components/AppLayout/AppLayout.tsx | 14 + .../ArtistAbout/ArtistAbout.module.css | 44 +++ .../ArtistPage/ArtistAbout/ArtistAbout.tsx | 60 +++ .../ArtistActions/ArtistActions.module.css | 97 +++++ .../ArtistActions/ArtistActions.tsx | 174 ++++++++ .../ArtistBanner/ArtistBanner.module.css | 146 +++++++ .../ArtistPage/ArtistBanner/ArtistBanner.tsx | 102 +++++ .../ArtistPlaylists.module.css | 39 ++ .../ArtistPlaylists/ArtistPlaylists.tsx | 71 ++++ .../RelatedArtists/RelatedArtists.module.css | 134 +++++++ .../RelatedArtists/RelatedArtists.tsx | 72 ++++ .../AudioQueueTest/AudioQueueTest.tsx | 270 +++++++++++++ .../CoverLightbox/CoverLightbox.module.css | 73 ++++ .../CoverLightbox/CoverLightbox.tsx | 50 +++ .../components/DevBanner/DevBanner.module.css | 42 ++ client/src/components/DevBanner/DevBanner.tsx | 44 +++ .../EntityItem/EntityItem.module.css | 258 ++++++------ .../src/components/EntityItem/EntityItem.tsx | 2 +- .../EntityItemCard/EntityItemCard.module.css | 113 ++++++ .../EntityItemCard/EntityItemCard.tsx | 153 +++++++ .../components/ErrorPage/ErrorPage.module.css | 57 +++ client/src/components/ErrorPage/ErrorPage.tsx | 38 ++ .../FollowProfiles/FollowProfiles.module.css | 106 +++++ .../FollowProfiles/FollowProfiles.tsx | 105 +++++ .../FormButton/FormSubmitButton.module.css | 25 ++ .../Forms/FormButton/FormSubmitButton.tsx | 24 ++ .../Forms/InputGroup/InputGroup.module.css | 61 +++ .../Forms/InputGroup/InputGroup.tsx | 56 +++ .../HorizontalRule/HorizontalRule.module.css | 8 + .../Layout/HorizontalRule/HorizontalRule.tsx | 8 + .../VerticalRule/VerticalRule.module.css | 7 + .../Layout/VerticalRule/VerticalRule.tsx | 8 + .../MainLayout/MainLayout.module.css | 44 +++ .../src/components/MainLayout/MainLayout.tsx | 21 + .../MainLayoutHeader.module.css | 121 ++++++ .../MainLayoutHeader/MainLayoutHeader.tsx | 78 ++++ .../MainLayoutNowPlayingBar.module.css | 312 +++++++++++++++ .../MainLayoutNowPlayingBar.tsx | 373 ++++++++++++++++++ .../MainLayoutSearchBar.module.css | 70 ++++ .../MainLayoutSearchBar.tsx | 18 + .../MainLayoutSidebar.module.css | 72 ++++ .../MainLayoutSidebar/MainLayoutSidebar.tsx | 61 +++ .../QueueManager/QueueManager.module.css | 222 +++++++++++ .../MainLayout/QueueManager/QueueManager.tsx | 183 +++++++++ .../PageLoader/PageLoader.module.css | 8 + .../src/components/PageLoader/PageLoader.tsx | 13 + .../components/PlayerBar/playerBar.module.css | 142 ------- client/src/components/PlayerBar/playerBar.tsx | 57 --- .../ProtectedRoute/ProtectedRoute.tsx | 25 ++ .../components/QueueMenu/QueueMenu.module.css | 115 ++++++ client/src/components/QueueMenu/QueueMenu.tsx | 95 +++++ .../ShareModal/ShareModal.module.css | 192 +++++++++ .../src/components/ShareModal/ShareModal.tsx | 135 +++++++ .../src/components/SideBar/sideBar.module.css | 70 ---- client/src/components/SideBar/sidebar.tsx | 42 -- .../SlidingCardList.module.css | 100 +++++ .../SlidingCardList/SlidingCardList.tsx | 222 +++++++++++ .../components/SongCard/SongCard.module.css | 5 +- client/src/components/SongCard/SongCard.tsx | 30 +- .../SongPage/ArtistInfo/ArtistInfo.module.css | 231 +++++++++++ .../SongPage/ArtistInfo/ArtistInfo.tsx | 139 +++++++ .../CommentItem/CommentItem.module.css | 129 ++++++ .../SongPage/CommentItem/CommentItem.tsx | 127 ++++++ .../SongActions/SongActions.module.css | 32 ++ .../SongPage/SongActions/SongActions.tsx | 141 +++++++ .../SongComments/SongComments.module.css | 103 +++++ .../SongPage/SongComments/SongComments.tsx | 142 +++++++ .../SongContainer/SongContainer.module.css | 105 +++++ .../SongPage/SongContainer/SongContainer.tsx | 101 +++++ .../SongDetails/SongDetails.module.css | 57 +++ .../SongPage/SongDetails/SongDetails.tsx | 45 +++ .../SongPage/SongStats/SongStats.module.css | 32 ++ .../SongPage/SongStats/SongStats.tsx | 114 ++++++ .../SongSuggestions.module.css | 39 ++ .../SongSuggestions/SongSuggestions.tsx | 133 +++++++ .../WaveformPlayer/WaveformPlayer.module.css | 102 +++++ .../WaveformPlayer/WaveformPlayer.tsx | 281 +++++++++++++ .../components/SongsList/SongsList.module.css | 55 +++ client/src/components/SongsList/SongsList.tsx | 90 +++++ .../src/components/TopBar/topBar.module.css | 89 ----- client/src/components/TopBar/topBar.tsx | 78 ---- client/src/components/index.ts | 60 ++- client/src/hooks/useAsyncData.ts | 0 .../pages/ArtistPage/ArtistPage.module.css | 0 client/src/pages/ArtistPage/ArtistPage.tsx | 30 ++ client/src/pages/HomePage/HomePage.tsx | 46 ++- .../SearchResultsPage/SearchResultsPage.tsx | 21 +- client/src/pages/index.ts | 1 + client/src/types/artist.types.ts | 0 server/src/routes/search.routes.ts | 24 +- 93 files changed, 7204 insertions(+), 650 deletions(-) create mode 100644 client/src/api/artist.api.ts create mode 100644 client/src/components/AppLayout/AppLayout.tsx create mode 100644 client/src/components/ArtistPage/ArtistAbout/ArtistAbout.module.css create mode 100644 client/src/components/ArtistPage/ArtistAbout/ArtistAbout.tsx create mode 100644 client/src/components/ArtistPage/ArtistActions/ArtistActions.module.css create mode 100644 client/src/components/ArtistPage/ArtistActions/ArtistActions.tsx create mode 100644 client/src/components/ArtistPage/ArtistBanner/ArtistBanner.module.css create mode 100644 client/src/components/ArtistPage/ArtistBanner/ArtistBanner.tsx create mode 100644 client/src/components/ArtistPage/ArtistPlaylists/ArtistPlaylists.module.css create mode 100644 client/src/components/ArtistPage/ArtistPlaylists/ArtistPlaylists.tsx create mode 100644 client/src/components/ArtistPage/RelatedArtists/RelatedArtists.module.css create mode 100644 client/src/components/ArtistPage/RelatedArtists/RelatedArtists.tsx create mode 100644 client/src/components/AudioQueueTest/AudioQueueTest.tsx create mode 100644 client/src/components/CoverLightbox/CoverLightbox.module.css create mode 100644 client/src/components/CoverLightbox/CoverLightbox.tsx create mode 100644 client/src/components/DevBanner/DevBanner.module.css create mode 100644 client/src/components/DevBanner/DevBanner.tsx create mode 100644 client/src/components/EntityItemCard/EntityItemCard.module.css create mode 100644 client/src/components/EntityItemCard/EntityItemCard.tsx create mode 100644 client/src/components/ErrorPage/ErrorPage.module.css create mode 100644 client/src/components/ErrorPage/ErrorPage.tsx create mode 100644 client/src/components/FollowProfiles/FollowProfiles.module.css create mode 100644 client/src/components/FollowProfiles/FollowProfiles.tsx create mode 100644 client/src/components/Forms/FormButton/FormSubmitButton.module.css create mode 100644 client/src/components/Forms/FormButton/FormSubmitButton.tsx create mode 100644 client/src/components/Forms/InputGroup/InputGroup.module.css create mode 100644 client/src/components/Forms/InputGroup/InputGroup.tsx create mode 100644 client/src/components/Layout/HorizontalRule/HorizontalRule.module.css create mode 100644 client/src/components/Layout/HorizontalRule/HorizontalRule.tsx create mode 100644 client/src/components/Layout/VerticalRule/VerticalRule.module.css create mode 100644 client/src/components/Layout/VerticalRule/VerticalRule.tsx create mode 100644 client/src/components/MainLayout/MainLayout.module.css create mode 100644 client/src/components/MainLayout/MainLayout.tsx create mode 100644 client/src/components/MainLayout/MainLayoutHeader/MainLayoutHeader.module.css create mode 100644 client/src/components/MainLayout/MainLayoutHeader/MainLayoutHeader.tsx create mode 100644 client/src/components/MainLayout/MainLayoutNowPlayingBar/MainLayoutNowPlayingBar.module.css create mode 100644 client/src/components/MainLayout/MainLayoutNowPlayingBar/MainLayoutNowPlayingBar.tsx create mode 100644 client/src/components/MainLayout/MainLayoutSearchBar/MainLayoutSearchBar.module.css create mode 100644 client/src/components/MainLayout/MainLayoutSearchBar/MainLayoutSearchBar.tsx create mode 100644 client/src/components/MainLayout/MainLayoutSidebar/MainLayoutSidebar.module.css create mode 100644 client/src/components/MainLayout/MainLayoutSidebar/MainLayoutSidebar.tsx create mode 100644 client/src/components/MainLayout/QueueManager/QueueManager.module.css create mode 100644 client/src/components/MainLayout/QueueManager/QueueManager.tsx create mode 100644 client/src/components/PageLoader/PageLoader.module.css create mode 100644 client/src/components/PageLoader/PageLoader.tsx delete mode 100644 client/src/components/PlayerBar/playerBar.module.css delete mode 100644 client/src/components/PlayerBar/playerBar.tsx create mode 100644 client/src/components/ProtectedRoute/ProtectedRoute.tsx create mode 100644 client/src/components/QueueMenu/QueueMenu.module.css create mode 100644 client/src/components/QueueMenu/QueueMenu.tsx create mode 100644 client/src/components/ShareModal/ShareModal.module.css create mode 100644 client/src/components/ShareModal/ShareModal.tsx delete mode 100644 client/src/components/SideBar/sideBar.module.css delete mode 100644 client/src/components/SideBar/sidebar.tsx create mode 100644 client/src/components/SlidingCardList/SlidingCardList.module.css create mode 100644 client/src/components/SlidingCardList/SlidingCardList.tsx create mode 100644 client/src/components/SongPage/ArtistInfo/ArtistInfo.module.css create mode 100644 client/src/components/SongPage/ArtistInfo/ArtistInfo.tsx create mode 100644 client/src/components/SongPage/CommentItem/CommentItem.module.css create mode 100644 client/src/components/SongPage/CommentItem/CommentItem.tsx create mode 100644 client/src/components/SongPage/SongActions/SongActions.module.css create mode 100644 client/src/components/SongPage/SongActions/SongActions.tsx create mode 100644 client/src/components/SongPage/SongComments/SongComments.module.css create mode 100644 client/src/components/SongPage/SongComments/SongComments.tsx create mode 100644 client/src/components/SongPage/SongContainer/SongContainer.module.css create mode 100644 client/src/components/SongPage/SongContainer/SongContainer.tsx create mode 100644 client/src/components/SongPage/SongDetails/SongDetails.module.css create mode 100644 client/src/components/SongPage/SongDetails/SongDetails.tsx create mode 100644 client/src/components/SongPage/SongStats/SongStats.module.css create mode 100644 client/src/components/SongPage/SongStats/SongStats.tsx create mode 100644 client/src/components/SongPage/SongSuggestions/SongSuggestions.module.css create mode 100644 client/src/components/SongPage/SongSuggestions/SongSuggestions.tsx create mode 100644 client/src/components/SongPage/WaveformPlayer/WaveformPlayer.module.css create mode 100644 client/src/components/SongPage/WaveformPlayer/WaveformPlayer.tsx create mode 100644 client/src/components/SongsList/SongsList.module.css create mode 100644 client/src/components/SongsList/SongsList.tsx delete mode 100644 client/src/components/TopBar/topBar.module.css delete mode 100644 client/src/components/TopBar/topBar.tsx create mode 100644 client/src/hooks/useAsyncData.ts create mode 100644 client/src/pages/ArtistPage/ArtistPage.module.css create mode 100644 client/src/pages/ArtistPage/ArtistPage.tsx create mode 100644 client/src/types/artist.types.ts diff --git a/client/src/Routes.tsx b/client/src/Routes.tsx index 7537691..7b7313e 100644 --- a/client/src/Routes.tsx +++ b/client/src/Routes.tsx @@ -1,12 +1,13 @@ import { Routes, Route } from "react-router-dom"; import * as Pages from "./pages"; -import HomePage from "./pages/HomePage/HomePage" +import HomePage from "./pages/HomePage/HomePage"; export default function AppRoutes() { return ( } /> } /> + } /> } /> ); diff --git a/client/src/api/artist.api.ts b/client/src/api/artist.api.ts new file mode 100644 index 0000000..e69de29 diff --git a/client/src/api/search.api.ts b/client/src/api/search.api.ts index fd0a8fa..68c84de 100644 --- a/client/src/api/search.api.ts +++ b/client/src/api/search.api.ts @@ -2,14 +2,21 @@ import api from "./api"; export type SearchType = "all" | "songs" | "artists" | "albums" | "playlists"; +export interface SearchSongArtistRef { + id: string | number; + name: string; +} + export interface SearchSong { id: string | number; title: string; - artist: string; image: string; - plays: number; - likes: number; - comments: number; + // Optional fields depending on API response + artist?: string; + artists?: SearchSongArtistRef[]; + plays?: number; + likes?: number; + comments?: number; duration?: number; } @@ -17,7 +24,7 @@ export interface SearchArtist { id: string | number; name: string; image: string; - plays: number; + plays?: number; likes?: number; comments?: number; } diff --git a/client/src/components/AppLayout/AppLayout.tsx b/client/src/components/AppLayout/AppLayout.tsx new file mode 100644 index 0000000..55d11a4 --- /dev/null +++ b/client/src/components/AppLayout/AppLayout.tsx @@ -0,0 +1,14 @@ +import { Outlet } from "react-router-dom"; +import { AudioQueueProvider } from "@contexts"; +import { DevBanner } from "@components"; + +const AppLayout: React.FC = () => { + return ( + + + + + ); +}; + +export default AppLayout; diff --git a/client/src/components/ArtistPage/ArtistAbout/ArtistAbout.module.css b/client/src/components/ArtistPage/ArtistAbout/ArtistAbout.module.css new file mode 100644 index 0000000..ec118b6 --- /dev/null +++ b/client/src/components/ArtistPage/ArtistAbout/ArtistAbout.module.css @@ -0,0 +1,44 @@ +.loaderContainer { + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + min-height: 15vh; +} + +.error { + text-align: center; + color: var(--color-text-gray); + font-size: var(--font-size-sm); +} + +.aboutContainer { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: var(--spacing-md); + background: var(--color-panel-gray); + border-radius: var(--border-radius-md); + border: 2px solid var(--color-panel-border); + padding: var(--spacing-md); + min-width: 0; + width: 100%; +} + +.aboutTitle { + font-size: var(--font-size-lg); + color: var(--color-white); + font-weight: 500; +} + +.monthlyListenersText { + font-size: var(--font-size-md); + color: var(--color-white); + font-weight: 500; +} + +.artistBio { + font-size: var(--font-size-md); + color: var(--color-text-gray); + font-weight: 400; +} diff --git a/client/src/components/ArtistPage/ArtistAbout/ArtistAbout.tsx b/client/src/components/ArtistPage/ArtistAbout/ArtistAbout.tsx new file mode 100644 index 0000000..22cfcd1 --- /dev/null +++ b/client/src/components/ArtistPage/ArtistAbout/ArtistAbout.tsx @@ -0,0 +1,60 @@ +import { memo, useMemo } from "react"; +import { PuffLoader } from "react-spinners"; +import type { UUID } from "@types"; +import { formatNumber } from "@util"; +import { useAsyncData } from "@hooks"; +import { artistApi } from "@api"; +import styles from "./ArtistAbout.module.css"; + +export interface ArtistAboutProps { + artistId: UUID; + artistName: string; + artistBio?: string; +} + +const ArtistAbout: React.FC = ({ + artistId, + artistName, + artistBio, +}) => { + const { data, loading, error } = useAsyncData( + { + monthlyListeners: () => artistApi.getMonthlyListeners(artistId), + }, + [artistId], + { + cacheKey: `about_${artistId}`, + } + ); + + const monthlyListeners = useMemo(() => { + const count = formatNumber(data?.monthlyListeners ?? 0); + return count; + }, [data]); + + if (loading) { + return ( +
+ +
+ ); + } + + if (error) { + return
Failed to load about section.
; + } + + return ( +
+ About + + {monthlyListeners} monthly listeners + + + {artistBio || `${artistName} has no bio yet...`} + +
+ ); +}; + +export default memo(ArtistAbout); diff --git a/client/src/components/ArtistPage/ArtistActions/ArtistActions.module.css b/client/src/components/ArtistPage/ArtistActions/ArtistActions.module.css new file mode 100644 index 0000000..a4ee388 --- /dev/null +++ b/client/src/components/ArtistPage/ArtistActions/ArtistActions.module.css @@ -0,0 +1,97 @@ +.loaderContainer { + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + min-height: 15vh; +} + +.error { + text-align: center; + color: var(--color-text-gray); + font-size: var(--font-size-sm); +} + +.artistActionsContainer { + display: flex; + flex-direction: column; + gap: var(--spacing-md); + background: var(--color-panel-gray); + border-radius: var(--border-radius-md); + border: 2px solid var(--color-panel-border); + padding: var(--spacing-md); + min-width: 0; +} + +.actionsLayout { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + align-items: center; + row-gap: var(--spacing-md); + column-gap: var(--spacing-sm); +} + +.actionButton, +.actionButtonAlt { + font-family: "Inter", sans-serif; + display: flex; + align-items: center; + justify-content: center; + gap: var(--spacing-sm); + border-radius: var(--border-radius-sm); + cursor: pointer; + font-size: var(--font-size-sm); + padding: var(--spacing-sm) var(--spacing-md); + transition: background-color var(--transition-speed) ease-in-out; +} + +.actionButton { + background: var(--color-red); + border: 1px solid var(--color-red); + border: none; + color: var(--color-red-200); +} + +.actionButton:hover { + background-color: var(--color-red-700); +} + +.actionButtonAlt { + background: var(--color-gray-button); + border: 1px solid var(--color-gray-button-border); + color: var(--color-white); +} + +.actionButtonAlt:hover { + background-color: var(--color-gray-button-hover); +} + +.artistStat { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: var(--spacing-xs); +} + +.artistStatLarge { + display: flex; + align-items: center; + gap: var(--spacing-sm); + font-size: var(--font-size-lg); + color: var(--color-white); + font-weight: 700; +} + +.artistStatLabel { + font-size: var(--font-size-sm); + color: var(--color-text-gray); + font-weight: 500; +} + +.artistStatLarge, +.artistStatLabel { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 100%; +} diff --git a/client/src/components/ArtistPage/ArtistActions/ArtistActions.tsx b/client/src/components/ArtistPage/ArtistActions/ArtistActions.tsx new file mode 100644 index 0000000..bcf0ddb --- /dev/null +++ b/client/src/components/ArtistPage/ArtistActions/ArtistActions.tsx @@ -0,0 +1,174 @@ +import { useState, memo, useMemo, useCallback } from "react"; +import { PuffLoader } from "react-spinners"; +import { useNavigate } from "react-router-dom"; +import { useAuth } from "@contexts"; +import { useAsyncData } from "@hooks"; +import { formatNumber } from "@util"; +import { artistApi } from "@api"; +import { ShareModal } from "@components"; +import styles from "./ArtistActions.module.css"; +import { + LuCirclePlay, + LuUserRoundPlus, + LuShare, + LuCircleAlert, + LuUsersRound, + LuMusic, + LuAudioLines, + LuUserRoundCheck, +} from "react-icons/lu"; + +const StatItem = memo( + ({ + icon: Icon, + value, + label, + }: { + icon: React.ElementType; + value: string; + label: string; + }) => ( +
+
+
+ {label} +
+ ) +); + +export interface ArtistActionsProps { + artistId: string; + userId: string; + artistName: string; + shareLink: string; +} + +const ArtistActions: React.FC = ({ + artistId, + userId, + artistName, + shareLink, +}) => { + const navigate = useNavigate(); + const { isAuthenticated } = useAuth(); + const [isFollowed, setIsFollowed] = useState(false); + const [isShareModalOpen, setIsShareModalOpen] = useState(false); + + const asyncConfig = useMemo( + () => ({ + followingCount: () => artistApi.getFollowingCount(userId), + followerCount: () => artistApi.getFollowerCount(userId), + numberOfSongs: () => artistApi.getNumberOfSongs(artistId), + totalStreams: () => artistApi.getTotalStreams(artistId), + }), + [artistId, userId] + ); + + const { data, loading, error } = useAsyncData(asyncConfig, [artistId], { + cacheKey: `artist_actions_${artistId}`, + hasBlobUrl: true, + }); + + const stats = useMemo( + () => ({ + followers: formatNumber(data?.followerCount ?? 0), + following: formatNumber(data?.followingCount ?? 0), + tracks: formatNumber(data?.numberOfSongs ?? 0), + streams: formatNumber(data?.totalStreams ?? 0), + }), + [data] + ); + + const handleFollowArtist = useCallback(async () => { + try { + if (isAuthenticated) { + //! send request here + setIsFollowed((prev) => !prev); + } else { + navigate("/login"); + } + } catch (error) { + console.error("Toggling follow artist failed:", error); + } + }, [isAuthenticated, navigate]); + + const handleShare = useCallback(() => { + setIsShareModalOpen(true); + }, []); + + const handleReport = useCallback(() => { + // TODO: open report modal... + }, []); + + const handleCloseShareModal = useCallback(() => { + setIsShareModalOpen(false); + }, []); + + const handlePlayAll = useCallback(() => { + //todo: make new action - playArtist + make util function to get all songs by artist sorted by streams + }, []); + + return loading ? ( +
+ +
+ ) : ( + <> +
+
+ + + + + + {!error && ( + <> + + + + + + )} +
+
+ + + + ); +}; + +export default memo(ArtistActions); diff --git a/client/src/components/ArtistPage/ArtistBanner/ArtistBanner.module.css b/client/src/components/ArtistPage/ArtistBanner/ArtistBanner.module.css new file mode 100644 index 0000000..0c32e16 --- /dev/null +++ b/client/src/components/ArtistPage/ArtistBanner/ArtistBanner.module.css @@ -0,0 +1,146 @@ +.artistBanner { + position: relative; + display: flex; + width: 100%; + height: 32rem; + background: linear-gradient(to bottom, #181818, #0f0f0f); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); + border-radius: var(--border-radius-sm); + overflow: hidden; + padding: var(--spacing-lg); +} + +.bannerImage { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; + z-index: 0; +} + +.artistBanner::after { + content: ""; + position: absolute; + inset: 0; + background: linear-gradient(65deg, #080808 0%, transparent 25%); + pointer-events: none; + z-index: 1; +} + +.artistInfo { + z-index: 2; + display: flex; + gap: var(--spacing-lg); + align-items: center; +} + +.artistImage { + width: 24rem; + height: 24rem; + border-radius: 50%; + object-fit: cover; + aspect-ratio: 1 / 1; + flex-shrink: 0; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); + transition: box-shadow var(--transition-speed) ease; +} + +.artistImageClickable { + cursor: pointer; +} + +.artistImage:hover { + box-shadow: 0 0 15px rgba(0, 0, 0, 0.6); +} + +.artistInfoRight { + display: flex; + flex-direction: column; + gap: var(--spacing-sm); +} + +.artistNameContainer { + min-width: 0; + display: flex; + gap: var(--spacing-md); + align-items: center; +} + +.artistName { + font-size: 7.2rem; + color: var(--dynamic-text-color, var(--color-white)); + font-weight: 700; +} + +.badgeWrapper { + position: relative; + display: flex; + align-items: center; +} + +.tooltip { + position: absolute; + bottom: calc(100% + var(--spacing-sm)); + left: 50%; + transform: translateX(-50%); + background: rgba(246, 246, 246, 0.8); + color: var(--color-black); + padding: 0.6rem 1.2rem; + border-radius: var(--border-radius-sm); + font-size: 13px; + font-weight: 500; + white-space: nowrap; + pointer-events: none; + z-index: 1000; + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3); + opacity: 0; + animation: tooltipFadeIn 0.15s ease-out forwards; +} + +.verifiedBadge { + font-size: var(--icon-size-xl); + flex-shrink: 0; + color: var(--dynamic-text-color, var(--color-white)); + transition: color var(--transition-speed) ease-in-out; +} + +.verifiedBadge:hover { + color: var(--dynamic-text-color, var(--color-white-hover)); +} + +.tooltip::after { + content: ""; + position: absolute; + top: 100%; + left: 50%; + transform: translateX(-50%); + border: 5px solid transparent; + border-top-color: rgba(246, 246, 246, 0.75); +} + +@keyframes tooltipFadeIn { + from { + opacity: 0; + transform: translateX(-50%) translateY(-4px); + } + to { + opacity: 1; + transform: translateX(-50%) translateY(0); + } +} + +.artistLocation { + font-size: var(--font-size-lg); + color: var(--dynamic-text-color, var(--color-white)); + font-weight: 500; +} + +.artistName, +.artistLocation { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 100%; +} diff --git a/client/src/components/ArtistPage/ArtistBanner/ArtistBanner.tsx b/client/src/components/ArtistPage/ArtistBanner/ArtistBanner.tsx new file mode 100644 index 0000000..d9f911c --- /dev/null +++ b/client/src/components/ArtistPage/ArtistBanner/ArtistBanner.tsx @@ -0,0 +1,102 @@ +import { useState, useCallback, memo, useMemo } from "react"; +import { CoverLightbox } from "@components"; +import { useTextContrast } from "@hooks"; +import styles from "./ArtistBanner.module.css"; +import classNames from "classnames"; +import { LuBadgeCheck } from "react-icons/lu"; +import artistPlaceholder from "@assets/artist-placeholder.png"; + +export interface ArtistBannerProps { + bannerImageUrl?: string; + artistImageUrl?: string; + artistName: string; + artistLocation?: string; + isVerified?: boolean; +} + +const ArtistBanner: React.FC = ({ + bannerImageUrl, + artistImageUrl, + artistName, + artistLocation, + isVerified, +}) => { + const { textColor, loading } = useTextContrast(bannerImageUrl); + + const [isTooltipVisible, setIsTooltipVisible] = useState(false); + const [isLightboxOpen, setIsLightboxOpen] = useState(false); + + const handleTooltipShow = useCallback(() => setIsTooltipVisible(true), []); + const handleTooltipHide = useCallback(() => setIsTooltipVisible(false), []); + const handleLightboxClose = useCallback(() => setIsLightboxOpen(false), []); + + const handleImageClick = useCallback(() => { + setIsLightboxOpen(true); + }, []); + + const bannerStyle = useMemo( + () => + ({ + "--dynamic-text-color": + textColor === "white" ? "var(--color-white)" : "var(--color-black)", + } as React.CSSProperties), + [textColor] + ); + + return ( + <> +
+ {bannerImageUrl && !loading && ( + {`${artistName} + )} +
+ {`${artistName} +
+
+

{artistName}

+ {isVerified && ( +
+ + {isTooltipVisible && ( +
Verified by CoogMusic
+ )} +
+ )} +
+ {artistLocation && ( + {artistLocation} + )} +
+
+
+ + {artistImageUrl && ( + + )} + + ); +}; + +export default memo(ArtistBanner); diff --git a/client/src/components/ArtistPage/ArtistPlaylists/ArtistPlaylists.module.css b/client/src/components/ArtistPage/ArtistPlaylists/ArtistPlaylists.module.css new file mode 100644 index 0000000..dbdc933 --- /dev/null +++ b/client/src/components/ArtistPage/ArtistPlaylists/ArtistPlaylists.module.css @@ -0,0 +1,39 @@ +.loaderContainer { + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + min-height: 15vh; +} + +.error { + text-align: center; + color: var(--color-text-gray); + font-size: var(--font-size-sm); +} + +.sectionTitle { + font-size: var(--font-size-lg); + color: var(--color-white); + font-weight: 500; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 100%; +} + +.playlistsContainer { + display: flex; + flex-direction: column; + gap: var(--spacing-md); + min-width: 0; + width: 100%; +} + +.playlistsList { + width: 100%; + display: flex; + flex-direction: column; + gap: var(--spacing-md); + min-width: 0; +} diff --git a/client/src/components/ArtistPage/ArtistPlaylists/ArtistPlaylists.tsx b/client/src/components/ArtistPage/ArtistPlaylists/ArtistPlaylists.tsx new file mode 100644 index 0000000..92acf92 --- /dev/null +++ b/client/src/components/ArtistPage/ArtistPlaylists/ArtistPlaylists.tsx @@ -0,0 +1,71 @@ +import { memo } from "react"; +import { PuffLoader } from "react-spinners"; +import type { UUID } from "@types"; +import { useAsyncData } from "@hooks"; +import { artistApi } from "@api"; +import { EntityItem } from "@components"; +import styles from "./ArtistPlaylists.module.css"; +import musicPlaceholder from "@assets/music-placeholder.png"; + +export interface ArtistPlaylistsProps { + artistId: UUID; + artistName: string; +} + +const ArtistPlaylists: React.FC = ({ + artistId, + artistName, +}) => { + const { data, loading, error } = useAsyncData( + { + playlists: () => + artistApi.getPlaylists(artistId, { includeUser: true, limit: 10 }), + }, + [artistId], + { + cacheKey: `artist_playlists_${artistId}`, + hasBlobUrl: true, + } + ); + + if (loading) { + return ( +
+ +
+ ); + } + + if (error) { + return
Failed to load playlists.
; + } + + const playlists = data?.playlists; + + if (!playlists || playlists.length === 0) { + return null; + } + + return ( +
+ + Playlists Featuring {artistName} + +
+ {data?.playlists?.map((playlist) => ( + + ))} +
+
+ ); +}; + +export default memo(ArtistPlaylists); diff --git a/client/src/components/ArtistPage/RelatedArtists/RelatedArtists.module.css b/client/src/components/ArtistPage/RelatedArtists/RelatedArtists.module.css new file mode 100644 index 0000000..6d8aecf --- /dev/null +++ b/client/src/components/ArtistPage/RelatedArtists/RelatedArtists.module.css @@ -0,0 +1,134 @@ +.loaderContainer { + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + min-height: 15vh; +} + +.error { + text-align: center; + color: var(--color-text-gray); + font-size: var(--font-size-sm); +} + +.relatedArtistsContainer { + display: flex; + flex-direction: column; + gap: var(--spacing-md); + min-width: 0; + width: 100%; +} + +.sectionTitle { + font-size: var(--font-size-lg); + color: var(--color-white); + font-weight: 500; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 100%; +} + +.relatedArtistsList { + display: flex; + gap: var(--spacing-lg); + justify-content: space-between; + min-width: 0; + transition: transform 0.3s ease; + width: 100%; + overflow-x: hidden; +} + +.relatedArtistItem { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--spacing-sm); +} + +.relatedArtistImage { + width: 14rem; + height: 14rem; + border-radius: 50%; + object-fit: cover; + aspect-ratio: 1 / 1; + flex-shrink: 0; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); + cursor: pointer; + transition: opacity var(--transition-speed) ease; +} + +.relatedArtistImage:hover { + opacity: 0.8; +} + +.relatedArtistName { + font-size: var(--font-size-md); + color: var(--color-white); + font-weight: 500; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 100%; + cursor: pointer; + transition: color var(--transition-speed) ease-in-out; +} + +.relatedArtistName:hover { + color: var(--color-red); +} + +@media (max-width: 1700px) { + .relatedArtistsList .relatedArtistItem:last-child { + display: none; + } +} + +@media (max-width: 1550px) { + .relatedArtistsList .relatedArtistItem:nth-last-child(-n + 2) { + display: none; + } +} + +@media (max-width: 1390px) { + .relatedArtistsList .relatedArtistItem:nth-last-child(-n + 3) { + display: none; + } +} + +@media (max-width: 1230px) { + .relatedArtistsList .relatedArtistItem:nth-last-child(-n + 4) { + display: none; + } +} + +@media (max-width: 1072px) { + .relatedArtistsList .relatedArtistItem:nth-last-child(-n + 5) { + display: none; + } +} + +@media (max-width: 915px) { + .relatedArtistsList .relatedArtistItem:nth-last-child(-n + 6) { + display: none; + } +} + +@media (max-width: 670px) { + .relatedArtistsList .relatedArtistItem:nth-last-child(-n + 7) { + display: none; + } +} + +@media (max-width: 512px) { + .relatedArtistsList .relatedArtistItem:nth-last-child(-n + 8) { + display: none; + } +} + +@media (max-width: 355px) { + .relatedArtistsList .relatedArtistItem:nth-last-child(-n + 9) { + display: none; + } +} diff --git a/client/src/components/ArtistPage/RelatedArtists/RelatedArtists.tsx b/client/src/components/ArtistPage/RelatedArtists/RelatedArtists.tsx new file mode 100644 index 0000000..15ac659 --- /dev/null +++ b/client/src/components/ArtistPage/RelatedArtists/RelatedArtists.tsx @@ -0,0 +1,72 @@ +import { memo } from "react"; +import { PuffLoader } from "react-spinners"; +import { Link } from "react-router-dom"; +import type { UUID } from "@types"; +import { artistApi } from "@api"; +import { useAsyncData } from "@hooks"; +import styles from "./RelatedArtists.module.css"; +import artistPlaceholder from "@assets/artist-placeholder.png"; + +export interface RelatedArtistsProps { + artistId: UUID; +} + +const RelatedArtists: React.FC = ({ artistId }) => { + const { data, loading, error } = useAsyncData( + { + relatedArtists: () => + artistApi.getRelatedArtists(artistId, { includeUser: true, limit: 10 }), + }, + [artistId], + { + cacheKey: `related_artists_${artistId}`, + hasBlobUrl: true, + } + ); + + if (loading) { + return ( +
+ +
+ ); + } + + if (error) { + return
Failed to load related artists.
; + } + + const relatedArtists = data?.relatedArtists; + + if (!relatedArtists || relatedArtists.length === 0) { + return null; + } + + return ( +
+

Fans Also Like

+
+ {relatedArtists.map((related) => ( +
+ + {`${related.display_name}'s + + + {related.display_name} + +
+ ))} +
+
+ ); +}; + +export default memo(RelatedArtists); diff --git a/client/src/components/AudioQueueTest/AudioQueueTest.tsx b/client/src/components/AudioQueueTest/AudioQueueTest.tsx new file mode 100644 index 0000000..276508c --- /dev/null +++ b/client/src/components/AudioQueueTest/AudioQueueTest.tsx @@ -0,0 +1,270 @@ +import React, { useState, useEffect } from "react"; +import { useAudioQueue } from "@contexts"; +import { songApi } from "@api"; +import type { Song } from "@types"; + +const SONG_IDS = [ + "3960d25f-4c52-401a-befc-a4d86cd079e7", + "7d7c882d-21df-4645-8452-43c1015993f3", + "385c64a0-f8b6-47c4-bb5f-c98a6e3daf82", + "7d3422bb-4bb2-4fa7-a9a5-e715b432ce3f", + "8ac798e2-605e-4d3b-bc45-db87af811cab", + "6ac89875-9d7b-4a70-8324-dd0a03244736", +]; + +const AudioQueueTest: React.FC = () => { + const { state, actions } = useAudioQueue(); + const [testSongs, setTestSongs] = useState([]); + const [isLoadingSongs, setIsLoadingSongs] = useState(true); + const [loadError, setLoadError] = useState(null); + + useEffect(() => { + const fetchSongs = async () => { + try { + setIsLoadingSongs(true); + setLoadError(null); + + const songs = await Promise.all( + SONG_IDS.map(async (id) => { + try { + return await songApi.getSongById(id, { includeArtists: true }); + } catch (error) { + console.warn(`Failed to fetch song ${id}:`, error); + return null; + } + }) + ); + + const validSongs = songs.filter((song): song is Song => song !== null); + setTestSongs(validSongs); + + if (validSongs.length === 0) { + setLoadError("No songs could be loaded from the API"); + } + } catch (error) { + console.error("Failed to fetch test songs:", error); + setLoadError("Failed to load test songs"); + } finally { + setIsLoadingSongs(false); + } + }; + + fetchSongs(); + }, []); + + const formatTime = (seconds: number): string => { + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins}:${secs.toString().padStart(2, "0")}`; + }; + + if (isLoadingSongs) { + return ( +
+

AudioQueue Test

+

Loading songs from API...

+
+ ); + } + + if (loadError) { + return ( +
+

AudioQueue Test

+

Error: {loadError}

+
+ ); + } + + if (testSongs.length === 0) { + return ( +
+

AudioQueue Test Component

+

No test songs available.

+
+ ); + } + + return ( +
+

AudioQueue Test

+

+ Loaded {testSongs.length} songs from API +

+ +
+ Current Song: {state.currentSong?.title || "None"} +
+ +
+ Status: {state.isPlaying ? "Playing" : "Paused"} + {state.isLoading && " (Loading...)"} +
+ +
+ Progress: {formatTime(state.progress)} /{" "} + {formatTime(state.duration)} +
+ +
+ Queue: {state.queue.length} songs +
+ +
+ Current Index: {state.currentIndex} +
+ +
+ Navigation: + Previous: {state.hasPreviousSong ? "Available" : "Disabled"} + {state.progress > 3 && " (→ Start)"} | Next:{" "} + {state.hasNextSong ? "Available" : "Disabled"} +
+ +
+ Volume: {Math.round(state.volume * 100)}% +
+ +
+ Repeat Mode: {state.repeatMode} +
+ +
+ Shuffle: {state.isShuffled ? "On" : "Off"} +
+ + {state.error && ( +
+ Error: {state.error} +
+ )} + +
+

Playback :

+ + + + + + + + +
+ +
+

Queue :

+ + + + +
+ +
+ + + +
+ +
+

Persistence:

+ + + +
+ +
+

Volume:

+ actions.setVolume(parseInt(e.target.value) / 100)} + /> +
+ +
+

Seek:

+ { + const seekTime = (state.duration * parseInt(e.target.value)) / 100; + actions.seek(seekTime); + }} + disabled={!state.currentSong} + /> +
+ +
+

Test Songs:

+
    + {testSongs.map((song) => ( +
  • + {song.title} + +
  • + ))} +
+
+ +
+

Current Queue:

+
    + {state.queue.map((item, index) => ( +
  • + {item.song.title} + {item.isQueued && " (User Queued)"} + {item.originalIndex !== undefined && + ` [Orig: ${item.originalIndex}]`} + {index === state.currentIndex && " ← Current"} +
  • + ))} +
+
+
+ ); +}; + +export default AudioQueueTest; diff --git a/client/src/components/CoverLightbox/CoverLightbox.module.css b/client/src/components/CoverLightbox/CoverLightbox.module.css new file mode 100644 index 0000000..3875feb --- /dev/null +++ b/client/src/components/CoverLightbox/CoverLightbox.module.css @@ -0,0 +1,73 @@ +.overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.6); + backdrop-filter: blur(4px); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + animation: fadeIn var(--transition-speed) ease-out; + cursor: pointer; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.lightbox { + position: relative; + animation: slideIn var(--transition-speed) ease-out; + cursor: default; +} + +@keyframes slideIn { + from { + opacity: 0; + transform: scale(0.95) translateY(-10px); + } + to { + opacity: 1; + transform: scale(1) translateY(0); + } +} + +.closeButton { + position: absolute; + top: 1.6rem; + right: 1.6rem; + background: var(--color-panel-gray); + border: 1px solid var(--color-panel-border); + border-radius: var(--border-radius-sm); + width: 3.2rem; + height: 3.2rem; + color: var(--color-white); + font-size: 1.8rem; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all var(--transition-speed) ease; + backdrop-filter: blur(4px); +} + +.closeButton:hover { + background: var(--color-panel-border); +} + +.coverImage { + width: 75rem; + height: 75rem; + object-fit: contain; + border-radius: var(--border-radius-sm); + box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.5), + 0 10px 10px -5px rgba(0, 0, 0, 0.04); +} diff --git a/client/src/components/CoverLightbox/CoverLightbox.tsx b/client/src/components/CoverLightbox/CoverLightbox.tsx new file mode 100644 index 0000000..dd1e28d --- /dev/null +++ b/client/src/components/CoverLightbox/CoverLightbox.tsx @@ -0,0 +1,50 @@ +import { memo, useEffect } from "react"; +import { LuX } from "react-icons/lu"; +import styles from "./CoverLightbox.module.css"; + +interface CoverLightboxProps { + isOpen: boolean; + onClose: () => void; + imageUrl: string; + altText: string; +} + +const CoverLightbox: React.FC = ({ + isOpen, + onClose, + imageUrl, + altText, +}) => { + useEffect(() => { + const handleEscape = (event: KeyboardEvent) => { + if (event.key === "Escape") { + onClose(); + } + }; + + if (isOpen) { + document.addEventListener("keydown", handleEscape); + document.body.style.overflow = "hidden"; + } + + return () => { + document.removeEventListener("keydown", handleEscape); + document.body.style.overflow = "unset"; + }; + }, [isOpen, onClose]); + + if (!isOpen) return null; + + return ( +
+ +
e.stopPropagation()}> + {altText} +
+
+ ); +}; + +export default memo(CoverLightbox); diff --git a/client/src/components/DevBanner/DevBanner.module.css b/client/src/components/DevBanner/DevBanner.module.css new file mode 100644 index 0000000..812ff5d --- /dev/null +++ b/client/src/components/DevBanner/DevBanner.module.css @@ -0,0 +1,42 @@ +.banner { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 9999; + display: flex; + align-items: center; + justify-content: center; + gap: var(--spacing-md); + padding: var(--spacing-xs) var(--spacing-md); + background-color: var(--color-red); + color: var(--color-white); + font-size: var(--font-size-xs); + font-weight: 500; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); +} + +.text { + flex: 1; + text-align: center; +} + +.closeButton { + display: flex; + align-items: center; + justify-content: center; + background: none; + border: none; + color: var(--color-white); + cursor: pointer; + transition: color var(--transition-speed) ease-in-out; + font-size: var(--icon-size-xs); +} + +.closeButton:hover { + color: var(--color-white-hover); +} + +.closeButton:active { + color: var(--color-white-hover); +} diff --git a/client/src/components/DevBanner/DevBanner.tsx b/client/src/components/DevBanner/DevBanner.tsx new file mode 100644 index 0000000..bb76dcc --- /dev/null +++ b/client/src/components/DevBanner/DevBanner.tsx @@ -0,0 +1,44 @@ +import { useState, useEffect, memo } from "react"; +import { LuX } from "react-icons/lu"; +import styles from "./DevBanner.module.css"; + +const DevBanner: React.FC = () => { + const [isVisible, setIsVisible] = useState(false); + const [buildVersion, setBuildVersion] = useState(""); + + useEffect(() => { + const isDismissed = localStorage.getItem("dev-banner-dismissed"); + if (isDismissed) return; + if (import.meta.env.DEV) return; + + fetch("/version.json") + .then((res) => res.json()) + .then((data) => { + if (data.version) { + setBuildVersion(data.version); + setIsVisible(true); + } + }) + .catch(() => { + setIsVisible(true); + }); + }, []); + + const handleClose = () => { + setIsVisible(false); + localStorage.setItem("dev-banner-dismissed", "true"); + }; + + if (!isVisible) return null; + + return ( +
+ Development Build: {buildVersion} + +
+ ); +}; + +export default memo(DevBanner); diff --git a/client/src/components/EntityItem/EntityItem.module.css b/client/src/components/EntityItem/EntityItem.module.css index 025e0d8..b15968d 100644 --- a/client/src/components/EntityItem/EntityItem.module.css +++ b/client/src/components/EntityItem/EntityItem.module.css @@ -1,130 +1,130 @@ .entityItem { - display: flex; - gap: var(--spacing-md); - align-items: center; - min-width: 0; - width: 100%; - position: relative; - } - - .entityImage { - width: 8rem; - height: 8rem; - border-radius: var(--border-radius-sm); - object-fit: cover; - aspect-ratio: 1 / 1; - flex-shrink: 0; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); - } - - .entityInfo { - display: flex; - flex-direction: column; - gap: var(--spacing-xs); - min-width: 0; - width: 100%; - } - - .entityAuthor { - font-size: var(--font-size-sm); - color: var(--color-text-gray); - font-weight: 500; - } - - .entityTitle { - font-size: var(--font-size-md); - color: var(--color-white); - font-weight: 500; - transition: color var(--transition-speed) ease-in-out; - } - - .entityTitle:hover { - color: var(--color-red); - } - - .entitySubtitle { - font-size: var(--font-size-sm); - color: var(--color-text-gray); - font-weight: 500; - } - - .entityTitle, - .entityAuthor, - .entitySubtitle, - .entitySubtitle { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - width: 100%; - max-width: 100%; - } - - .entityActionButton { - display: flex; - align-items: center; - justify-content: center; - background: var(--color-panel-gray); - border-radius: var(--border-radius-sm); - border: 2px solid var(--color-panel-border); - color: var(--color-white); - cursor: pointer; - font-size: var(--icon-size-xs); - padding: var(--spacing-sm); - transition: color var(--transition-speed) ease-in-out; - } - - .entityActionButton:hover { - color: var(--color-red); - } - - .queueButtonContainer { - position: relative; - } - - .entityActionButtonContainer { - position: absolute; - right: 0; - top: 50%; - transform: translateY(-50%); - display: flex; - align-items: center; - gap: var(--spacing-sm); - opacity: 0; - visibility: hidden; - transition: all var(--transition-speed) ease; - background: linear-gradient( - to left, - var(--color-black) 0%, - var(--color-black) 75%, - transparent 100% - ); - padding: var(--spacing-sm) var(--spacing-md) var(--spacing-sm) - var(--spacing-xl); - border-radius: var(--border-radius-sm); - } - - .entityItem:hover .entityActionButtonContainer { - opacity: 1; - visibility: visible; - } - - .entityActionButtonContainerWide { - display: flex; - align-items: center; - gap: var(--spacing-sm); - flex-shrink: 0; - } - - .entityIndex { - font-size: var(--font-size-sm); - color: var(--color-white); - font-weight: 500; - width: 2rem; - min-width: 2rem; - max-width: 2rem; - flex-shrink: 0; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - text-align: center; - } \ No newline at end of file + display: flex; + gap: var(--spacing-md); + align-items: center; + min-width: 0; + width: 100%; + position: relative; +} + +.entityImage { + width: 8rem; + height: 8rem; + border-radius: var(--border-radius-sm); + object-fit: cover; + aspect-ratio: 1 / 1; + flex-shrink: 0; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); +} + +.entityInfo { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); + min-width: 0; + width: 100%; +} + +.entityAuthor { + font-size: var(--font-size-sm); + color: var(--color-text-gray); + font-weight: 500; +} + +.entityTitle { + font-size: var(--font-size-md); + color: var(--color-white); + font-weight: 500; + transition: color var(--transition-speed) ease-in-out; +} + +.entityTitle:hover { + color: var(--color-red); +} + +.entitySubtitle { + font-size: var(--font-size-sm); + color: var(--color-text-gray); + font-weight: 500; +} + +.entityTitle, +.entityAuthor, +.entitySubtitle, +.entitySubtitle { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + width: 100%; + max-width: 100%; +} + +.entityActionButton { + display: flex; + align-items: center; + justify-content: center; + background: var(--color-panel-gray); + border-radius: var(--border-radius-sm); + border: 2px solid var(--color-panel-border); + color: var(--color-white); + cursor: pointer; + font-size: var(--icon-size-xs); + padding: var(--spacing-sm); + transition: color var(--transition-speed) ease-in-out; +} + +.entityActionButton:hover { + color: var(--color-red); +} + +.queueButtonContainer { + position: relative; +} + +.entityActionButtonContainer { + position: absolute; + right: 0; + top: 50%; + transform: translateY(-50%); + display: flex; + align-items: center; + gap: var(--spacing-sm); + opacity: 0; + visibility: hidden; + transition: all var(--transition-speed) ease; + background: linear-gradient( + to left, + var(--color-black) 0%, + var(--color-black) 75%, + transparent 100% + ); + padding: var(--spacing-sm) var(--spacing-md) var(--spacing-sm) + var(--spacing-xl); + border-radius: var(--border-radius-sm); +} + +.entityItem:hover .entityActionButtonContainer { + opacity: 1; + visibility: visible; +} + +.entityActionButtonContainerWide { + display: flex; + align-items: center; + gap: var(--spacing-sm); + flex-shrink: 0; +} + +.entityIndex { + font-size: var(--font-size-sm); + color: var(--color-white); + font-weight: 500; + width: 2rem; + min-width: 2rem; + max-width: 2rem; + flex-shrink: 0; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + text-align: center; +} diff --git a/client/src/components/EntityItem/EntityItem.tsx b/client/src/components/EntityItem/EntityItem.tsx index b847586..6f4d055 100644 --- a/client/src/components/EntityItem/EntityItem.tsx +++ b/client/src/components/EntityItem/EntityItem.tsx @@ -190,4 +190,4 @@ const EntityItem: React.FC = ({ ); }; -export default memo(EntityItem); \ No newline at end of file +export default memo(EntityItem); diff --git a/client/src/components/EntityItemCard/EntityItemCard.module.css b/client/src/components/EntityItemCard/EntityItemCard.module.css new file mode 100644 index 0000000..2790870 --- /dev/null +++ b/client/src/components/EntityItemCard/EntityItemCard.module.css @@ -0,0 +1,113 @@ +.entityItemCard { + display: flex; + flex-direction: column; + gap: var(--spacing-md); + min-width: 0; + width: 18rem; + position: relative; +} + +.entityImageContainer { + position: relative; + width: 18rem; + height: 18rem; + flex-shrink: 0; +} + +.entityImage { + width: 100%; + height: 100%; + border-radius: var(--border-radius-sm); + object-fit: cover; + aspect-ratio: 1 / 1; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); + transition: all var(--transition-speed) ease; +} + +.entityInfo { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); + min-width: 0; + width: 100%; +} + +.entityAuthor { + font-size: var(--font-size-md); + color: var(--color-text-gray); + font-weight: 500; +} + +.entityTitle { + font-size: var(--font-size-lg); + color: var(--color-white); + font-weight: 500; + transition: color var(--transition-speed) ease-in-out; +} + +.entityTitle:hover { + color: var(--color-red); +} + +.entitySubtitle { + font-size: var(--font-size-md); + color: var(--color-text-gray); + font-weight: 500; +} + +.entityTitle, +.entityAuthor, +.entitySubtitle, +.entitySubtitle { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + width: 100%; + max-width: 100%; +} + +.entityActionButtonContainer { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + align-items: center; + justify-content: center; + gap: var(--spacing-md); + background: rgba(0, 0, 0, 0.6); + border-radius: var(--border-radius-sm); + opacity: 0; + visibility: hidden; + transition: all var(--transition-speed) ease; + z-index: 2; +} + +.entityItemCard:hover .entityActionButtonContainer { + opacity: 1; + visibility: visible; +} + +.entityActionButton { + display: flex; + align-items: center; + justify-content: center; + background: var(--color-panel-gray); + border-radius: 50%; + border: 2px solid var(--color-panel-border); + color: var(--color-white); + cursor: pointer; + font-size: var(--icon-size-md); + padding: var(--spacing-md); + transition: all var(--transition-speed) ease; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); +} + +.entityActionButton:hover { + color: var(--color-red); +} + +.queueButtonContainer { + position: relative; +} diff --git a/client/src/components/EntityItemCard/EntityItemCard.tsx b/client/src/components/EntityItemCard/EntityItemCard.tsx new file mode 100644 index 0000000..a222505 --- /dev/null +++ b/client/src/components/EntityItemCard/EntityItemCard.tsx @@ -0,0 +1,153 @@ +import { memo, useState, useCallback, useRef, useEffect } from "react"; +import { Link, useNavigate } from "react-router-dom"; +import { useAudioQueue, useAuth } from "@contexts"; +import type { Song, Playlist, Album } from "@types"; +import { QueueMenu } from "@components"; +import styles from "./EntityItemCard.module.css"; +import musicPlaceholder from "@assets/music-placeholder.png"; +import artistPlaceholder from "@assets/artist-placeholder.png"; +import { LuPlay, LuListEnd } from "react-icons/lu"; + +interface EntityActionButtonsProps { + type: "song" | "list" | "artist"; + entity?: Song | Playlist | Album; + isHovered: boolean; +} + +const EntityActionButtons: React.FC = memo( + ({ type, entity, isHovered }) => { + const { actions } = useAudioQueue(); + const { isAuthenticated } = useAuth(); + const navigate = useNavigate(); + + const [queueMenuOpen, setQueueMenuOpen] = useState(false); + const queueButtonRef = useRef(null); + + useEffect(() => { + if (!isHovered && queueMenuOpen) { + setQueueMenuOpen(false); + } + }, [isHovered, queueMenuOpen]); + + const handlePlay = useCallback(() => { + if (!entity) return; + actions.play(entity); + }, [actions, entity]); + + const handleAddToQueue = useCallback(async () => { + try { + if (isAuthenticated) { + setQueueMenuOpen((prev) => !prev); + } else { + navigate("/login"); + } + } catch (error) { + console.error("Adding to queue failed:", error); + } + }, [isAuthenticated, navigate]); + + return ( +
+ {type === "song" && ( +
+ + setQueueMenuOpen(false)} + song={entity as Song} + buttonRef={queueButtonRef} + justification="center" + /> +
+ )} + {(type === "song" || type === "list") && ( + + )} +
+ ); + } +); + +type EntityItemCardProps = + | { + type: "artist"; + linkTo: string; + author: string; + title: string; + subtitle: string; + imageUrl?: string; + entity?: never; + } + | { + type: "song" | "list"; + linkTo: string; + author: string; + title: string; + subtitle: string; + imageUrl?: string; + entity: Song | Playlist | Album; + }; + +/** + * @param EntityItemProps + * @param entity The entity object to play when clicking play (Song, Playlist, or Album) + * @param imageUrl Image URL for the entity + * @param linkTo Link to navigate to when clicking the title + * @param author Author name to display (text above title) + * @param title Title of the entity + * @param subtitle Subtitle text to display (text below title) + * @param type Type of entity: "song", "list", or "artist" + */ +const EntityItemCard: React.FC = ({ + entity, + imageUrl, + linkTo, + author, + title, + subtitle, + type, +}) => { + const [isHovered, setIsHovered] = useState(false); + + return ( +
setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + > +
+ {`${title} + +
+
+ {author} + + {title} + + {subtitle} +
+
+ ); +}; + +export default memo(EntityItemCard); diff --git a/client/src/components/ErrorPage/ErrorPage.module.css b/client/src/components/ErrorPage/ErrorPage.module.css new file mode 100644 index 0000000..bdb6ef9 --- /dev/null +++ b/client/src/components/ErrorPage/ErrorPage.module.css @@ -0,0 +1,57 @@ +.errorPageContainer { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + height: 75vh; + width: 100%; + gap: var(--spacing-sm); +} + +.errorIcon { + font-size: var(--icon-size-2xl); + color: var(--color-red); +} + +.errorTitle { + font-size: var(--font-size-2xl); + font-weight: 600; +} + +.errorMessage { + font-size: var(--font-size-lg); + max-width: 60rem; + line-height: 1.5; + color: var(--color-text-gray); +} + +.statusCode { + font-size: var(--font-size-md); + color: var(--color-text-gray); +} + +.homeButton { + display: flex; + align-items: center; + justify-content: center; + gap: var(--spacing-sm); + padding: var(--spacing-md); + background-color: var(--color-red); + color: var(--color-white); + border: none; + border-radius: var(--border-radius-sm); + font-family: "Inter", sans-serif; + font-size: var(--font-size-sm); + cursor: pointer; + transition: background-color var(--transition-speed) ease-in-out; +} + +.homeButton:hover:not(:disabled) { + background-color: var(--color-red-700); +} + +.homeButton:disabled { + opacity: 0.6; + cursor: not-allowed; +} diff --git a/client/src/components/ErrorPage/ErrorPage.tsx b/client/src/components/ErrorPage/ErrorPage.tsx new file mode 100644 index 0000000..d214784 --- /dev/null +++ b/client/src/components/ErrorPage/ErrorPage.tsx @@ -0,0 +1,38 @@ +import { memo } from "react"; +import { Helmet } from "react-helmet-async"; +import { useNavigate } from "react-router-dom"; +import { LuBan } from "react-icons/lu"; +import styles from "./ErrorPage.module.css"; + +type ErrorPageProps = { + title?: string; + message?: string; +}; + +const ErrorPage: React.FC = ({ title, message }) => { + const navigate = useNavigate(); + + const handleGoHome = () => { + navigate("/"); + }; + + return ( + <> + + Internal Server Error + +
+ +

{title || "An Error Occurred"}

+ + {message || "Sorry, something went wrong. Please try again later."} + + +
+ + ); +}; + +export default memo(ErrorPage); diff --git a/client/src/components/FollowProfiles/FollowProfiles.module.css b/client/src/components/FollowProfiles/FollowProfiles.module.css new file mode 100644 index 0000000..a71d5fa --- /dev/null +++ b/client/src/components/FollowProfiles/FollowProfiles.module.css @@ -0,0 +1,106 @@ +.loaderContainer { + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + min-height: 10vh; +} + +.error { + text-align: center; + color: var(--color-text-gray); + font-size: var(--font-size-sm); +} + +.sectionTitle { + font-size: var(--font-size-lg); + color: var(--color-white); + font-weight: 500; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 100%; +} + +.followContainer { + display: flex; + flex-direction: column; + gap: var(--spacing-md); + min-width: 0; + width: 100%; +} + +.avatarStack { + display: flex; + justify-content: center; + align-items: center; + gap: 0; + position: relative; +} + +.avatarLink { + position: relative; + margin-left: calc(-1 * var(--spacing-md)); +} + +.avatarLink:first-child { + margin-left: 0; +} + +.avatarLink::after { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-radius: 50%; + background-color: rgba(0, 0, 0, 0); + transition: background-color var(--transition-speed) ease; + pointer-events: none; +} + +.avatarLink:hover::after { + background-color: rgba(0, 0, 0, 0.2); +} + +.avatar { + width: var(--icon-size-3xl); + height: var(--icon-size-3xl); + border-radius: 50%; + object-fit: cover; + border: 0.2rem solid var(--color-black); + display: block; +} + +.avatarMore { + position: relative; + width: var(--icon-size-3xl); + height: var(--icon-size-3xl); + border-radius: 50%; + background-color: #2f2f2f; + border: 0.2rem solid var(--color-black); + display: flex; + align-items: center; + justify-content: center; + color: #454545; + font-size: 2rem; + margin-left: calc(-1 * var(--spacing-md)); +} + +.avatarMore::after { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-radius: 50%; + background-color: rgba(0, 0, 0, 0); + transition: background-color var(--transition-speed) ease; + pointer-events: none; +} + +.avatarMore:hover::after { + background-color: rgba(0, 0, 0, 0.2); +} diff --git a/client/src/components/FollowProfiles/FollowProfiles.tsx b/client/src/components/FollowProfiles/FollowProfiles.tsx new file mode 100644 index 0000000..77a02b5 --- /dev/null +++ b/client/src/components/FollowProfiles/FollowProfiles.tsx @@ -0,0 +1,105 @@ +import { memo, useMemo } from "react"; +import { PuffLoader } from "react-spinners"; +import { Link } from "react-router-dom"; +import { LuPlus } from "react-icons/lu"; +import { artistApi } from "@api"; +import { useAsyncData } from "@hooks"; +import type { UUID } from "@types"; +import styles from "./FollowProfiles.module.css"; +import userPlaceholder from "@assets/user-placeholder.png"; + +export interface FollowProfilesProps { + title: string; + userId: UUID; + following?: boolean; + profileLimit: number; + profileMin?: number; +} + +const FollowProfiles: React.FC = ({ + title, + userId, + following = true, + profileLimit, + profileMin = 0, +}) => { + const { data, loading, error } = useAsyncData( + { + profiles: () => + (following ? artistApi.getFollowing : artistApi.getFollowers)(userId, { + limit: profileLimit + 1, + }), + }, + [userId, following, profileLimit], + { + cacheKey: `${following ? "following" : "followers"}_${userId}`, + hasBlobUrl: true, + } + ); + + const profiles = data?.profiles; + + const { displayProfiles, hasMore } = useMemo(() => { + if (!profiles || profiles.length === 0) { + return { displayProfiles: [], hasMore: false }; + } + const display = profiles.slice(0, profileLimit); + const more = profiles.length > profileLimit; + return { displayProfiles: display, hasMore: more }; + }, [profiles, profileLimit]); + + if (loading) { + return ( +
+ +
+ ); + } + + if (error) { + return ( +
Failed to load {title.toLowerCase()}.
+ ); + } + + if (!profiles || profiles.length === 0) { + return null; + } + + if (profiles.length < profileMin) { + return null; + } + + return ( +
+ {title} +
+ {displayProfiles.map((profile) => ( + + {`${profile.username + + ))} + {hasMore && ( + +
+
+ ); +}; + +export default memo(FollowProfiles); diff --git a/client/src/components/Forms/FormButton/FormSubmitButton.module.css b/client/src/components/Forms/FormButton/FormSubmitButton.module.css new file mode 100644 index 0000000..a6d04ed --- /dev/null +++ b/client/src/components/Forms/FormButton/FormSubmitButton.module.css @@ -0,0 +1,25 @@ +.formSubmitButton { + display: flex; + align-items: center; + justify-content: center; + gap: var(--spacing-sm); + padding: var(--spacing-md); + background-color: var(--color-red); + color: var(--color-white); + border: none; + border-radius: var(--border-radius-md); + font-family: "Inter", sans-serif; + font-size: var(--font-size-md); + font-weight: 500; + cursor: pointer; + transition: background-color var(--transition-speed) ease-in-out; +} + +.formSubmitButton:hover:not(:disabled) { + background-color: var(--color-red-700); +} + +.formSubmitButton:disabled { + opacity: 0.6; + cursor: not-allowed; +} diff --git a/client/src/components/Forms/FormButton/FormSubmitButton.tsx b/client/src/components/Forms/FormButton/FormSubmitButton.tsx new file mode 100644 index 0000000..3f0f5d0 --- /dev/null +++ b/client/src/components/Forms/FormButton/FormSubmitButton.tsx @@ -0,0 +1,24 @@ +import styles from "./FormSubmitButton.module.css"; + +export interface FormSubmitButtonProps { + text: string; + disabled?: boolean; +} + +const FormSubmitButton: React.FC = ({ + text, + disabled, +}) => { + return ( + + ); +}; + +export default FormSubmitButton; diff --git a/client/src/components/Forms/InputGroup/InputGroup.module.css b/client/src/components/Forms/InputGroup/InputGroup.module.css new file mode 100644 index 0000000..5941acd --- /dev/null +++ b/client/src/components/Forms/InputGroup/InputGroup.module.css @@ -0,0 +1,61 @@ +.inputGroup { + display: flex; + flex-direction: column; + gap: var(--spacing-sm); +} + +.formLabel { + font-size: var(--font-size-sm); + font-weight: 500; + color: var(--color-text-gray); + padding-left: var(--spacing-2xs); +} + +.input { + font-family: "Inter", sans-serif; + padding: 1.2rem; + background-color: var(--color-panel-gray-dark); + border: 2px solid var(--color-panel-border); + border-radius: var(--border-radius-sm); + color: var(--color-white); + font-size: var(--font-size-sm); + width: 100%; +} + +.input:focus { + outline: none; +} + +.input::placeholder { + color: var(--color-text-gray); +} + +.input::placeholder { + color: var(--color-text-gray); +} + +.input:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.inputError { + border-color: var(--color-red); +} + +.inputErrorText { + font-size: var(--font-size-xs); + color: var(--color-red); + padding-left: var(--spacing-2xs); +} + +.inputHint { + margin-top: calc(var(--spacing-xs) * -1); +} + +.inputHintText { + font-size: var(--font-size-xs); + color: var(--color-text-gray); + font-style: italic; + padding-left: var(--spacing-2xs); +} diff --git a/client/src/components/Forms/InputGroup/InputGroup.tsx b/client/src/components/Forms/InputGroup/InputGroup.tsx new file mode 100644 index 0000000..aa87285 --- /dev/null +++ b/client/src/components/Forms/InputGroup/InputGroup.tsx @@ -0,0 +1,56 @@ +import styles from "./InputGroup.module.css"; +import classNames from "classnames"; + +export interface InputGroupProps { + label: string; + type: string; + id: string; + name?: string; // if different from id + value: string; + onChange: (e: React.ChangeEvent) => void; + placeholder?: string; + error?: string; + disabled?: boolean; + hint?: string; +} + +const InputGroup: React.FC = ({ + label, + type, + id, + name, + value, + onChange, + placeholder, + error, + disabled, + hint, +}) => { + return ( +
+ + + {error && {error}} + {hint && ( +
+ {hint} +
+ )} +
+ ); +}; + +export default InputGroup; diff --git a/client/src/components/Layout/HorizontalRule/HorizontalRule.module.css b/client/src/components/Layout/HorizontalRule/HorizontalRule.module.css new file mode 100644 index 0000000..761e63b --- /dev/null +++ b/client/src/components/Layout/HorizontalRule/HorizontalRule.module.css @@ -0,0 +1,8 @@ +.horizontalRule { + width: 100%; + height: 1px; + background-color: var(--color-text-gray); + opacity: 0.25; + border-radius: 1px; + margin: 0.2rem 0; +} diff --git a/client/src/components/Layout/HorizontalRule/HorizontalRule.tsx b/client/src/components/Layout/HorizontalRule/HorizontalRule.tsx new file mode 100644 index 0000000..7ef7ead --- /dev/null +++ b/client/src/components/Layout/HorizontalRule/HorizontalRule.tsx @@ -0,0 +1,8 @@ +import { memo } from "react"; +import styles from "./HorizontalRule.module.css"; + +const HorizontalRule: React.FC = () => { + return
; +}; + +export default memo(HorizontalRule); diff --git a/client/src/components/Layout/VerticalRule/VerticalRule.module.css b/client/src/components/Layout/VerticalRule/VerticalRule.module.css new file mode 100644 index 0000000..0d5edbd --- /dev/null +++ b/client/src/components/Layout/VerticalRule/VerticalRule.module.css @@ -0,0 +1,7 @@ +.verticalRule { + width: 1.25px; + height: 100%; + background-color: var(--color-text-gray); + opacity: 0.25; + border-radius: 1px; +} diff --git a/client/src/components/Layout/VerticalRule/VerticalRule.tsx b/client/src/components/Layout/VerticalRule/VerticalRule.tsx new file mode 100644 index 0000000..2a8534f --- /dev/null +++ b/client/src/components/Layout/VerticalRule/VerticalRule.tsx @@ -0,0 +1,8 @@ +import { memo } from "react"; +import styles from "./VerticalRule.module.css"; + +const VerticalRule: React.FC = () => { + return
; +}; + +export default memo(VerticalRule); diff --git a/client/src/components/MainLayout/MainLayout.module.css b/client/src/components/MainLayout/MainLayout.module.css new file mode 100644 index 0000000..99886de --- /dev/null +++ b/client/src/components/MainLayout/MainLayout.module.css @@ -0,0 +1,44 @@ +body { + font-family: "Inter", sans-serif; + background-color: var(--color-black); + color: var(--color-white); + font-size: var(--font-size-md); +} + +/* Layout Container */ +.layoutContainer { + display: flex; + height: 100vh; + overflow: hidden; + padding: var(--spacing-sm); +} + +/* Main Content */ +.mainContent { + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; + padding-left: var(--spacing-sm); + position: relative; +} + +/* Content Area */ +.contentArea { + flex: 1; + overflow-y: auto; + padding: var(--spacing-xl) calc(var(--spacing-xl) - var(--spacing-sm)) + calc(var(--now-playing-height) + var(--spacing-xl)) + calc(var(--spacing-xl) - var(--spacing-sm)); +} + +/* Media Queries */ +@media (max-width: 768px) { + :root { + --sidebar-width: 0; + } + + .mainContent { + padding-left: 0; + } +} diff --git a/client/src/components/MainLayout/MainLayout.tsx b/client/src/components/MainLayout/MainLayout.tsx new file mode 100644 index 0000000..fa2c11d --- /dev/null +++ b/client/src/components/MainLayout/MainLayout.tsx @@ -0,0 +1,21 @@ +import styles from "./MainLayout.module.css"; +import { + MainLayoutHeader, + MainLayoutNowPlayingBar, + MainLayoutSidebar, +} from "@components"; + +const MainLayout: React.FC<{ children: React.ReactNode }> = ({ children }) => { + return ( +
+ +
+ +
{children}
+
+ +
+ ); +}; + +export default MainLayout; diff --git a/client/src/components/MainLayout/MainLayoutHeader/MainLayoutHeader.module.css b/client/src/components/MainLayout/MainLayoutHeader/MainLayoutHeader.module.css new file mode 100644 index 0000000..55728cb --- /dev/null +++ b/client/src/components/MainLayout/MainLayoutHeader/MainLayoutHeader.module.css @@ -0,0 +1,121 @@ +/* Header */ +.header { + height: var(--header-height); + display: flex; + align-items: center; + gap: var(--spacing-sm); + z-index: 50; +} + +.headerNav { + height: var(--header-height); + background-color: var(--color-panel-gray); + border-radius: var(--border-radius-md); + border: 2px solid var(--color-panel-border); + display: flex; + align-items: center; +} + +.navbarLink, +.navbarLinkActive { + display: flex; + align-items: center; + gap: var(--spacing-sm); + padding: 0 var(--spacing-md); + color: var(--color-text-gray) !important; + font-size: var(--font-size-sm); + transition: color var(--transition-speed) ease-in-out; +} + +.navbarLink:hover { + color: var(--color-white) !important; +} + +.navbarLinkActive { + color: var(--color-red) !important; +} + +.navIcon { + font-size: var(--icon-size-sm); +} + +/* Header Actions */ +.headerActions { + height: var(--header-height); + background-color: var(--color-panel-gray); + border-radius: var(--border-radius-md); + border: 2px solid var(--color-panel-border); + display: flex; +} + +.iconButton { + display: flex; + align-items: center; + justify-content: center; + padding: 0 var(--spacing-md); + background: none; + border: none; + color: var(--color-text-gray) !important; + cursor: pointer; + border-radius: var(--border-radius-md); + transition: color var(--transition-speed) ease-in-out; + text-decoration: none; +} + +.iconButton:hover { + color: var(--color-white) !important; +} + +.actionIcon { + font-size: var(--icon-size-md); +} + +/* Header shadow */ +.headerNav, +.searchContainer, +.headerActions { + position: relative; +} + +.headerNav::after, +.searchContainer::after, +.headerActions::after { + content: ""; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 4px; + border-radius: inherit; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.75); + pointer-events: none; +} + +@media (max-width: 768px) { + .nowPlayingInfo { + max-width: 16rem; + } + + .playlistButton { + display: none; + } + + .progressContainer { + max-width: 40rem; + } + + .navbarLink span, + .navbarLinkActive span { + display: none; + } + + .nowPlayingBar { + left: var(--spacing-sm); + } +} + +@media (max-width: 480px) { + .headerActions { + display: none; + } +} diff --git a/client/src/components/MainLayout/MainLayoutHeader/MainLayoutHeader.tsx b/client/src/components/MainLayout/MainLayoutHeader/MainLayoutHeader.tsx new file mode 100644 index 0000000..3af3f5b --- /dev/null +++ b/client/src/components/MainLayout/MainLayoutHeader/MainLayoutHeader.tsx @@ -0,0 +1,78 @@ +import React, { memo } from "react"; +import { NavLink, Link } from "react-router-dom"; +import classNames from "classnames"; + +import { useAuth } from "@contexts"; +import { MainLayoutSearchBar } from "@components"; + +import styles from "./MainLayoutHeader.module.css"; +import { + LuHouse, + LuRss, + LuBell, + LuSettings, + LuCircleUser, +} from "react-icons/lu"; + +const MainLayoutHeader: React.FC = () => { + const { user, isAuthenticated } = useAuth(); + + return ( +
+ + + + +
+ {isAuthenticated ? ( + <> + + + + + + + + + ) : ( + <> + + Sign In + + + Sign Up + + + )} +
+
+ ); +}; + +export default memo(MainLayoutHeader); diff --git a/client/src/components/MainLayout/MainLayoutNowPlayingBar/MainLayoutNowPlayingBar.module.css b/client/src/components/MainLayout/MainLayoutNowPlayingBar/MainLayoutNowPlayingBar.module.css new file mode 100644 index 0000000..4f47771 --- /dev/null +++ b/client/src/components/MainLayout/MainLayoutNowPlayingBar/MainLayoutNowPlayingBar.module.css @@ -0,0 +1,312 @@ +.nowPlayingBar { + position: fixed; + bottom: var(--spacing-sm); + left: calc(var(--sidebar-width) + 2 * var(--spacing-sm)); + right: var(--spacing-sm); + height: var(--now-playing-height); + background-color: var(--color-panel-gray); + border-radius: var(--border-radius-md); + border: 2px solid var(--color-panel-border); + display: flex; + gap: var(--spacing-sm); + align-items: center; + padding: 0 var(--spacing-lg); + z-index: 50; +} + +/* Now Playing Info */ +.nowPlayingInfo { + display: flex; + align-items: center; + gap: var(--spacing-md); + min-width: 0; + width: 30rem; +} + +.albumArt { + width: 6.4rem; + height: 6.4rem; + border-radius: var(--border-radius-sm); + object-fit: cover; + aspect-ratio: 1 / 1; + flex-shrink: 0; + cursor: pointer; +} + +.songInfo { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); + min-width: 0; +} + +.songTitle { + font-size: var(--font-size-lg); + color: var(--color-white); + font-weight: 500; +} + +.artistName { + font-size: var(--font-size-sm); + color: var(--color-text-gray) !important; +} + +.songTitle:hover { + color: var(--color-red); +} + +.artistName:hover { + color: var(--color-white) !important; +} + +.songTitle, +.artistName { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + width: 100%; + max-width: 100%; + transition: color var(--transition-speed) ease-in-out; +} + +/* Player Controls */ +.playerControls { + flex: 1; + display: flex; + flex-direction: column; + gap: var(--spacing-sm); + align-items: center; +} + +.controlButtons { + display: flex; + align-items: center; + gap: var(--spacing-md); +} + +.controlButton { + display: flex; + align-items: center; + justify-content: center; + background: none; + border: none; + color: var(--color-text-gray); + cursor: pointer; + font-size: var(--icon-size-md); + padding: var(--spacing-sm); + transition: color var(--transition-speed) ease-in-out; +} + +.controlButton:hover { + color: var(--color-white); +} + +.controlButtonActive { + color: var(--color-red); +} + +.controlButtonDisabled { + opacity: 0.5; + cursor: not-allowed; +} + +.controlButtonDisabled:hover { + color: var(--color-text-gray); +} + +.playButton { + font-size: var(--icon-size-xl); + color: var(--color-white); +} + +.playButton:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.playButton:not(:disabled):hover { + color: var(--color-red); +} + +.playButtonActive { + color: var(--color-red); +} + +.repeatIndicator { + position: absolute; + top: -2px; + right: -2px; + font-size: 10px; + font-weight: bold; + color: var(--color-white); + background-color: var(--color-red); + border-radius: 50%; + width: 14px; + height: 14px; + display: flex; + align-items: center; + justify-content: center; + line-height: 1; +} + +.repeatButton { + position: relative; +} + +/* Progress Bar */ +.progressContainer { + display: flex; + align-items: center; + gap: var(--spacing-md); + width: 100%; + max-width: 60rem; +} + +.timeLabel { + font-size: var(--font-size-xs); + color: var(--color-text-gray); + min-width: 4rem; + text-align: center; +} + +.progressBar { + flex: 1; + position: relative; + height: 0.4rem; + background-color: rgba(255, 255, 255, var(--opacity-high)); + border-radius: var(--border-radius-sm); +} + +.progressFill { + position: absolute; + height: 100%; + background-color: var(--color-red); + border-radius: var(--border-radius-sm); +} + +.progressSlider { + position: absolute; + top: 50%; + left: 0; + width: 100%; + height: 100%; + transform: translateY(-50%); + opacity: 0; + cursor: pointer; +} + +/* Right Controls */ +.rightControls { + display: flex; + align-items: center; + gap: var(--spacing-md); + justify-content: flex-end; +} + +.queueButtonContainer { + position: relative; +} + +.volumeControl { + display: flex; + align-items: center; + gap: var(--spacing-sm); +} + +.volumeIcon { + font-size: var(--icon-size-sm); + color: var(--color-text-gray); +} + +.volumeSlider { + width: 12rem; + height: 0.4rem; + -webkit-appearance: none; + appearance: none; + background: rgba(255, 255, 255, var(--opacity-high)); + border-radius: var(--border-radius-sm); + outline: none; + cursor: pointer; +} + +.volumeSlider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 1.2rem; + height: 1.2rem; + background: var(--color-white); + border-radius: 50%; + cursor: pointer; +} + +.volumeSlider::-moz-range-thumb { + width: 1.2rem; + height: 1.2rem; + background: var(--color-white); + border-radius: 50%; + cursor: pointer; + border: none; +} + +/* Media Queries */ +@media (max-width: 1400px) { + .nowPlayingInfo { + max-width: 20rem; + } + + .progressContainer { + max-width: 50rem; + } + + .nowPlayingBar { + padding: 0 var(--spacing-md); + } +} + +@media (max-width: 1200px) { + .volumeSlider { + max-width: 8rem; + } + + .shareButton { + display: none; + } +} + +@media (max-width: 968px) { + .volumeControl { + display: none; + } +} + +@media (max-width: 768px) { + .nowPlayingInfo { + max-width: 16rem; + } + + .playlistButton { + display: none; + } + + .progressContainer { + max-width: 40rem; + } + + .nowPlayingBar { + left: var(--spacing-sm); + } +} + +@media (max-width: 560px) { + .shuffleButton, + .repeatButton { + display: none; + } +} + +@media (max-width: 480px) { + .progressContainer, + .rightControls { + display: none; + } +} diff --git a/client/src/components/MainLayout/MainLayoutNowPlayingBar/MainLayoutNowPlayingBar.tsx b/client/src/components/MainLayout/MainLayoutNowPlayingBar/MainLayoutNowPlayingBar.tsx new file mode 100644 index 0000000..15da14f --- /dev/null +++ b/client/src/components/MainLayout/MainLayoutNowPlayingBar/MainLayoutNowPlayingBar.tsx @@ -0,0 +1,373 @@ +import React, { + useState, + useEffect, + memo, + useMemo, + useCallback, + useRef, +} from "react"; +import { Link, useNavigate } from "react-router-dom"; +import { useLikeStatus } from "@hooks"; +import { useQueryClient } from "@tanstack/react-query"; +import { useAuth, useAudioQueue } from "@contexts"; +import { formatPlaybackTime, getMainArtist } from "@util"; +import { ShareModal, CoverLightbox } from "@components"; +import { QueueManager } from "@components"; +import classNames from "classnames"; +import styles from "./MainLayoutNowPlayingBar.module.css"; +import { + LuCirclePlay, + LuCirclePause, + LuRepeat, + LuSkipBack, + LuSkipForward, + LuShuffle, + LuVolume2, + LuThumbsUp, + LuListPlus, + LuShare, + LuListEnd, +} from "react-icons/lu"; +import musicPlaceholder from "@assets/music-placeholder.png"; + +const NowPlayingBar: React.FC = () => { + const [isShareModalOpen, setIsShareModalOpen] = useState(false); + const [isLightboxOpen, setIsLightboxOpen] = useState(false); + const [isQueueManagerOpen, setIsQueueManagerOpen] = useState(false); + const queueButtonRef = useRef(null); + + const { user, isAuthenticated } = useAuth(); + const { state, actions } = useAudioQueue(); + const queryClient = useQueryClient(); + const navigate = useNavigate(); + + const { + isPlaying, + currentSong, + progress, + duration, + volume, + repeatMode, + hasNextSong, + hasPreviousSong, + isLoading, + isShuffled, + } = state; + + const { + isLiked, + toggleLike, + isLoading: isLikeLoading, + } = useLikeStatus({ + userId: user?.id || "", + entityId: currentSong?.id || "", + entityType: "song", + isAuthenticated, + }); + + useEffect(() => { + if (user?.id && currentSong?.id) { + queryClient.invalidateQueries({ + queryKey: ["likeStatus", user.id, currentSong.id, "song"], + }); + } + }, [user?.id, currentSong?.id]); + + const handleToggleLike = useCallback(async () => { + try { + if (!isAuthenticated) return navigate("/login"); + if (!currentSong) return; + await toggleLike(); + } catch (error) { + console.error("Toggling like failed:", error); + } + }, [isAuthenticated, navigate]); + + //! add to playlist + const handleAddToPlaylist = useCallback(async () => { + try { + if (!currentSong) return; + if (isAuthenticated) { + console.log("added to playlist"); + } else { + navigate("/login"); + } + } catch (error) { + console.error("Adding to playlist failed:", error); + } + }, [isAuthenticated, navigate]); + + const handleToggleShuffle = useCallback(() => { + actions.toggleShuffleQueue(); + }, [actions]); + + const handleToggleRepeat = useCallback(() => { + actions.toggleRepeatMode(); + }, [actions]); + + const handleTogglePlay = useCallback(() => { + if (isPlaying) { + actions.pause(); + } else { + actions.resume(); + } + }, [isPlaying, actions]); + + const handleNext = useCallback(() => { + if (hasNextSong) { + actions.next(); + } + }, [hasNextSong, actions]); + + const handlePrevious = useCallback(() => { + if (hasPreviousSong) { + actions.previous(); + } + }, [hasPreviousSong, actions]); + + const handleSeek = useCallback( + (e: React.ChangeEvent) => { + const newTime = Number(e.target.value); + actions.seek(newTime); + }, + [actions] + ); + + const handleVolumeChange = useCallback( + (e: React.ChangeEvent) => { + const newVolume = Number(e.target.value) / 100; + actions.setVolume(newVolume); + }, + [actions] + ); + + const handleShare = useCallback(() => { + if (!currentSong) return; + setIsShareModalOpen(true); + }, []); + + const handleManageQueue = useCallback(() => { + setIsQueueManagerOpen((prev) => !prev); + }, []); + + const mainArtist = useMemo(() => { + if (!currentSong) return { id: "", display_name: "Unknown Artist" }; + + if (!currentSong.artists || currentSong.artists.length === 0) { + return { id: "", display_name: "Unknown Artist" }; + } + + return ( + getMainArtist(currentSong.artists) ?? { + id: "", + display_name: "Unknown Artist", + } + ); + }, [currentSong]); + + return ( + <> +
+
+ {`${currentSong?.title} setIsLightboxOpen(true)} + /> +
+ {mainArtist.id ? ( + + {mainArtist.display_name || "Unknown Artist"} + + ) : ( + + {mainArtist.display_name || "Unknown Artist"} + + )} + + {currentSong?.title || "Unknown Song"} + +
+
+ +
+
+ + + + + +
+
+ + {formatPlaybackTime(progress)} + +
+
0 ? (progress / duration) * 100 : 0}%`, + }} + /> + +
+ + {formatPlaybackTime(duration)} + +
+
+ +
+ +
+ + setIsQueueManagerOpen(false)} + buttonRef={queueButtonRef} + /> +
+ +
+ + +
+ +
+
+ + setIsShareModalOpen(false)} + pageUrl={`${window.location.origin}/songs/${currentSong?.id}`} + pageTitle={currentSong?.title} + /> + + {currentSong && currentSong.image_url && ( + setIsLightboxOpen(false)} + imageUrl={currentSong.image_url} + altText={`${currentSong.title} Cover`} + /> + )} + + ); +}; + +export default memo(NowPlayingBar); diff --git a/client/src/components/MainLayout/MainLayoutSearchBar/MainLayoutSearchBar.module.css b/client/src/components/MainLayout/MainLayoutSearchBar/MainLayoutSearchBar.module.css new file mode 100644 index 0000000..f313c4c --- /dev/null +++ b/client/src/components/MainLayout/MainLayoutSearchBar/MainLayoutSearchBar.module.css @@ -0,0 +1,70 @@ +.searchContainer { + height: var(--header-height); + background-color: var(--color-panel-gray); + border-radius: var(--border-radius-md); + border: 2px solid var(--color-panel-border); + flex: 1; + position: relative; + display: flex; + align-items: center; +} + +.searchIcon { + position: absolute; + left: var(--spacing-md); + font-size: var(--icon-size-sm); + color: var(--color-text-gray); + pointer-events: none; +} + +.searchInput { + font-family: "Inter", sans-serif; + width: 100%; + padding: var(--spacing-sm) var(--spacing-md) var(--spacing-sm) + calc(var(--spacing-md) * 3); + background-color: transparent; + border: none; + border-radius: var(--border-radius-lg); + color: var(--color-white); + font-size: var(--font-size-sm); + outline: none; +} + +.searchInput::placeholder { + color: var(--color-text-gray); +} +.searchContainer { + height: var(--header-height); + background-color: var(--color-panel-gray); + border-radius: var(--border-radius-md); + border: 2px solid var(--color-panel-border); + flex: 1; + position: relative; + display: flex; + align-items: center; +} + +.searchIcon { + position: absolute; + left: var(--spacing-md); + font-size: var(--icon-size-sm); + color: var(--color-text-gray); + pointer-events: none; +} + +.searchInput { + font-family: "Inter", sans-serif; + width: 100%; + padding: var(--spacing-sm) var(--spacing-md) var(--spacing-sm) + calc(var(--spacing-md) * 3); + background-color: transparent; + border: none; + border-radius: var(--border-radius-lg); + color: var(--color-white); + font-size: var(--font-size-sm); + outline: none; +} + +.searchInput::placeholder { + color: var(--color-text-gray); +} diff --git a/client/src/components/MainLayout/MainLayoutSearchBar/MainLayoutSearchBar.tsx b/client/src/components/MainLayout/MainLayoutSearchBar/MainLayoutSearchBar.tsx new file mode 100644 index 0000000..18e72ca --- /dev/null +++ b/client/src/components/MainLayout/MainLayoutSearchBar/MainLayoutSearchBar.tsx @@ -0,0 +1,18 @@ +import styles from "./MainLayoutSearchBar.module.css"; +import { LuSearch } from "react-icons/lu"; + +const MainLayoutSearchBar: React.FC = () => { + return ( +
+ + +
+ ); +}; + +export default MainLayoutSearchBar; diff --git a/client/src/components/MainLayout/MainLayoutSidebar/MainLayoutSidebar.module.css b/client/src/components/MainLayout/MainLayoutSidebar/MainLayoutSidebar.module.css new file mode 100644 index 0000000..64e1f21 --- /dev/null +++ b/client/src/components/MainLayout/MainLayoutSidebar/MainLayoutSidebar.module.css @@ -0,0 +1,72 @@ +.sidebar { + width: var(--sidebar-width); + background-color: var(--color-panel-gray); + border-radius: var(--border-radius-md); + display: flex; + flex-direction: column; + justify-content: space-between; + padding: var(--spacing-lg) 0; + border: 2px solid var(--color-panel-border); + z-index: 100; +} + +.sidebarTop { + display: flex; + flex-direction: column; + gap: var(--spacing-xl); +} + +.sidebarLogo { + display: flex; + justify-content: center; +} + +.logoImage { + width: var(--icon-size-xl); + height: var(--icon-size-xl); +} + +.sidebarNav { + display: flex; + flex-direction: column; + gap: var(--spacing-xl); +} + +.sidebarLink { + display: flex; + align-items: center; + justify-content: center; + color: var(--color-text-gray) !important; + border-radius: var(--border-radius-md); + transition: color var(--transition-speed) ease-in-out; +} + +.sidebarLink:hover { + color: var(--color-white) !important; +} + +.sidebarIcon { + font-size: var(--icon-size-md); +} + +.logoutButton { + display: flex; + align-items: center; + justify-content: center; + color: var(--color-text-gray) !important; + border-radius: var(--border-radius-md); + transition: color var(--transition-speed) ease-in-out; + background: none; + border: none; + cursor: pointer; +} + +.logoutButton:hover { + color: var(--color-white) !important; +} + +@media (max-width: 768px) { + .sidebar { + display: none; + } +} diff --git a/client/src/components/MainLayout/MainLayoutSidebar/MainLayoutSidebar.tsx b/client/src/components/MainLayout/MainLayoutSidebar/MainLayoutSidebar.tsx new file mode 100644 index 0000000..36b50f6 --- /dev/null +++ b/client/src/components/MainLayout/MainLayoutSidebar/MainLayoutSidebar.tsx @@ -0,0 +1,61 @@ +import React, { useCallback } from "react"; +import { Link, useNavigate } from "react-router-dom"; +import { useAuth } from "@contexts"; +import styles from "./MainLayoutSidebar.module.css"; +import logo from "@assets/logo.svg"; +import { + LuListMusic, + LuLibrary, + LuDisc3, + LuUserPen, + LuHistory, + LuLogOut, +} from "react-icons/lu"; + +const MainLayoutSidebar: React.FC = () => { + const { logout, isAuthenticated } = useAuth(); + const navigate = useNavigate(); + + const handleLogout = useCallback(async () => { + try { + await logout(); + navigate("/"); + } catch (error) { + console.error("Logout failed:", error); + } + }, [logout, navigate]); + + return ( + + ); +}; + +export default MainLayoutSidebar; diff --git a/client/src/components/MainLayout/QueueManager/QueueManager.module.css b/client/src/components/MainLayout/QueueManager/QueueManager.module.css new file mode 100644 index 0000000..db9a1b1 --- /dev/null +++ b/client/src/components/MainLayout/QueueManager/QueueManager.module.css @@ -0,0 +1,222 @@ +.queueManager { + position: absolute; + bottom: calc(var(--now-playing-height) - var(--spacing-md)); + right: 0; + background: var(--color-panel-gray); + border: 2px solid var(--color-panel-border); + border-radius: var(--border-radius-md); + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -1px rgba(0, 0, 0, 0.06); + z-index: 1000; + animation: menuFadeIn var(--transition-speed) ease-out; + width: 32rem; + max-height: 40rem; + display: flex; + flex-direction: column; + overflow: hidden; + overflow-x: hidden; +} + +@keyframes menuFadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.header { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--spacing-md); + border-bottom: 1px solid var(--color-panel-border); +} + +.headerButtons { + display: flex; + align-items: center; + gap: var(--spacing-sm); +} + +.title { + font-size: var(--font-size-lg); + font-weight: 600; + color: var(--color-white); + margin: 0; +} + +.closeButton { + background: none; + border: none; + color: var(--color-text-gray); + font-size: var(--font-size-lg); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + padding: var(--spacing-xs); + border-radius: var(--border-radius-sm); + transition: all var(--transition-speed) ease; +} + +.closeButton:hover { + color: var(--color-white); + background: var(--color-panel-border); +} + +.clearButton { + background: none; + border: none; + color: var(--color-text-gray); + font-size: var(--font-size-lg); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + padding: var(--spacing-xs); + transition: all var(--transition-speed) ease; +} + +.clearButton:hover { + color: var(--color-red); +} + +.clearButton:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.clearButton:disabled:hover { + color: var(--color-text-gray); + background: none; +} + +.queueContent { + flex: 1; + overflow: hidden; + display: flex; + flex-direction: column; +} + +.emptyQueue { + display: flex; + align-items: center; + justify-content: center; + padding: var(--spacing-lg); +} + +.emptyText { + font-size: var(--font-size-sm); + color: var(--color-text-gray); + font-weight: 500; +} + +.queueList { + overflow-y: auto; + overflow-x: hidden; + display: flex; + flex-direction: column; + max-height: 32rem; +} + +.queueItem { + background: var(--color-panel-gray); + padding: var(--spacing-md); + display: flex; + align-items: center; + gap: var(--spacing-md); + cursor: grab; + transition: all var(--transition-speed) ease; + user-select: none; + border-bottom: 1px solid var(--color-panel-border); +} + +.queueItem:hover { + background: var(--color-panel-border); +} + +.queueItem:last-child { + border-bottom: none; +} + +.queueItemUserQueued { + background: var(--color-gray-button); +} + +.queueItemUserQueued:hover { + background: var(--color-gray-button-hover); +} + +.queueItemDragging { + opacity: 0.5; + cursor: grabbing; +} + +.queueItemDragOver { + background: var(--color-gray-button-hover); + border-top: 2px solid var(--color-red); +} + +.dragHandle { + color: var(--color-text-gray); + font-size: var(--font-size-md); + cursor: grab; + display: flex; + align-items: center; + transition: color var(--transition-speed) ease; +} + +.queueItem:hover .dragHandle { + color: var(--color-white); +} + +.queueItemDragging .dragHandle { + cursor: grabbing; +} + +.songInfo { + flex: 1; + display: flex; + flex-direction: column; + gap: var(--spacing-xs); + min-width: 0; +} + +.artistName { + font-size: var(--font-size-xs); + color: var(--color-text-gray); + font-weight: 500; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.songTitle { + font-size: var(--font-size-sm); + color: var(--color-white); + font-weight: 500; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.removeButton { + background: none; + border: none; + color: var(--color-text-gray); + font-size: var(--font-size-md); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + padding: var(--spacing-xs); + border-radius: var(--border-radius-sm); + transition: all var(--transition-speed) ease; +} + +.removeButton:hover { + color: var(--color-red); + background: rgba(213, 49, 49, 0.1); +} diff --git a/client/src/components/MainLayout/QueueManager/QueueManager.tsx b/client/src/components/MainLayout/QueueManager/QueueManager.tsx new file mode 100644 index 0000000..327bede --- /dev/null +++ b/client/src/components/MainLayout/QueueManager/QueueManager.tsx @@ -0,0 +1,183 @@ +import { memo, useEffect, useRef, useState, useCallback } from "react"; +import { LuX, LuGripHorizontal, LuTrash } from "react-icons/lu"; +import { useAudioQueue } from "@contexts"; +import { getMainArtist } from "@util"; +import classNames from "classnames"; +import styles from "./QueueManager.module.css"; + +interface QueueManagerProps { + isOpen: boolean; + onClose: () => void; + buttonRef: React.RefObject; +} + +const QueueManager: React.FC = ({ + isOpen, + onClose, + buttonRef, +}) => { + const { state, actions } = useAudioQueue(); + const modalRef = useRef(null); + const [draggedIndex, setDraggedIndex] = useState(null); + const [dragOverIndex, setDragOverIndex] = useState(null); + + const queueItems = state.queue.slice(state.currentIndex + 1); + + useEffect(() => { + const handleEscape = (event: KeyboardEvent) => { + if (event.key === "Escape") { + onClose(); + } + }; + + const handleClickOutside = (event: MouseEvent) => { + if ( + modalRef.current && + !modalRef.current.contains(event.target as Node) && + buttonRef.current && + !buttonRef.current.contains(event.target as Node) + ) { + onClose(); + } + }; + + if (isOpen) { + document.addEventListener("keydown", handleEscape); + document.addEventListener("mousedown", handleClickOutside); + document.body.style.overflow = "hidden"; + } + + return () => { + document.removeEventListener("keydown", handleEscape); + document.removeEventListener("mousedown", handleClickOutside); + document.body.style.overflow = "unset"; + }; + }, [isOpen, onClose, buttonRef]); + + const handleRemoveFromQueue = useCallback( + (queueId: string) => { + actions.removeFromQueue(queueId); + }, + [actions] + ); + + const handleDragStart = useCallback((e: React.DragEvent, index: number) => { + setDraggedIndex(index); + e.dataTransfer.effectAllowed = "move"; + e.dataTransfer.setData("text/html", ""); + }, []); + + const handleDragOver = useCallback((e: React.DragEvent, index: number) => { + e.preventDefault(); + e.dataTransfer.dropEffect = "move"; + setDragOverIndex(index); + }, []); + + const handleDragLeave = useCallback(() => { + setDragOverIndex(null); + }, []); + + const handleDrop = useCallback( + (e: React.DragEvent, dropIndex: number) => { + e.preventDefault(); + + if (draggedIndex !== null && draggedIndex !== dropIndex) { + // add 1 for current song + const actualFromIndex = state.currentIndex + 1 + draggedIndex; + const actualToIndex = state.currentIndex + 1 + dropIndex; + + actions.moveQueueItem(actualFromIndex, actualToIndex); + } + + setDraggedIndex(null); + setDragOverIndex(null); + }, + [draggedIndex, state.currentIndex, actions] + ); + + const handleDragEnd = useCallback(() => { + setDraggedIndex(null); + setDragOverIndex(null); + }, []); + + const handleClearQueue = useCallback(() => { + actions.clearQueue(false, true); + }, [actions]); + + if (!isOpen) return null; + + return ( +
+
+

Queue

+
+ + +
+
+ +
+ {queueItems.length === 0 ? ( +
+ No songs in queue +
+ ) : ( +
+ {queueItems.map((item, index) => { + const mainArtist = getMainArtist(item.song.artists ?? []); + const isDragging = draggedIndex === index; + const isDragOver = dragOverIndex === index; + + return ( +
handleDragStart(e, index)} + onDragOver={(e) => handleDragOver(e, index)} + onDragLeave={handleDragLeave} + onDrop={(e) => handleDrop(e, index)} + onDragEnd={handleDragEnd} + > +
+ +
+ +
+ + {mainArtist?.display_name || "Unknown Artist"} + + {item.song.title} +
+ + +
+ ); + })} +
+ )} +
+
+ ); +}; + +export default memo(QueueManager); diff --git a/client/src/components/PageLoader/PageLoader.module.css b/client/src/components/PageLoader/PageLoader.module.css new file mode 100644 index 0000000..6a30b67 --- /dev/null +++ b/client/src/components/PageLoader/PageLoader.module.css @@ -0,0 +1,8 @@ +.loaderContainer { + position: fixed; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; +} diff --git a/client/src/components/PageLoader/PageLoader.tsx b/client/src/components/PageLoader/PageLoader.tsx new file mode 100644 index 0000000..beda0d8 --- /dev/null +++ b/client/src/components/PageLoader/PageLoader.tsx @@ -0,0 +1,13 @@ +import styles from "./PageLoader.module.css"; +import { PuffLoader } from "react-spinners"; +import React from "react"; + +const PageLoader: React.FC = () => { + return ( +
+ +
+ ); +}; + +export default PageLoader; diff --git a/client/src/components/PlayerBar/playerBar.module.css b/client/src/components/PlayerBar/playerBar.module.css deleted file mode 100644 index 77f8b0e..0000000 --- a/client/src/components/PlayerBar/playerBar.module.css +++ /dev/null @@ -1,142 +0,0 @@ -.PlayerBar { - position: fixed; - bottom: 0; - left: 80px; /* Match sidebar width */ - right: 0; - height: 90px; - background-color: #121212; - border-top: 1px solid #222; - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 16px; - z-index: 900; -} - -/* Left section - Song info */ -.playerInfo { - display: flex; - align-items: center; - gap: 12px; - min-width: 180px; - width: 30%; -} - -.playerImage { - width: 56px; - height: 56px; - border-radius: 4px; - object-fit: cover; -} - -.playerSong { - display: flex; - flex-direction: column; - gap: 4px; -} - -.playerSong p { - color: #fff; - margin: 0; - font-size: 14px; - font-weight: 600; - font-family: 'Inter', sans-serif; -} - -.playerSong span { - color: #a7a7a7; - font-size: 12px; - font-weight: 400; - font-family: 'Inter', sans-serif; -} - -/* Center section - Controls */ -.playerControls { - display: flex; - flex-direction: column; - align-items: center; - gap: 8px; - flex: 1; - max-width: 722px; -} - -.playButtons { - display: flex; - align-items: center; - gap: 16px; - margin-bottom: 8px; -} - -.playButtons button { - background: none; - border: none; - padding: 8px; - cursor: pointer; - border-radius: 50%; - transition: all 0.2s ease; -} - -.playButtons button:hover { - background-color: rgba(255, 255, 255, 0.1); -} - -.playButton { - width: 32px; - height: 32px; -} - -/* Progress bar */ -.progressContainer { - width: 100%; - height: 4px; - background-color: #4d4d4d; - border-radius: 2px; - cursor: pointer; -} - -.progressBar { - height: 100%; - background-color: #fff; - border-radius: 2px; - width: 30%; /* Update dynamically with JS */ -} - -/* Right section - Volume */ -.playerExtra { - display: flex; - align-items: center; - gap: 16px; - min-width: 180px; - width: 30%; - justify-content: flex-end; -} - -.volumeControl { - display: flex; - align-items: center; - gap: 8px; -} - -.iconButton { - background: none; - border: none; - padding: 8px; - cursor: pointer; - border-radius: 50%; - transition: all 0.2s ease; -} - -.iconButton:hover { - background-color: rgba(255, 255, 255, 0.1); -} - -.iconButton img { - width: 20px; - height: 20px; - opacity: 0.7; - transition: opacity 0.2s ease; -} - -.iconButton:hover img { - opacity: 1; -} \ No newline at end of file diff --git a/client/src/components/PlayerBar/playerBar.tsx b/client/src/components/PlayerBar/playerBar.tsx deleted file mode 100644 index 19282c9..0000000 --- a/client/src/components/PlayerBar/playerBar.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React from 'react'; -import styles from './playerBar.module.css'; - -const PlayerBar: React.FC = () => { - return ( -
- {/* Left: Song Info */} -
- Song Cover -
-

Song Name

- Artist Name -
-
- - {/* Center: Player Controls */} -
-
- - - - - -
- -
-
-
-
- - {/* Right: Volume & Extra Controls */} -
- - -
- Volume -
-
-
- ); -}; - -export default PlayerBar; \ No newline at end of file diff --git a/client/src/components/ProtectedRoute/ProtectedRoute.tsx b/client/src/components/ProtectedRoute/ProtectedRoute.tsx new file mode 100644 index 0000000..01f9243 --- /dev/null +++ b/client/src/components/ProtectedRoute/ProtectedRoute.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import { Navigate, useLocation } from "react-router-dom"; +import { useAuth } from "../../contexts"; +import { PageLoader } from "../"; + +interface ProtectedRouteProps { + children: React.ReactNode; +} + +const ProtectedRoute: React.FC = ({ children }) => { + const { isAuthenticated, isLoading } = useAuth(); + const location = useLocation(); + + if (isLoading) { + return ; + } + + if (!isAuthenticated) { + return ; + } + + return <>{children}; +}; + +export default ProtectedRoute; diff --git a/client/src/components/QueueMenu/QueueMenu.module.css b/client/src/components/QueueMenu/QueueMenu.module.css new file mode 100644 index 0000000..3bef30f --- /dev/null +++ b/client/src/components/QueueMenu/QueueMenu.module.css @@ -0,0 +1,115 @@ +.queueMenu { + position: absolute; + bottom: calc(100% + 0.8rem); + background: var(--color-panel-gray); + border: 2px solid var(--color-panel-border) !important; + border-radius: var(--border-radius-md); + box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.5), + 0 4px 6px -2px rgba(0, 0, 0, 0.1); + z-index: 1000; + animation: menuFadeIn var(--transition-speed) ease-out; + min-width: 15rem; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + overflow: hidden; +} + +.justifyCenter { + left: 50%; + transform: translateX(-50%); +} + +.justifyLeft { + left: 0; + transform: translateX(0); +} + +.justifyRight { + right: 0; + transform: translateX(0); +} + +@keyframes menuFadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.justifyCenter { + animation: menuFadeInCenter var(--transition-speed) ease-out; +} + +.justifyLeft { + animation: menuFadeInLeft var(--transition-speed) ease-out; +} + +.justifyRight { + animation: menuFadeInRight var(--transition-speed) ease-out; +} + +@keyframes menuFadeInCenter { + from { + opacity: 0; + transform: translateX(-50%) translateY(-4px); + } + to { + opacity: 1; + transform: translateX(-50%) translateY(0); + } +} + +@keyframes menuFadeInLeft { + from { + opacity: 0; + transform: translateX(0) translateY(-4px); + } + to { + opacity: 1; + transform: translateX(0) translateY(0); + } +} + +@keyframes menuFadeInRight { + from { + opacity: 0; + transform: translateX(0) translateY(-4px); + } + to { + opacity: 1; + transform: translateX(0) translateY(0); + } +} + +.menuButton { + font-family: "Inter", sans-serif; + width: 100%; + background: var(--color-panel-gray); + border: none; + padding: var(--spacing-md); + display: flex; + align-items: center; + gap: var(--spacing-sm); + color: var(--color-white-hover); + font-size: var(--font-size-sm); + font-weight: 400; + cursor: pointer; + transition: all var(--transition-speed) ease; +} + +.menuButton:hover { + background: var(--color-panel-border); + color: var(--color-white); +} + +.menuButton:first-child { + border-bottom: 1px solid var(--color-panel-border); +} + +.menuIcon { + font-size: var(--icon-size-sm); +} diff --git a/client/src/components/QueueMenu/QueueMenu.tsx b/client/src/components/QueueMenu/QueueMenu.tsx new file mode 100644 index 0000000..ed015ed --- /dev/null +++ b/client/src/components/QueueMenu/QueueMenu.tsx @@ -0,0 +1,95 @@ +import { memo, useEffect, useRef } from "react"; +import { LuListStart, LuListEnd } from "react-icons/lu"; +import { useAudioQueue } from "@contexts"; +import type { Song } from "@types"; +import styles from "./QueueMenu.module.css"; +import { useCallback } from "react"; +import classNames from "classnames"; + +interface QueueMenuProps { + isOpen: boolean; + onClose: () => void; + song: Song; + buttonRef: React.RefObject; + justification?: "left" | "center" | "right"; +} + +const QueueMenu: React.FC = ({ + isOpen, + onClose, + song, + buttonRef, + justification = "center", +}) => { + const { actions } = useAudioQueue(); + const menuRef = useRef(null); + + const handleEscape = useCallback( + (event: KeyboardEvent) => { + if (event.key === "Escape") { + onClose(); + } + }, + [onClose] + ); + + const handleClickOutside = useCallback( + (event: MouseEvent) => { + if ( + menuRef.current && + !menuRef.current.contains(event.target as Node) && + buttonRef.current && + !buttonRef.current.contains(event.target as Node) + ) { + onClose(); + } + }, + [onClose, buttonRef] + ); + + useEffect(() => { + if (isOpen) { + document.addEventListener("keydown", handleEscape); + document.addEventListener("mousedown", handleClickOutside); + } + + return () => { + document.removeEventListener("keydown", handleEscape); + document.removeEventListener("mousedown", handleClickOutside); + }; + }, [isOpen, handleEscape, handleClickOutside]); + + const handleQueueNext = () => { + actions.queueNext(song); + onClose(); + }; + + const handleQueueLast = () => { + actions.queueLast(song); + onClose(); + }; + + if (!isOpen) return null; + + return ( +
+ + +
+ ); +}; + +export default memo(QueueMenu); diff --git a/client/src/components/ShareModal/ShareModal.module.css b/client/src/components/ShareModal/ShareModal.module.css new file mode 100644 index 0000000..080a60b --- /dev/null +++ b/client/src/components/ShareModal/ShareModal.module.css @@ -0,0 +1,192 @@ +.overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.6); + backdrop-filter: blur(4px); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + animation: fadeIn 0.2s ease-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.modal { + background: var(--color-panel-gray); + border: 2px solid var(--color-panel-border); + border-radius: var(--border-radius-md); + width: 90%; + max-width: 46rem; + padding: var(--spacing-lg); + box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.5), + 0 10px 10px -5px rgba(0, 0, 0, 0.04); + animation: slideIn 0.2s ease-out; + display: flex; + flex-direction: column; + gap: var(--spacing-lg); +} + +@keyframes slideIn { + from { + opacity: 0; + transform: scale(0.95) translateY(-10px); + } + to { + opacity: 1; + transform: scale(1) translateY(0); + } +} + +.header { + display: flex; + align-items: center; + justify-content: space-between; +} + +.title { + font-size: 2rem; + font-weight: 600; + color: var(--color-white); + margin: 0; +} + +.closeButton { + background: none; + border: none; + color: var(--color-text-gray); + font-size: 2rem; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all var(--transition-speed) ease; +} + +.closeButton:hover { + color: var(--color-white); +} + +.socialIcons { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--spacing-sm); +} + +.socialButton { + font-family: "Inter", sans-serif; + background: var(--color-gray-button); + border: 1px solid var(--color-gray-button-border); + border-radius: var(--border-radius-md); + padding: 2rem 1.2rem; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 1.2rem; + cursor: pointer; + transition: background var(--transition-speed) ease; + color: var(--color-white); + font-size: var(--font-size-lg); +} + +.socialButton:hover { + background: var(--color-gray-button-border); +} + +.socialLabel { + font-size: var(--font-size-sm); + font-weight: 500; + color: var(--color-white-hover); +} + +.linkSection { + display: flex; + flex-direction: column; + gap: var(--spacing-sm); + line-height: 1.1; +} + +.linkLabel { + font-size: var(--font-size-sm); + font-weight: 500; + color: var(--color-white-hover); +} + +.linkInputWrapper { + position: relative; + display: flex; + align-items: center; +} + +.linkInput { + font-family: "Inter", sans-serif; + width: 100%; + background: var(--color-gray-button); + border: 1px solid var(--color-gray-button-border); + border-radius: var(--border-radius-md); + padding: 1.04rem 4.58rem 1.04rem 1.25rem; + color: var(--color-text-gray); + font-size: var(--font-size-sm); + font-family: inherit; + transition: all var(--transition-speed) ease; +} + +.copyButton { + position: absolute; + right: 0.3125rem; + background: var(--color-gray-button-border); + border: none; + border-radius: 0.6rem; + padding: 0.8rem; + color: var(--color-white-hover); + font-size: var(--font-size-md); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all var(--transition-speed) ease; +} + +.copyButton:hover { + background: #5d5d5d; + color: var(--color-white); +} + +.tooltip { + position: absolute; + bottom: calc(100% + 0.8rem); + left: 50%; + transform: translateX(-50%); + background: var(--color-white); + color: var(--color-panel-gray); + padding: 0.6rem 1.2rem; + border-radius: 0.6rem; + font-size: var(--font-size-sm); + font-weight: 500; + white-space: nowrap; + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3); + animation: tooltipFadeIn var(--transition-speed) ease-out; + pointer-events: none; +} + +@keyframes tooltipFadeIn { + from { + opacity: 0; + transform: translateX(-50%) translateY(-4px); + } + to { + opacity: 1; + transform: translateX(-50%) translateY(0); + } +} diff --git a/client/src/components/ShareModal/ShareModal.tsx b/client/src/components/ShareModal/ShareModal.tsx new file mode 100644 index 0000000..50ce23c --- /dev/null +++ b/client/src/components/ShareModal/ShareModal.tsx @@ -0,0 +1,135 @@ +import { useState, memo } from "react"; +import { FaXTwitter, FaFacebook, FaReddit, FaEnvelope } from "react-icons/fa6"; +import { LuCopy, LuX } from "react-icons/lu"; +import styles from "./ShareModal.module.css"; + +interface ShareModalProps { + isOpen: boolean; + onClose: () => void; + pageUrl?: string; + pageTitle?: string; +} + +const ShareModal: React.FC = ({ + isOpen, + onClose, + pageUrl = window.location.href, + pageTitle = document.title, +}) => { + const [copied, setCopied] = useState(false); + + if (!isOpen) return null; + + const handleCopy = async () => { + try { + await navigator.clipboard.writeText(pageUrl); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch (error) { + console.error("Failed to copy:", error); + } + }; + + interface ShareLink { + name: string; + icon: React.ComponentType; + url: string; + isEmail?: boolean; + } + + const shareLinks: ShareLink[] = [ + { + name: "Twitter", + icon: FaXTwitter, + url: `https://twitter.com/intent/tweet?url=${encodeURIComponent( + pageUrl + )}&text=${encodeURIComponent(pageTitle)}`, + }, + { + name: "Facebook", + icon: FaFacebook, + url: `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent( + pageUrl + )}`, + }, + { + name: "Reddit", + icon: FaReddit, + url: `https://reddit.com/submit?url=${encodeURIComponent( + pageUrl + )}&title=${encodeURIComponent(pageTitle)}`, + }, + { + name: "Email", + icon: FaEnvelope, + url: `mailto:?subject=${encodeURIComponent( + pageTitle + )}&body=${encodeURIComponent(pageUrl)}`, + isEmail: true, + }, + ]; + + const handleShareClick = (link: ShareLink): void => { + if (link.isEmail) { + window.location.href = link.url; + } else { + window.open( + link.url, + "_blank", + "noopener,noreferrer,width=600,height=400" + ); + } + }; + + return ( +
+
e.stopPropagation()}> +
+

Share

+ +
+ +
+ {shareLinks.map((link) => { + const Icon = link.icon; + return ( + + ); + })} +
+ +
+ +
+ + + {copied &&
Copied!
} +
+
+
+
+ ); +}; + +export default memo(ShareModal); diff --git a/client/src/components/SideBar/sideBar.module.css b/client/src/components/SideBar/sideBar.module.css deleted file mode 100644 index f69e40d..0000000 --- a/client/src/components/SideBar/sideBar.module.css +++ /dev/null @@ -1,70 +0,0 @@ -.sideBarContainer { - position: fixed; - top: 0; - left: 0; - width: 80px; - height: 100vh; - background-color: #111; - display: flex; - flex-direction: column; - align-items: center; - padding: 24px 0; - z-index: 1000; -} - -.sidebar-icons { - display: flex; - flex-direction: column; - align-items: center; - gap: 32px; - width: 100%; -} - -.sidebar-icon { - position: relative; - width: 40px; - height: 40px; - display: flex; - align-items: center; - justify-content: center; - transition: all 0.2s ease; - border-radius: 8px; -} - -.sidebar-icon:hover { - transform: scale(1.1); - background-color: rgba(255, 59, 48, 0.1); -} - -.sidebar-icon img { - width: 24px; - height: 24px; - transition: all 0.2s ease; -} - -.sidebar-icon:hover img { - filter: brightness(1.2) sepia(1) saturate(3) hue-rotate(315deg); -} - -.logoContainer { - margin-bottom: 48px; -} - -.logoIcon { - width: 48px; - height: 48px; -} - -.active { - background-color: rgba(255, 59, 48, 0.15); -} - -.active img { - filter: brightness(1.2) sepia(1) saturate(3) hue-rotate(315deg); -} - -/* Push logout button to bottom */ -.sidebarBottom { - margin-top: auto; - padding-top: 32px; -} \ No newline at end of file diff --git a/client/src/components/SideBar/sidebar.tsx b/client/src/components/SideBar/sidebar.tsx deleted file mode 100644 index 90e82d8..0000000 --- a/client/src/components/SideBar/sidebar.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { useState } from 'react'; -import styles from './sideBar.module.css'; - -const Sidebar: React.FC = () => { - const [activeIcon, setActiveIcon] = useState('home'); - - const icons = [ - { id: 'expand', src: '/SideBar/Expand.svg', alt: 'Expand' }, - { id: 'songs', src: '/SideBar/SongOrder.svg', alt: 'Songs' }, - { id: 'playlists', src: '/SideBar/Vector-2.svg', alt: 'Playlists' }, - { id: 'artists', src: '/SideBar/Vector-3.svg', alt: 'Artists' }, - { id: 'albums', src: '/SideBar/Vector-4.svg', alt: 'Albums' }, - ]; - - return ( -
-
-
- Logo -
- - {icons.map(icon => ( -
setActiveIcon(icon.id)} - > - {icon.alt} -
- ))} - -
-
- Logout -
-
-
-
- ); -}; - -export default Sidebar; \ No newline at end of file diff --git a/client/src/components/SlidingCardList/SlidingCardList.module.css b/client/src/components/SlidingCardList/SlidingCardList.module.css new file mode 100644 index 0000000..7a34501 --- /dev/null +++ b/client/src/components/SlidingCardList/SlidingCardList.module.css @@ -0,0 +1,100 @@ +.loaderContainer { + display: flex; + align-items: center; + justify-content: center; + padding: var(--spacing-xl); + min-height: 10rem; +} + +.error { + display: flex; + align-items: center; + justify-content: center; + padding: var(--spacing-xl); + color: var(--color-text-gray); + font-size: var(--font-size-md); +} + +.container { + display: flex; + flex-direction: column; + gap: var(--spacing-md); + min-width: 0; + width: 100%; +} + +.sectionTitle { + font-size: var(--font-size-lg); + color: var(--color-white); + font-weight: 500; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 100%; +} + +.withNavigation { + display: flex; + align-items: center; + gap: var(--spacing-md); + width: 100%; +} + +.scrollContainer { + flex: 1; + overflow: hidden; + position: relative; + min-width: 0; + width: 0; +} + +.list { + display: flex; + gap: var(--spacing-lg); + min-width: 0; + transition: transform 0.3s ease; + width: max-content; +} + +.navButton { + display: flex; + align-items: center; + justify-content: center; + background: none; + border: none; + color: var(--color-text-gray); + cursor: pointer; + font-size: var(--icon-size-lg); + padding: var(--spacing-sm); + transition: all var(--transition-speed) ease; + flex-shrink: 0; +} + +.navButton:hover:not(:disabled) { + color: var(--color-white); + transform: scale(1.1); +} + +.navButton:disabled { + opacity: 0.3; + cursor: not-allowed; +} + +.scrollGradient { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: linear-gradient( + to right, + rgba(8, 8, 8, 0.7) 0%, + transparent 8%, + transparent 92%, + rgba(8, 8, 8, 0.7) 100% + ); + pointer-events: none; + z-index: 2; + opacity: 1; + transition: opacity var(--transition-speed) ease; +} diff --git a/client/src/components/SlidingCardList/SlidingCardList.tsx b/client/src/components/SlidingCardList/SlidingCardList.tsx new file mode 100644 index 0000000..f65e1fe --- /dev/null +++ b/client/src/components/SlidingCardList/SlidingCardList.tsx @@ -0,0 +1,222 @@ +import { memo, useCallback, useState, useMemo, useRef, useEffect } from "react"; +import { PuffLoader } from "react-spinners"; +import { LuChevronLeft, LuChevronRight } from "react-icons/lu"; +import type { Song, Album, Playlist } from "@types"; +import { useAsyncData } from "@hooks"; +import { EntityItemCard } from "@components"; +import { formatDateString, getMainArtist } from "@util"; +import styles from "./SlidingCardList.module.css"; +import musicPlaceholder from "@assets/music-placeholder.png"; + +type CardEntityType = "song" | "album" | "playlist"; + +const CARD_WIDTH = 18; +const CARD_GAP = 2.4; +const SCROLL_TRANSITION_DURATION = 300; + +export interface SlidingCardListProps { + title: string; + artistName?: string; + fetchData: () => Promise; + type: CardEntityType; + itemsPerView?: number; + cacheKey: string; + dependencies?: any[]; +} + +const SlidingCardList: React.FC = ({ + title, + artistName, + fetchData, + type, + itemsPerView = 6, + cacheKey, + dependencies = [], +}) => { + const [scrollPosition, setScrollPosition] = useState(0); + const [isScrolling, setIsScrolling] = useState(false); + + const timeoutRef = useRef(undefined); + + const asyncConfig = useMemo( + () => ({ + items: fetchData, + }), + [fetchData] + ); + + const { data, loading, error } = useAsyncData(asyncConfig, dependencies, { + cacheKey, + hasBlobUrl: true, + }); + + const items = data?.items || []; + const scrollState = useMemo(() => { + const totalItems = items.length; + const maxScrollPosition = Math.max(0, totalItems - itemsPerView); + const needsScrolling = totalItems > itemsPerView; + const canScrollNext = scrollPosition < maxScrollPosition; + const canScrollPrevious = scrollPosition > 0; + + return { + totalItems, + maxScrollPosition, + needsScrolling, + canScrollNext, + canScrollPrevious, + }; + }, [items.length, itemsPerView, scrollPosition]); + + const transformStyle = useMemo( + () => ({ + transform: `translateX(-${scrollPosition * (CARD_WIDTH + CARD_GAP)}rem)`, + }), + [scrollPosition] + ); + + const handleScrollNext = useCallback(() => { + setIsScrolling(true); + setScrollPosition((prev) => + Math.min(prev + itemsPerView, scrollState.maxScrollPosition) + ); + if (timeoutRef.current) clearTimeout(timeoutRef.current); + timeoutRef.current = setTimeout( + () => setIsScrolling(false), + SCROLL_TRANSITION_DURATION + ); + }, [scrollState.maxScrollPosition, itemsPerView]); + + const handleScrollPrevious = useCallback(() => { + setIsScrolling(true); + setScrollPosition((prev) => Math.max(prev - itemsPerView, 0)); + if (timeoutRef.current) clearTimeout(timeoutRef.current); + timeoutRef.current = setTimeout( + () => setIsScrolling(false), + SCROLL_TRANSITION_DURATION + ); + }, [itemsPerView]); + + useEffect(() => { + return () => { + if (timeoutRef.current) clearTimeout(timeoutRef.current); + }; + }, []); + + useEffect(() => { + setScrollPosition(0); + }, [cacheKey]); + + const getEntityProps = useCallback( + (item: Song | Album | Playlist) => { + switch (type) { + case "song": { + const song = item as Song; + return { + type: "song" as const, + linkTo: `/songs/${song.id}`, + author: + getMainArtist(song.artists ?? [])?.display_name || + artistName || + "", + title: song.title, + subtitle: formatDateString(song.release_date), + imageUrl: song.image_url || musicPlaceholder, + entity: song, + }; + } + case "album": { + const album = item as Album; + return { + type: "list" as const, + linkTo: `/albums/${album.id}`, + author: artistName || "", + title: album.title, + subtitle: formatDateString(album.release_date), + imageUrl: album.image_url || musicPlaceholder, + entity: album, + }; + } + case "playlist": { + const playlist = item as Playlist; + return { + type: "list" as const, + linkTo: `/playlists/${playlist.id}`, + author: playlist.user?.username || "Unknown", + title: playlist.title, + subtitle: "", + imageUrl: playlist.image_url || musicPlaceholder, + entity: playlist, + }; + } + default: + throw new Error(`Unknown entity type: ${type}`); + } + }, + [type, artistName] + ); + + if (loading) { + return ( +
+ +
+ ); + } + + if (error) { + return ( +
Failed to load {title.toLowerCase()}.
+ ); + } + + if (!items || items.length === 0) { + return null; + } + + return ( +
+ {title} + {scrollState.needsScrolling ? ( +
+ +
+
+ {items.map((item) => { + const props = getEntityProps(item); + return ; + })} +
+
+
+ +
+ ) : ( +
+ {items.map((item) => { + const props = getEntityProps(item); + return ; + })} +
+ )} +
+ ); +}; + +export default memo(SlidingCardList); diff --git a/client/src/components/SongCard/SongCard.module.css b/client/src/components/SongCard/SongCard.module.css index f1e7ad3..7357313 100644 --- a/client/src/components/SongCard/SongCard.module.css +++ b/client/src/components/SongCard/SongCard.module.css @@ -67,11 +67,10 @@ } .songTitle { - font-weight: 600; /* semi-bold */ + font-weight: 600; color: #ffffff; margin-bottom: 4px; font-size: 0.95rem; - font-family: 'Inter', sans-serif; } .songArtist { @@ -103,4 +102,4 @@ width: 14px; height: 14px; fill: currentColor; -} \ No newline at end of file +} diff --git a/client/src/components/SongCard/SongCard.tsx b/client/src/components/SongCard/SongCard.tsx index 844b79b..83dcfe2 100644 --- a/client/src/components/SongCard/SongCard.tsx +++ b/client/src/components/SongCard/SongCard.tsx @@ -8,7 +8,6 @@ export interface SongCardProps { plays: number; likes: number; comments: number; - showStats?: boolean; } const SongCard: React.FC = ({ @@ -18,15 +17,13 @@ const SongCard: React.FC = ({ plays, likes, comments, - showStats = true, }) => { return (
{title}
- +
@@ -34,21 +31,20 @@ const SongCard: React.FC = ({

{title}

{artist}
- {showStats && ( -
-
- {plays} -
-
- {likes} -
-
- {comments} -
+ +
+
+ {plays} +
+
+ {likes}
- )} +
+ {comments} +
+
); }; -export default SongCard; \ No newline at end of file +export default SongCard; diff --git a/client/src/components/SongPage/ArtistInfo/ArtistInfo.module.css b/client/src/components/SongPage/ArtistInfo/ArtistInfo.module.css new file mode 100644 index 0000000..49a235e --- /dev/null +++ b/client/src/components/SongPage/ArtistInfo/ArtistInfo.module.css @@ -0,0 +1,231 @@ +.artistInfoLayout { + display: flex; + flex-direction: column; + gap: var(--spacing-sm); + min-width: 0; + width: 100%; +} + +.artistInfoContainer { + display: flex; + align-items: flex-start; + gap: var(--spacing-md); + height: auto; + background: var(--color-panel-gray); + border-radius: var(--border-radius-md); + border: 2px solid var(--color-panel-border); + padding: var(--spacing-md); + min-width: 0; +} + +.artistInfoLeft { + display: flex; + flex-direction: column; + align-items: center; + gap: 1.2rem; + width: 11rem; +} + +.artistImage { + width: 11rem; + height: 11rem; + border-radius: 50%; + object-fit: cover; + aspect-ratio: 1 / 1; + flex-shrink: 0; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); +} + +.artistFollowButton { + font-family: "Inter", sans-serif; + display: flex; + align-items: center; + justify-content: center; + gap: var(--spacing-sm); + background: var(--color-red); + border-radius: var(--border-radius-sm); + border: none; + color: var(--color-red-200); + cursor: pointer; + font-size: var(--font-size-sm); + padding: var(--spacing-sm) var(--spacing-md); + transition: color var(--transition-speed) ease-in-out; +} + +.artistFollowButton:hover { + background-color: var(--color-red-700); +} + +.artistFollowButtonActive { + background-color: var(--color-red-700); +} + +.artistInfoRight { + display: flex; + flex-direction: column; + gap: var(--spacing-sm); + min-width: 0; + font-size: var(--font-size-sm); + padding: var(--spacing-sm) 0; +} + +.artistNameContainer { + min-width: 0; + display: flex; + gap: var(--spacing-sm); + align-items: center; +} + +.artistInfoName { + font-size: var(--font-size-lg); + color: var(--color-white); + font-weight: 500; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 100%; + transition: color var(--transition-speed) ease-in-out; + cursor: pointer; +} + +.artistInfoName:hover { + color: var(--color-red); +} + +.badgeWrapper { + position: relative; + display: flex; + align-items: center; +} + +.tooltip { + position: absolute; + bottom: calc(100% + var(--spacing-sm)); + left: 50%; + transform: translateX(-50%); + background: rgba(246, 246, 246, 0.8); + color: var(--color-black); + padding: 0.6rem 1.2rem; + border-radius: var(--border-radius-sm); + font-size: 13px; + font-weight: 500; + white-space: nowrap; + pointer-events: none; + z-index: 1000; + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3); + opacity: 0; + animation: tooltipFadeIn 0.15s ease-out forwards; +} + +.tooltip::after { + content: ""; + position: absolute; + top: 100%; + left: 50%; + transform: translateX(-50%); + border: 5px solid transparent; + border-top-color: rgba(246, 246, 246, 0.75); +} + +@keyframes tooltipFadeIn { + from { + opacity: 0; + transform: translateX(-50%) translateY(-4px); + } + to { + opacity: 1; + transform: translateX(-50%) translateY(0); + } +} + +.verifiedBadge { + font-size: var(--icon-size-sm); + flex-shrink: 0; + transition: color var(--transition-speed) ease-in-out; +} + +.verifiedBadge:hover { + color: var(--color-white-hover); +} + +.artistBio { + color: var(--color-text-gray); + font-size: var(--font-size-sm); + white-space: normal; + overflow-wrap: anywhere; + word-break: break-word; + overflow: hidden; + text-overflow: ellipsis; + hyphens: auto; + width: 100%; + max-width: 100%; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 6; + line-clamp: 6; + min-width: 0; + line-height: 1.2; +} + +.otherArtistsContainer { + display: flex; + flex-direction: column; + gap: var(--spacing-sm); + background: var(--color-panel-gray); + border-radius: var(--border-radius-md); + border: 2px solid var(--color-panel-border); + padding: var(--spacing-md); + min-width: 0; + width: 100%; + font-size: var(--font-size-sm); +} + +.otherArtistWrapper { + display: flex; + flex-direction: column; +} + +.otherArtistItem { + display: flex; + align-items: center; + gap: var(--spacing-sm); + min-width: 0; + width: 100%; +} + +.otherArtistIcon { + color: var(--color-text-gray); +} + +.otherArtistInfo { + display: grid; + grid-template-columns: 1fr 1fr; + width: 100%; + min-width: 0; + gap: var(--spacing-sm); +} + +.otherArtistName { + color: var(--color-white); + transition: color var(--transition-speed) ease-in-out; + cursor: pointer; + min-width: 0; + width: fit-content; +} + +.otherArtistName:hover { + color: var(--color-red); +} + +.otherArtistRole { + color: var(--color-text-gray); + min-width: 0; +} + +.otherArtistName, +.otherArtistRole { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 100%; +} diff --git a/client/src/components/SongPage/ArtistInfo/ArtistInfo.tsx b/client/src/components/SongPage/ArtistInfo/ArtistInfo.tsx new file mode 100644 index 0000000..84bcab5 --- /dev/null +++ b/client/src/components/SongPage/ArtistInfo/ArtistInfo.tsx @@ -0,0 +1,139 @@ +import { useState, Fragment, memo, useCallback, useMemo } from "react"; +import { Link, useNavigate } from "react-router-dom"; +import type { SongArtist } from "@types"; +import { useAuth } from "@contexts"; +import styles from "./ArtistInfo.module.css"; +import { HorizontalRule } from "@components"; +import classNames from "classnames"; +import userPlaceholder from "@assets/user-placeholder.png"; +import { + LuUserRoundCheck, + LuUserRoundPlus, + LuBadgeCheck, + LuUserRoundPen, +} from "react-icons/lu"; + +export interface ArtistInfoProps { + mainArtist: SongArtist | undefined; + otherArtists: SongArtist[]; +} + +const ArtistInfo: React.FC = ({ + mainArtist, + otherArtists, +}) => { + //! user + const { isAuthenticated } = useAuth(); + const navigate = useNavigate(); + + const [isFollowed, setIsFollowed] = useState(false); + const [isTooltipVisible, setIsTooltipVisible] = useState(false); + + const handleFollowArtist = useCallback(async () => { + try { + if (isAuthenticated) { + //! send request here + setIsFollowed((prev) => !prev); + } else { + navigate("/login"); + } + } catch (error) { + console.error("Toggling follow artist failed:", error); + } + }, [isAuthenticated, navigate]); + + const artistDisplayName = useMemo( + () => mainArtist?.display_name || mainArtist?.user?.username, + [mainArtist] + ); + + const artistImageUrl = useMemo( + () => mainArtist?.user?.profile_picture_url || userPlaceholder, + [mainArtist] + ); + + const OtherArtistItem = memo(({ artist }: { artist: SongArtist }) => ( +
+
+ )); + + if (!mainArtist) { + return null; + } + + return ( +
+
+
+ {`${artistDisplayName} + +
+
+
+ + {artistDisplayName} + + {mainArtist?.verified && ( +
setIsTooltipVisible(true)} + onMouseLeave={() => setIsTooltipVisible(false)} + > + + {isTooltipVisible && ( +
Verified by CoogMusic
+ )} +
+ )} +
+ +
+ {mainArtist?.bio || `${artistDisplayName} has no bio yet...`} +
+
+
+ + {otherArtists.length > 0 && ( +
+ {otherArtists.map((artist: SongArtist, i: number) => ( + + + {i < otherArtists.length - 1 && } + + ))} +
+ )} +
+ ); +}; + +export default memo(ArtistInfo); diff --git a/client/src/components/SongPage/CommentItem/CommentItem.module.css b/client/src/components/SongPage/CommentItem/CommentItem.module.css new file mode 100644 index 0000000..9faab9d --- /dev/null +++ b/client/src/components/SongPage/CommentItem/CommentItem.module.css @@ -0,0 +1,129 @@ +.comment { + display: flex; + gap: var(--spacing-sm); + align-items: center; + min-width: 0; + width: 100%; +} + +.commentListUserPfp { + width: 4rem; + height: 4rem; + border-radius: 50%; + object-fit: cover; + aspect-ratio: 1 / 1; + flex-shrink: 0; +} + +.commentContentWrapper { + display: flex; + align-items: flex-start; + justify-content: space-between; + min-width: 0; + width: 100%; +} + +.commentContent { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); + min-width: 0; + width: 100%; + padding-right: var(--spacing-md); +} + +.commentHeader { + display: flex; + align-items: center; + min-width: 0; + width: 100%; + gap: 0; +} + +.commentSeparator { + margin: 0 var(--spacing-xs); + color: var(--color-text-gray); + font-size: var(--font-size-sm); + flex-shrink: 0; +} + +.commentUsername { + font-size: var(--font-size-sm); + color: var(--color-white); + font-weight: 500; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 100%; + min-width: 0; + flex-shrink: 1; +} + +.commentTimestamp { + font-size: var(--font-size-sm); + color: var(--color-text-gray); + white-space: nowrap; + flex-shrink: 0; +} + +.commentText { + font-size: var(--font-size-sm); + color: var(--color-text-gray-light); + line-height: 1.2; +} + +.commentTag { + color: var(--color-red) !important; + font-weight: 600; + text-decoration: underline transparent !important; + transition: text-decoration var(--transition-speed) ease-in-out; +} + +.commentTag:hover { + text-decoration: underline var(--color-red) !important; +} + +.commentLikesContainer { + display: flex; + align-items: center; + justify-content: space-between; + background-color: none; + border-radius: var(--border-radius-md); + border: 1px solid var(--color-panel-border); + padding: var(--spacing-sm); + min-width: 6.4rem; +} + +.commentLikesContainerActive { + background-color: var(--color-panel-gray-dark); +} + +.commentLikeCount { + font-size: var(--font-size-sm); + color: var(--color-text-gray-light); + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + width: 100%; + max-width: 100%; +} + +.commentLikeButton { + display: flex; + align-items: center; + justify-content: center; + background: none; + color: var(--color-text-gray-light); + border: none; + font-size: var(--icon-size-sm); + transition: color var(--transition-speed) ease-in-out; + cursor: pointer; +} + +.commentLikeButton:hover { + color: var(--color-red); +} + +.commentLikeButtonActive { + color: var(--color-red); +} diff --git a/client/src/components/SongPage/CommentItem/CommentItem.tsx b/client/src/components/SongPage/CommentItem/CommentItem.tsx new file mode 100644 index 0000000..86f1edf --- /dev/null +++ b/client/src/components/SongPage/CommentItem/CommentItem.tsx @@ -0,0 +1,127 @@ +import { memo, useCallback, useMemo, useEffect } from "react"; +import { useNavigate, Link } from "react-router-dom"; +import { useState } from "react"; +import { useAuth } from "@contexts"; +import { formatRelativeDate } from "@util"; +import type { Comment } from "@types"; +import userPlaceholder from "@assets/user-placeholder.png"; +import styles from "./CommentItem.module.css"; +import classNames from "classnames"; +import { LuThumbsUp } from "react-icons/lu"; + +const CommentItem: React.FC<{ comment: Comment }> = ({ comment }) => { + const [isLiked, setIsLiked] = useState(comment.user_liked ?? false); + const [likeCount, setLikeCount] = useState(Number(comment.likes) || 0); + + const { isAuthenticated } = useAuth(); + const navigate = useNavigate(); + + //! send request here too + const toggleCommentLike = useCallback(() => { + if (!isAuthenticated) { + navigate("/login"); + return; + } + + if (isLiked) { + setLikeCount((prev) => prev - 1); + setIsLiked(false); + } else { + setLikeCount((prev) => prev + 1); + setIsLiked(true); + } + }, [isAuthenticated, navigate, isLiked]); + + useEffect(() => { + setIsLiked(comment.user_liked ?? false); + setLikeCount(Number(comment.likes) || 0); + }, [comment.id, comment.user_liked, comment.likes]); + + const { comment_text, tags } = comment; + + const segments = useMemo(() => { + const result: React.ReactNode[] = []; + let lastIndex = 0; + + if (tags && tags.length > 0) { + const sortedTags = [...tags].sort((a, b) => a.start - b.start); + + for (const tag of sortedTags) { + if (tag.start > lastIndex) { + result.push(comment_text.slice(lastIndex, tag.start)); + } + + result.push( + + {comment_text.slice(tag.start, tag.end)} + + ); + + lastIndex = tag.end; + } + } + + if (lastIndex < comment_text.length) { + result.push( + + {comment_text.slice(lastIndex)} + + ); + } + + return result; + }, [comment_text, tags]); + + const profilePicUrl = useMemo( + () => comment.profile_picture_url || userPlaceholder, + [comment.profile_picture_url] + ); + + const formattedDate = useMemo( + () => formatRelativeDate(comment.commented_at), + [comment.commented_at] + ); + + return ( +
+ {comment.username} +
+
+
+ {comment.username} + + {formattedDate} +
+ {segments} +
+
+ {likeCount} + +
+
+
+ ); +}; + +export default memo(CommentItem); diff --git a/client/src/components/SongPage/SongActions/SongActions.module.css b/client/src/components/SongPage/SongActions/SongActions.module.css new file mode 100644 index 0000000..064f2f2 --- /dev/null +++ b/client/src/components/SongPage/SongActions/SongActions.module.css @@ -0,0 +1,32 @@ +.songActionsContainer { + flex: 0; + display: flex; + align-items: center; + justify-content: space-between; +} + +.actionButton { + display: flex; + align-items: center; + justify-content: center; + background: var(--color-panel-gray); + border-radius: var(--border-radius-sm); + border: 2px solid var(--color-panel-border); + color: var(--color-white); + cursor: pointer; + font-size: var(--icon-size-md); + padding: var(--spacing-md) 2.1rem; + transition: color var(--transition-speed) ease-in-out; +} + +.actionButton:hover { + color: var(--color-red); +} + +.actionButtonActive { + color: var(--color-red); +} + +.queueButtonContainer { + position: relative; +} diff --git a/client/src/components/SongPage/SongActions/SongActions.tsx b/client/src/components/SongPage/SongActions/SongActions.tsx new file mode 100644 index 0000000..32cee1a --- /dev/null +++ b/client/src/components/SongPage/SongActions/SongActions.tsx @@ -0,0 +1,141 @@ +import React, { memo, useEffect, useState, useRef } from "react"; +import { useNavigate } from "react-router-dom"; +import type { Song } from "@types"; +import { useLikeStatus } from "@hooks"; +import { useAuth } from "@contexts"; +import { ShareModal, QueueMenu } from "@components"; +import { useQueryClient } from "@tanstack/react-query"; +import styles from "./SongActions.module.css"; +import classNames from "classnames"; +import { + LuThumbsUp, + LuListPlus, + LuListEnd, + LuShare, + LuCircleAlert, +} from "react-icons/lu"; + +export interface SongActionsProps { + song: Song; + songUrl?: string; +} + +const SongActions: React.FC = ({ song, songUrl }) => { + const { user, isAuthenticated } = useAuth(); + const queryClient = useQueryClient(); + const navigate = useNavigate(); + const { + isLiked, + toggleLike, + isLoading: isLikeLoading, + } = useLikeStatus({ + userId: user?.id || "", + entityId: song.id, + entityType: "song", + isAuthenticated, + }); + + const [isShareModalOpen, setIsShareModalOpen] = useState(false); + const [queueMenuOpen, setQueueMenuOpen] = useState(false); + + const queueButtonRef = useRef(null); + + useEffect(() => { + if (user?.id && song?.id) { + queryClient.invalidateQueries({ + queryKey: ["likeStatus", user.id, song.id, "song"], + }); + } + }, [user?.id, song?.id]); + + const handleToggleSongLike = async () => { + try { + if (!isAuthenticated) return navigate("/login"); + await toggleLike(); + } catch (error) { + console.error("Toggling song like failed:", error); + } + }; + + const handleAddToPlaylist = async () => { + try { + if (isAuthenticated) { + //! send request here + console.log("added to playlist: " + song.id); + } else { + navigate("/login"); + } + } catch (error) { + console.error("Adding to playlist failed:", error); + } + }; + + const handleAddToQueue = async () => { + try { + if (isAuthenticated) { + setQueueMenuOpen((prev) => !prev); + } else { + navigate("/login"); + } + } catch (error) { + console.error("Adding to queue failed:", error); + } + }; + + const handleShare = () => { + setIsShareModalOpen(true); + }; + + const handleReport = () => { + //! open report modal... + }; + + return ( + <> +
+ + +
+ + setQueueMenuOpen(false)} + song={song} + buttonRef={queueButtonRef} + /> +
+ + +
+ + setIsShareModalOpen(false)} + pageUrl={songUrl} + pageTitle={song.title} + /> + + ); +}; + +export default memo(SongActions); diff --git a/client/src/components/SongPage/SongComments/SongComments.module.css b/client/src/components/SongPage/SongComments/SongComments.module.css new file mode 100644 index 0000000..0bbe81a --- /dev/null +++ b/client/src/components/SongPage/SongComments/SongComments.module.css @@ -0,0 +1,103 @@ +.commentsContainer { + flex: 1; + display: flex; + flex-direction: column; + gap: var(--spacing-md); + min-width: 0; + width: 100%; +} + +.error { + text-align: center; + color: var(--color-text-gray); + font-size: var(--font-size-sm); +} + +.noComments { + text-align: center; + color: var(--color-text-gray); + font-size: var(--font-size-sm); +} + +.commentsContainerTop { + display: flex; + gap: var(--spacing-md); + align-items: center; +} + +.commentUserPfp { + width: 4.8rem; + height: 4.8rem; + border-radius: 50%; + object-fit: cover; + aspect-ratio: 1 / 1; + flex-shrink: 0; +} + +.commentInputContainer { + background-color: var(--color-panel-gray); + border-radius: var(--border-radius-sm); + border: 2px solid var(--color-panel-border); + flex: 1; + position: relative; + display: flex; + align-items: center; +} + +.commentInput { + font-family: "Inter", sans-serif; + width: 96%; + padding: var(--spacing-md); + background-color: transparent; + border: none; + border-radius: var(--border-radius-lg); + color: var(--color-white); + font-size: var(--font-size-sm); + outline: none; +} + +.commentInput::placeholder { + color: var(--color-text-gray); +} + +.commentButton { + position: absolute; + right: var(--spacing-sm); + font-size: var(--icon-size-md); + color: var(--color-text-gray); + display: flex; + align-items: center; + justify-content: center; + background: var(--color-red); + border-radius: var(--border-radius-sm); + border: none; + color: var(--color-red-200); + cursor: pointer; + padding: var(--spacing-sm); + transition: color var(--transition-speed) ease-in-out; +} + +.commentButton:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.commentButton:not(:disabled):hover { + color: var(--color-red-950) !important; +} + +.commentLoaderContainer { + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + min-height: 15vh; +} + +.commentsList { + display: flex; + flex-direction: column; + gap: var(--spacing-lg); + min-width: 0; + width: 100%; +} diff --git a/client/src/components/SongPage/SongComments/SongComments.tsx b/client/src/components/SongPage/SongComments/SongComments.tsx new file mode 100644 index 0000000..bc14a77 --- /dev/null +++ b/client/src/components/SongPage/SongComments/SongComments.tsx @@ -0,0 +1,142 @@ +import { memo, useCallback, useMemo, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { useAsyncData } from "@hooks"; +import { useAuth } from "@contexts"; +import { PuffLoader } from "react-spinners"; +import { commentApi } from "@api"; +import { CommentItem, HorizontalRule } from "@components"; +import styles from "./SongComments.module.css"; +import userPlaceholder from "@assets/user-placeholder.png"; +import { LuSend } from "react-icons/lu"; + +export interface SongCommentsProps { + songId: string; +} + +const SongComments: React.FC = ({ songId }) => { + const { user, isAuthenticated } = useAuth(); + const navigate = useNavigate(); + + const [commentText, setCommentText] = useState(""); + const [isSubmitting, setIsSubmitting] = useState(false); + + const { data, loading, error } = useAsyncData( + { + comments: () => + commentApi.getCommentsBySongId(songId, { + includeLikes: true, + currentUserId: isAuthenticated && user ? user.id : undefined, + limit: 25, + }), + }, + [songId], + { cacheKey: `comments_${songId}`, hasBlobUrl: true } + ); + + const comments = data?.comments; + + const handleCommentChange = useCallback( + (e: React.ChangeEvent) => { + setCommentText(e.target.value); + }, + [] + ); + + const handleAddComment = useCallback(() => { + if (!commentText.trim()) return; + + try { + if (isAuthenticated) { + setIsSubmitting(true); + //! send request with commentText + console.log("added comment to song: " + songId, commentText); + setCommentText(""); + } else { + navigate("/login"); + } + } catch (error) { + console.error("Adding comment failed:", error); + } finally { + setIsSubmitting(false); + } + }, [isAuthenticated, navigate, songId, commentText, isSubmitting]); + + const handleKeyPress = useCallback( + (e: React.KeyboardEvent) => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + handleAddComment(); + } + }, + [handleAddComment] + ); + + const userProfilePic = useMemo( + () => user?.profile_picture_url || userPlaceholder, + [user] + ); + + if (error) { + return
Failed to load comments.
; + } + + return ( +
+
+ {user?.username + +
+ + +
+
+ {loading ? ( +
+ +
+ ) : ( + comments && + comments.length > 0 && ( + <> + +
+ {comments.map((comment: any) => ( + + ))} +
+ + ) + )} + {!loading && comments && comments.length === 0 && ( +
+ No comments yet. Be the first to comment! +
+ )} +
+ ); +}; + +export default memo(SongComments); diff --git a/client/src/components/SongPage/SongContainer/SongContainer.module.css b/client/src/components/SongPage/SongContainer/SongContainer.module.css new file mode 100644 index 0000000..4f5443a --- /dev/null +++ b/client/src/components/SongPage/SongContainer/SongContainer.module.css @@ -0,0 +1,105 @@ +.songContainer { + position: relative; + display: flex; + gap: var(--spacing-lg); + flex: 1; + padding: var(--spacing-lg); + background: linear-gradient(to bottom, #181818, #0f0f0f); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); + border-radius: var(--border-radius-sm); + overflow: hidden; +} + +.songContainer::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: linear-gradient( + 65deg, + var(--cover-gradient-color1) 0%, + var(--cover-gradient-color2) 15%, + transparent 35% + ); + pointer-events: none; + border-radius: var(--border-radius-sm); +} + +.coverImage { + width: 24rem; + height: 24rem; + border-radius: var(--border-radius-sm); + object-fit: cover; + aspect-ratio: 1 / 1; + flex-shrink: 0; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); + transition: box-shadow var(--transition-speed) ease; +} + +.coverImageClickable { + cursor: pointer; +} + +.coverImage:hover { + box-shadow: 0 0 15px rgba(0, 0, 0, 0.6); +} + +.songRight { + display: flex; + flex-direction: column; + justify-content: space-between; + padding: var(--spacing-sm) 0; + gap: var(--spacing-md); + flex: 1; +} + +.songInfoContainer { + display: flex; + flex-direction: column; + min-width: 0; +} + +.artistName { + font-size: 2.4rem; + color: var(--color-text-gray-light); + font-weight: 500; +} + +.songTitle { + font-size: 4.2rem; + color: var(--color-white); + font-weight: 700; +} + +.songTitle, +.artistName { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + width: 100%; + max-width: 100%; +} + +.interactionsContainer { + padding-top: 1rem; + display: flex; + align-items: center; + gap: var(--spacing-lg); + color: var(--color-text-gray) !important; +} + +.interactionStat { + display: flex; + align-items: center; + gap: var(--spacing-sm); + font-size: var(--font-size-md); +} + +.interactionText { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 100%; +} diff --git a/client/src/components/SongPage/SongContainer/SongContainer.tsx b/client/src/components/SongPage/SongContainer/SongContainer.tsx new file mode 100644 index 0000000..2eee9c7 --- /dev/null +++ b/client/src/components/SongPage/SongContainer/SongContainer.tsx @@ -0,0 +1,101 @@ +import { useMemo, useCallback, memo, useState } from "react"; +import { useStreamTracking } from "@hooks"; +import { WaveformPlayer, CoverLightbox } from "@components"; +import type { Song, CoverGradient, SongArtist } from "@types"; +import { useAudioQueue } from "@contexts"; +import { LuPlay, LuThumbsUp, LuMessageSquareText } from "react-icons/lu"; +import styles from "./SongContainer.module.css"; +import classNames from "classnames"; +import musicPlaceholder from "@assets/music-placeholder.png"; + +export interface SongContainerProps { + coverGradient: CoverGradient; + song: Song; + mainArtist: SongArtist | undefined; + numberComments?: number; +} + +const SongContainer: React.FC = ({ + coverGradient, + song, + mainArtist, + numberComments, +}) => { + const { actions } = useAudioQueue(); + const [isLightboxOpen, setIsLightboxOpen] = useState(false); + useStreamTracking(); + + const gradientStyle = useMemo( + () => + ({ + "--cover-gradient-color1": `rgba(${coverGradient.color1.r}, ${coverGradient.color1.g}, ${coverGradient.color1.b}, 0.2)`, + "--cover-gradient-color2": `rgba(${coverGradient.color2.r}, ${coverGradient.color2.g}, ${coverGradient.color2.b}, 0.2)`, + } as React.CSSProperties), + [coverGradient] + ); + + const InteractionStat = memo( + ({ icon: Icon, value }: { icon: React.ElementType; value: number }) => ( +
+ + {value} +
+ ) + ); + + const handlePlay = useCallback(() => { + actions.play(song); + }, [actions, song]); + + const handleImageClick = useCallback(() => { + setIsLightboxOpen(true); + }, []); + + return ( +
+ {`${song.title} +
+
+ {mainArtist?.display_name} + {song.title} +
+
+ + + +
+
+
+ {song.audio_url && ( + + )} +
+ + {song.image_url && ( + setIsLightboxOpen(false)} + imageUrl={song.image_url} + altText={`${song.title} Cover`} + /> + )} +
+ ); +}; + +export default SongContainer; diff --git a/client/src/components/SongPage/SongDetails/SongDetails.module.css b/client/src/components/SongPage/SongDetails/SongDetails.module.css new file mode 100644 index 0000000..ffb3032 --- /dev/null +++ b/client/src/components/SongPage/SongDetails/SongDetails.module.css @@ -0,0 +1,57 @@ +.detailsContainer { + background-color: var(--color-panel-gray); + border-radius: var(--border-radius-sm); + border: 2px solid var(--color-panel-border); + color: var(--color-white); + padding: var(--spacing-md); + display: grid; + grid-template-columns: 1fr 2rem 1fr; + column-gap: 0.4rem; + align-items: center; + flex: 1; +} + +.detailsColumn { + display: flex; + flex-direction: column; + gap: var(--spacing-sm); + align-items: flex-start; + min-width: 0; + width: 100%; +} + +.detailLabel { + color: var(--color-text-gray); +} + +.detailWrapper { + display: flex; + gap: var(--spacing-sm); + align-items: center; + min-width: 0; + width: 100%; +} + +.detailIcon { + font-size: var(--font-size-lg); + min-width: var(--font-size-lg); + color: var(--color-text-gray); +} + +.detailName { + font-size: var(--font-size-lg); + font-weight: 600; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 100%; +} + +.genreName { + transition: color var(--transition-speed) ease-in-out; + cursor: pointer; +} + +.genreName:hover { + color: var(--color-red); +} diff --git a/client/src/components/SongPage/SongDetails/SongDetails.tsx b/client/src/components/SongPage/SongDetails/SongDetails.tsx new file mode 100644 index 0000000..896cc55 --- /dev/null +++ b/client/src/components/SongPage/SongDetails/SongDetails.tsx @@ -0,0 +1,45 @@ +import { memo, useMemo } from "react"; +import { formatDateString } from "@util"; +import { VerticalRule } from "@components"; +import styles from "./SongDetails.module.css"; +import classNames from "classnames"; +import { LuMusic, LuCalendar } from "react-icons/lu"; + +export interface SongDetailsProps { + genre: string; + releaseDate: string; +} + +const SongDetails: React.FC = ({ genre, releaseDate }) => { + const formattedDate = useMemo( + () => formatDateString(releaseDate), + [releaseDate] + ); + + return ( +
+
+ Genre +
+ + {/* eventually this should link somewhere... */} + + {genre || "Unknown"} + +
+
+ +
+ Release Date +
+ + + {formattedDate || "Unknown"} + +
+
+
+ ); +}; + +export default memo(SongDetails); diff --git a/client/src/components/SongPage/SongStats/SongStats.module.css b/client/src/components/SongPage/SongStats/SongStats.module.css new file mode 100644 index 0000000..c2ba10f --- /dev/null +++ b/client/src/components/SongPage/SongStats/SongStats.module.css @@ -0,0 +1,32 @@ +.songStatsContainer { + padding: var(--spacing-sm); + background-color: var(--color-panel-gray); + border-radius: var(--border-radius-sm); + border: 2px solid var(--color-panel-border); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: var(--spacing-sm); +} + +.statsText { + color: var(--color-text-gray); + font-weight: 500; +} + +.noDataMessage { + color: var(--color-text-gray); + font-size: var(--font-size-sm); + display: flex; + align-items: center; + justify-content: center; + height: 8.33rem; +} + +.loaderContainer { + display: flex; + align-items: center; + justify-content: center; + height: 8.33rem; +} diff --git a/client/src/components/SongPage/SongStats/SongStats.tsx b/client/src/components/SongPage/SongStats/SongStats.tsx new file mode 100644 index 0000000..3a5f202 --- /dev/null +++ b/client/src/components/SongPage/SongStats/SongStats.tsx @@ -0,0 +1,114 @@ +import { useMemo, memo, useCallback } from "react"; +import { useAsyncData } from "@hooks"; +import { songApi } from "@api"; +import { PuffLoader } from "react-spinners"; +import { SparkLineChart } from "@mui/x-charts/SparkLineChart"; +import type { SparkLineChartProps } from "@mui/x-charts/SparkLineChart"; +import { + areaElementClasses, + lineElementClasses, +} from "@mui/x-charts/LineChart"; +import { chartsAxisHighlightClasses } from "@mui/x-charts/ChartsAxisHighlight"; +import styles from "./SongStats.module.css"; + +const CHART_HEIGHT = 80; +const CHART_WIDTH = 330; +const CHART_COLOR = "rgb(213, 49, 49)"; + +const CHART_SX = { + [`& .${areaElementClasses.root}`]: { opacity: 0.2 }, + [`& .${lineElementClasses.root}`]: { strokeWidth: 3 }, + [`& .${chartsAxisHighlightClasses.root}`]: { + stroke: CHART_COLOR, + strokeDasharray: "none", + strokeWidth: 2, + }, +}; + +const CHART_SLOT_PROPS = { + lineHighlight: { r: 4 }, +}; + +const CLIP_AREA_OFFSET = { top: 2, bottom: 2 }; + +export interface SongStatsProps { + songId: string; +} + +const SongStats: React.FC = ({ songId }) => { + const { data, loading, error } = useAsyncData( + { + weeklyPlays: () => songApi.getWeeklyPlays(songId), + }, + [songId], + { cacheKey: `weekly_plays_${songId}` } + ); + + const playsData = data?.weeklyPlays || { weeks: [], plays: [] }; + const plays = playsData.plays ?? []; + const weeks = playsData.weeks ?? []; + + const domainLimit = useCallback( + (_: any, maxValue: number) => ({ + min: -maxValue / 6, + max: maxValue, + }), + [] + ); + + const sparkLineSettings = useMemo( + () => ({ + data: plays, + baseline: "min", + xAxis: { id: "week-axis", data: weeks }, + yAxis: { + domainLimit: domainLimit, + }, + sx: CHART_SX, + slotProps: CHART_SLOT_PROPS, + clipAreaOffset: CLIP_AREA_OFFSET, + axisHighlight: { x: "line" }, + }), + [plays, weeks] + ); + + if ( + !playsData || + !plays.length || + !weeks.length || + plays.length == 1 || + weeks.length == 1 || + error + ) { + return ( +
+ Weekly Plays +
No play data available
+
+ ); + } + + return ( +
+ Weekly Plays + {loading ? ( +
+ +
+ ) : ( + + )} +
+ ); +}; + +export default memo(SongStats); diff --git a/client/src/components/SongPage/SongSuggestions/SongSuggestions.module.css b/client/src/components/SongPage/SongSuggestions/SongSuggestions.module.css new file mode 100644 index 0000000..84901bd --- /dev/null +++ b/client/src/components/SongPage/SongSuggestions/SongSuggestions.module.css @@ -0,0 +1,39 @@ +.error { + text-align: center; + color: var(--color-text-gray); + font-size: var(--font-size-sm); +} + +.loaderContainer { + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + min-height: 25vh; +} + +.suggestionsContainer { + display: flex; + flex-direction: column; + gap: var(--spacing-lg); +} + +.suggestionsWrapper { + display: flex; + flex-direction: column; + gap: var(--spacing-md); + min-width: 0; + width: 100%; +} + +.suggestionLabel { + font-size: var(--font-size-md); +} + +.suggestionsSection { + width: 100%; + display: flex; + flex-direction: column; + gap: var(--spacing-md); + min-width: 0; +} diff --git a/client/src/components/SongPage/SongSuggestions/SongSuggestions.tsx b/client/src/components/SongPage/SongSuggestions/SongSuggestions.tsx new file mode 100644 index 0000000..aea40d5 --- /dev/null +++ b/client/src/components/SongPage/SongSuggestions/SongSuggestions.tsx @@ -0,0 +1,133 @@ +import { useMemo, memo } from "react"; +import { useAsyncData } from "@hooks"; +import { PuffLoader } from "react-spinners"; +import { useAuth } from "@contexts"; +import { songApi, artistApi } from "@api"; +import { formatDateString } from "@util"; +import { EntityItem } from "@components"; +import type { Song, Album, Artist, ArtistSong, SuggestedSong } from "@types"; +import styles from "./SongSuggestions.module.css"; + +export interface SongSuggestionsProps { + song: Song; + mainArtist?: Artist; +} + +const SongSuggestions: React.FC = ({ + song, + mainArtist, +}) => { + const songId = song.id; + const { user, isAuthenticated } = useAuth(); + + const asyncConfig = useMemo( + () => ({ + ...(mainArtist && { + moreSongsByArtist: async () => + artistApi.getSongs(mainArtist.id, { + includeArtists: true, + limit: 5, + }), + }), + suggestedSongs: () => + songApi.getSuggestedSongs(songId, { + userId: isAuthenticated && user ? user.id : undefined, + includeArtists: true, + limit: 5, + }), + }), + [songId, mainArtist, isAuthenticated, user] + ); + + const { data, loading, error } = useAsyncData( + asyncConfig, + [songId, mainArtist], + { cacheKey: `suggestions_song_${songId}`, hasBlobUrl: true } + ); + + if (error) { + return
Failed to load suggestions.
; + } + + const moreSongsByArtist = data?.moreSongsByArtist; + const filteredMoreSongs = useMemo( + () => + moreSongsByArtist?.filter( + (songItem: ArtistSong) => songItem.id !== songId + ) ?? [], + [moreSongsByArtist, songId] + ); + const suggestedSongs = data?.suggestedSongs; + + return loading ? ( +
+ +
+ ) : ( +
+ {song.albums && song.albums.length > 0 && ( +
+ On Albums +
+ {song.albums.map((album: Album) => ( + + ))} +
+
+ )} + + {filteredMoreSongs && filteredMoreSongs.length > 0 && ( +
+ + More by {mainArtist?.display_name} + +
+ {filteredMoreSongs.map((songItem: ArtistSong) => ( + + ))} +
+
+ )} + + {suggestedSongs && suggestedSongs.length > 0 && ( +
+ Related Songs +
+ {suggestedSongs.map((songItem: SuggestedSong) => ( + + ))} +
+
+ )} +
+ ); +}; + +export default memo(SongSuggestions); diff --git a/client/src/components/SongPage/WaveformPlayer/WaveformPlayer.module.css b/client/src/components/SongPage/WaveformPlayer/WaveformPlayer.module.css new file mode 100644 index 0000000..5484f0f --- /dev/null +++ b/client/src/components/SongPage/WaveformPlayer/WaveformPlayer.module.css @@ -0,0 +1,102 @@ +.playerContainer { + display: flex; + gap: var(--spacing-md); + flex: 1; + align-items: center; +} + +.playerPlayBtn { + display: flex; + align-items: center; + justify-content: center; + background: none; + border: none; + color: var(--color-white); + cursor: pointer; + font-size: var(--icon-size-md); + transition: color var(--transition-speed) ease-in-out; + font-size: 6.4rem; +} + +.playerPlayBtn:hover { + color: var(--color-red); +} + +.playerPlayBtn:disabled { + cursor: not-allowed; + opacity: 0.5; +} + +.playerPlayBtnActive { + color: var(--color-red); +} + +.playerPlayBtn svg { + padding: 0; +} + +.skeletonContainer { + position: relative; +} + +.waveWrapper { + display: grid; + grid-template-rows: 1fr; + grid-template-columns: 1fr; + position: relative; + width: 100%; + min-width: 0; + height: 80px; /* WAVEFORM_HEIGHT */ + box-sizing: border-box; +} + +.playerWaveform { + grid-row: 1 / 2; + grid-column: 1 / 2; + width: 100%; + height: 100%; + min-width: 0; + overflow: hidden; +} + +.hiddenWaveform { + opacity: 0; + pointer-events: none; +} + +.skeletonWaveform { + grid-row: 1 / 2; + grid-column: 1 / 2; + display: flex; + align-items: center; + gap: 5px; /* BAR_GAP */ + padding: 0 4px; + height: 100%; + box-sizing: border-box; + pointer-events: none; + z-index: 2; + animation: pulse 1.5s ease-in-out infinite; +} + +.skeletonBar { + flex: 0 0 auto; + border-radius: 6px; + background: var(--color-white); + opacity: 0.8; + box-sizing: border-box; +} + +.playerWaveform, +.skeletonWaveform { + overflow: hidden; +} + +@keyframes pulse { + 0%, + 100% { + opacity: 0.8; + } + 50% { + opacity: 0.2; + } +} diff --git a/client/src/components/SongPage/WaveformPlayer/WaveformPlayer.tsx b/client/src/components/SongPage/WaveformPlayer/WaveformPlayer.tsx new file mode 100644 index 0000000..2257558 --- /dev/null +++ b/client/src/components/SongPage/WaveformPlayer/WaveformPlayer.tsx @@ -0,0 +1,281 @@ +import { useState, useRef, useEffect, useCallback, memo, useMemo } from "react"; +import Hover from "wavesurfer.js/dist/plugins/hover.esm.js"; +import WaveSurfer from "wavesurfer.js"; +import { useElementWidth } from "@hooks"; +import { useAudioQueue } from "@contexts"; +import classNames from "classnames"; +import styles from "./WaveformPlayer.module.css"; +import { LuCirclePause, LuCirclePlay } from "react-icons/lu"; + +const BAR_WIDTH = 3; +const BAR_GAP = 5; +const WAVEFORM_HEIGHT = 80; +const BAR_RADIUS = 6; +const LINE_WIDTH = 2; +const SKELETON_PADDING = 8; + +export interface WaveformPlayerProps { + audioSrc: string; + captureKeyboard?: boolean; + onPlay?: () => void; + disabled?: boolean; +} + +const WaveformPlayer: React.FC = ({ + audioSrc, + captureKeyboard, + onPlay, + disabled, +}) => { + const [isReady, setIsReady] = useState(false); + const [showSkeleton, setShowSkeleton] = useState(true); + + const { state, actions } = useAudioQueue(); + const { isPlaying, progress, duration, currentSong, error } = state; + + const waveformRef = useRef(null); + const wavesurferRef = useRef(null); + const measureRef = useRef(null); + const skeletonBarsRef = useRef([]); + const prevCurrentSongRef = useRef(null); + + const isCurrentSong = currentSong?.audio_url === audioSrc; + + const rawWidth = useElementWidth(measureRef); + const wrapperWidth = useMemo( + () => Math.floor(rawWidth / 10) * 10, + [rawWidth] + ); + + const barSlot = BAR_WIDTH + BAR_GAP; + const skeletonCount = Math.max( + 1, + Math.floor((wrapperWidth - SKELETON_PADDING) / barSlot) + ); + + if (skeletonBarsRef.current.length !== skeletonCount) { + skeletonBarsRef.current = new Array(skeletonCount) + .fill(0) + .map(() => 20 + Math.floor(Math.random() * 80)); + } + + const skeletonBars = skeletonBarsRef.current; + + const togglePlay = useCallback(() => { + if (isCurrentSong) { + if (isPlaying) { + actions.pause(); + } else { + actions.resume(); + } + } else { + onPlay?.(); + } + }, [isCurrentSong, isPlaying, actions, onPlay]); + + const handleReady = useCallback(() => { + setIsReady(true); + setTimeout(() => setShowSkeleton(false), 100); + }, []); + + const handleWaveformClick = useCallback( + (relativeX: number) => { + const ws = wavesurferRef.current; + if (!ws) return; + + if (state.currentSong?.audio_url !== audioSrc) return; + + if (state.duration > 0) { + const seekTime = relativeX * state.duration; + actions.seek(seekTime); + } + }, + [audioSrc, actions] + ); + + const handleError = useCallback((error: any) => { + console.error("WaveSurfer error:", error); + setIsReady(false); + }, []); + + useEffect(() => { + if (!captureKeyboard || !isCurrentSong) return; + + const handleKeyPress = (e: KeyboardEvent) => { + if ( + e.code === "Space" && + e.target instanceof HTMLElement && + !["INPUT", "TEXTAREA"].includes(e.target.tagName) + ) { + e.preventDefault(); + e.stopPropagation(); + togglePlay(); + } + }; + + window.addEventListener("keydown", handleKeyPress, { capture: true }); + return () => + window.removeEventListener("keydown", handleKeyPress, { + capture: true, + }); + }, [captureKeyboard, togglePlay, isCurrentSong]); + + useEffect(() => { + setShowSkeleton(true); + setIsReady(false); + }, [audioSrc]); + + const hoverPlugin = useMemo( + () => + Hover.create({ + lineColor: "#B22323", + lineWidth: LINE_WIDTH, + labelBackground: "#B22323", + labelColor: "#F6F6F6", + labelSize: "11px", + }), + [] + ); + + useEffect(() => { + if (!waveformRef.current || !audioSrc) return; + + const loadAudioWithCORSBypass = async () => { + try { + const ws = WaveSurfer.create({ + container: waveformRef.current!, + height: WAVEFORM_HEIGHT, + waveColor: "#F6F6F6", + progressColor: "#d53131", + barWidth: BAR_WIDTH, + barRadius: BAR_RADIUS, + barGap: BAR_GAP, + normalize: true, + backend: "MediaElement" as const, + sampleRate: 44100, + autoplay: false, + plugins: [hoverPlugin], + }); + + ws.on("ready", handleReady); + ws.on("error", handleError); + wavesurferRef.current = ws; + + const urlParts = audioSrc.split("/"); + const filename = urlParts[urlParts.length - 1].split("?")[0]; + + const proxyUrl = `/api/proxy/audio/${filename}`; + const response = await fetch(proxyUrl); + if (!response.ok) { + throw new Error(`Failed to fetch audio: ${response.status}`); + } + + const arrayBuffer = await response.arrayBuffer(); + + const audioContext = new (window.AudioContext || + (window as any).webkitAudioContext)(); + const decodedData = await audioContext.decodeAudioData(arrayBuffer); + + const channelsNumber = decodedData.numberOfChannels; + const peaks = + channelsNumber > 1 + ? [decodedData.getChannelData(0), decodedData.getChannelData(1)] + : [decodedData.getChannelData(0)]; + const duration = decodedData.duration; + + ws.load(proxyUrl, peaks, duration); + } catch (error) { + console.error("Failed to load audio:", error); + handleError(error); + } + }; + + loadAudioWithCORSBypass(); + + return () => { + if (wavesurferRef.current) { + wavesurferRef.current.un("ready", handleReady); + wavesurferRef.current.un("error", handleError); + wavesurferRef.current.destroy(); + } + }; + }, [audioSrc, handleReady, handleError, hoverPlugin]); + + useEffect(() => { + const ws = wavesurferRef.current; + if (!ws) return; + + ws.on("click", handleWaveformClick); + return () => { + ws.un("click", handleWaveformClick); + }; + }, [handleWaveformClick]); + + useEffect(() => { + if (!wavesurferRef.current) return; + + const currentAudioUrl = currentSong?.audio_url || null; + const prevAudioUrl = prevCurrentSongRef.current; + + if (currentAudioUrl !== prevAudioUrl) { + prevCurrentSongRef.current = currentAudioUrl; + + if (currentAudioUrl === audioSrc) { + return; + } else { + wavesurferRef.current.seekTo(0); + return; + } + } + + if (isCurrentSong && duration > 0 && progress > 1) { + const progressPercent = progress / duration; + wavesurferRef.current.seekTo(progressPercent); + } + }, [currentSong?.audio_url, audioSrc, isCurrentSong, progress, duration]); + + return ( +
+ + +
+ {showSkeleton && ( + + ); +}; + +export default memo(WaveformPlayer); diff --git a/client/src/components/SongsList/SongsList.module.css b/client/src/components/SongsList/SongsList.module.css new file mode 100644 index 0000000..eb04fcf --- /dev/null +++ b/client/src/components/SongsList/SongsList.module.css @@ -0,0 +1,55 @@ +.loaderContainer { + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + min-height: 15vh; +} + +.error { + text-align: center; + color: var(--color-text-gray); + font-size: var(--font-size-sm); +} + +.songsContainer { + display: flex; + flex-direction: column; + gap: var(--spacing-md); + min-width: 0; + width: 100%; +} + +.sectionHeader { + display: flex; + align-items: flex-end; + justify-content: space-between; +} + +.viewMoreLink { + font-size: var(--font-size-sm); + color: var(--color-text-gray) !important; + text-decoration: none; +} + +.viewMoreLink:hover { + color: var(--color-white) !important; +} + +.sectionTitle { + font-size: var(--font-size-lg); + color: var(--color-white); + font-weight: 500; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 100%; +} + +.songsList { + width: 100%; + display: flex; + flex-direction: column; + gap: var(--spacing-md); + min-width: 0; +} diff --git a/client/src/components/SongsList/SongsList.tsx b/client/src/components/SongsList/SongsList.tsx new file mode 100644 index 0000000..fc247b0 --- /dev/null +++ b/client/src/components/SongsList/SongsList.tsx @@ -0,0 +1,90 @@ +import { memo, useMemo } from "react"; +import { PuffLoader } from "react-spinners"; +import type { Song } from "@types"; +import { useAsyncData } from "@hooks"; +import { EntityItem } from "@components"; +import { getMainArtist } from "@util"; +import styles from "./SongsList.module.css"; +import { Link } from "react-router-dom"; + +export interface SongsListProps { + title: string; + fetchData: () => Promise; + cacheKey: string; + dependencies?: any[]; + viewMoreLink?: string; +} + +const SongsList: React.FC = ({ + title, + fetchData, + cacheKey, + dependencies = [], + viewMoreLink, +}) => { + const asyncConfig = useMemo( + () => ({ + songs: fetchData, + }), + [fetchData] + ); + + const { data, loading, error } = useAsyncData(asyncConfig, dependencies, { + cacheKey, + hasBlobUrl: true, + }); + + if (loading) { + return ( +
+ +
+ ); + } + + if (error) { + return ( +
Failed to load {title.toLowerCase()}.
+ ); + } + + const songs = data?.songs; + + if (!songs || songs.length === 0) { + return null; + } + + return ( +
+ {viewMoreLink ? ( +
+

{title}

+ + View More + +
+ ) : ( +

{title}

+ )} + +
+ {songs.map((song, i) => ( + + ))} +
+
+ ); +}; + +export default memo(SongsList); diff --git a/client/src/components/TopBar/topBar.module.css b/client/src/components/TopBar/topBar.module.css deleted file mode 100644 index ead8427..0000000 --- a/client/src/components/TopBar/topBar.module.css +++ /dev/null @@ -1,89 +0,0 @@ -.topBarContainer { - position: fixed; - top: 0; - left: 80px; /* Match sidebar width */ - right: 0; - height: 64px; - background-color: #181818; - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 24px; - z-index: 900; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); -} - -.topBarNav { - display: flex; - align-items: center; - gap: 16px; -} - -.navButton { - background: none; - border: none; - padding: 8px; - cursor: pointer; - transition: all 0.2s ease; - border-radius: 8px; -} - -.navButton:hover { - background-color: rgba(255, 255, 255, 0.1); -} - -.navIcon { - width: 24px; - height: 24px; - opacity: 0.8; - transition: opacity 0.2s ease; -} - -.navButton:hover .navIcon { - opacity: 1; -} - -.searchContainer { - flex: 1; - max-width: 600px; - margin: 0 32px; -} - -.searchInput { - width: 100%; - height: 40px; - background-color: rgba(255, 255, 255, 0.1); - border: none; - border-radius: 20px; - padding: 0 16px; - color: white; - font-size: 14px; -} - -.searchInput::placeholder { - color: rgba(255, 255, 255, 0.5); -} - -.searchInput:focus { - outline: none; - background-color: rgba(255, 255, 255, 0.15); -} - -.rightSection { - display: flex; - align-items: center; - gap: 16px; -} - -.iconButton { - background: none; - border: none; - padding: 8px; - cursor: pointer; - transition: all 0.2s ease; - border-radius: 50%; -} - -.iconButton:hover { - background-color: rgba(255, 255, 255, 0.1); -} \ No newline at end of file diff --git a/client/src/components/TopBar/topBar.tsx b/client/src/components/TopBar/topBar.tsx deleted file mode 100644 index aff2f87..0000000 --- a/client/src/components/TopBar/topBar.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { useNavigate, useSearchParams } from "react-router-dom"; -import styles from "./topBar.module.css"; -const HomeButton = "/TopBar/HomeButton.svg"; -const FeedButton = "/TopBar/FeedButton.svg"; -const NotificationButton = "/TopBar/NotificationButton.svg"; -const SettingButton = "/TopBar/SettingButton.svg"; -const ProfileButton = "/TopBar/ProfileButton.svg"; - - -const TopBar: React.FC = () => { - const navigate = useNavigate(); - const [searchParams] = useSearchParams(); - const [search, setSearch] = useState(searchParams.get("q") ?? ""); - - // Keep input in sync when query param changes (e.g., via navigation) - useEffect(() => { - setSearch(searchParams.get("q") ?? ""); - }, [searchParams]); - - const submitSearch = () => { - const q = search.trim(); - if (!q) return; - navigate(`/search?q=${encodeURIComponent(q)}`); - }; - - const onKeyDown: React.KeyboardEventHandler = (e) => { - if (e.key === "Enter") { - e.preventDefault(); - submitSearch(); - } - }; - - return ( -
- {/* Navigation Buttons */} -
- - - -
- - {/* Search Bar */} -
- setSearch(e.target.value)} - onKeyDown={onKeyDown} - /> -
- - {/* Profile, Settings, Notifications */} -
- - - - - -
-
- ); -}; -export default TopBar; \ No newline at end of file diff --git a/client/src/components/index.ts b/client/src/components/index.ts index 1c35700..f7c0482 100644 --- a/client/src/components/index.ts +++ b/client/src/components/index.ts @@ -1 +1,59 @@ -export { default as SongCard } from './SongCard/SongCard'; \ No newline at end of file +/* ================================= Layout ================================= */ +export { default as HorizontalRule } from "./Layout/HorizontalRule/HorizontalRule.js"; +export { default as VerticalRule } from "./Layout/VerticalRule/VerticalRule.js"; + +/* =============================== MainLayout =============================== */ +export { default as MainLayout } from "./MainLayout/MainLayout.js"; +export { default as MainLayoutHeader } from "./MainLayout/MainLayoutHeader/MainLayoutHeader.js"; +export { default as MainLayoutSidebar } from "./MainLayout/MainLayoutSidebar/MainLayoutSidebar.js"; +export { default as MainLayoutSearchBar } from "./MainLayout/MainLayoutSearchBar/MainLayoutSearchBar.js"; +export { default as MainLayoutNowPlayingBar } from "./MainLayout/MainLayoutNowPlayingBar/MainLayoutNowPlayingBar.js"; + +/* ================================== Forms ================================= */ +export { default as InputGroup } from "./Forms/InputGroup/InputGroup.js"; +export { default as FormSubmitButton } from "./Forms/FormButton/FormSubmitButton.js"; + +/* ================================= Routes ================================= */ +export { default as ProtectedRoute } from "./ProtectedRoute/ProtectedRoute.js"; +export { default as AppLayout } from "./AppLayout/AppLayout.js"; + +/* ================================ SongPage ================================ */ +export { default as WaveformPlayer } from "./SongPage/WaveformPlayer/WaveformPlayer.js"; +export { default as SongContainer } from "./SongPage/SongContainer/SongContainer.js"; +export { default as SongStats } from "./SongPage/SongStats/SongStats.js"; +export { default as SongDetails } from "./SongPage/SongDetails/SongDetails.js"; +export { default as SongActions } from "./SongPage/SongActions/SongActions.js"; +export { default as ArtistInfo } from "./SongPage/ArtistInfo/ArtistInfo.js"; +export { default as SongComments } from "./SongPage/SongComments/SongComments.js"; +export { default as CommentItem } from "./SongPage/CommentItem/CommentItem.js"; +export { default as SongSuggestions } from "./SongPage/SongSuggestions/SongSuggestions.js"; + +/* =============================== ArtistPage =============================== */ +export { default as ArtistBanner } from "./ArtistPage/ArtistBanner/ArtistBanner.js"; +export { default as RelatedArtists } from "./ArtistPage/RelatedArtists/RelatedArtists.js"; +export { default as ArtistActions } from "./ArtistPage/ArtistActions/ArtistActions.js"; +export { default as ArtistPlaylists } from "./ArtistPage/ArtistPlaylists/ArtistPlaylists.js"; +export { default as ArtistAbout } from "./ArtistPage/ArtistAbout/ArtistAbout.js"; + +/* ================================== Lists ================================= */ +export { default as SongsList } from "./SongsList/SongsList.js"; +export { default as FollowProfiles } from "./FollowProfiles/FollowProfiles.js"; + +/* ================================== Cards ================================== */ +export { default as SongCard } from "./SongCard/SongCard.js"; +export { default as EntityItem } from "./EntityItem/EntityItem.js"; +export { default as EntityItemCard } from "./EntityItemCard/EntityItemCard.js"; +export { default as SlidingCardList } from "./SlidingCardList/SlidingCardList.js"; + +/* ================================= Modals ================================= */ +export { default as ShareModal } from "./ShareModal/ShareModal.js"; +export { default as QueueMenu } from "./QueueMenu/QueueMenu.js"; +export { default as CoverLightbox } from "./CoverLightbox/CoverLightbox.js"; +export { default as QueueManager } from "./MainLayout/QueueManager/QueueManager.js"; + +/* =============================== Page States ============================== */ +export { default as PageLoader } from "./PageLoader/PageLoader.js"; +export { default as ErrorPage } from "./ErrorPage/ErrorPage.js"; + +/* ================================ Dev Tools =============================== */ +export { default as DevBanner } from "./DevBanner/DevBanner.js"; diff --git a/client/src/hooks/useAsyncData.ts b/client/src/hooks/useAsyncData.ts new file mode 100644 index 0000000..e69de29 diff --git a/client/src/pages/ArtistPage/ArtistPage.module.css b/client/src/pages/ArtistPage/ArtistPage.module.css new file mode 100644 index 0000000..e69de29 diff --git a/client/src/pages/ArtistPage/ArtistPage.tsx b/client/src/pages/ArtistPage/ArtistPage.tsx new file mode 100644 index 0000000..390e71e --- /dev/null +++ b/client/src/pages/ArtistPage/ArtistPage.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import { useParams } from "react-router-dom"; +import Topbar from "../../components/TopBar/topBar"; +import Sidebar from "../../components/SideBar/sidebar"; +import PlayerBar from "../../components/PlayerBar/playerBar"; +import homeStyles from "../HomePage/HomePage.module.css"; + +const ArtistPage: React.FC = () => { + const { id } = useParams(); + + return ( + <> + + +
+
+
+
+

Artist

+
+

Artist ID: {id}

+
+
+
+ + + ); +}; + +export default ArtistPage; diff --git a/client/src/pages/HomePage/HomePage.tsx b/client/src/pages/HomePage/HomePage.tsx index d3d116f..6ccc985 100644 --- a/client/src/pages/HomePage/HomePage.tsx +++ b/client/src/pages/HomePage/HomePage.tsx @@ -3,9 +3,40 @@ import styles from "./HomePage.module.css"; import Sidebar from "../../components/SideBar/sidebar"; import Topbar from "../../components/TopBar/topBar"; import PlayerBar from "../../components/PlayerBar/playerBar"; -import FeaturedSection from "./sections/FeaturedSection"; import SongCard from "../../components/SongCard/SongCard"; +// Local FeaturedSection component to replace missing import/file +function FeaturedSection({ + title, + description, + image, + likes, + tracks, + duration, +}: { + title: string; + description: string; + image: string; + likes: number; + tracks: number; + duration: string; +}) { + return ( +
+

{title}

+

{description}

+
+ {title} +
+

Likes: {likes.toLocaleString()}

+

Tracks: {tracks}

+

Duration: {duration}

+
+
+
+ ); +} + const HomePage: React.FC = () => { // Mock data const recentSongs = Array(8).fill({ @@ -37,7 +68,7 @@ const HomePage: React.FC = () => { {
{newSongs.map((song, index) => ( - + ))}
diff --git a/client/src/pages/SearchResultsPage/SearchResultsPage.tsx b/client/src/pages/SearchResultsPage/SearchResultsPage.tsx index 2269fc3..547c4e1 100644 --- a/client/src/pages/SearchResultsPage/SearchResultsPage.tsx +++ b/client/src/pages/SearchResultsPage/SearchResultsPage.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { useSearchParams } from "react-router-dom"; +import { useSearchParams, Link } from "react-router-dom"; import homeStyles from "../HomePage/HomePage.module.css"; import styles from "./SearchResultsPage.module.css"; import Sidebar from "../../components/SideBar/sidebar"; @@ -59,12 +59,23 @@ export default function SearchResultsPage() {

Songs

- {songs.map((song) => ( -
+ {songs.map((song, index) => ( +
{song.title}

{song.title}

-

{song.artist}

+

+ {song.artists && song.artists.length > 0 ? ( + song.artists.map((a, i) => ( + + {a.name} + {i < song.artists!.length - 1 ? ", " : ""} + + )) + ) : ( + song.artist || "" + )} +

))} @@ -83,7 +94,7 @@ export default function SearchResultsPage() { title={artist.name} artist={""} image={artist.image} - plays={artist.plays} + plays={artist.plays ?? 0} likes={artist.likes ?? 0} comments={artist.comments ?? 0} showStats={false} diff --git a/client/src/pages/index.ts b/client/src/pages/index.ts index e5ede7d..5efc27d 100644 --- a/client/src/pages/index.ts +++ b/client/src/pages/index.ts @@ -1,2 +1,3 @@ export { default as TestPage } from "./TestPage/TestPage.js"; export { default as SearchResultsPage } from "./SearchResultsPage/SearchResultsPage"; +export { default as ArtistPage } from "./ArtistPage/ArtistPage"; diff --git a/client/src/types/artist.types.ts b/client/src/types/artist.types.ts new file mode 100644 index 0000000..e69de29 diff --git a/server/src/routes/search.routes.ts b/server/src/routes/search.routes.ts index 03250c4..ef2d9b1 100644 --- a/server/src/routes/search.routes.ts +++ b/server/src/routes/search.routes.ts @@ -30,18 +30,28 @@ router.get("/", async (req: Request, res: Response): Promise => { const results: any = {}; - // Songs + // Songs (include artists) if (type === "all" || type === "songs") { const songsQuery = ` SELECT - title, - image_url AS image, - genre - FROM songs - WHERE title ILIKE $1 OR genre ILIKE $1 - ORDER BY title ASC + s.id, + s.title, + s.image_url AS image, + s.genre, + COALESCE( + ( + SELECT json_agg(json_build_object('id', ar.user_id, 'name', ar.display_name)) + FROM song_artists sa + JOIN artists ar ON sa.artist_id = ar.id + WHERE sa.song_id = s.id + ), '[]'::json + ) AS artists + FROM songs s + WHERE s.title ILIKE $1 OR s.genre ILIKE $1 + ORDER BY s.title ASC LIMIT $2 OFFSET $3 `; + const rows = await safeQuery(songsQuery, [searchTerm, limitNum, offsetNum]); results.songs = rows.map((row: any) => ({ ...row,
+
+ {/* Top Grid Layout */} +
+ {/* Featured Column */} +
+ +
+ + {/* Recently Played Column */} +
+ +
+ {recentSongs.map((song, index) => ( +
+ {song.title} +
+

{song.title}

+

{song.artist}

+
+
+ ))} +
+
+
+ + {/* New Releases Section - Full Width */} +
+
+

New Releases

+ View More +
+
+ {newSongs.map((song, index) => ( + + ))} +
+
+
+