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

[Bugfix/FE] 프론트엔드 버그 이슈 해결 #347

Merged
merged 5 commits into from
Aug 2, 2022
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
26 changes: 16 additions & 10 deletions frontend/src/components/ProductListSection/ProductListSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import InfiniteScroll from '@/components/common/InfiniteScroll/InfiniteScroll';
import Masonry from '@/components/common/Masonry/Masonry';
import AsyncWrapper from '@/components/common/AsyncWrapper/AsyncWrapper';
import Loading from '@/components/common/Loading/Loading';
import NoDataPlaceholder from '@/components/common/NoDataPlaceholder/NoDataPlaceholder';

type Props = {
title: string;
Expand All @@ -29,14 +30,6 @@ function ProductListSection({
isError,
getNextPage,
}: Props) {
const ProductCardList = (data: Product[]) => {
return data.map(({ id, imageUrl, name, rating }) => (
<Link to={`${ROUTES.PRODUCT}/${id}`} key={id}>
<ProductCard productImage={imageUrl} name={name} rating={rating} />
</Link>
));
};

return (
<S.Container>
<SectionHeader>
Expand All @@ -55,7 +48,7 @@ function ProductListSection({
isLoading={isLoading}
isError={isError}
>
<Masonry columnCount={4}>{ProductCardList(data)}</Masonry>
<ProductCardList data={data} />
</InfiniteScroll>
</AsyncWrapper>
) : (
Expand All @@ -64,12 +57,25 @@ function ProductListSection({
isReady={isReady}
isError={isError}
>
<Masonry columnCount={4}>{ProductCardList(data)}</Masonry>
<ProductCardList data={data} />
</AsyncWrapper>
)}
</S.Wrapper>
</S.Container>
);
}

const ProductCardList = ({ data }: { data: Product[] }) => {
return (
<Masonry columnCount={4}>
{data.map(({ id, imageUrl, name, rating }) => (
<Link to={`${ROUTES.PRODUCT}/${id}`} key={id}>
<ProductCard productImage={imageUrl} name={name} rating={rating} />
</Link>
))}
{data.length === 0 && <NoDataPlaceholder />}
</Masonry>
);
};

export default ProductListSection;
3 changes: 0 additions & 3 deletions frontend/src/components/ProfileCard/ProfileCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ const chipMapper = {
};

function ProfileCard({
id,
gitHubId,
imageUrl,
careerLevel,
Expand Down Expand Up @@ -65,8 +64,6 @@ function ProfileCard({
(product) => product.category === 'keyboard'
);

console.log(keyboard);

return (
<S.Container>
<S.LeftSection>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import * as S from '@/components/ProfileSearchResult/ProfileSearchResult.style';
import AsyncWrapper from '@/components/common/AsyncWrapper/AsyncWrapper';
import Loading from '@/components/common/Loading/Loading';
import InfiniteScroll from '@/components/common/InfiniteScroll/InfiniteScroll';
import ProfileCard from '@/components/ProfileCard/ProfileCard';
import NoDataPlaceholder from '@/components/common/NoDataPlaceholder/NoDataPlaceholder';

type Props = {
data: ProfileSearchResult[];
Expand All @@ -16,7 +15,6 @@ function ProfileSearchResult({
data: profileSearchData,
getNextPage,
isLoading,
isReady,
isError,
}: Props) {
const profileSearchDataList = profileSearchData.map(
Expand All @@ -36,15 +34,14 @@ function ProfileSearchResult({
);

return (
<AsyncWrapper fallback={<Loading />} isReady={isReady} isError={isError}>
<InfiniteScroll
handleContentLoad={getNextPage}
isLoading={isLoading}
isError={isError}
>
<S.Container>{profileSearchDataList}</S.Container>
</InfiniteScroll>
</AsyncWrapper>
<InfiniteScroll
handleContentLoad={getNextPage}
isLoading={isLoading}
isError={isError}
>
<S.Container>{profileSearchDataList}</S.Container>
{profileSearchData.length === 0 && <NoDataPlaceholder />}
</InfiniteScroll>
);
}

Expand Down
51 changes: 34 additions & 17 deletions frontend/src/components/ReviewListSection/ReviewListSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,6 @@ function ReviewListSection({
const userData = useContext(UserDataContext);
const loginUserGithubId = userData?.member.gitHubId;

const reviewCardList = reviewData.map(
({ id, author, product, content, rating }) => (
<ReviewCard
key={id}
reviewId={id}
product={product}
profileImage={author.imageUrl}
username={author.gitHubId}
rating={rating}
content={content}
loginUserGithubId={loginUserGithubId}
handleDelete={handleDelete}
handleEdit={handleEdit}
/>
)
);
return (
<S.Container>
<SectionHeader>
Expand All @@ -58,11 +42,44 @@ function ReviewListSection({
isLoading={isLoading}
isError={isError}
>
<S.Wrapper columns={columns}>{reviewCardList}</S.Wrapper>
<S.Wrapper columns={columns}>
<ReviewCardList
data={reviewData}
handleDelete={handleDelete}
handleEdit={handleEdit}
loginUserGithubId={loginUserGithubId}
/>
</S.Wrapper>
</InfiniteScroll>
</AsyncWrapper>
</S.Container>
);
}

const ReviewCardList = ({
data,
handleDelete,
handleEdit,
loginUserGithubId,
}: Pick<Props, 'data' | 'handleDelete' | 'handleEdit'> & {
loginUserGithubId: string;
}) => (
<>
{data.map(({ id, author, product, content, rating }) => (
<ReviewCard
key={id}
reviewId={id}
product={product}
profileImage={author.imageUrl}
username={author.gitHubId}
rating={rating}
content={content}
loginUserGithubId={loginUserGithubId}
handleDelete={handleDelete}
handleEdit={handleEdit}
/>
))}
</>
);

export default ReviewListSection;
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Player } from '@lottiefiles/react-lottie-player';

function NoDataPlaceholder() {
return (
<>
<Player
autoplay
loop
src="https://assets1.lottiefiles.com/private_files/lf30_oqpbtola.json"
style={{ height: '200px', width: '200px' }}
/>
<div style={{ width: '100%', textAlign: 'center' }}>
아무것도 찾지 못했어요..
</div>
</>
);
}

export default NoDataPlaceholder;
32 changes: 15 additions & 17 deletions frontend/src/components/common/ProductSelect/ProductSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ProductBar from '@/components/common/ProductBar/ProductBar';
import { useReducer } from 'react';
import { useState } from 'react';
import DownArrow from '@/assets/down_arrow.svg';

import * as S from '@/components/common/ProductSelect/ProductSelect.style';
Expand All @@ -10,7 +10,7 @@ type Props = {
selectedProduct: InventoryProduct;
setSelectedProduct: React.Dispatch<React.SetStateAction<InventoryProduct>>;
otherProducts: InventoryProduct[];
updateProfileProduct: () => Promise<void>;
updateProfileProduct: () => Promise<boolean>;
};

function ProductSelect({
Expand All @@ -20,35 +20,33 @@ function ProductSelect({
otherProducts,
updateProfileProduct,
}: Props) {
const [isEditMode, setEditMode] = useReducer(
(isEditMode: boolean) => !isEditMode,
false
);
const [isOptionsOpen, setOptionOpen] = useReducer(
(isOptionsOpen: boolean) => !isOptionsOpen,
false
);
const [isEditMode, setEditMode] = useState(false);
const [isOptionsOpen, setOptionOpen] = useState(false);

const handleProductSelect = (value: InventoryProduct) => {
setSelectedProduct(value);
setOptionOpen();
setOptionOpen(false);
};

const handleEditDone = () => {
if (isEditMode) {
updateProfileProduct()
.then(() => {
submitHandler();
setOptionOpen();
setEditMode();
.then((didPatch) => {
if (didPatch) submitHandler();
setOptionOpen(false);
setEditMode(false);
})
.catch((error) => {
console.error(error);
});
return;
}

setEditMode();
setEditMode(true);
};

const handleOptionOpen = () => {
setOptionOpen(true);
};

return (
Expand All @@ -59,7 +57,7 @@ function ProductSelect({
{isEditMode ? (
<>
<S.Selected>
<S.PseudoButton onClick={setOptionOpen}>
<S.PseudoButton onClick={handleOptionOpen}>
{selectedProduct !== undefined ? (
<ProductBar
name={selectedProduct.product.name}
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/hooks/api/useAxios.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import {
API_ERROR_CODE_EXCEPTION_MESSAGES,
API_ERROR_MESSAGES,
} from '@/constants/messages';
import { LogoutContext } from '@/contexts/LoginContextProvider';
import axios, { AxiosError, AxiosInstance } from 'axios';
import { useState } from 'react';
import { useContext, useState } from 'react';

type ErrorResponseBody = {
errorCode: keyof typeof API_ERROR_MESSAGES;
Expand All @@ -19,6 +20,7 @@ type Return = {
function useAxios(): Return {
const [isLoading, setLoading] = useState(false);
const [isError, setError] = useState(false);
const logout = useContext(LogoutContext);

const axiosInstance = axios.create({ baseURL: BASE_URL });

Expand All @@ -28,6 +30,10 @@ function useAxios(): Return {
setError(true);
setLoading(false);

if (error.response.status === 401) {
logout();
}

if (!('errorCode' in errorResponseBody)) {
throw new Error(API_ERROR_CODE_EXCEPTION_MESSAGES.NO_CODE);
}
Expand Down
11 changes: 6 additions & 5 deletions frontend/src/hooks/api/useGetMany.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type Return<T> = {
};

function useGetMany<T>({ url, params, body, headers }: Props): Return<T> {
const [data, setData] = useState<T[]>([]);
const [data, setData] = useState<T[]>(null);

const [page, setPage] = useState(0);
const [hasNextPage, setHasNextPage] = useState(true);
Expand Down Expand Up @@ -64,7 +64,7 @@ function useGetMany<T>({ url, params, body, headers }: Props): Return<T> {
setRefetchTrigger((prevTrigger) => prevTrigger + 1);
setPage(0);
setHasNextPage(true);
setData([]);
setData(null);
};

const getCurrentParamString = () =>
Expand All @@ -81,7 +81,8 @@ function useGetMany<T>({ url, params, body, headers }: Props): Return<T> {

fetchData()
.then(({ hasNext, items }) => {
!!items && setData((prevData) => [...prevData, ...items]);
!!items &&
setData((prevData) => (prevData ? [...prevData, ...items] : items));
return hasNext;
})
.then((hasNext) => {
Expand All @@ -100,11 +101,11 @@ function useGetMany<T>({ url, params, body, headers }: Props): Return<T> {
const searchParams = new URLSearchParams(params);

useEffect(() => {
if (data.length === 0) return; // 최초 렌더링 시 refetch 방지 임시 조치
if (!data) return; // 최초 렌더링 시 refetch 방지 임시 조치
refetch();
}, [searchParams.toString()]);

const isReady = data.length !== 0;
const isReady = !!data;

return { data, getNextPage, refetch, isLoading, isReady, isError };
}
Expand Down
Loading