Skip to content

Commit 6ec6896

Browse files
authored
Merge pull request #48 from DevKor-github/feat/#27/item-card
[ν™ˆν™”λ©΄ / #27] μƒν’ˆ μΉ΄λ“œ κ΅¬ν˜„ κ΅¬ν˜„!
2 parents 24a2801 + caffafb commit 6ec6896

14 files changed

Lines changed: 281 additions & 2 deletions

File tree

β€Žsrc/common/components/Navigator/index.tsxβ€Ž

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Link, useLocation } from 'react-router';
22
import * as s from './style.css';
3+
import { NAVIGATOR_HEIGHT_PX } from '@/libs/constants/sizes';
34

45
const MENU_LIST = [
56
{
@@ -33,7 +34,7 @@ const Navigator = () => {
3334
const { pathname } = useLocation();
3435

3536
return (
36-
<nav className={s.Container}>
37+
<nav className={s.Container} style={{ height: `${NAVIGATOR_HEIGHT_PX}px` }}>
3738
{MENU_LIST.map(({ label, path, selectedClassName, unSelectedClassName }) => {
3839
const selected = pathname === path;
3940
return (

β€Žsrc/common/components/Navigator/style.css.tsβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const Menu = cva({
2727
flexShrink: 0,
2828
textAlign: 'center',
2929
fontSize: '0.875rem',
30-
lineHeight: 'normal',
30+
lineHeight: 1.2,
3131
letterSpacing: '-0.0175rem',
3232
cursor: 'pointer',
3333
'& p': {

β€Žsrc/common/components/SafeArea/style.css.tsβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ import { css } from '@styled-system/css';
22

33
export const Container = css({
44
position: 'absolute',
5+
bottom: 0,
56
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import type { PropsWithChildren } from 'react';
2+
3+
import * as s from './style.css';
4+
5+
const Token = ({ children }: PropsWithChildren) => {
6+
return <span className={s.Container}>{children}</span>;
7+
};
8+
export default Token;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { css } from '@styled-system/css';
2+
3+
export const Container = css({
4+
padding: '0.1875rem 0.3125rem',
5+
borderRadius: '4px',
6+
bgColor: 'main-26',
7+
color: 'main',
8+
fontSize: '0.625rem',
9+
fontWeight: 500,
10+
letterSpacing: '-0.025rem',
11+
});
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { PRODUCT_TYPES_MAP, type PostInterface } from '@/libs/types/post';
2+
3+
import * as s from './style.css';
4+
5+
import Token from '@/common/components/Token';
6+
7+
interface Props {
8+
data: PostInterface;
9+
}
10+
const PostCard = ({ data }: Props) => {
11+
return (
12+
<div className={s.Container}>
13+
<img className={s.Image} src={data.thumbnail} aria-hidden />
14+
<div className={s.Info}>
15+
<div className={s.Header}>
16+
<h2 className={s.Title}>{data.title}</h2>
17+
<div className={s.Price}>
18+
<div className={s.PriceItem}>
19+
<label>λŒ€μ—¬λ£Œ</label>
20+
<p>{data.price.toLocaleString()}원</p>
21+
</div>
22+
<div className={s.PriceItem}>
23+
<label>보증금</label>
24+
<p>{data.price.toLocaleString()}원</p>
25+
</div>
26+
</div>
27+
</div>
28+
<div className={s.Footer}>
29+
<div className={s.Tokens}>
30+
{data.productTypes.map((type, index) => (
31+
<Token key={`${type}-${index}`}>{PRODUCT_TYPES_MAP[type]}</Token>
32+
))}
33+
</div>
34+
<div className={s.Interactions}>
35+
<div className={s.InteractionItem}>
36+
<span className="mgc_heart_fill" />
37+
<p>{data.likeCount}</p>
38+
</div>
39+
<div className={s.InteractionItem}>
40+
<span className="mgc_chat_2_fill" />
41+
<p>{data.chatRoomCount}</p>
42+
</div>
43+
</div>
44+
</div>
45+
</div>
46+
</div>
47+
);
48+
};
49+
export default PostCard;
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { css } from '@styled-system/css';
2+
3+
export const Container = css({
4+
w: 'full',
5+
h: '6.25rem',
6+
display: 'flex',
7+
alignItems: 'stretch',
8+
gap: '1rem',
9+
});
10+
11+
export const Image = css({
12+
w: '6.25rem',
13+
h: '6.25rem',
14+
borderRadius: '12.5px',
15+
objectFit: 'cover',
16+
});
17+
18+
export const Info = css({
19+
flex: '1 0 0',
20+
display: 'flex',
21+
flexDir: 'column',
22+
justifyContent: 'space-between',
23+
padding: '0.25rem 0',
24+
});
25+
26+
export const Header = css({
27+
display: 'flex',
28+
flexDir: 'column',
29+
gap: '0.25rem',
30+
});
31+
32+
export const Title = css({
33+
color: '100',
34+
fontSize: '1rem',
35+
fontWeight: 500,
36+
lineHeight: 1.2,
37+
letterSpacing: '-0.04rem',
38+
});
39+
40+
export const Price = css({
41+
display: 'flex',
42+
alignItems: 'center',
43+
gap: '0.875rem',
44+
height: '1.5625rem',
45+
});
46+
47+
export const PriceItem = css({
48+
display: 'flex',
49+
alignItems: 'baseline',
50+
gap: '0.25rem',
51+
'& label': {
52+
color: '54',
53+
fontSize: '0.875rem',
54+
fontWeight: 500,
55+
lineHeight: 1.4,
56+
letterSpacing: '-0.035rem',
57+
},
58+
'& p': {
59+
color: '100',
60+
fontSize: '1rem',
61+
fontWeight: 600,
62+
lineHeight: 1.4,
63+
letterSpacing: '-0.04rem',
64+
},
65+
});
66+
67+
export const Footer = css({
68+
display: 'flex',
69+
alignItems: 'center',
70+
justifyContent: 'space-between',
71+
});
72+
73+
export const Tokens = css({
74+
display: 'flex',
75+
alignItems: 'center',
76+
gap: '0.25rem',
77+
});
78+
79+
export const Interactions = css({
80+
display: 'flex',
81+
alignItems: 'center',
82+
gap: '0.875rem',
83+
});
84+
85+
export const InteractionItem = css({
86+
display: 'flex',
87+
alignItems: 'flex-end',
88+
gap: '0.1875rem',
89+
color: '54',
90+
'& span': {
91+
fontSize: '1rem',
92+
},
93+
'& p': {
94+
fontSize: '0.75rem',
95+
fontWeight: 400,
96+
letterSpacing: '-0.03rem',
97+
lineHeight: 1.2,
98+
},
99+
});
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import PostCard from '@/features/home/components/PostCard';
2+
import { useGetPostList } from '@/features/home/hooks/apis/useGetPostList';
3+
4+
import * as s from './style.css';
5+
6+
const RecentList = () => {
7+
const { data: postList } = useGetPostList();
8+
9+
return (
10+
<div className={s.Wrapper}>
11+
<h2 className={s.Title}>μ΅œμ‹  μƒν’ˆ</h2>
12+
<div className={s.PostList}>{postList?.map(post => <PostCard key={post.id} data={post} />)}</div>
13+
</div>
14+
);
15+
};
16+
export default RecentList;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { css } from '@styled-system/css';
2+
3+
export const Wrapper = css({
4+
display: 'flex',
5+
flexDir: 'column',
6+
gap: '0.625rem',
7+
px: '1rem',
8+
w: 'full',
9+
});
10+
11+
export const Title = css({
12+
color: '100',
13+
fontSize: '1rem',
14+
lineHeight: 1.4,
15+
letterSpacing: '-0.0255rem',
16+
fontWeight: 600,
17+
});
18+
19+
export const PostList = css({
20+
display: 'flex',
21+
flexDir: 'column',
22+
gap: '1rem',
23+
});
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import client from '@/common/utils/client';
2+
import type { PostInterface } from '@/libs/types/post';
3+
import { useQuery } from '@tanstack/react-query';
4+
5+
const getPostList = async () => {
6+
const response = await client.get<{ message: string; data: PostInterface[] }>('/api/v1/post/search');
7+
return response.data;
8+
};
9+
10+
export const useGetPostList = () => {
11+
return useQuery({
12+
queryKey: ['post-list'],
13+
queryFn: getPostList,
14+
select: data => data.data as PostInterface[],
15+
});
16+
};

0 commit comments

Comments
Β (0)