Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/create clothes intro page #12

Merged
merged 6 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/components/ApplyBtn/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Button } from '@mui/material';

interface ApplyBtnProp {
status: string;
}
export default function ApplyBtn({ status }: ApplyBtnProp) {
if (status === '대여가능') {
return (
<Button sx={{ borderRadius: 10, width: 250, backgroundColor: 'black', color: 'white' }}>대여 신청하기</Button>
);
}
if (status === '대여불가능') {
return (
<Button disabled sx={{ borderRadius: 10, width: 250, backgroundColor: 'red', color: 'white' }}>
대여가 불가능한 옷이에요
</Button>
);
}
if (status === '대여중') {
return (
<Button disabled sx={{ borderRadius: 10, width: 250, backgroundColor: 'orange', color: 'white' }}>
지금 대여 중인 옷이에요
</Button>
);
}
return null;
}
6 changes: 2 additions & 4 deletions src/components/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import { useRecoilValue } from 'recoil';
import { Link, useNavigate } from 'react-router-dom';
import { useState } from 'react';
import { Typography, Box, Button } from '@mui/material';
import AccountCircleIcon from '@mui/icons-material/AccountCircle';

import ConfirmDialog from '../ConfirmDialog';
import { userAtom } from '../../recoil/atom';

export default function Header() {
const navigate = useNavigate();
const isAuthenticated = sessionStorage.getItem('accessToken');
const userNickname = sessionStorage.getItem('userNickname');

const [isOpen, setIsOpen] = useState(false);

const userState = useRecoilValue(userAtom);
const handleLogout = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
sessionStorage.removeItem('accessToken');
Expand Down Expand Up @@ -56,7 +54,7 @@ export default function Header() {
{isAuthenticated ? (
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<AccountCircleIcon sx={{ mr: 0.5 }} />
<Typography sx={{ fontSize: 20, fontWeight: 'bold', mr: 2 }}>{userState.nickname} 님</Typography>
<Typography sx={{ fontSize: 20, fontWeight: 'bold', mr: 2 }}>{userNickname} 님</Typography>
<Button sx={{ color: 'black', fontSize: 20, fontWeight: 'bold', mr: 2 }} onClick={handleMyPage}>
마이페이지
</Button>
Expand Down
73 changes: 73 additions & 0 deletions src/components/StatusSign/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Box, Typography } from '@mui/material';

interface StatusSignProp {
status: string;
}
export default function StatusSign({ status }: StatusSignProp) {
if (status === '대여가능') {
return (
<Box display={'flex'} alignItems={'center'} sx={{ mr: 1 }}>
<Box
sx={{
backgroundColor: 'green',
width: 10,
height: 10,
borderRadius: 100,
mr: 1,
}}
/>
<Typography>{status}</Typography>
</Box>
);
}
if (status === '대여불가능') {
return (
<Box display={'flex'} alignItems={'center'} sx={{ mr: 1 }}>
<Box
sx={{
backgroundColor: 'red',
width: 10,
height: 10,
borderRadius: 100,
mr: 1,
}}
/>
<Typography>{status}</Typography>
</Box>
);
}
if (status === '대여중') {
return (
<Box display={'flex'} alignItems={'center'} sx={{ mr: 1 }}>
<Box
sx={{
backgroundColor: 'orange',
width: 10,
height: 10,
borderRadius: 100,
mr: 1,
}}
/>
<Typography>{status}</Typography>
</Box>
);
}
if (status === '공개중') {
return (
<Box display={'flex'} alignItems={'center'} sx={{ mr: 1 }}>
<Box
sx={{
backgroundColor: 'black',
width: 10,
height: 10,
borderRadius: 100,
mr: 1,
}}
/>
<Typography>{status}</Typography>
</Box>
);
}
Comment on lines +55 to +70
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서 혹시 공개중으로 빠지는 경우가 있나요??
clothes page보니까 status가 대여불가능/대여중/대여가능 셋 중 하나일 것 같아서요!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아 그건 맞는데 공개중도 똑같은 컴포넌트로 표시하기도 해서요! 제가 쓰지는 않지만 다른 데서도 이거를 써가지구 혹시 몰라서 넣어놨습니다!


return null;
}
18 changes: 18 additions & 0 deletions src/components/WishBtn/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { IconButton } from '@mui/material';
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
import FavoriteIcon from '@mui/icons-material/Favorite';

interface WishBtnProps {
handleWish: React.MouseEventHandler<HTMLButtonElement>;
isWished: boolean;
}

const WishBtn: React.FC<WishBtnProps> = ({ handleWish, isWished = false }: WishBtnProps) => {
return (
<IconButton onClick={handleWish} size="small">
{isWished ? <FavoriteIcon sx={{ color: 'black' }} /> : <FavoriteBorderIcon sx={{ color: 'black' }} />}
</IconButton>
);
};

export default WishBtn;
10 changes: 10 additions & 0 deletions src/data/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,13 @@ export const LOGIN_MESSAGE = {
export const SEARCH_MESSAGE = {
SEARCH_FAIL: '검색에 실패하였습니다 :(',
};
export const CLOTHES_MESSAGE = {
CLOTHES_NOT_FOUND: '옷을 찾을 수 없어요 :(',
CLOTHES_DELETED: '옷이 삭제되었어요',
CLOTHES_EDITED: '옷 정보가 수정되었어요',
};
export const WISH_MESSAGE = {
WISH_CREATED: '찜한 옷에 추가되었어요',
WISH_DELETED: '찜한 옷에서 삭제되었어요',
WISH_FAIL: '알 수 없는 오류가 발생했습니다',
};
2 changes: 2 additions & 0 deletions src/hooks/api/auth/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export async function postLoginAPICall(values: Login) {
if (response.status === 200) {
const { id, nickname, isBannded, accessToken } = response.data;
sessionStorage.setItem('accessToken', accessToken);
sessionStorage.setItem('userId', id);
sessionStorage.setItem('userNickname', nickname);
enqueueSnackbar(`${nickname}님 안녕하세요 :)`, { variant: 'success' });
if (isBannded === true) {
enqueueSnackbar(`현재 ${nickname}님의 계정은 사용 정지되었습니다.`, { variant: 'warning' });
Expand Down
101 changes: 101 additions & 0 deletions src/hooks/api/clothes/clothes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { enqueueSnackbar } from 'notistack';
import axios, { AxiosError } from 'axios';

import { CLOTHES_MESSAGE } from '../../../data/messages';

interface GetClothesParams {
clothesId: number;
token?: string;
}
interface Reviewer {
id?: number;
username: string;
nickname?: string;
}
interface Review {
review: string;
reviewer: Reviewer;
}
interface Owner {
id?: number;
nickname?: string;
location?: string;
}
export interface GetClothesResponse {
id: number;
description: string;
category: string;
season: string;
status: string;
isOpen: boolean;
name: string;
tag: string;
image: string;
owner: Owner;
review: Review[];
isWished: boolean;
}

export async function getClothesAPICall({ clothesId, token }: GetClothesParams) {
try {
const response = await axios.get<GetClothesResponse>(`${process.env.REACT_APP_API_URL}/clothes/${clothesId}`, {
headers: { Authorization: `Bearer ${token}` },
});
if (response.status === 200) {
return response.data;
}
} catch (err) {
if (err instanceof AxiosError) {
enqueueSnackbar(err.response?.data?.message ?? CLOTHES_MESSAGE.CLOTHES_NOT_FOUND, { variant: 'error' });
} else {
enqueueSnackbar(CLOTHES_MESSAGE.CLOTHES_NOT_FOUND, { variant: 'error' });
}
}
return null;
}

export async function deleteClothesAPICall({ clothesId, token }: GetClothesParams) {
try {
const response = await axios.delete(`${process.env.REACT_APP_API_URL}/clothes/${clothesId}`, {
headers: { Authorization: `Bearer ${token}` },
});
if (response.status === 200) {
enqueueSnackbar(CLOTHES_MESSAGE.CLOTHES_DELETED, { variant: 'success' });
}
} catch (err) {
if (err instanceof AxiosError) {
enqueueSnackbar(err.response?.data?.message ?? CLOTHES_MESSAGE.CLOTHES_NOT_FOUND, { variant: 'error' });
} else {
enqueueSnackbar(CLOTHES_MESSAGE.CLOTHES_NOT_FOUND, { variant: 'error' });
}
}
}
interface Clothes {
category: string;
season: string;
status: string;
isOpen: boolean;
name: string;
tag: string;
}
interface EditClothesParams {
clothesId: number;
token?: string;
clothes: Clothes;
}
export async function editClothesAPICall({ clothesId, token, clothes }: EditClothesParams) {
try {
const response = await axios.put(`${process.env.REACT_APP_API_URL}/clothes/${clothesId}`, clothes, {
headers: { Authorization: `Bearer ${token}` },
});
if (response.status === 200) {
enqueueSnackbar(CLOTHES_MESSAGE.CLOTHES_EDITED, { variant: 'success' });
}
} catch (err) {
if (err instanceof AxiosError) {
enqueueSnackbar(err.response?.data?.message ?? CLOTHES_MESSAGE.CLOTHES_NOT_FOUND, { variant: 'error' });
} else {
enqueueSnackbar(CLOTHES_MESSAGE.CLOTHES_NOT_FOUND, { variant: 'error' });
}
}
}
55 changes: 55 additions & 0 deletions src/hooks/api/wish/wish.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { enqueueSnackbar } from 'notistack';
import axios, { AxiosError } from 'axios';

import { WISH_MESSAGE } from '../../../data/messages';

interface WishAPIParams {
clothesId: number;
token: string;
}

export async function createWishAPICall({ clothesId, token }: WishAPIParams) {
try {
const response = await axios.post(
`${process.env.REACT_APP_API_URL}/wish/${clothesId}`,
{},
{
headers: {
Authorization: `Bearer ${token}`,
},
},
);
if (response.status === 200) {
enqueueSnackbar(WISH_MESSAGE.WISH_CREATED, { variant: 'success' });
}
} catch (err) {
if (err instanceof AxiosError) {
enqueueSnackbar(err.response?.data?.message ?? WISH_MESSAGE.WISH_FAIL, { variant: 'error' });
} else {
enqueueSnackbar(WISH_MESSAGE.WISH_FAIL, { variant: 'error' });
}
}
}

export async function deleteWishAPICall({ clothesId, token }: WishAPIParams) {
try {
const response = await axios.put(
`${process.env.REACT_APP_API_URL}/wish/${clothesId}`,
{},
{
headers: {
Authorization: `Bearer ${token}`,
},
},
);
if (response.status === 200) {
enqueueSnackbar(WISH_MESSAGE.WISH_DELETED, { variant: 'success' });
}
} catch (err) {
if (err instanceof AxiosError) {
enqueueSnackbar(err.response?.data?.message ?? WISH_MESSAGE.WISH_FAIL, { variant: 'error' });
} else {
enqueueSnackbar(WISH_MESSAGE.WISH_FAIL, { variant: 'error' });
}
}
}
6 changes: 1 addition & 5 deletions src/models/enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,4 @@ export enum Season {
WINTER = '겨울',
}

export enum Status {
AVAILABLE = '대여가능',
UNAVAILABLE = '대여불가능',
RENTED = '대여중',
}
export const StatusEnums = ['대여가능', '대여중', '대여불가능'];
Loading