Skip to content

Commit

Permalink
Merge branch 'develop' into auth-refresh-token
Browse files Browse the repository at this point in the history
  • Loading branch information
seoye0ng authored Feb 20, 2024
2 parents c96dbd1 + f4dc943 commit 98851c5
Show file tree
Hide file tree
Showing 22 changed files with 314 additions and 58 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
"react-cookie": "^7.0.2",
"react-dom": "^18",
"react-hook-form": "^7.49.2",
"react-infinite-scroll-component": "^6.1.0",
"react-redux": "^9.0.4",
"react-slick": "^0.29.0",
"react-toastify": "^10.0.4",
"redux-persist": "^6.0.0"
},
"devDependencies": {
Expand Down
10 changes: 5 additions & 5 deletions src/app/find-id/complete/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ import { COMPLETE_FIND_ID } from '@constants/completeMessage';
import Confirmation from '@shared/confirmation/Confirmation';
import Header from '@shared/header/Header';

function CompleteFindIdPage() {
const topMargin = 16;
const bottomMargin = 66;
const TOP_MARGIN = 16;
const BOTTOM_MARGIN = 66;

function CompleteFindIdPage() {
return (
<>
<Header />
<Confirmation
options={COMPLETE_FIND_ID.options}
title={COMPLETE_FIND_ID.title}
description={COMPLETE_FIND_ID.description}
topMargin={topMargin}
bottomMargin={bottomMargin}
topMargin={TOP_MARGIN}
bottomMargin={BOTTOM_MARGIN}
isHeader
/>
</>
Expand Down
12 changes: 1 addition & 11 deletions src/app/find-id/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,7 @@ function FindIdPage() {

const onSubmit = (data: FindId) => {
const { email } = data;
mutate({ email }, {
onError: (error) => {
console.error('Error:', error);
alert('다시 입력해주세요');
// TODO: 아이디 찾기 실패 시 알림 메세지 바로 출력
},
onSuccess: () => {
alert('회원님의 이메일로 아이디 전송완료');
// TODO: 아이디 전송완료 페이지 로드하기
},
});
mutate({ email });
};

return (
Expand Down
7 changes: 5 additions & 2 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import type { Metadata } from 'next';
import localFont from 'next/font/local';

import './globals.css';

import 'react-toastify/dist/ReactToastify.min.css';
import { ModalContextProvider } from '@contexts/ModalContext';
import { CookieProvider } from '@providers/CookieProvider';
import MockProvider from '@providers/MockProvider';
import QueryProvider from '@providers/QueryProvider';
import RefreshTokenProvider from '@providers/RefreshTokenProvider';
import StoreProvider from '@providers/StoreProvider';
// eslint-disable-next-line import/order
import ToastProvider from '@providers/ToastProvider';

// import { CookiesProvider } from 'react-cookie';

export const metadata: Metadata = {
Expand Down Expand Up @@ -40,11 +41,13 @@ export default function RootLayout({
<CookieProvider>
<QueryProvider>
<StoreProvider>
<ToastProvider>
<ModalContextProvider>
<RefreshTokenProvider>
{children}
</RefreshTokenProvider>
</ModalContextProvider>
</ToastProvider>
</StoreProvider>
</QueryProvider>
</CookieProvider>
Expand Down
43 changes: 26 additions & 17 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
/* eslint-disable react/no-array-index-key */
/* eslint-disable @typescript-eslint/no-unused-vars */

'use client';

import InfiniteScroll from 'react-infinite-scroll-component';

import classNames from 'classnames/bind';

import { MOCK_BANNER_DATA, MOCK_PRODUCT_LIST, MOCK_RECOMMEND_PRODUCTS } from '@mocks/homeHandler/mocks';
import FilterGroup from '@components/home/filer-group/FilterGroup';
import { HomeSortType } from '@components/home/filer-group/types/filterGroup.type';
import { MOCK_BANNER_DATA, MOCK_RECOMMEND_PRODUCTS } from '@mocks/homeHandler/mocks';
import useBanner from '@remote/queries/home/useBanner';
import useProductList from '@remote/queries/home/useProductList';
import useRecommendProducts from '@remote/queries/home/useRecommendProducts';
import BottomNav from '@shared/bottom-nav/BottomNav';
import Banner from '@shared/carousel/Banner';
import RecommendList from '@shared/carousel/RecommendList';
import Flex from '@shared/flex/Flex';
import Header from '@shared/header/Header';
import Loader from '@shared/loader/Loader';
import ProductArticle from '@shared/product-article/ProductArticle';
import Radio from '@shared/radio/Radio';
import ScrollToTop from '@shared/scroll-to-top/ScrollToTop';
import Spacing from '@shared/spacing/Spacing';
import Text from '@shared/text/Text';
Expand All @@ -24,7 +27,7 @@ import styles from './page.module.scss';

const cx = classNames.bind(styles);

function Home() {
function Home({ searchParams }: { searchParams: { filter: HomeSortType } }) {
// 테스트
// TODO: 비로그인 회원과 부가정보를 입력하지 않은 회원은 부가정보 입력 배너 보이도록 UI 추가
// const { data: bannerData, isLoading: bannerLoading } = useBanner();
Expand All @@ -38,6 +41,10 @@ function Home() {
// return <Loader />;
// }

const {
data: productList, hasNextPage, loadMore,
} = useProductList(searchParams.filter);

return (
<>
<Header className={cx('home')} type="home" />
Expand All @@ -52,21 +59,23 @@ function Home() {
</div>
<Spacing size={35} />
<div className={cx('productListWrapper')}>
<Text typography="t4" bold>WashPedia 랭킹</Text>
<Text typography="t4" bold>WashFit 랭킹</Text>
<Spacing size={16} />
<Flex justify="space-between" align="center" gap={8}>
<Radio label="조회순" name="filter" type="filter" value="view" defaultChecked />
<Radio label="위반제품" name="filter" type="filter" value="violatingProduct" />
<Radio label="추천순" name="filter" type="filter" value="recommend" />
<Radio label="최신순" name="filter" type="filter" value="latest" />
</Flex>
<FilterGroup />
<Spacing size={16} />
<div className={cx('productArticleWrapper')}>
{MOCK_PRODUCT_LIST?.value.map((item) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
return <ProductArticle key={item.productNo} itemData={item} />;
})}
</div>
<InfiniteScroll
dataLength={productList?.length ?? 0}
next={loadMore}
hasMore={hasNextPage}
loader={<div className="loader" key={0}>Loading ...</div>}
inverse={false}
>
<div className={cx('productArticleWrapper')}>
{productList?.map((item, index) => {
return <ProductArticle key={index} itemData={item} />;
})}
</div>
</InfiniteScroll>
</div>
<ScrollToTop />
</main>
Expand Down
26 changes: 26 additions & 0 deletions src/components/home/filer-group/FilterGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';

import { useRouter } from 'next/navigation';

import Flex from '@shared/flex/Flex';
import Radio from '@shared/radio/Radio';

function FilterGroup() {
const router = useRouter();

const handleRadioValue = (e: React.ChangeEvent<HTMLInputElement>) => {
const sortType = e.target.value;
router.push(`/?filter=${sortType}`, { scroll: false });
};

return (
<Flex justify="space-between" align="center" gap={8}>
<Radio label="조회순" name="filter" type="filter" value="viewCnt-order" defaultChecked onChange={handleRadioValue} />
<Radio label="위반제품" name="filter" type="filter" value="violation-products" onChange={handleRadioValue} />
<Radio label="추천순" name="filter" type="filter" value="recommend-order" onChange={handleRadioValue} />
<Radio label="최신순" name="filter" type="filter" value="recent-order" onChange={handleRadioValue} />
</Flex>
);
}

export default FilterGroup;
1 change: 1 addition & 0 deletions src/components/home/filer-group/types/filterGroup.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type HomeSortType = 'viewCnt-order' | 'violation-products' | 'recommend-order' | 'recent-order';
4 changes: 2 additions & 2 deletions src/components/shared/header/headerItems/RightIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import FilledHeart from '@components/icons/FilledHeart';
import Filter from '@components/icons/Filter';
import Heart from '@components/icons/Heart';
import Search from '@components/icons/Search';
import Share from '@components/icons/Share';
import KakaoShareButton from '@shared/kakao-share-button/KakaoShareButton';

import { RightIconProps } from '../types/headerType';

Expand Down Expand Up @@ -50,7 +50,7 @@ function RightIcon({
: <Heart onClick={handleHeartClick} />}
</li>
<li>
<Share />
<KakaoShareButton />
</li>
</ul>
);
Expand Down
4 changes: 3 additions & 1 deletion src/components/shared/kakao-script/KakaoLoginScript.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ declare global {

function KakaoLoginScript() {
const onLoad = () => {
window.Kakao.init(process.env.NEXT_PUBLIC_KAKAO_APP_JS_KEY);
if (!window.Kakao.isInitialized()) {
window.Kakao.init(process.env.NEXT_PUBLIC_KAKAO_APP_JS_KEY);
}
};

return (
Expand Down
24 changes: 24 additions & 0 deletions src/components/shared/kakao-share-button/KakaoShareButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* eslint-disable jsx-a11y/control-has-associated-label */

import Script from 'next/script';

import Share from '@components/icons/Share';
import useKakaoShare from '@hooks/useKakaoShare';

function KakaoShareButton() {
const containerId = useKakaoShare('#kakao-link-btn', process.env.NEXT_PUBLIC_KAKAO_APP_JS_KEY!);

return (
<>
<button id={containerId} style={{ cursor: 'pointer' }}>
<Share />
</button>
<Script
strategy="afterInteractive"
type="text/javascript"
src={`https://t1.kakaocdn.net/kakao_js_sdk/${process.env.NEXT_PUBLIC_KAKAO_LOGIN_VERSION}/kakao.min.js`}
/>
</>
);
}
export default KakaoShareButton;
4 changes: 2 additions & 2 deletions src/components/shared/modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ interface ModalProps {
title: React.ReactNode
description: React.ReactNode
leftButtonLabel: React.ReactNode
rightButtonLabel: React.ReactNode
rightButtonLabel?: React.ReactNode
onLeftButtonClick: () => void
onRightButtonClick: () => void
onRightButtonClick?: () => void
}

function Modal({
Expand Down
2 changes: 1 addition & 1 deletion src/components/shared/product-article/ProductArticle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function ProductArticle({ isRow = false, itemData }: ProductArticleProps) {
<article className={cx('container', { row: isRow })}>
<div className={cx('imgBox')}>
<Image
src={itemData.imageSource!}
src={itemData.imageSource ?? '/assets/profile.JPG'}
alt="제품 이미지"
width={0}
height={0}
Expand Down
2 changes: 1 addition & 1 deletion src/contexts/ModalContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function ModalContextProvider({ children }: { children: React.ReactNode }
},
onRightButtonClick: () => {
close();
onRightButtonClick();
onRightButtonClick?.();
},
open: true,
});
Expand Down
73 changes: 73 additions & 0 deletions src/hooks/useKakaoShare.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { useCallback, useEffect } from 'react';

declare global {
interface Window {
Kakao: any
}
}

function useKakaoShare(containerId: string, key: string) {
const createShareButton = useCallback(() => {
// kakao sdk script이 정상적으로 불러와졌으면 window.Kakao로 접근이 가능합니다
if (window.Kakao) {
const kakao = window.Kakao;
// 중복 initialization 방지
if (!kakao.isInitialized()) {
// 두번째 step 에서 가져온 javascript key 를 이용하여 initialize
kakao.init(key);
}
kakao.Share.createDefaultButton({
// Render 부분 id=kakao-link-btn 을 찾아 그부분에 렌더링을 합니다
container: containerId,
objectType: 'feed',
content: {
title: 'Washfit',
description: '안전한 세차용품 정보 제공 플랫폼',
imageUrl:
'https://tago.kr/images/sub/TG300-D02_img01.png',
link: {
webUrl: 'https://dev.washfit.site/',
mobileWebUrl: 'https://dev.washfit.site/',
},
},
social: {
likeCount: 77,
commentCount: 55,
sharedCount: 333,
},
buttons: [
// 카카오톡 웹에서 보기
{
title: '웹으로 보기',
link: {
mobileWebUrl: 'https://dev.washfit.site/',
webUrl: 'https://dev.washfit.site/',
},
},
// 카카오톡 모바일에서 보기
{
title: '앱으로 보기',
link: {
mobileWebUrl: 'https://dev.washfit.site/',
webUrl: 'https://dev.washfit.site/',
},
},
],
});
}
}, [containerId, key]);

useEffect(() => {
createShareButton();
}, [createShareButton]);

// #kakao-link-btn과 같은 id에서 '#'제거 과정
const id = containerId.substring(1);
return id;
}

export default useKakaoShare;
18 changes: 18 additions & 0 deletions src/providers/ToastProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use client';

import { ToastContainer } from 'react-toastify';

interface ToastProviderProps {
children: React.ReactNode;
}

function ToastProvider({ children }: ToastProviderProps) {
return (
<>
{children}
<ToastContainer />
</>
);
}

export default ToastProvider;
3 changes: 2 additions & 1 deletion src/remote/api/requests/auth/auth.post.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
ChangePassword,
FindId, FindPassword, RefreshTokenType, ISignIn, ISignUp, UserInfoType,
} from '../../types/auth';
import { ICommon } from '../../types/common';
import { postRequest, putRequest } from '../requests.api';

export const signup = async ({
Expand Down Expand Up @@ -33,7 +34,7 @@ export const refreshToken = async () => {
export const findId = async ({
email,
}: FindId) => {
const response = await postRequest<null, FindId>('/member/find-id', {
const response = await postRequest<ICommon<null>, FindId>('/member/find/memberId', {
email,
});

Expand Down
Loading

0 comments on commit 98851c5

Please sign in to comment.