diff --git a/src/pages/home/LandingPage.tsx b/src/pages/home/LandingPage.tsx
index 2ba138a2..a899f517 100644
--- a/src/pages/home/LandingPage.tsx
+++ b/src/pages/home/LandingPage.tsx
@@ -182,7 +182,7 @@ const LandingPage = () => {
{/* ── Embedded Navbar ──────────────────────────────────────── */}
- {/* TODO: Replace with Rhythmify logo SVG */}
+
RHYTHMIFY
@@ -203,7 +203,7 @@ const LandingPage = () => {
Create account
For Artists
@@ -224,7 +224,7 @@ const LandingPage = () => {
cta.variant === "primary" ? (
{cta.label}
@@ -232,7 +232,7 @@ const LandingPage = () => {
) : (
{cta.label}
@@ -374,7 +374,7 @@ const LandingPage = () => {
your audience. What are you waiting for?
Find out more
diff --git a/src/pages/signin/PasswordLogin.tsx b/src/pages/signin/PasswordLogin.tsx
index c6c2c85b..411167d3 100644
--- a/src/pages/signin/PasswordLogin.tsx
+++ b/src/pages/signin/PasswordLogin.tsx
@@ -39,7 +39,7 @@ export default function PasswordLogin({ email, onBack, onContinue, onForgotPassw
>
- Welcome back!
+ Sign in or create an account
diff --git a/src/pages/you/albums/AlbumsForYouSlugPage.tsx b/src/pages/you/albums/AlbumsForYouSlugPage.tsx
index a54dba3c..bdd74c02 100644
--- a/src/pages/you/albums/AlbumsForYouSlugPage.tsx
+++ b/src/pages/you/albums/AlbumsForYouSlugPage.tsx
@@ -281,7 +281,7 @@ function AlbumsForYouSlugPage() {
return (
- {likedRadioTracks.length > 0 && (
-
- {likedRadioTracks.map((item) => (
-
- ))}
-
- )}
+
{/* Playlists */}
extends { daily_mix: infer D } ? D : never : never) {
+function getMadeForYouCoverUrl(
+ mix: HomeData["made_for_you"] extends infer T
+ ? NonNullable extends { daily_mix: infer D }
+ ? D
+ : never
+ : never,
+) {
return mix.cover_url ?? mix.preview_track.cover_image ?? "";
}
@@ -90,7 +96,8 @@ export default function SetsPage() {
]);
setHomeData(home);
seedFromHomeData(home);
- const isSetPlaylist = (p: Playlist) => !p.is_album_view && p.subtype !== "album";
+ const isSetPlaylist = (p: Playlist) =>
+ !p.is_album_view && p.subtype !== "album";
setCreatedPlaylists(created.data.items.filter(isSetPlaylist));
setLikedPlaylists(liked.data.items.filter(isSetPlaylist));
} catch (err) {
@@ -116,38 +123,18 @@ export default function SetsPage() {
}, [fetchAll]);
// Filter and Search Logic
- const visiblePlaylists = useMemo(() => {
- const match = (name: string) =>
- name.toLowerCase().includes(filterText.toLowerCase());
-
- let list: Playlist[] = [];
- if (activeFilter === "Created") {
- list = createdPlaylists;
- } else if (activeFilter === "Liked") {
- list = likedPlaylists;
- } else {
- // "All" - Merge and remove duplicates by ID
- const merged = [...createdPlaylists, ...likedPlaylists];
- const seen = new Set();
- list = merged.filter((p) => {
- if (seen.has(p.playlist_id)) return false;
- seen.add(p.playlist_id);
- return true;
- });
- }
- return list.filter((p) => match(p.name));
- }, [activeFilter, filterText, createdPlaylists, likedPlaylists]);
// Helper to map Playlist API data to PlaylistCard props
- const mapToCardData = (p: Playlist): PlaylistCardData => ({
+ const mapToCardData = (p: Playlist | any): PlaylistCardData => ({
id: p.playlist_id,
title: p.name,
owner: p.owner_user_id,
- ownerUsername:
- user && p.owner_user_id === user.id ? user.username : undefined,
+ ownerDisplayName: p.ownerDisplayName,
+ ownerUsername: p.ownerUsername || (user && p.owner_user_id === user.id ? user.username : undefined),
coverUrl: p.cover_image || null,
isPrivate: !p.is_public,
- isLiked: likedPlaylists.some((lp) => lp.playlist_id === p.playlist_id),
+ isLiked: p.isLikedOverride ?? likedPlaylists.some((lp) => lp.playlist_id === p.playlist_id),
+ hideOwner: p.hideOwner,
});
const madeForYouItems: MadeForYouItem[] = useMemo(() => {
@@ -164,7 +151,9 @@ export default function SetsPage() {
madeKind: "daily",
badgeWords: ["DAILY", "DROPS"],
badgeBg: "#1a237e",
- previewTrack: mapDiscoveryTrack(homeData.made_for_you.daily_mix.preview_track),
+ previewTrack: mapDiscoveryTrack(
+ homeData.made_for_you.daily_mix.preview_track,
+ ),
});
}
@@ -177,7 +166,9 @@ export default function SetsPage() {
madeKind: "weekly",
badgeWords: ["WEEKLY", "WAVE"],
badgeBg: "#1b5e20",
- previewTrack: mapDiscoveryTrack(homeData.made_for_you.weekly_mix.preview_track),
+ previewTrack: mapDiscoveryTrack(
+ homeData.made_for_you.weekly_mix.preview_track,
+ ),
});
}
@@ -211,23 +202,92 @@ export default function SetsPage() {
return [...mixedForYou, ...madeForYouItems];
}, [homeData, madeForYouItems]);
+ const visiblePlaylists = useMemo(() => {
+ const match = (name: string) =>
+ name.toLowerCase().includes(filterText.toLowerCase());
+
+ const mixIds = new Set(mixItems.map((m) => m.id));
+ const isExcluded = (id: string) => mixIds.has(id);
+
+ const radioMap = new Map(likedRadioTracks.map((r) => [r.playlistId, r]));
+
+ const enhanceWithRadio = (p: Playlist): Playlist | any => {
+ const r = radioMap.get(p.playlist_id);
+ if (r) {
+ return {
+ ...p,
+ name: p.name.replace(/\s+Radio$/i, ""),
+ cover_image: r.coverImage ?? p.cover_image,
+ isLikedOverride: true,
+ hideOwner: true,
+ };
+ }
+ return p;
+ };
+
+ let list: Playlist[] = [];
+ if (activeFilter === "Created") {
+ list = createdPlaylists.filter(
+ (p) => !isExcluded(p.playlist_id) && p.name && p.name.trim() !== "",
+ ).map(enhanceWithRadio);
+ } else if (activeFilter === "Liked") {
+ list = likedPlaylists.filter(
+ (p) => !isExcluded(p.playlist_id) && p.name && p.name.trim() !== "",
+ ).map(enhanceWithRadio);
+ } else {
+ // "All" - Merge and remove duplicates by ID
+ const merged = [...createdPlaylists, ...likedPlaylists];
+ const seen = new Set();
+ list = merged.filter((p) => {
+ if (!p.name || p.name.trim() === "") return false;
+ if (isExcluded(p.playlist_id)) return false;
+ if (seen.has(p.playlist_id)) return false;
+ seen.add(p.playlist_id);
+ return true;
+ }).map(enhanceWithRadio);
+ }
+
+ const filteredList = list.filter((p) => match(p.name));
+
+ const radioPlaylists: any[] = likedRadioTracks.map((r) => ({
+ playlist_id: r.playlistId,
+ name: r.title.replace(/\s+Radio$/i, ""),
+ owner_user_id: user?.id ?? "",
+ is_public: true,
+ cover_image: r.coverImage,
+ subtype: "playlist",
+ track_count: 0,
+ like_count: 1,
+ created_at: new Date().toISOString(),
+ is_album_view: false,
+ isLikedOverride: true,
+ hideOwner: true,
+ }));
+
+ // Only add radioPlaylists that are not already in the main list
+ const existingIds = new Set(filteredList.map(p => p.playlist_id));
+ const filteredRadio = radioPlaylists.filter((p) => match(p.name) && !existingIds.has(p.playlist_id));
+
+ if (activeFilter === "Created") return filteredList;
+ return [...filteredList, ...filteredRadio];
+ }, [
+ activeFilter,
+ filterText,
+ createdPlaylists,
+ likedPlaylists,
+ mixItems,
+ likedRadioTracks,
+ user,
+ ]);
+
const visibleMixItems = useMemo(() => {
if (activeFilter === "Created") return [];
- return mixItems.filter((mix) => mix.title.toLowerCase().includes(filterText.toLowerCase()));
+ return mixItems.filter((mix) =>
+ mix.title.toLowerCase().includes(filterText.toLowerCase()),
+ );
}, [activeFilter, filterText, mixItems]);
- const visibleRadioItems = useMemo(() => {
- if (activeFilter === "Created") return [];
- const query = filterText.toLowerCase();
- return likedRadioTracks.filter((item) => {
- if (!query) return true;
- return (
- item.track.title.toLowerCase().includes(query) ||
- item.title.toLowerCase().includes(query) ||
- item.description.toLowerCase().includes(query)
- );
- });
- }, [activeFilter, filterText, likedRadioTracks]);
+
const isMadeForYouItem = (item: SetsCarouselItem): item is MadeForYouItem =>
item.madeKind === "daily" || item.madeKind === "weekly";
@@ -257,7 +317,6 @@ export default function SetsPage() {
const hasVisibleContent =
visiblePlaylists.length > 0 ||
- visibleRadioItems.length > 0 ||
visibleMixItems.length > 0 ||
genreItems.length > 0;
@@ -301,43 +360,41 @@ export default function SetsPage() {
) : (
),
)}
- {visibleRadioItems.map((item) => (
-
- ))}
+
{genreItems.map((genre) => (
) : (
-
+
{filterText
? "No playlists match your search."
diff --git a/src/pages/you/sets/TrendingByGenreSlugPage.tsx b/src/pages/you/sets/TrendingByGenreSlugPage.tsx
index 6629393b..4ae25687 100644
--- a/src/pages/you/sets/TrendingByGenreSlugPage.tsx
+++ b/src/pages/you/sets/TrendingByGenreSlugPage.tsx
@@ -263,7 +263,7 @@ function TrendingByGenreSlugPage() {
return (