Skip to content

Commit

Permalink
Merge pull request #152 from 80000Coding/feat/feed-lists
Browse files Browse the repository at this point in the history
feat(web): Feed 리스트 구현
  • Loading branch information
leekh716 authored Sep 25, 2023
2 parents cdb3edb + 4390764 commit 196d43f
Show file tree
Hide file tree
Showing 19 changed files with 427 additions and 9 deletions.
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"autoprefixer": "10.4.14",
"aws-sdk": "^2.1431.0",
"classnames": "^2.3.2",
"date-fns": "^2.30.0",
"framer-motion": "^10.16.0",
"next": "13.4.9",
"open-graph-scraper": "^6.2.2",
Expand Down
11 changes: 11 additions & 0 deletions apps/web/public/profile.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 7 additions & 3 deletions apps/web/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
'use client'

import Header from '@/components/common/Header'
import FeedList from '@/components/main/FeedList'
import Filters from '@/components/main/Filters'
import { listMockData } from '@/components/main/list/mock/listMockData'
import MainQuickPanel from '@/components/main/MainQuickPanel'

export default function Home() {
export default async function Home() {
const result = listMockData

return (
<main>
<Header />
Expand All @@ -13,6 +15,8 @@ export default function Home() {
<MainQuickPanel />
<Filters />
</div>

<FeedList items={result} />
</main>
)
}
1 change: 1 addition & 0 deletions apps/web/src/components/common/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use client'
import { DynamicBackIcon, DynamicCloseIcon, StaticMenuIcon, StaticProfileIcon } from '@80000coding/web-icons'
import {
StaticCategoryIcon,
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/main/CategoryFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default function CategoryFilter() {
return (
<>
<button onClick={onOpen} className='flex shrink-0 items-center gap-x-2 rounded-[20px] border border-gray-300 py-2 pl-4 pr-3'>
<span className='body-3'>카테고리</span>
<span className='body-3 text-gray-600'>카테고리</span>
<span className='body-2 text-green'>{defaultCategory.label}</span>
<StaticFilteringIcon className='mt-0.5 h-[7px] w-[7px]' />
</button>
Expand Down
85 changes: 85 additions & 0 deletions apps/web/src/components/main/Feed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { CategoryIconNames, categoryIcons, Chip } from '@80000coding/ui'
import { StaticCommnetFlatIcon, StaticLikeFlatIcon, StaticScrapFlatIcon, StaticViewFlatIcon } from '@80000coding/web-icons'
import Link from 'next/link'

import { RefinedFeedsType } from './useFeedLists'
import useFeedRouter from './useFeedRouter'
import ImageProfile from '../shared/ImageProfile'

export default function Feed({ item }: { item: RefinedFeedsType }) {
const { moveToContent } = useFeedRouter()

const {
content_id,
title,
body,
displayCommentCount,
displayCreatedAt,
displayLikeCount,
displayBookmarkCount,
displayViewCount,
content_image_url,
profile_image_url,
user_id,
user_name,
hash_tag_list,
category_tag_list,
displayRestTagCount,
} = item

return (
<button onClick={() => moveToContent(content_id)} className='bg-white text-left'>
{content_image_url && <img src={content_image_url} alt={title} className='h-[172px] w-[390px]' />}

<div className='p-5 pt-6'>
<div className='title-1A line-clamp-1'>{title}</div>
<div className='body-3A mb-7 mt-3 line-clamp-2 text-gray-600'>{body}</div>

<div className='flex justify-between'>
<div className='flex items-center gap-x-1'>
{category_tag_list.map(({ category_name }) => (
<div key={category_name}>{categoryIcons[category_name as CategoryIconNames]?.source({ className: 'w-[21px] h-[21px]' })}</div>
))}
</div>
<div className='flex items-center gap-x-2'>
{hash_tag_list.slice(0, 2).map(({ hash_tag_id, hash_tag_name }) => (
<Chip key={hash_tag_id} text={`#${hash_tag_name}`} />
))}
{displayRestTagCount && <Chip text={displayRestTagCount} />}
</div>
</div>
</div>

<div className='flex items-center justify-between px-4 py-3'>
<div className='flex items-center gap-x-2'>
<ImageProfile src={profile_image_url} alt={user_name} className='h-8 w-8 rounded-full' />
<div className='space-y-1'>
<Link href={`/profile/${user_id}`} className='note-1 flex text-gray-700' onClick={(e) => e.stopPropagation()}>
{user_name}
</Link>
<div className='caption-3 text-gray-400'>{displayCreatedAt}</div>
</div>
</div>

<div className='caption-3 flex items-center space-x-4 text-gray-600'>
<div className='flex items-center gap-x-1'>
<StaticViewFlatIcon className='h-3 w-3' />
<span>{displayViewCount}</span>
</div>
<div className='flex items-center gap-x-1'>
<StaticCommnetFlatIcon className='h-3 w-3' />
<span>{displayCommentCount}</span>
</div>
<div className='flex items-center gap-x-1'>
<StaticScrapFlatIcon className='h-3 w-3' />
<span>{displayBookmarkCount}</span>
</div>
<div className='flex items-center gap-x-1'>
<StaticLikeFlatIcon className='h-3 w-3' />
<span>{displayLikeCount}</span>
</div>
</div>
</div>
</button>
)
}
19 changes: 19 additions & 0 deletions apps/web/src/components/main/FeedList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use client'

import Feed from './Feed'
import { ContentListType } from './list/mock/listMockData'
import useFeedLists from './useFeedLists'

export default function FeedList({ items }: { items: ContentListType }) {
const { feeds } = useFeedLists(items)

return (
<div className='min-h-screen space-y-3 bg-gray-200 py-3'>
{feeds.map((feed) => (
<li key={feed.content_id} className='list-none'>
<Feed item={feed} />
</li>
))}
</div>
)
}
2 changes: 2 additions & 0 deletions apps/web/src/components/main/Filters.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use client'

import CategoryFilter from './CategoryFilter'
import OrganizationFilter from './OrganizationFilter'
import SortFilter from './SortFilter'
Expand Down
8 changes: 5 additions & 3 deletions apps/web/src/components/main/MainQuickPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
'use client'

import Link from 'next/link'

import { DEFAULT_MENU_ITEMS } from '../common/Header'

export default function MainQuickPanel() {
return (
<div className='flex items-center divide-x divide-gray-300 border-b border-gray-300 py-3.5'>
<div className='flex items-center divide-x divide-gray-300 border-b border-gray-200 py-3.5'>
<div className='shrink-0 pb-2 pl-9 pr-8 pt-1.5'>
{DEFAULT_MENU_ITEMS.slice(0, 1).map(({ icon: Icon, shortLabel, url }) => (
<Link href={url} key={shortLabel} className='flex flex-col items-center'>
<Icon className='icon-lg' />
<aside className='caption-1'>{shortLabel}</aside>
<aside className='caption-1 text-gray-700'>{shortLabel}</aside>
</Link>
))}
</div>
<div className='flex w-full items-center justify-between pb-2 pl-9 pr-11 pt-1.5'>
{DEFAULT_MENU_ITEMS.slice(1).map(({ icon: Icon, shortLabel, url }) => (
<Link href={url} key={shortLabel} className='flex flex-col items-center'>
<Icon className='icon-lg' />
<aside className='caption-1'>{shortLabel}</aside>
<aside className='caption-1 text-gray-700'>{shortLabel}</aside>
</Link>
))}
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/main/OrganizationFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default function OrganizationFilter() {
return (
<>
<button onClick={onOpen} className='flex shrink-0 items-center gap-x-2 rounded-[20px] border border-gray-300 py-2 pl-4 pr-3'>
<span className='body-3'>조직</span>
<span className='body-3 text-gray-600'>조직</span>
<span className='body-2 text-green'>{defaultOrganization.label}</span>
<StaticFilteringIcon className='mt-0.5 h-[7px] w-[7px]' />
</button>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/main/SortFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default function SortFilter() {
return (
<>
<button onClick={onOpen} className='flex shrink-0 items-center gap-x-2 rounded-[20px] border border-gray-300 py-2 pl-4 pr-3'>
<span className='body-3'>정렬</span>
<span className='body-3 text-gray-600'>정렬</span>
<span className='body-2 text-green'>{defaultSort.label}</span>
<StaticFilteringIcon className='mt-0.5 h-[7px] w-[7px]' />
</button>
Expand Down
154 changes: 154 additions & 0 deletions apps/web/src/components/main/list/mock/listMockData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { ContentFeedType } from './listMockType'

export type ContentListType = {
content: ContentFeedType[]
}

export const listMockData: ContentListType = {
content: [
{
content_id: 1,
content_image_url: 'https://picsum.photos/200/300',
title: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Velit sed ullamcorper morbi tincidunt ornare. Nisl tincidunt eget nullam non nisi est sit amet facilisis. Amet justo donec enim diam vulputate ut pharetra sit. Sed velit dignissim sodales ut eu. Quis enim lobortis scelerisque fermentum dui faucibus in. In ante metus dictum at tempor commodo ullamcorper. Porta nibh venenatis cras sed felis. Phasellus vestibulum lorem sed risus ultricies tristique nulla aliquet enim. Enim nulla aliquet porttitor lacus. Purus gravida quis blandit turpis cursus in hac habitasse. Nisl suscipit adipiscing bibendum est ultricies integer quis. Posuere morbi leo urna molestie at. Faucibus purus in massa tempor nec. Consectetur adipiscing elit ut aliquam purus sit amet luctus venenatis. Ultricies leo integer malesuada nunc vel. Massa tincidunt dui ut ornare lectus sit amet est placerat.',
category_tag_list: [
{
category_id: 1,
category_name: 'NetworkWired',
},
{
category_id: 2,
category_name: 'NetworkWireless',
},
],
hash_tag_list: [
{
hash_tag_id: 1,
hash_tag_name: 'hash',
},
{
hash_tag_id: 2,
hash_tag_name: 'tag',
},
{
hash_tag_id: 3,
hash_tag_name: 'hashTag',
},
{
hash_tag_id: 4,
hash_tag_name: '해시태그',
},
],
profile_image_url: 'https://picsum.photos/200/300',
user_id: 1,
user_name: 'kunlee',
create_dt: '2023-08-30T12:02:52.015Z',
views: 1234,
comment_count: 12,
mark_count: 34,
like_count: 12,
},
{
content_id: 2,
content_image_url: undefined,
title: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Velit sed ullamcorper morbi tincidunt ornare. Nisl tincidunt eget nullam non nisi est sit amet facilisis. Amet justo donec enim diam vulputate ut pharetra sit. Sed velit dignissim sodales ut eu. Quis enim lobortis scelerisque fermentum dui faucibus in. In ante metus dictum at tempor commodo ullamcorper. Porta nibh venenatis cras sed felis. Phasellus vestibulum lorem sed risus ultricies tristique nulla aliquet enim. Enim nulla aliquet porttitor lacus. Purus gravida quis blandit turpis cursus in hac habitasse. Nisl suscipit adipiscing bibendum est ultricies integer quis. Posuere morbi leo urna molestie at. Faucibus purus in massa tempor nec. Consectetur adipiscing elit ut aliquam purus sit amet luctus venenatis. Ultricies leo integer malesuada nunc vel. Massa tincidunt dui ut ornare lectus sit amet est placerat.',
category_tag_list: [
{
category_id: 1,
category_name: 'Microsoft-rounded',
},
{
category_id: 2,
category_name: 'NGINX',
},
],
hash_tag_list: [
{
hash_tag_id: 1,
hash_tag_name: 'hash',
},
{
hash_tag_id: 2,
hash_tag_name: 'tag',
},
{
hash_tag_id: 3,
hash_tag_name: 'hashTag',
},
],
profile_image_url: 'https://80000coding.s3.ap-northeast-2.amazonaws.com/image.png',
user_id: 1,
user_name: 'kunlee',
create_dt: '2023-07-30T12:02:52.015Z',
views: 1234,
comment_count: 1234,
mark_count: 1234,
like_count: 1234,
},
{
content_id: 3,
content_image_url: undefined,
title: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Velit sed ullamcorper morbi tincidunt ornare. Nisl tincidunt eget nullam non nisi est sit amet facilisis. Amet justo donec enim diam vulputate ut pharetra sit. Sed velit dignissim sodales ut eu. Quis enim lobortis scelerisque fermentum dui faucibus in. In ante metus dictum at tempor commodo ullamcorper. Porta nibh venenatis cras sed felis. Phasellus vestibulum lorem sed risus ultricies tristique nulla aliquet enim. Enim nulla aliquet porttitor lacus. Purus gravida quis blandit turpis cursus in hac habitasse. Nisl suscipit adipiscing bibendum est ultricies integer quis. Posuere morbi leo urna molestie at. Faucibus purus in massa tempor nec. Consectetur adipiscing elit ut aliquam purus sit amet luctus venenatis. Ultricies leo integer malesuada nunc vel. Massa tincidunt dui ut ornare lectus sit amet est placerat.',
category_tag_list: [
{
category_id: 1,
category_name: 'NextJs',
},
{
category_id: 2,
category_name: 'Nodejs',
},
],
hash_tag_list: [
{
hash_tag_id: 1,
hash_tag_name: 'hash',
},
],
profile_image_url: 'https://80000coding.s3.ap-northeast-2.amazonaws.com/image.png',
user_id: 1,
user_name: 'kunlee',
create_dt: '2023-07-28T12:02:52.015Z',
views: 1234,
comment_count: 1234,
mark_count: 1234,
like_count: 1234,
},
{
content_id: 4,
content_image_url: undefined,
title: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Velit sed ullamcorper morbi tincidunt ornare. Nisl tincidunt eget nullam non nisi est sit amet facilisis. Amet justo donec enim diam vulputate ut pharetra sit. Sed velit dignissim sodales ut eu. Quis enim lobortis scelerisque fermentum dui faucibus in. In ante metus dictum at tempor commodo ullamcorper. Porta nibh venenatis cras sed felis. Phasellus vestibulum lorem sed risus ultricies tristique nulla aliquet enim. Enim nulla aliquet porttitor lacus. Purus gravida quis blandit turpis cursus in hac habitasse. Nisl suscipit adipiscing bibendum est ultricies integer quis. Posuere morbi leo urna molestie at. Faucibus purus in massa tempor nec. Consectetur adipiscing elit ut aliquam purus sit amet luctus venenatis. Ultricies leo integer malesuada nunc vel. Massa tincidunt dui ut ornare lectus sit amet est placerat.',
category_tag_list: [
{
category_id: 1,
category_name: 'Notion',
},
{
category_id: 2,
category_name: 'Python',
},
],
hash_tag_list: [
{
hash_tag_id: 1,
hash_tag_name: 'hash',
},
{
hash_tag_id: 2,
hash_tag_name: 'tag',
},
],
profile_image_url: 'https://80000coding.s3.ap-northeast-2.amazonaws.com/image.png',
user_id: 1,
user_name: 'kunlee',
create_dt: '2022-06-30T12:02:52.015Z',
views: 1234,
comment_count: 1234,
mark_count: 1234,
like_count: 1234,
},
],
}
26 changes: 26 additions & 0 deletions apps/web/src/components/main/list/mock/listMockType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export type CategoryType = {
category_id: number
category_name: string
}

export type HashTagType = {
hash_tag_id: number
hash_tag_name: string
}

export type ContentFeedType = {
content_id: number // 게시글 id
content_image_url?: string // 게시글 이미지 url
title: string // 제목
body: string // 내용
category_tag_list: CategoryType[] // 카테고리 태그 리스트
hash_tag_list: HashTagType[] // 해시태그 리스트
profile_image_url: string // 프로필 이미지
user_id: number // 유저 아이디
user_name: string // 유저 닉네임
create_dt: string // 업로드 시간
views: number // 조회수
comment_count: number // 댓글 수
mark_count: number // 북마크 수
like_count: number // 좋아요 수
}
Loading

0 comments on commit 196d43f

Please sign in to comment.