From 6cca9126b00ddf9a79d8a8de077a6f8b0328d2b0 Mon Sep 17 00:00:00 2001 From: GulSam00 Date: Tue, 27 May 2025 23:26:02 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat=20:=20=EB=AC=B4=ED=95=9C=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A1=A4=20API=20=EB=8B=A8=EC=97=90=20=EC=84=B8?= =?UTF-8?q?=ED=8C=85.=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=B0=9B=EA=B3=A0?= =?UTF-8?q?=20=EB=8B=A4=EC=9D=8C=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=A6=AC?= =?UTF-8?q?=ED=84=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/app/api/search/route.ts | 22 +++++++++++++++++++--- apps/web/src/lib/api/searchSong.ts | 2 ++ apps/web/src/types/song.ts | 6 ++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/apps/web/src/app/api/search/route.ts b/apps/web/src/app/api/search/route.ts index 2dd0f52..bff8266 100644 --- a/apps/web/src/app/api/search/route.ts +++ b/apps/web/src/app/api/search/route.ts @@ -25,6 +25,11 @@ export async function GET(request: Request): Promise to + 1, }); } const userId = await getAuthenticatedUser(supabase); // userId 가져오기 - const { data, error } = await supabase + const { data, error, count } = await supabase .from('songs') .select( ` @@ -85,8 +97,11 @@ export async function GET(request: Request): Promise to + 1, }); } catch (error) { if (error instanceof Error && error.cause === 'auth') { diff --git a/apps/web/src/lib/api/searchSong.ts b/apps/web/src/lib/api/searchSong.ts index 505886f..e9abea0 100644 --- a/apps/web/src/lib/api/searchSong.ts +++ b/apps/web/src/lib/api/searchSong.ts @@ -8,5 +8,7 @@ export async function getSearchSong(search: string, searchType: string, isAuthen params: { q: search, type: searchType, authenticated: isAuthenticated }, }); + console.log('response : ', response.data); + return response.data; } diff --git a/apps/web/src/types/song.ts b/apps/web/src/types/song.ts index 4168a7e..d7a4987 100644 --- a/apps/web/src/types/song.ts +++ b/apps/web/src/types/song.ts @@ -64,6 +64,12 @@ export interface SearchSong extends Song { isSave: boolean; } +export interface SearchSongResponse { + data: SearchSong[]; + hasMore: boolean; + nextPage: number; +} + export interface AddListModalSong extends Song { isInToSingList: boolean; id: string; From 107a9996ee1f914db13d284e4948ebda2d2eeb38 Mon Sep 17 00:00:00 2001 From: GulSam00 Date: Sat, 7 Jun 2025 19:50:21 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat=20:=20=EB=AC=B4=ED=95=9C=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A1=A4=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/package.json | 1 + apps/web/src/app/api/search/route.ts | 1 + apps/web/src/app/search/HomePage.tsx | 44 +++++++++++++++++++++++-- apps/web/src/components/ui/spinner.tsx | 24 ++++++++++++++ apps/web/src/hooks/useSearchSong.ts | 18 ++++++++++ apps/web/src/lib/api/searchSong.ts | 26 +++++++++++++-- apps/web/src/queries/searchSongQuery.ts | 29 +++++++++++++++- apps/web/src/types/song.ts | 4 +-- packages/crawling/src/progress.json | 1 + pnpm-lock.yaml | 18 ++++++++++ 10 files changed, 158 insertions(+), 8 deletions(-) create mode 100644 apps/web/src/components/ui/spinner.tsx create mode 100644 packages/crawling/src/progress.json diff --git a/apps/web/package.json b/apps/web/package.json index fde6ec0..bba64d1 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -46,6 +46,7 @@ "next-themes": "^0.4.6", "react": "^19.0.0", "react-dom": "^19.0.0", + "react-intersection-observer": "^9.16.0", "sonner": "^2.0.3", "tailwind-merge": "^3.0.2", "tw-animate-css": "^1.2.4", diff --git a/apps/web/src/app/api/search/route.ts b/apps/web/src/app/api/search/route.ts index bff8266..09557bc 100644 --- a/apps/web/src/app/api/search/route.ts +++ b/apps/web/src/app/api/search/route.ts @@ -76,6 +76,7 @@ export async function GET(request: Request): Promise to + 1, }); } diff --git a/apps/web/src/app/search/HomePage.tsx b/apps/web/src/app/search/HomePage.tsx index 4cbc269..7fc7c7b 100644 --- a/apps/web/src/app/search/HomePage.tsx +++ b/apps/web/src/app/search/HomePage.tsx @@ -1,6 +1,9 @@ 'use client'; import { Search, SearchX } from 'lucide-react'; +import { Loader2 } from 'lucide-react'; +import { useEffect } from 'react'; +import { useInView } from 'react-intersection-observer'; import StaticLoading from '@/components/StaticLoading'; import { Button } from '@/components/ui/button'; @@ -8,6 +11,7 @@ import { Input } from '@/components/ui/input'; import { ScrollArea } from '@/components/ui/scroll-area'; import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'; import useSearchSong from '@/hooks/useSearchSong'; +import { SearchSong } from '@/types/song'; import AddFolderModal from './AddFolderModal'; import SearchResultCard from './SearchResultCard'; @@ -30,8 +34,29 @@ export default function SearchPage() { handleToggleSave, postSaveSong, patchSaveSong, + + testInfiniteData, + fetchNextPage, + hasNextPage, + isFetchingNextPage, + isError, } = useSearchSong(); + const { ref, inView } = useInView(); + + console.log('searchSongs', searchSongs); + console.log('testInfiniteData', testInfiniteData); + let pageParams: number[] = []; + let pages: SearchSong[] = []; + + if (testInfiniteData) { + pageParams = testInfiniteData.pageParams as number[]; + pages = testInfiniteData.pages.flat(); + } + + console.log('pageParams', pageParams); + console.log('pages', pages); + // 엔터 키 처리 const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { @@ -39,6 +64,16 @@ export default function SearchPage() { } }; + useEffect(() => { + const timeout = setTimeout(() => { + if (inView && hasNextPage && !isFetchingNextPage && !isError) { + fetchNextPage(); + } + }, 1000); // 1000ms 정도 지연 + + return () => clearTimeout(timeout); + }, [inView, hasNextPage, isFetchingNextPage, fetchNextPage, isError]); + return (
@@ -72,9 +107,9 @@ export default function SearchPage() {
- {searchSongs.length > 0 && ( + {pages.length > 0 && (
- {searchSongs.map((song, index) => ( + {pages.map((song, index) => ( handleToggleSave(song, song.isSave ? 'PATCH' : 'POST')} /> ))} + {hasNextPage && ( +
+ +
+ )}
)} {searchSongs.length === 0 && query && ( diff --git a/apps/web/src/components/ui/spinner.tsx b/apps/web/src/components/ui/spinner.tsx new file mode 100644 index 0000000..cd89ea3 --- /dev/null +++ b/apps/web/src/components/ui/spinner.tsx @@ -0,0 +1,24 @@ +import { cn } from '@/lib/utils'; + +interface SpinnerProps extends React.HTMLAttributes { + size?: 'sm' | 'md' | 'lg'; +} + +export function Spinner({ className, size = 'md', ...props }: SpinnerProps) { + return ( +
+ 로딩 중... +
+ ); +} diff --git a/apps/web/src/hooks/useSearchSong.ts b/apps/web/src/hooks/useSearchSong.ts index 6c2b760..d2f7a7a 100644 --- a/apps/web/src/hooks/useSearchSong.ts +++ b/apps/web/src/hooks/useSearchSong.ts @@ -5,6 +5,7 @@ import { useMoveSaveSongMutation } from '@/queries/saveSongQuery'; import { useSaveMutation, useSearchSongQuery, + useTestInfiniteQuery, useToggleLikeMutation, useToggleToSingMutation, } from '@/queries/searchSongQuery'; @@ -30,6 +31,16 @@ export default function useSearchSong() { const { mutate: postSong } = useSaveMutation(); const { mutate: moveSong } = useMoveSaveSongMutation(); + const { + data: testInfiniteData, + fetchNextPage, + hasNextPage, + isFetchingNextPage, + isError, + } = useTestInfiniteQuery(query, searchType, isAuthenticated); + + console.log('status', hasNextPage, isFetchingNextPage, isError); + const searchSongs = searchResults ?? []; const handleSearch = () => { @@ -80,6 +91,7 @@ export default function useSearchSong() { query, searchSongs, isLoading, + searchType, handleSearchTypeChange, handleSearch, @@ -91,5 +103,11 @@ export default function useSearchSong() { selectedSaveSong, postSaveSong, patchSaveSong, + + testInfiniteData, + fetchNextPage, + hasNextPage, + isFetchingNextPage, + isError, }; } diff --git a/apps/web/src/lib/api/searchSong.ts b/apps/web/src/lib/api/searchSong.ts index e9abea0..37e0d99 100644 --- a/apps/web/src/lib/api/searchSong.ts +++ b/apps/web/src/lib/api/searchSong.ts @@ -1,11 +1,31 @@ import { ApiResponse } from '@/types/apiRoute'; -import { SearchSong } from '@/types/song'; +import { SearchSong, SearchSongResponse } from '@/types/song'; import { instance } from './client'; -export async function getSearchSong(search: string, searchType: string, isAuthenticated: boolean) { +export async function getInfiniteSearchSong( + search: string, + searchType: string, + isAuthenticated: boolean, + page?: number, +) { + const response = await instance.get>('/search', { + params: { q: search, type: searchType, authenticated: isAuthenticated, page }, + }); + + console.log('response : ', response.data); + + return response.data; +} + +export async function getSearchSong( + search: string, + searchType: string, + isAuthenticated: boolean, + page?: number, +) { const response = await instance.get>('/search', { - params: { q: search, type: searchType, authenticated: isAuthenticated }, + params: { q: search, type: searchType, authenticated: isAuthenticated, page }, }); console.log('response : ', response.data); diff --git a/apps/web/src/queries/searchSongQuery.ts b/apps/web/src/queries/searchSongQuery.ts index 2ccda50..91666b6 100644 --- a/apps/web/src/queries/searchSongQuery.ts +++ b/apps/web/src/queries/searchSongQuery.ts @@ -1,4 +1,4 @@ -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { deleteLikeSong, postLikeSong } from '@/lib/api/likeSong'; import { postSaveSong } from '@/lib/api/saveSong'; @@ -11,6 +11,33 @@ import { SearchSong } from '@/types/song'; let invalidateToSingTimeout: NodeJS.Timeout | null = null; let invalidateLikeTimeout: NodeJS.Timeout | null = null; +export const useTestInfiniteQuery = ( + search: string, + searchType: string, + isAuthenticated: boolean, +) => { + return useInfiniteQuery({ + queryKey: ['testInfiniteQuery', search, searchType], + queryFn: async ({ pageParam }) => { + const response = await getSearchSong(search, searchType, isAuthenticated, pageParam); + console.log('response', response); + if (!response.success) { + throw new Error('Search API failed'); + } + return response.data || []; + }, + getNextPageParam: (lastPage, pages) => { + // lastPage : 직전 페이지의 데이터 + // pages : 현재까지 조회된 모든 데이터 + // console.log('lastPage', lastPage); + // console.log('pages', pages); + if (!lastPage || lastPage.length === 0) return undefined; + return pages.length; + }, + initialPageParam: 0, + }); +}; + export const useSearchSongQuery = ( search: string, searchType: string, diff --git a/apps/web/src/types/song.ts b/apps/web/src/types/song.ts index d7a4987..8d4c717 100644 --- a/apps/web/src/types/song.ts +++ b/apps/web/src/types/song.ts @@ -66,8 +66,8 @@ export interface SearchSong extends Song { export interface SearchSongResponse { data: SearchSong[]; - hasMore: boolean; - nextPage: number; + success: boolean; + hasNext: boolean; } export interface AddListModalSong extends Song { diff --git a/packages/crawling/src/progress.json b/packages/crawling/src/progress.json new file mode 100644 index 0000000..853de70 --- /dev/null +++ b/packages/crawling/src/progress.json @@ -0,0 +1 @@ +{"index":53927} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7a1d7ba..1a4cfb4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -232,6 +232,9 @@ importers: react-dom: specifier: ^19.0.0 version: 19.1.0(react@19.1.0) + react-intersection-observer: + specifier: ^9.16.0 + version: 9.16.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) sonner: specifier: ^2.0.3 version: 2.0.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -6398,6 +6401,15 @@ packages: react: ^16.6.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0 + react-intersection-observer@9.16.0: + resolution: {integrity: sha512-w9nJSEp+DrW9KmQmeWHQyfaP6b03v+TdXynaoA964Wxt7mdR3An11z4NNCQgL4gKSK7y1ver2Fq+JKH6CWEzUA==} + peerDependencies: + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + react-dom: + optional: true + react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -14896,6 +14908,12 @@ snapshots: react-fast-compare: 3.2.2 shallowequal: 1.1.0 + react-intersection-observer@9.16.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + react: 19.1.0 + optionalDependencies: + react-dom: 19.1.0(react@19.1.0) + react-is@16.13.1: {} react-is@18.3.1: {} From cf832d6e1b398385bcec6c6aee866cc767874863 Mon Sep 17 00:00:00 2001 From: GulSam00 Date: Sat, 7 Jun 2025 23:53:25 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat=20:=20=EB=AC=B4=ED=95=9C=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A1=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/app/search/HomePage.tsx | 34 +++++++++++-------------- apps/web/src/hooks/useSearchSong.ts | 27 ++++++++------------ apps/web/src/lib/api/searchSong.ts | 8 ++---- apps/web/src/queries/searchSongQuery.ts | 22 +++++++++++----- apps/web/src/types/apiRoute.ts | 1 + apps/web/src/types/song.ts | 6 ----- packages/crawling/src/progress.json | 2 +- 7 files changed, 45 insertions(+), 55 deletions(-) diff --git a/apps/web/src/app/search/HomePage.tsx b/apps/web/src/app/search/HomePage.tsx index 7fc7c7b..d896396 100644 --- a/apps/web/src/app/search/HomePage.tsx +++ b/apps/web/src/app/search/HomePage.tsx @@ -21,8 +21,14 @@ export default function SearchPage() { search, query, setSearch, - searchSongs, + + searchResults, isLoading, + fetchNextPage, + hasNextPage, + isFetchingNextPage, + isError, + saveModalType, setSaveModalType, selectedSaveSong, @@ -34,28 +40,18 @@ export default function SearchPage() { handleToggleSave, postSaveSong, patchSaveSong, - - testInfiniteData, - fetchNextPage, - hasNextPage, - isFetchingNextPage, - isError, } = useSearchSong(); const { ref, inView } = useInView(); - console.log('searchSongs', searchSongs); - console.log('testInfiniteData', testInfiniteData); - let pageParams: number[] = []; - let pages: SearchSong[] = []; + let searchSongs: SearchSong[] = []; - if (testInfiniteData) { - pageParams = testInfiniteData.pageParams as number[]; - pages = testInfiniteData.pages.flat(); + if (searchResults) { + searchSongs = searchResults.pages.flatMap(page => page.data); } - console.log('pageParams', pageParams); - console.log('pages', pages); + // console.log('searchResults', searchResults); + // console.log('pages', searchSongs); // 엔터 키 처리 const handleKeyDown = (e: React.KeyboardEvent) => { @@ -107,9 +103,9 @@ export default function SearchPage() { - {pages.length > 0 && ( + {searchSongs.length > 0 && (
- {pages.map((song, index) => ( + {searchSongs.map((song, index) => ( handleToggleSave(song, song.isSave ? 'PATCH' : 'POST')} /> ))} - {hasNextPage && ( + {hasNextPage && !isFetchingNextPage && (
diff --git a/apps/web/src/hooks/useSearchSong.ts b/apps/web/src/hooks/useSearchSong.ts index d2f7a7a..1b1855a 100644 --- a/apps/web/src/hooks/useSearchSong.ts +++ b/apps/web/src/hooks/useSearchSong.ts @@ -3,9 +3,8 @@ import { toast } from 'sonner'; import { useMoveSaveSongMutation } from '@/queries/saveSongQuery'; import { + useInfiniteSearchSongQuery, useSaveMutation, - useSearchSongQuery, - useTestInfiniteQuery, useToggleLikeMutation, useToggleToSingMutation, } from '@/queries/searchSongQuery'; @@ -25,23 +24,20 @@ export default function useSearchSong() { const [searchType, setSearchType] = useState('title'); const [saveModalType, setSaveModalType] = useState(''); const [selectedSaveSong, setSelectedSaveSong] = useState(null); - const { data: searchResults, isLoading } = useSearchSongQuery(query, searchType, isAuthenticated); + // const { data: searchResults, isLoading } = useSearchSongQuery(query, searchType, isAuthenticated); const { mutate: toggleToSing } = useToggleToSingMutation(); const { mutate: toggleLike } = useToggleLikeMutation(); const { mutate: postSong } = useSaveMutation(); const { mutate: moveSong } = useMoveSaveSongMutation(); const { - data: testInfiniteData, + data: searchResults, fetchNextPage, hasNextPage, isFetchingNextPage, + isLoading, isError, - } = useTestInfiniteQuery(query, searchType, isAuthenticated); - - console.log('status', hasNextPage, isFetchingNextPage, isError); - - const searchSongs = searchResults ?? []; + } = useInfiniteSearchSongQuery(query, searchType, isAuthenticated); const handleSearch = () => { setQuery(search); @@ -89,8 +85,13 @@ export default function useSearchSong() { search, setSearch, query, - searchSongs, + + searchResults, + fetchNextPage, + hasNextPage, + isFetchingNextPage, isLoading, + isError, searchType, handleSearchTypeChange, @@ -103,11 +104,5 @@ export default function useSearchSong() { selectedSaveSong, postSaveSong, patchSaveSong, - - testInfiniteData, - fetchNextPage, - hasNextPage, - isFetchingNextPage, - isError, }; } diff --git a/apps/web/src/lib/api/searchSong.ts b/apps/web/src/lib/api/searchSong.ts index 37e0d99..4e6df71 100644 --- a/apps/web/src/lib/api/searchSong.ts +++ b/apps/web/src/lib/api/searchSong.ts @@ -1,5 +1,5 @@ import { ApiResponse } from '@/types/apiRoute'; -import { SearchSong, SearchSongResponse } from '@/types/song'; +import { SearchSong } from '@/types/song'; import { instance } from './client'; @@ -9,12 +9,10 @@ export async function getInfiniteSearchSong( isAuthenticated: boolean, page?: number, ) { - const response = await instance.get>('/search', { + const response = await instance.get>('/search', { params: { q: search, type: searchType, authenticated: isAuthenticated, page }, }); - console.log('response : ', response.data); - return response.data; } @@ -28,7 +26,5 @@ export async function getSearchSong( params: { q: search, type: searchType, authenticated: isAuthenticated, page }, }); - console.log('response : ', response.data); - return response.data; } diff --git a/apps/web/src/queries/searchSongQuery.ts b/apps/web/src/queries/searchSongQuery.ts index 91666b6..15f5375 100644 --- a/apps/web/src/queries/searchSongQuery.ts +++ b/apps/web/src/queries/searchSongQuery.ts @@ -2,7 +2,7 @@ import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tansta import { deleteLikeSong, postLikeSong } from '@/lib/api/likeSong'; import { postSaveSong } from '@/lib/api/saveSong'; -import { getSearchSong } from '@/lib/api/searchSong'; +import { getInfiniteSearchSong, getSearchSong } from '@/lib/api/searchSong'; import { deleteToSingSong, postToSingSong } from '@/lib/api/tosing'; import { postTotalStat } from '@/lib/api/totalStat'; import { Method } from '@/types/common'; @@ -11,30 +11,38 @@ import { SearchSong } from '@/types/song'; let invalidateToSingTimeout: NodeJS.Timeout | null = null; let invalidateLikeTimeout: NodeJS.Timeout | null = null; -export const useTestInfiniteQuery = ( +export const useInfiniteSearchSongQuery = ( search: string, searchType: string, isAuthenticated: boolean, ) => { return useInfiniteQuery({ - queryKey: ['testInfiniteQuery', search, searchType], + queryKey: ['searchSong', search, searchType], queryFn: async ({ pageParam }) => { - const response = await getSearchSong(search, searchType, isAuthenticated, pageParam); + const response = await getInfiniteSearchSong(search, searchType, isAuthenticated, pageParam); + console.log('response', response); + if (!response.success) { throw new Error('Search API failed'); } - return response.data || []; + return { + data: response.data || [], + hasNext: response.hasNext, + }; }, + getNextPageParam: (lastPage, pages) => { // lastPage : 직전 페이지의 데이터 // pages : 현재까지 조회된 모든 데이터 // console.log('lastPage', lastPage); // console.log('pages', pages); - if (!lastPage || lastPage.length === 0) return undefined; - return pages.length; + + if (!lastPage || lastPage.data.length === 0) return undefined; + return lastPage.hasNext ? pages.length : undefined; }, initialPageParam: 0, + enabled: !!search, }); }; diff --git a/apps/web/src/types/apiRoute.ts b/apps/web/src/types/apiRoute.ts index 278803a..239cc83 100644 --- a/apps/web/src/types/apiRoute.ts +++ b/apps/web/src/types/apiRoute.ts @@ -1,6 +1,7 @@ export interface ApiSuccessResponse { success: true; data?: T; + hasNext?: boolean; // data: T; 타입 에러 } diff --git a/apps/web/src/types/song.ts b/apps/web/src/types/song.ts index 8d4c717..4168a7e 100644 --- a/apps/web/src/types/song.ts +++ b/apps/web/src/types/song.ts @@ -64,12 +64,6 @@ export interface SearchSong extends Song { isSave: boolean; } -export interface SearchSongResponse { - data: SearchSong[]; - success: boolean; - hasNext: boolean; -} - export interface AddListModalSong extends Song { isInToSingList: boolean; id: string; diff --git a/packages/crawling/src/progress.json b/packages/crawling/src/progress.json index 853de70..b0794ec 100644 --- a/packages/crawling/src/progress.json +++ b/packages/crawling/src/progress.json @@ -1 +1 @@ -{"index":53927} \ No newline at end of file +{"index":55203} \ No newline at end of file From 5c4b51c28c94d082bc4cbbbcbc0081575995c69a Mon Sep 17 00:00:00 2001 From: GulSam00 Date: Sun, 8 Jun 2025 00:03:06 +0900 Subject: [PATCH 4/6] =?UTF-8?q?chore=20:=20=EB=94=94=EC=9E=90=EC=9D=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/app/search/HomePage.tsx | 2 +- apps/web/src/queries/searchSongQuery.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/src/app/search/HomePage.tsx b/apps/web/src/app/search/HomePage.tsx index b94d208..ff2bb6c 100644 --- a/apps/web/src/app/search/HomePage.tsx +++ b/apps/web/src/app/search/HomePage.tsx @@ -139,7 +139,7 @@ export default function SearchPage() {
)} - + {searchSongs.length > 0 && (
{searchSongs.map((song, index) => ( diff --git a/apps/web/src/queries/searchSongQuery.ts b/apps/web/src/queries/searchSongQuery.ts index 15f5375..6c71029 100644 --- a/apps/web/src/queries/searchSongQuery.ts +++ b/apps/web/src/queries/searchSongQuery.ts @@ -21,7 +21,7 @@ export const useInfiniteSearchSongQuery = ( queryFn: async ({ pageParam }) => { const response = await getInfiniteSearchSong(search, searchType, isAuthenticated, pageParam); - console.log('response', response); + // console.log('response', response); if (!response.success) { throw new Error('Search API failed'); From 2d824dd2ab2d5dd35b1892071f7afc363d50fd32 Mon Sep 17 00:00:00 2001 From: GulSam00 Date: Sun, 8 Jun 2025 00:06:41 +0900 Subject: [PATCH 5/6] chore : ver 1.5.0 --- apps/web/package.json | 2 +- apps/web/public/changelog.json | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/web/package.json b/apps/web/package.json index bba64d1..9aa64f3 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "web", - "version": "1.4.0", + "version": "1.5.0", "type": "module", "private": true, "scripts": { diff --git a/apps/web/public/changelog.json b/apps/web/public/changelog.json index 521564b..4386806 100644 --- a/apps/web/public/changelog.json +++ b/apps/web/public/changelog.json @@ -32,5 +32,13 @@ "부를곡 페이지에서 재생목록을 통해 노래를 추가할 수 있습니다.", "로직을 수정하여 검색 페이지에서 재생목록으로 저장 시 재생목록의 개수를 확인할 수 있습니다." ] + }, + "1.5.0": { + "title": "버전 1.5.0", + "message": [ + "검색 페이지에서 무한 스크롤 기능이 추가되었습니다.", + "검색 페이지에서 검색 기록 기능이 추가되었습니다.", + "TJ 노래방의 10000개 곡을 업데이트했습니다." + ] } } From e63ff9dc1367a219febadfb861ca3744215fd2d1 Mon Sep 17 00:00:00 2001 From: GulSam00 Date: Sun, 8 Jun 2025 00:10:11 +0900 Subject: [PATCH 6/6] =?UTF-8?q?delete=20:=20shadcn=20spinner=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/components/ui/spinner.tsx | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 apps/web/src/components/ui/spinner.tsx diff --git a/apps/web/src/components/ui/spinner.tsx b/apps/web/src/components/ui/spinner.tsx deleted file mode 100644 index cd89ea3..0000000 --- a/apps/web/src/components/ui/spinner.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { cn } from '@/lib/utils'; - -interface SpinnerProps extends React.HTMLAttributes { - size?: 'sm' | 'md' | 'lg'; -} - -export function Spinner({ className, size = 'md', ...props }: SpinnerProps) { - return ( -
- 로딩 중... -
- ); -}