Skip to content

Commit 5110af6

Browse files
authored
Merge pull request #88 from DevKor-github/fix/#32/home-page
[#32] ν™ˆν™”λ©΄ λ””μžμΈ μˆ˜μ •
2 parents c303a5d + bcf213e commit 5110af6

File tree

8 files changed

+132
-58
lines changed

8 files changed

+132
-58
lines changed

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

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,47 @@
1-
import type { ItemInfoInterface } from '@/features/detail/types';
21
import Token from '@/common/components/Token';
3-
import { TAG_TYPES_MAP, type TagType } from '@/libs/types/item';
2+
import {
3+
TAG_TYPES_MAP,
4+
type Color,
5+
type ProductType,
6+
type Quality,
7+
type Size,
8+
type TagType,
9+
type TradeMethods,
10+
type TransactionType,
11+
} from '@/libs/types/item';
412

513
interface Props {
6-
itemInfo: ItemInfoInterface;
14+
itemInfo: {
15+
productTypes?: ProductType[];
16+
transactionTypes?: TransactionType[];
17+
color?: Color;
18+
tradeMethods?: TradeMethods[];
19+
quality?: Quality;
20+
size: Size;
21+
};
22+
showAll?: boolean;
723
}
8-
const ItemTokenList = ({ itemInfo }: Props) => {
24+
const ItemTokenList = ({ itemInfo, showAll = true }: Props) => {
925
const tags: TagType[] = [
10-
...itemInfo.transactionTypes,
11-
...itemInfo.productTypes,
12-
itemInfo.color,
13-
...itemInfo.tradeMethods,
14-
itemInfo.quality,
15-
itemInfo.size,
26+
...(itemInfo.transactionTypes || []),
27+
...(itemInfo.productTypes || []),
28+
...(itemInfo.size ? [itemInfo.size] : []),
29+
...(itemInfo.quality ? [itemInfo.quality] : []),
30+
...(itemInfo.color ? [itemInfo.color] : []),
31+
...(itemInfo.tradeMethods || []),
1632
];
33+
const showTags = showAll ? tags : tags.slice(0, 4);
34+
const noneShownCount = tags.length - showTags.length;
1735

1836
return (
1937
<>
20-
{tags.map(type => (
21-
<Token key={type}>{TAG_TYPES_MAP[type]}</Token>
22-
))}
38+
{showTags.map(type => {
39+
// κΈ°νƒ€λŠ” ν‘œμ‹œ X
40+
if (type === 'COLOR_OTHER' || type === 'PRODUCT_OTHER') return null;
41+
42+
return <Token key={type}>{TAG_TYPES_MAP[type]}</Token>;
43+
})}
44+
{!showAll && noneShownCount > 0 && <Token>+{noneShownCount}</Token>}
2345
</>
2446
);
2547
};

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ export const Container = css({
99
fontSize: '0.625rem',
1010
fontWeight: 500,
1111
letterSpacing: '-0.025rem',
12+
flexShrink: 0,
1213
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import * as s from './style.css';
2+
3+
interface Props {
4+
price: number;
5+
deposit?: number;
6+
}
7+
const PriceToken = ({ price, deposit }: Props) => {
8+
const isRental = deposit !== undefined;
9+
return (
10+
<div className={s.PriceItem}>
11+
<label>{isRental ? 'λŒ€μ—¬' : '판맀'}</label>
12+
<p>{price.toLocaleString()}원</p>
13+
{isRental && (
14+
<p>
15+
<label>보증금</label>
16+
{deposit.toLocaleString()}원
17+
</p>
18+
)}
19+
</div>
20+
);
21+
};
22+
export default PriceToken;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { css } from '@styled-system/css';
2+
3+
export const PriceItem = css({
4+
display: 'flex',
5+
alignItems: 'center',
6+
gap: '0.375rem',
7+
'& > label': {
8+
padding: '0.125rem 0.25rem',
9+
display: 'flex',
10+
alignItems: 'center',
11+
justifyContent: 'center',
12+
rounded: '0.25rem',
13+
bgColor: 'systemGray4',
14+
color: '54',
15+
fontSize: '0.625rem',
16+
fontWeight: 500,
17+
lineHeight: 1.4,
18+
letterSpacing: '-0.025rem',
19+
flexShrink: 0,
20+
},
21+
'& p': {
22+
color: '100',
23+
fontSize: '1rem',
24+
fontWeight: 600,
25+
lineHeight: 1.4,
26+
letterSpacing: '-0.04rem',
27+
display: 'flex',
28+
gap: '0.375rem',
29+
alignItems: 'baseline',
30+
'& > label': {
31+
color: '54',
32+
fontSize: '0.875rem',
33+
fontWeight: 500,
34+
letterSpacing: '-0.035rem',
35+
},
36+
},
37+
});

β€Žsrc/features/home/components/ItemCard/index.tsxβ€Ž

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,40 @@ import { Link } from 'react-router';
22

33
import * as s from './style.css';
44

5-
import { PRODUCT_TYPES_MAP } from '@/libs/types/item';
65
import type { ItemInterface } from '@/features/home/types';
7-
import Token from '@/common/components/Token';
6+
import ItemTokenList from '@/common/components/ItemTokenList';
7+
import PriceToken from '@/features/home/components/ItemCard/PriceToken';
88

99
interface Props {
1010
data: ItemInterface;
1111
}
1212
const ItemCard = ({ data }: Props) => {
13+
const isRental = data.transactionTypes.includes('RENTAL');
14+
const isSale = data.transactionTypes.includes('SALE');
15+
1316
return (
1417
<Link className={s.Container} to={`/detail/${data.itemId}`}>
1518
<img className={s.Image} src={data.thumbnail} aria-hidden />
1619
<div className={s.Info}>
1720
<div className={s.Header}>
1821
<h2 className={s.Title}>{data.title}</h2>
1922
<div className={s.Price}>
20-
<div className={s.PriceItem}>
21-
<label>λŒ€μ—¬λ£Œ</label>
22-
<p>{data.rentalFee.toLocaleString()}원</p>
23-
</div>
24-
<div className={s.PriceItem}>
25-
<label>보증금</label>
26-
<p>{data.deposit.toLocaleString()}원</p>
27-
</div>
23+
{isRental && <PriceToken price={data.rentalFee} deposit={data.deposit} />}
24+
{isSale && <PriceToken price={data.salePrice} />}
2825
</div>
2926
</div>
3027
<div className={s.Footer}>
3128
<div className={s.Tokens}>
32-
{data.productTypes.map((type, index) => (
33-
<Token key={`${type}-${index}`}>{PRODUCT_TYPES_MAP[type]}</Token>
34-
))}
29+
{/* TODO: API μˆ˜μ • μš”μ²­ */}
30+
<ItemTokenList
31+
showAll={false}
32+
itemInfo={{
33+
productTypes: data.productTypes,
34+
quality: 'BEST',
35+
size: 'L',
36+
tradeMethods: ['DIRECT'],
37+
}}
38+
/>
3539
</div>
3640
<div className={s.Interactions}>
3741
<div className={s.InteractionItem}>

β€Žsrc/features/home/components/ItemCard/style.css.tsβ€Ž

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,84 +2,71 @@ import { css } from '@styled-system/css';
22

33
export const Container = css({
44
w: 'full',
5-
h: '6.25rem',
5+
h: '6.5rem',
66
display: 'flex',
77
alignItems: 'stretch',
88
gap: '1rem',
99
});
1010

1111
export const Image = css({
12-
w: '6.25rem',
13-
h: '6.25rem',
14-
borderRadius: '12.5px',
12+
w: '6.5rem',
13+
h: '6.5rem',
14+
borderRadius: '0.78125rem',
1515
objectFit: 'cover',
16+
flexShrink: 0,
1617
});
1718

1819
export const Info = css({
1920
flex: '1 0 0',
2021
display: 'flex',
2122
flexDir: 'column',
2223
justifyContent: 'space-between',
23-
padding: '0.25rem 0',
24+
padding: '0.125rem 0',
25+
overflow: 'hidden',
2426
});
2527

2628
export const Header = css({
2729
display: 'flex',
2830
flexDir: 'column',
2931
gap: '0.25rem',
32+
alignItems: 'stretch',
3033
});
3134

3235
export const Title = css({
3336
color: '100',
3437
fontSize: '1rem',
35-
fontWeight: 500,
36-
lineHeight: 1.2,
38+
fontWeight: 400,
39+
lineHeight: 'normal',
3740
letterSpacing: '-0.04rem',
41+
lineClamp: 1,
3842
});
3943

4044
export const Price = css({
4145
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-
},
46+
flexDir: 'column',
47+
gap: '0.125rem',
6548
});
6649

6750
export const Footer = css({
6851
display: 'flex',
6952
alignItems: 'center',
7053
justifyContent: 'space-between',
54+
width: 'full',
55+
gap: '0.25rem',
7156
});
7257

7358
export const Tokens = css({
7459
display: 'flex',
7560
alignItems: 'center',
7661
gap: '0.25rem',
62+
overflowX: 'auto',
7763
});
7864

7965
export const Interactions = css({
8066
display: 'flex',
8167
alignItems: 'center',
82-
gap: '0.875rem',
68+
gap: '0.625rem',
69+
flexShrink: 0,
8370
});
8471

8572
export const InteractionItem = css({

β€Žsrc/libs/constants/index.tsβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const MAX_PRICE = 999999;

β€Žsrc/libs/types/item.tsβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export const PRODUCT_TYPES_MAP = {
66
SOCCER: '좕ꡬ',
77
BASKETBALL: '농ꡬ',
88
BASEBALL: '야ꡬ',
9-
HOCKEY: 'μ•„μ΄μŠ€ν•˜ν‚€',
9+
HOCKEY: 'ν•˜ν‚€',
1010
VARSITY_JACKET: '과잠',
1111
ACCESSORY: '악세사리',
1212
SELF_MADE: 'μžμ²΄μ œμž‘',

0 commit comments

Comments
Β (0)