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: 5 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"permissions": {
"permissions": {
"defaultMode": "bypassPermissions"
}
},
"hooks": {
"SessionStart": [
{
Expand Down
18 changes: 18 additions & 0 deletions apps/web/public/changelog.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"1.1.0": {
"title": "버전 1.1.0",
"date": "2025-05-12",
"message": [
"기존 노래방 데이터를 새로운 데이터로 교체하였습니다.",
"- TJ 노래방의 38519개의 곡 데이터 업데이트!",
Expand All @@ -9,6 +10,7 @@
},
"1.2.0": {
"title": "버전 1.2.0",
"date": "2025-05-11",
"message": [
"인기곡 페이지를 추가했습니다.",
"- 전체, 연도별, 월별 부른 곡의 통계와 즐겨찾기 한 곡의 통계를 확인할 수 있습니다.",
Expand All @@ -17,6 +19,7 @@
},
"1.3.0": {
"title": "버전 1.3.0",
"date": "2025-05-23",
"message": [
"저장 기능을 추가했습니다.",
"로그인 하지 않고도 인기곡 페이지를 조회할 수 있습니다.",
Expand All @@ -27,6 +30,7 @@

"1.4.0": {
"title": "버전 1.4.0",
"date": "2025-05-24",
"message": [
"스크롤 디자인 높이를 조정했습니다.",
"부를곡 페이지에서 재생목록을 통해 노래를 추가할 수 있습니다.",
Expand All @@ -35,6 +39,7 @@
},
"1.5.0": {
"title": "버전 1.5.0",
"date": "2025-06-08",
"message": [
"검색 페이지에서 무한 스크롤 기능이 추가되었습니다.",
"검색 페이지에서 검색 기록 기능이 추가되었습니다.",
Expand All @@ -43,6 +48,7 @@
},
"1.6.0": {
"title": "버전 1.6.0",
"date": "2025-06-18",
"message": [
"회원 탈퇴 기능이 추가되었습니다.",
"화면 높이를 조정했습니다.",
Expand All @@ -51,29 +57,35 @@
},
"1.7.0": {
"title": "버전 1.7.0",
"date": "2025-08-23",
"message": [
"화면 UX를 개선했습니다. 세부적인 디자인을 조정했습니다.",
"로그인 상태에서 전체 검색 시 오류가 나는 현상을 수정했습니다."
]
},
"1.8.0": {
"title": "버전 1.8.0",
"date": "2025-09-15",
"message": ["노래방에 최근 추가된 곡을 확인할 수 있는 페이지를 추가했습니다."]
},
"1.8.1": {
"title": "버전 1.8.1",
"date": "2025-12-12",
"message": ["UI를 개선했습니다."]
},
"1.9.0": {
"title": "버전 1.9.0",
"date": "2026-01-04",
"message": ["챗봇 기능이 추가되었습니다."]
},
"1.9.1": {
"title": "버전 1.9.1",
"date": "2026-01-12",
"message": ["로그인 인증 이슈를 해결했습니다."]
},
"2.0.0": {
"title": "버전 2.0.0",
"date": "2026-01-26",
"message": [
"출석 체크 기능을 추가했습니다.",
"유저 별 포인트 기능을 추가했습니다.",
Expand All @@ -83,38 +95,44 @@
},
"2.0.1": {
"title": "버전 2.0.1",
"date": "2026-02-03",
"message": [
"로컬 스토리지 저장 기능을 개선했습니다.",
"검색 카드 디자인 및 기능을 개선했습니다."
]
},
"2.1.0": {
"title": "버전 2.1.0",
"date": "2026-02-08",
"message": [
"비로그인 (Guest) 유저로 부를 곡 기능을 사용할 수 있습니다.",
"하단 네비게이션 바에 애니메이션 효과를 추가하여 UX를 개선했습니다."
]
},
"2.2.0": {
"title": "버전 2.2.0",
"date": "2026-02-20",
"message": [
"일본 가수를 한글로 검색할 수 있습니다. 초성으로도 가능합니다.",
"유명 일본 가수를 한눈에 조회할 수 있습니다."
]
},
"2.3.0": {
"title": "버전 2.3.0",
"date": "2026-03-02",
"message": [
"인기곡 페이지의 UI를 개선했습니다. 이제 인기곡 페이지에서 곡을 추천할 수 있습니다.",
"로그인 시 제공되는 코인을 30개로 변경했습니다."
]
},
"2.4.0": {
"title": "버전 2.4.0",
"date": "2026-04-06",
"message": ["네온 나이트 다크 테마를 추가했습니다.", "전체적인 UI를 개선했습니다."]
},
"2.5.0": {
"title": "버전 2.5.0",
"date": "2026-04-19",
"message": ["일본 가수, 곡의 한글 번역을 추가했습니다."]
}
}
18 changes: 16 additions & 2 deletions apps/web/src/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { Check, LogOut, Menu, Pencil, User, X } from 'lucide-react';
import { Check, LogOut, Menu, Pencil, ScrollText, User, X } from 'lucide-react';
import Image from 'next/image';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
Expand Down Expand Up @@ -57,6 +57,11 @@ export default function Sidebar() {
setIsOpenSidebar(false);
};

const handleOpenPatchNotes = () => {
router.push('/patch-notes');
setIsOpenSidebar(false);
};

const handleLogin = () => {
router.push('/login');
setIsOpenSidebar(false);
Expand Down Expand Up @@ -129,7 +134,16 @@ export default function Sidebar() {

<Separator />

<div className="space-y-2"></div>
<div className="space-y-2">
<Button
variant="ghost"
className="w-full justify-start"
onClick={handleOpenPatchNotes}
>
<ScrollText className="mr-2 h-4 w-4" />
패치노트
</Button>
</div>
</div>

<SheetFooter>
Expand Down
78 changes: 78 additions & 0 deletions apps/web/src/app/patch-notes/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
'use client';

import { ArrowLeft } from 'lucide-react';
import { useRouter } from 'next/navigation';

import { Button } from '@/components/ui/button';
import { ScrollArea } from '@/components/ui/scroll-area';

import changelog from '../../../public/changelog.json';

type ChangelogEntry = { title: string; date?: string; message: string[] };

const entries = Object.entries(changelog as Record<string, ChangelogEntry>).reverse();

export default function PatchNotesPage() {
const router = useRouter();

return (
<div className="bg-background flex h-full flex-col">
<div className="flex items-center">
<Button variant="ghost" size="icon" onClick={() => router.back()} className="mr-2">
<ArrowLeft className="h-5 w-5" />
</Button>
<h1 className="text-2xl font-bold">패치노트</h1>
</div>

<ScrollArea className="mt-4 flex-1">
<ol className="relative flex flex-col gap-6 pb-8">
<span
aria-hidden
className="bg-border absolute top-3 bottom-3 left-[5rem] w-px sm:left-[6rem]"
/>

{entries.map(([version, entry]) => (
<li
key={version}
className="grid grid-cols-[4rem_2rem_1fr] items-start sm:grid-cols-[5rem_2rem_1fr]"
>
<div className="text-muted-foreground text-right text-xs leading-5">
{entry.date ?? ''}
</div>

<div className="relative h-5">
<span
aria-hidden
className="border-border absolute top-1/2 right-0 left-0 -translate-y-1/2 border-t border-dashed"
/>
<span
aria-hidden
className="bg-primary absolute top-1/2 left-1/2 h-1.5 w-1.5 -translate-x-1/2 -translate-y-1/2 rounded-full"
/>
</div>

<div className="flex flex-col gap-1 pl-2">
<div className="text-base leading-5 font-semibold">버전 {version}</div>
<ul className="flex flex-col gap-1">
{entry.message.map((line, idx) => {
const isSub = line.startsWith('-');
return (
<li
key={idx}
className={
isSub ? 'text-muted-foreground pl-4 text-sm' : 'text-sm font-medium'
}
>
{isSub ? line : `• ${line}`}
</li>
);
})}
</ul>
</div>
</li>
))}
</ol>
</ScrollArea>
</div>
);
}
61 changes: 27 additions & 34 deletions apps/web/src/app/search/SearchHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,48 +9,41 @@ interface SearchHistoryProps {

export default function SearchHistory({ onHistoryClick }: SearchHistoryProps) {
const { searchHistory, removeFromHistory } = useSearchHistoryStore();
const [isHydrated, setIsHydrated] = useState(false);

useEffect(() => {
if (searchHistory.length > 0) {
setIsHydrated(true);
}
}, [searchHistory]);

return (
<div className="h-30 overflow-hidden">
<div className="flex items-center gap-2">
<Clock className="h-4 w-4" />
<p className="m-2">최근 검색어</p>
</div>
{!isHydrated ? (
<div className="flex items-center justify-center py-4">
<Loader2 className="h-5 w-5 animate-spin" />
</div>
) : (
<div className="flex flex-wrap gap-2 pb-4">
{searchHistory.slice(0, 10).map((term, index) => (
<div
key={`${term}-${index}`}
className="bg-background flex items-center gap-2 rounded-full border px-3 py-1.5 text-sm"

<div className="flex flex-wrap gap-2 pb-4">
{searchHistory.length === 0 && (
<div className="text-muted-foreground flex h-15 w-full items-center justify-center">
최근 검색어가 없습니다.
</div>
)}
{searchHistory.slice(0, 10).map((term, index) => (
<div
key={`${term}-${index}`}
className="bg-background flex items-center gap-2 rounded-full border px-3 py-1.5 text-sm"
>
<span
className="hover:text-primary max-w-30 cursor-pointer truncate text-left"
onClick={() => onHistoryClick(term)}
>
<span
className="hover:text-primary max-w-30 cursor-pointer truncate text-left"
onClick={() => onHistoryClick(term)}
>
{term}
</span>
<span
className="hover:text-destructive cursor-pointer"
onClick={() => removeFromHistory(term)}
title="검색 기록 삭제"
>
<X className="h-4 w-4" />
</span>
</div>
))}
</div>
)}
{term}
</span>
<span
className="hover:text-destructive cursor-pointer"
onClick={() => removeFromHistory(term)}
title="검색 기록 삭제"
>
<X className="h-4 w-4" />
</span>
</div>
))}
</div>
</div>
);
}
1 change: 1 addition & 0 deletions apps/web/src/auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const ALLOW_PATHS = [
'/recent',
'/tosing',
'/update-password',
'/patch-notes',
];

export default function AuthProvider({ children }: { children: React.ReactNode }) {
Expand Down