Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions apps/frontend/src/app/(content)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Metadata } from 'next';

import { BROWSER_SONGS } from '@nbw/config';
import type { FeaturedSongsDto, PageDto, SongPreviewDto } from '@nbw/database';
import axiosInstance from '@web/lib/axios';
import { HomePageProvider } from '@web/modules/browse/components/client/context/HomePage.context';
Expand All @@ -9,8 +10,8 @@ async function fetchRecentSongs() {
try {
const response = await axiosInstance.get<PageDto<SongPreviewDto>>('/song', {
params: {
page: 1, // TODO: fix constants
limit: 11, // TODO: change 'limit' parameter to 'skip' and load 12 songs initially, then load 8 more songs on each pagination
page: 1,
limit: BROWSER_SONGS.recentFetchCount,
sort: 'recent',
order: 'desc',
},
Expand Down
35 changes: 17 additions & 18 deletions apps/frontend/src/modules/browse/components/HomePageComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,19 @@ import { WelcomeBanner } from '../WelcomeBanner';

import { CategoryButtonGroup } from './client/CategoryButton';
import { useFeaturedSongsProvider } from './client/context/FeaturedSongs.context';
import {
useRecentSongsProvider,
useRecentSongsPageLoader,
useRecentSongsCategoriesLoader,
} from './client/context/RecentSongs.context';
import { useRecentSongsStore } from './client/context/RecentSongs.context';
import LoadMoreButton from './client/LoadMoreButton';
import { TimespanButtonGroup } from './client/TimespanButton';
import SongCard from './SongCard';
import SongCardGroup from './SongCardGroup';

export const HomePageComponent = () => {
// Initialize sync hooks for proper effect handling
useRecentSongsPageLoader();
useRecentSongsCategoriesLoader();

const { featuredSongsPage, timespan } = useFeaturedSongsProvider();
const { recentSongs, increasePageRecent, hasMore } = useRecentSongsProvider();
const recentItems = useRecentSongsStore((state) => state.recentItems);
const increasePageRecent = useRecentSongsStore(
(state) => state.increasePageRecent,
);
const hasMore = useRecentSongsStore((state) => state.hasMore);
return (
<>
{/* Welcome banner/Hero */}
Expand Down Expand Up @@ -87,14 +83,17 @@ export const HomePageComponent = () => {
</div>
<div className='h-6' />
<SongCardGroup data-test='recent-songs'>
{recentSongs.map((song, i) =>
// TODO: currently null = skeleton, undefined = ad slot. There must be a more robust system to indicate this.
song === undefined ? (
<SongCardAdSlot key={i} />
) : (
<SongCard key={i} song={song} />
),
)}
{recentItems.map((item, i) => {
if (item.type === 'ad') {
return <SongCardAdSlot key={i} />;
}

if (item.type === 'loading') {
return <SongCard key={i} song={null} />;
}

return <SongCard key={i} song={item.data} />;
})}
</SongCardGroup>
<div className='flex flex-col w-full justify-between items-center mt-4'>
{hasMore ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
'use client';
import { useEffect } from 'react';

import { UPLOAD_CONSTANTS } from '@nbw/config';
import type { CategoryType } from '@nbw/database';
import {
Expand All @@ -9,7 +11,7 @@ import {
CarouselPreviousSmall,
} from '@web/modules/shared/components/client/Carousel';

import { useRecentSongsProvider } from './context/RecentSongs.context';
import { useRecentSongsStore } from './context/RecentSongs.context';

type CategoryButtonProps = {
children: React.ReactNode;
Expand All @@ -20,8 +22,21 @@ type CategoryButtonProps = {
};

export const CategoryButtonGroup = () => {
const { categories, setSelectedCategory, selectedCategory } =
useRecentSongsProvider();
const categories = useRecentSongsStore((state) => state.categories);
const fetchCategories = useRecentSongsStore((state) => state.fetchCategories);
const setSelectedCategory = useRecentSongsStore(
(state) => state.setSelectedCategory,
);
const selectedCategory = useRecentSongsStore(
(state) => state.selectedCategory,
);
const categoryCount = Object.keys(categories).length;

useEffect(() => {
if (categoryCount === 0) {
void fetchCategories();
}
}, [categoryCount, fetchCategories]);

return (
<Carousel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,8 @@

import type { FeaturedSongsDtoType, SongPreviewDtoType } from '@nbw/database';

import {
FeaturedSongsProvider,
useFeaturedSongsStore,
} from './FeaturedSongs.context';
import {
RecentSongsProvider,
useRecentSongsStore,
} from './RecentSongs.context';

/**
* Composed hook that provides access to both FeaturedSongs and RecentSongs stores
*/
export function useHomePageStore() {
const featuredSongs = useFeaturedSongsStore();
const recentSongs = useRecentSongsStore();

return {
featuredSongs,
recentSongs,
};
}
import { FeaturedSongsProvider } from './FeaturedSongs.context';
import { RecentSongsProvider } from './RecentSongs.context';

export function HomePageProvider({
children,
Expand All @@ -41,8 +22,3 @@ export function HomePageProvider({
</RecentSongsProvider>
);
}

// Legacy hook name for backward compatibility
export function useHomePageProvider() {
return useHomePageStore();
}
Loading
Loading