Skip to content

Commit

Permalink
Merge pull request #47 from dnd-side-project/feat/#42
Browse files Browse the repository at this point in the history
feat: 별별 저장소 페이지 UI 작업
  • Loading branch information
lsy20140 authored Aug 22, 2024
2 parents 940f130 + 0a18777 commit 566a735
Show file tree
Hide file tree
Showing 21 changed files with 249 additions and 72 deletions.
3 changes: 0 additions & 3 deletions public/icons/bookmark.svg

This file was deleted.

3 changes: 3 additions & 0 deletions public/icons/bookmark_fill.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/icons/bookmark_outline.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 67 additions & 0 deletions src/app/bookmarks/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use client'
import { words } from '@/components/shared/WordListItem/data'
import TabFilter from '@/components/domain/dictionary/TabFilter'
import Header from '@/components/shared/Header'
import TopButton from '@/components/shared/TopButton'
import { FilterType, SimpleWordType } from '@/types/word'
import { useSearchParams } from 'next/navigation'
import WordListItem from '@/components/shared/WordListItem'
import Link from 'next/link'
import Image from 'next/image'
import EmptyLayout from '@/components/shared/EmptyLayout'

export default function BookmarksPage() {
const searchParams = useSearchParams()
const filters: FilterType[] = ['전체', '개발', '디자인', '비즈니스']
const category: any = searchParams.get('category') ?? '전체'
const wordCount = words.length

return (
<>
<Header title="별별 저장소" />
{wordCount === 0 ? (
<div className="h-[calc(100%-90px)]">
<EmptyLayout target="bookmarks" />
</div>
) : (
<div className="relative overflow-y-auto bg-background text-onSurface-300">
<div className="flex gap-2 px-4 pt-1 mb-5">
{filters.map((filter: FilterType, idx: number) => (
<TabFilter
isSelected={filter === category}
filter={filter}
key={idx}
/>
))}
</div>
<div className="px-4 mb-2">
<p className="text-body3 text-onSurface-200 mb-4">
나만의 별 단어 {wordCount}
</p>
<Link
href={'/dictionary'}
className="flex justify-between p-4 rounded-lg bg-gray-800 hover:bg-gray-700"
>
<p className="text-sub3">
<span className="text-primary-400">별 단어</span>라고 생각이
드는 실무 용어를 더 추가해보세요.
</p>
<Image
alt="dictionary"
width={20}
height={20}
src={'/icons/right_arrow.svg'}
/>
</Link>
</div>

{words.map((word: SimpleWordType, idx: number) => (
<WordListItem key={word.id} word={word} isMarked showBookmarkBtn />
))}
</div>
)}

<TopButton />
</>
)
}
10 changes: 2 additions & 8 deletions src/app/dictionary/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import TabFilter from '@/components/domain/dictionary/TabFilter'
import WordsList from '@/components/domain/dictionary/WordsList'
import SearchHeader from '@/components/shared/SearchHeader'
import TopButton from '@/components/shared/TopButton'
import { FilterType } from '@/types/word'
import Image from 'next/image'
import { useSearchParams } from 'next/navigation'

export default function DictionaryPage() {
Expand Down Expand Up @@ -33,13 +33,7 @@ export default function DictionaryPage() {
</div>
<WordsList category={category} />
</div>
{/* floating button */}
<button
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
className="fixed bottom-10 right-4 w-14 h-14 p-4 rounded-full bg-gray-800"
>
<Image alt="up" src={'/icons/arrow_up.svg'} width={24} height={24} />
</button>
<TopButton />
</>
)
}
2 changes: 1 addition & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default function RootLayout({
<body
className={`flex justify-center min-h-dvh ${pretendard.variable} font-pretendard ${notoSansKr.variable}`}
>
<div className="w-full max-w-[430px] bg-black whitespace-pre-wrap">
<div className="w-full max-w-[430px] bg-background whitespace-pre-wrap">
{children}
</div>
</body>
Expand Down
18 changes: 15 additions & 3 deletions src/app/words/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
import Header from '@/components/domain/wordDetail/Header'
import WordInfo from '@/components/domain/wordDetail/WordInfo'
import { wordData } from './data'
import ContactButton from '@/components/domain/wordDetail/ContactButton'
import CommentsList from '@/components/domain/wordDetail/CommentsList'
import Header from '@/components/shared/Header'
import BookmarkButton from '@/components/shared/BookmarkButton'

export default function WordDetailPage({
params,
}: {
params: { slug: string }
}) {
const wordId = parseInt(params.slug.split('/').at(-1) ?? '')
const markCount = 23
return (
<div className=" text-onSurface-300">
<Header markedCount={wordData.markedCount} />
<div className="text-onSurface-300">
<Header
title="실무 영어"
rightItem={
<BookmarkButton
isMarked={false}
wordId={wordId}
markCount={markCount}
/>
}
/>
<WordInfo word={wordData} />
<ContactButton />
<CommentsList />
Expand Down
4 changes: 2 additions & 2 deletions src/components/domain/dictionary/TabFilter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ export default function TabFilter({
)

const handleSelect = () => {
router.push(pathname + '?' + createQueryString('category', filter))
router.replace(pathname + '?' + createQueryString('category', filter))
}

return (
<button
className={cn('w-fit px-3 py-[7px] rounded-full ', {
className={cn('w-fit px-3 py-[7px] rounded-full', {
'bg-primary-400 text-background': isSelected,
'bg-none text-onSurface-300 outline outline-outline': !isSelected,
})}
Expand Down
6 changes: 3 additions & 3 deletions src/components/domain/dictionary/WordsList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import WordListItem from '@/components/shared/WordListItem'
import { words } from '@/components/shared/WordListItem/data'
import { FilterType, SimpleWordType } from '@/types/word'
import { words } from '../OneWordItem/data'
import OneWordItem from '../OneWordItem'

type WordsListProps = {
category: FilterType
Expand All @@ -10,7 +10,7 @@ export default function WordsList({ category }: WordsListProps) {
return (
<>
{words.map((word: SimpleWordType, idx: number) => (
<OneWordItem key={word.id} word={word} />
<WordListItem key={word.id} word={word} />
))}
</>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { WordItemProps } from '../../../../shared/WordItem'
import { WordCardProps } from '@/components/shared/WordCard'

export const WordsList: WordItemProps[] = [
export const WordsList: WordCardProps[] = [
{
id: 0,
name: 'Agenda',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import HorizontalScrollArea from '@/components/common/HorizontalScrollArea'
import WordItem, { WordItemProps } from '../../../../shared/WordItem'
import WordCard, { WordCardProps } from '@/components/shared/WordCard'

export default function RecentlyAddedWords({
wordsList,
}: {
wordsList: WordItemProps[]
wordsList: WordCardProps[]
}) {
return (
<>
<HorizontalScrollArea title="최근 등록된 업무 용어 🌟" scrollDivisor={2}>
{wordsList.map(({ id, name, meaning, category }, idx) => (
<WordItem
<WordCard
key={id}
id={id}
name={name}
Expand Down
6 changes: 3 additions & 3 deletions src/components/domain/home/learning/TodayWords/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import HorizontalScrollArea from '@/components/common/HorizontalScrollArea'
import WordItem, { WordItemProps } from '@/components/shared/WordItem'
import WordCard, { WordCardProps } from '@/components/shared/WordCard'

export default function TodayWords({
wordsList,
}: {
wordsList: WordItemProps[]
wordsList: WordCardProps[]
}) {
return (
<>
<HorizontalScrollArea title="오늘의 실무 용어 🔭" scrollDivisor={2}>
{wordsList.map(({ id, name, meaning, category }, idx) => (
<WordItem
<WordCard
key={id}
id={id}
name={name}
Expand Down
35 changes: 0 additions & 35 deletions src/components/domain/wordDetail/Header/index.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/domain/wordDetail/WordInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function WordInfo({ word }: { word: DetailWordType }) {
return (
<>
{/* 용어 상세 기본 정보 */}
<div className="py-10 border-b-[1px] border-outline px-4">
<div className="py-7 border-b-[1px] border-outline px-4">
<CategoryTag category={category} />
<div className="flex flex-col gap-1 mt-3">
<p className="text-h2">{name}</p>
Expand Down
33 changes: 33 additions & 0 deletions src/components/shared/BookmarkButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use client'
import Image from 'next/image'

type BookmarkButtonProps = {
wordId: number
isMarked: boolean
markCount?: number
}

export default function BookmarkButton({
wordId,
isMarked,
markCount,
}: BookmarkButtonProps) {
const handleClick = (e: React.MouseEvent) => {
e.preventDefault()
alert(`${wordId} 북마크`)
}
return (
<button>
<Image
alt="bookmark"
src={
isMarked ? '/icons/bookmark_fill.svg' : '/icons/bookmark_outline.svg'
}
width={24}
height={24}
onClick={handleClick}
/>
<p className="text-caption text-onSurface-200">{markCount}</p>
</button>
)
}
53 changes: 53 additions & 0 deletions src/components/shared/Header/Header.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { Meta, StoryObj } from '@storybook/react'
import Header from '.'
import {
AppRouterContext,
type AppRouterInstance,
} from 'next/dist/shared/lib/app-router-context.shared-runtime'
import BookmarkButton from '../BookmarkButton'

const meta: Meta<typeof Header> = {
title: 'components/Header',
component: Header,
tags: ['autodocs'],
decorators: [
(Story) => (
<AppRouterContext.Provider value={{} as AppRouterInstance}>
<Story />
</AppRouterContext.Provider>
),
],
argTypes: {
title: {
description: '헤더 중앙에 표기할 텍스트를 작성합니다.',
},
rightItem: {
description: '헤더 맨 우측에 표기할 요소를 작성합니다.',
},
},
}

export default meta

type Story = StoryObj<typeof Header>

export const Default: Story = {
args: {
title: '실무 용어',
},
}

export const HeaderWithRightItem: Story = {
render: () => (
<>
<Header
title="실무 용어"
rightItem={<BookmarkButton isMarked={false} markCount={8} wordId={2} />}
/>
<Header
title="실무 용어"
rightItem={<BookmarkButton isMarked={true} markCount={34} wordId={1} />}
/>
</>
),
}
26 changes: 26 additions & 0 deletions src/components/shared/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use client'
import Image from 'next/image'
import { useRouter } from 'next/navigation'

type HeaderProps = {
title: string
rightItem?: React.ReactNode
}

export default function Header({ title, rightItem }: HeaderProps) {
const router = useRouter()
return (
<header className="w-full h-[90px] sticky top-0 flex justify-between items-start pt-8 pb-4 px-4 z-50 bg-background text-onSurface-300">
<Image
alt="back"
src={'/icons/left_arrow.svg'}
width={24}
height={24}
className="cursor-pointer"
onClick={() => router.back()}
/>
<p className="text-sub1">{title}</p>
{rightItem ?? <div className="text-center w-6 h-6"></div>}
</header>
)
}
Loading

0 comments on commit 566a735

Please sign in to comment.