Skip to content

Commit 934a0e9

Browse files
authored
Merge pull request #199 from DevKor-github/feat/#169/my-trade
feat: ν”„λ‘œν•„ 이미지 μˆ˜μ •
2 parents 7e1632a + 15ebd2e commit 934a0e9

14 files changed

Lines changed: 212 additions & 23 deletions

File tree

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ interface Props {
66
src: string | null;
77
nickname: string;
88
isMyEdit?: boolean;
9+
isEdited?: boolean;
910
}
1011

11-
export const UserProfileImage = ({ src, nickname, isMyEdit }: Props) => {
12-
const cn = isMyEdit ? s.MyProfileEditImage : s.ProfileImage;
12+
export const UserProfileImage = ({ src, nickname, isMyEdit, isEdited }: Props) => {
13+
const cn = isMyEdit ? s.MyProfileEditImage({ isImgEdited: isEdited }) : s.ProfileImage;
1314
const profileImage = src ? getImageUrl(src) : defaultImg;
1415

1516
return <img className={cn} src={profileImage} alt={nickname} />;
Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { css } from '@styled-system/css';
1+
import { css, cva } from '@styled-system/css';
22

33
export const ProfileImage = css({
44
w: '2.625rem',
@@ -11,13 +11,23 @@ export const ProfileImage = css({
1111
objectFit: 'cover',
1212
});
1313

14-
export const MyProfileEditImage = css({
15-
borderRadius: 'full',
16-
display: 'block',
17-
w: '7.5rem',
18-
h: '7.5rem',
19-
flexShrink: 0,
20-
aspectRatio: '1/1',
21-
bg: 'systemGray4',
22-
objectFit: 'cover',
14+
export const MyProfileEditImage = cva({
15+
base: {
16+
borderRadius: 'full',
17+
display: 'block',
18+
w: '7.5rem',
19+
h: '7.5rem',
20+
flexShrink: 0,
21+
aspectRatio: '1/1',
22+
bg: 'systemGray4',
23+
objectFit: 'cover',
24+
border: '1px solid #2C2C2E',
25+
},
26+
variants: {
27+
isImgEdited: {
28+
true: {
29+
// ν”Όκ·Έλ§ˆ λ‹΅λ³€ λ°›κ³  μˆ˜μ •
30+
},
31+
},
32+
},
2333
});

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import type { ItemInterface } from '@/features/home/types';
66
import ItemTokenList from '@/common/components/ItemTokenList';
77
import PriceToken from '@/features/home/components/ItemCard/PriceToken';
88
import getImageUrl from '@/common/utils/getImageUrl';
9+
import type { UserItemInterface } from '@/features/myTrade/types';
910

1011
interface Props {
11-
data: ItemInterface;
12+
data: ItemInterface | UserItemInterface;
1213
}
1314
const ItemCard = ({ data }: Props) => {
1415
const isRental = data.transactionTypes.includes('RENTAL');

β€Žsrc/features/my/components/MyTrade/index.tsxβ€Ž

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,8 @@ const MyTrade = () => {
4646
<div className={s.Title}>λ‚˜μ˜ 거래</div>
4747
<div className={s.Menu}>
4848
<Menu Icon="mgc_heart_fill" Title="관심 λͺ©λ‘" Addr="/liked" />
49+
<Menu Icon="mgc_shopping_bag_1_fill" Title="λ‚˜μ˜ 판맀 λ‚΄μ—­" Addr="/my-trade" />
4950
<Menu Icon="mgc_exit_fill" Title="λ‘œκ·Έμ•„μ›ƒ" Addr="/my-trade" />
50-
{/* TODO: api λ‚˜μ˜€λ©΄ 달아주기 */}
51-
{/* <Menu Icon="mgc_document_fill" Title="졜근 λ³Έ κ²Œμ‹œλ¬Ό" Addr="/recent" /> */}
52-
{/* <Menu Icon="mgc_shopping_bag_1_fill" Title="λ‚˜μ˜ 판맀 λ‚΄μ—­" Addr="/my-trade" /> */}
5351
</div>
5452
</div>
5553
);

β€Žsrc/features/myEdit/components/MyEditContent/index.tsxβ€Ž

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ interface Props {
1111
setFile: (value: File) => void;
1212
profileImageUrl: string | null;
1313
isNicknameEdited: boolean;
14+
isImgEdited: boolean;
1415
}
1516

16-
const MyEditContent = ({ nickname, setNickname, isNicknameEdited, setFile, profileImageUrl }: Props) => {
17+
const MyEditContent = ({ nickname, setNickname, isNicknameEdited, setFile, profileImageUrl, isImgEdited }: Props) => {
1718
const fileInputRef = useRef<HTMLInputElement | null>(null);
1819
const [src, setSrc] = useState<string | null>(profileImageUrl);
1920

@@ -32,7 +33,7 @@ const MyEditContent = ({ nickname, setNickname, isNicknameEdited, setFile, profi
3233
return (
3334
<div className={s.Wrapper}>
3435
<div className={s.EditImage} onClick={onClickCamera}>
35-
<UserProfileImage nickname={nickname} src={src} isMyEdit />
36+
<UserProfileImage nickname={nickname} src={src} isMyEdit isEdited={isImgEdited} />
3637
<div className={cx('mgc_camera_2_fill', s.SelectPhoto)} />
3738
</div>
3839

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import client from '@/common/utils/client';
2+
import { useQuery } from '@tanstack/react-query';
3+
import { QUERY_KEYS } from '@/libs/queryKeys';
4+
import type { UserItemInterface } from '../types';
5+
6+
export interface UserItemResponse {
7+
message: string;
8+
data: UserItemInterface[];
9+
}
10+
11+
const getUserItem = async (userId: number) => {
12+
const res = await client.get<UserItemResponse>(`/api/v1/user/${userId}/item`);
13+
14+
console.log(res);
15+
16+
return res.data.data;
17+
};
18+
19+
export const useGetUserItem = (userId: number) => {
20+
return useQuery({
21+
queryKey: [QUERY_KEYS.USER_ITEM_LIST, userId],
22+
queryFn: () => getUserItem(userId),
23+
staleTime: 0,
24+
});
25+
};
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import NoResult from '@/common/components/NoResult';
2+
import ItemCard from '@/features/home/components/ItemCard';
3+
4+
import * as s from './style.css';
5+
import { useGetUserItem } from '../../apis/useGetUserItem';
6+
import { useNavigate } from 'react-router';
7+
import NotFoundPage from '@/pages/NotFoundPage';
8+
import Btn from '@/common/components/Button';
9+
10+
interface Props {
11+
userId: number;
12+
}
13+
14+
const UserItemList = ({ userId }: Props) => {
15+
const { data: userItems, isSuccess, isLoading } = useGetUserItem(userId);
16+
const navigate = useNavigate();
17+
18+
if (isLoading) return null;
19+
if (!userItems) return <NotFoundPage />;
20+
21+
const isEmpty = isSuccess && userItems.length === 0;
22+
23+
return (
24+
<div className={s.Content({ isEmpty })}>
25+
{isEmpty ? (
26+
<div className={s.NoResult}>
27+
<NoResult type="like" />
28+
<Btn mode="main" className={s.Button} onClick={() => navigate('/')}>
29+
ν™ˆμœΌλ‘œ λŒμ•„κ°€κΈ°
30+
</Btn>
31+
</div>
32+
) : (
33+
userItems.map(item => <ItemCard key={item.itemId} data={item} />)
34+
)}
35+
</div>
36+
);
37+
};
38+
39+
export default UserItemList;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { css, cva } from '@styled-system/css';
2+
3+
export const Container = cva({
4+
base: {
5+
display: 'flex',
6+
flexDir: 'column',
7+
gap: '1rem',
8+
},
9+
variants: {
10+
isEmpty: {
11+
true: {
12+
justifyContent: 'center',
13+
alignItems: 'center',
14+
height: '100%',
15+
},
16+
},
17+
},
18+
});
19+
20+
export const Wrapper = css({
21+
display: 'flex',
22+
flexDir: 'column',
23+
flex: 1,
24+
h: '100%',
25+
});
26+
27+
export const NoResult = css({
28+
display: 'flex',
29+
flexDir: 'column',
30+
gap: '1rem',
31+
alignItems: 'center',
32+
});
33+
34+
export const Content = cva({
35+
base: {
36+
display: 'flex',
37+
flexDir: 'column',
38+
p: '1rem',
39+
overflowY: 'auto',
40+
gap: '1rem',
41+
},
42+
variants: {
43+
isEmpty: {
44+
true: {
45+
justifyContent: 'center',
46+
alignItems: 'center',
47+
height: '100%',
48+
},
49+
},
50+
},
51+
});
52+
53+
export const Button = css({
54+
width: '17rem',
55+
});
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import type { Color, ProductType, Quality, Size, TradeMethods, TransactionType } from '@/libs/types/item';
2+
3+
export interface UserItemInterface {
4+
itemId: number;
5+
productTypes: ProductType[];
6+
transactionTypes: TransactionType[];
7+
thumbnail: string;
8+
title: string;
9+
rentalFee: number;
10+
salePrice: number;
11+
deposit: number;
12+
size: Size;
13+
color: Color;
14+
quality: Quality;
15+
tradeMethods: TradeMethods[];
16+
likeCount: number;
17+
chatRoomCount: number;
18+
repostDate: string;
19+
isSold: boolean;
20+
}

β€Žsrc/libs/queryKeys.tsβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export const QUERY_KEYS = {
99
ITEM_COUNT: 'item-count', // μƒν’ˆ 검색 κ²°κ³Ό 개수
1010
ITEM_CHAT_LIST: 'item-chat', // νŠΉμ • μ•„μ΄ν…œμ— λŒ€ν•œ μ±„νŒ… 리슀트
1111
LIKE_LIST: 'like', // λ‚΄ μ’‹μ•„μš” λͺ©λ‘
12+
USER_ITEM_LIST: 'user-item-list', // νŠΉμ • μœ μ €μ˜ μ•„μ΄ν…œ 리슀트
1213
USER: 'user', // λ‚΄ 정보
1314
PICK_DETAIL: 'pick', // νŠΉμ • id에 ν•΄λ‹Ήν•˜λŠ” 약속 상세
1415
APPOINTMENT_LIST: 'pick-list', // λ‚˜μ˜ ν”½ νŽ˜μ΄μ§€ 리슀트

0 commit comments

Comments
Β (0)