Skip to content

Commit

Permalink
Merge pull request #84 from dnd-side-project/sprint/refactor-the-project
Browse files Browse the repository at this point in the history
Refactor: 프로젝트의 전반적인 리팩토링
  • Loading branch information
guesung authored Aug 14, 2024
2 parents 2b4cd65 + 0c5a91e commit 6b1ab23
Show file tree
Hide file tree
Showing 75 changed files with 483 additions and 508 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: 'CI'
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@main
name: Checkout repository

- name: Cache dependencies
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('yarn.lock') }}
restore-keys: ${{ runner.os }}-nextjs-${{ hashFiles('yarn.lock') }}-

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Check typescript
run: yarn run type:check

- name: Check eslint
run: yarn run lint
32 changes: 15 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,37 @@
<img align="left" width="170" src="https://github.com/pose-picker/.github/assets/75469131/012da976-4d52-45e9-abfc-fdd700b927be" />

<img height="30" src="https://github.com/pose-picker/.github/assets/75469131/87357edf-8a99-4d4e-88ce-afb48752e45e"/> &nbsp;
---
## <img height="30" src="https://github.com/pose-picker/.github/assets/75469131/87357edf-8a99-4d4e-88ce-afb48752e45e"/> &nbsp;

*포토부스에서 고민하는 당신을 위한 포즈추천 서비스*
_포토부스에서 고민하는 당신을 위한 포즈추천 서비스_

<a href="https://www.posepicker.site/pick">Website</a> | <a href='https://www.instagram.com/posepicker/'>Instagram</a> | <a href='https://github.com/pose-picker'>Github</a> | <a href='https://litt.ly/posepicker'>Feedback</a>
<a href="https://www.posepicker.site/pick">Website</a> | <a href='https://www.instagram.com/posepicker/'>Instagram</a> | <a href='https://github.com/pose-picker'>Github</a> | <a href='https://litt.ly/posepicker'>Feedback</a>

<br/>

## 🪄 Introduce

> 네컷사진 찍을 때면 늘 포즈가 고민되지 않나요? <br/>
포즈피커가 포즈 고민을 해결해 드릴게요! <br/>
미리 포즈 고민할 필요 없이, 찍기 직전에 빠르고 재밌게 포즈를 추천해 주는 포즈피커를 이용해 보세요!
> 포즈피커가 포즈 고민을 해결해 드릴게요! <br/>
> 미리 포즈 고민할 필요 없이, 찍기 직전에 빠르고 재밌게 포즈를 추천해 주는 포즈피커를 이용해 보세요!
<br/>

<img align="right" width="350" src="https://github.com/pose-picker/.github/assets/75469131/1e23a8de-d331-41ba-bc7a-f2bc62f7de01"/>

✨ <br/>
*“빨리 빨리! 우리 무슨 포즈로 찍을래?”* <br/>
_“빨리 빨리! 우리 무슨 포즈로 찍을래?”_ <br/>
시간 없을 땐 **포즈픽**으로 빠르게 랜덤 포즈를 추천받아보세요.

<br/>

🃏 <br/>
*“이미 있는 포즈는 시시해, 우리만의 특별한 포즈가 필요해!”* <br/>
_“이미 있는 포즈는 시시해, 우리만의 특별한 포즈가 필요해!”_ <br/>
**포즈톡**에서 뽑은 랜덤 제시어로 나만의 개성있는 포즈를 완성해보세요.

<br/>

🎞 <br/>
*“또 어떤 포즈가 있을까? 우리 이 포즈로 찍어볼까?”* <br/>
_“또 어떤 포즈가 있을까? 우리 이 포즈로 찍어볼까?”_ <br/>
**포즈피드**에서 특정한 상황을 빛내줄 포즈를 찾고, 친구한테 공유해보세요.

<br/>
Expand All @@ -44,10 +43,8 @@
![18](https://github.com/dnd-side-project/dnd-9th-5-frontend/assets/75469131/7b4bfdb1-a8bf-4cde-b57c-c254fe221985)
![19](https://github.com/dnd-side-project/dnd-9th-5-frontend/assets/75469131/a3fc9896-5fc4-4612-949e-557f3f088815)


<br/>


## 🎞 Demo

[PosePicker Demo Video](https://youtube.com/shorts/dP7VdyoieMs?si=hv7ou7y1iZwkc7m3)
Expand All @@ -56,12 +53,12 @@

## 🙌 Team

| Design | FrontEnd | BackEnd |
|:-:|:-:|:-:|
|<img src='https://hackmd.io/_uploads/r1YwPun63.png' width="200" /> |<img src='https://avatars.githubusercontent.com/u/75469131?v=4' width="200" />|<img src="https://avatars.githubusercontent.com/u/67156494?v=4" width="200"/>|
| 이지영 | [seondal](https://github.com/seondal) | [olive-su](https://github.com/olive-su) |
|<img src="https://hackmd.io/_uploads/Bybimdn62.jpg" width="200"/> |<img src='https://avatars.githubusercontent.com/u/62178788?v=4' width="200"/>|<img src="https://avatars.githubusercontent.com/u/61766218?v=4" width="200"/>|
| 김수빈 | [guesung](https://github.com/guesung) | [leejw-lu](https://github.com/leejw-lu) |
| Design | FrontEnd | BackEnd |
| :----------------------------------------------------------------: | :----------------------------------------------------------------------------: | :---------------------------------------------------------------------------: |
| <img src='https://hackmd.io/_uploads/r1YwPun63.png' width="200" /> | <img src='https://avatars.githubusercontent.com/u/75469131?v=4' width="200" /> | <img src="https://avatars.githubusercontent.com/u/67156494?v=4" width="200"/> |
| 이지영 | [seondal](https://github.com/seondal) | [olive-su](https://github.com/olive-su) |
| <img src="https://hackmd.io/_uploads/Bybimdn62.jpg" width="200"/> | <img src='https://avatars.githubusercontent.com/u/62178788?v=4' width="200"/> | <img src="https://avatars.githubusercontent.com/u/61766218?v=4" width="200"/> |
| 김수빈 | [guesung](https://github.com/guesung) | [leejw-lu](https://github.com/leejw-lu) |

<br/>

Expand All @@ -72,6 +69,7 @@
<br/>

## 📂 Folder Structure

> Next13의 App Rounting을 기반으로 하고있습니다.
```
Expand Down
16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"build": "next build",
"start": "next start",
"lint": "next lint",
"type:check": "tsc --noEmit",
"format": "prettier --write --ignore-path .gitignore .",
"make-sprite": "rm public/sprite/sprite.svg && svgstore -o public/sprite/sprite.svg public/sprite/icons/**/*.svg"
},
Expand All @@ -16,6 +17,7 @@
"@tanstack/react-query": "^4.32.6",
"axios": "^1.4.0",
"clsx": "^2.0.0",
"es-toolkit": "^1.15.1",
"eslint": "^8.46.0",
"eslint-config-next": "^13.4.12",
"framer-motion": "^10.15.0",
Expand All @@ -33,6 +35,10 @@
"typescript": "5.1.6"
},
"devDependencies": {
"@tanstack/react-query-devtools": "^4.35.0",
"@types/node": "20.4.5",
"@types/react": "18.2.17",
"@types/react-dom": "18.2.7",
"@typescript-eslint/eslint-plugin": "^6.2.1",
"@typescript-eslint/parser": "^6.2.1",
"autoprefixer": "^10.4.14",
Expand All @@ -46,11 +52,7 @@
"postcss": "^8.4.27",
"prettier": "^3.0.0",
"prettier-plugin-tailwindcss": "^0.4.1",
"tailwindcss": "^3.3.3",
"@types/node": "20.4.5",
"@types/react": "18.2.17",
"@types/react-dom": "18.2.7",
"@tanstack/react-query-devtools": "^4.35.0",
"svgstore-cli": "^2.0.1"
"svgstore-cli": "^2.0.1",
"tailwindcss": "^3.3.3"
}
}
}
2 changes: 1 addition & 1 deletion src/apis/apis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from '.';
import privateApi from './config/privateApi';
import publicApi from './config/publicApi';
import { KAKAO_REDIRECT_URI } from '@/constants/env';
import { KAKAO_REDIRECT_URI } from '@/constants';

export const getPosePick = (peopleCount: number) =>
publicApi.get<PosePickResponse>(`/pose/pick/${peopleCount}`);
Expand Down
12 changes: 8 additions & 4 deletions src/apis/config/privateApi.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import axios from 'axios';

import { CustomInstance } from './type';
import { ACCESS_TOKEN, ERROR_UNAUTHORIZED, ERROR_UNSUPPORTED_MEDIA_TYPE } from '@/constants';
import { BASE_API_URL } from '@/constants/env';
import {
BASE_API_URL,
COOKIE_ACCESS_TOKEN,
ERROR_UNAUTHORIZED,
ERROR_UNSUPPORTED_MEDIA_TYPE,
} from '@/constants';
import { getClientCookie, removeClientCookie } from '@/utils';

const privateApi: CustomInstance = axios.create({
Expand All @@ -16,7 +20,7 @@ privateApi.interceptors.response.use(
const status = error.response.status;
if (status === ERROR_UNAUTHORIZED || status === ERROR_UNSUPPORTED_MEDIA_TYPE) {
alert('세션이 만료되었어요. 다시 로그인이 필요해요!');
removeClientCookie(ACCESS_TOKEN);
removeClientCookie(COOKIE_ACCESS_TOKEN);
}
location.href = '/';
return Promise.reject(error);
Expand All @@ -25,7 +29,7 @@ privateApi.interceptors.response.use(

privateApi.interceptors.request.use(
(config) => {
const accessToken = getClientCookie(ACCESS_TOKEN);
const accessToken = getClientCookie(COOKIE_ACCESS_TOKEN);
config.headers.Authorization = `Bearer ${accessToken}`;
return config;
},
Expand Down
2 changes: 1 addition & 1 deletion src/apis/config/publicApi.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import axios from 'axios';

import { CustomInstance } from './type';
import { BASE_API_URL } from '@/constants/env';
import { BASE_API_URL } from '@/constants';

const publicApi: CustomInstance = axios.create({
baseURL: `${BASE_API_URL}/api`,
Expand Down
17 changes: 17 additions & 0 deletions src/app/(Main)/MainFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import AppDownloadBanner from '../../components/Header/AppDownloadBanner';
import { StrictPropsWithChildren } from '@/types';
import { isIOS } from '@/utils';

export function MainFooter({ children }: StrictPropsWithChildren) {
return (
<>
<div className="fixed inset-x-0 bottom-0 z-30">
<div className="mx-auto max-w-layout bg-white px-20 pb-24 pt-10">
<div className="flex gap-8 [&>*]:flex-1 [&>*]:grow">{children}</div>
</div>
{isIOS() && <AppDownloadBanner />}
</div>
<div className="h-88" />
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

import { usePathname } from 'next/navigation';

import Header from '.';
import FilterTab from './FilterTab';
import MyposeTab from './MyposeTab';
import Tab from './Tab';
import { Spacing } from '../Spacing';
import Header from '@/components/Header';
import FilterTab from '@/components/Header/FilterTab';
import MyposeTab from '@/components/Header/MyposeTab';
import Tab from '@/components/Header/Tab';
import { Spacing } from '@/components/Spacing';

export default function MainHeader() {
const curPath = usePathname();
Expand Down
23 changes: 23 additions & 0 deletions src/app/(Main)/feed/FeedComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use client';

import { QueryAsyncBoundary } from '@suspensive/react-query';

import FeedContent from './FeedContent';
import FilterSheet from './FilterSheet';
import { RejectedFallback } from '@/components/ErrorBoundary';
import { Loading } from '@/components/Loading';
import { PageAnimation } from '@/components/PageAnimation';

export default function FeedComponent() {
return (
<QueryAsyncBoundary
rejectedFallback={RejectedFallback}
pendingFallback={<Loading className="h-[calc(100dvh-178px)]" />}
>
<PageAnimation>
<FeedContent />
<FilterSheet />
</PageAnimation>
</QueryAsyncBoundary>
);
}
4 changes: 2 additions & 2 deletions src/app/(Main)/feed/FeedContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { usePoseFeedQuery } from '@/apis';
import { PrimaryButton } from '@/components/Button';
import EmptyCase from '@/components/Feed/EmptyCase';
import FeedSection from '@/components/Feed/FeedSection';
import { URL } from '@/constants/url';
import useFilterState from '@/hooks/useFilterState';
import { URL } from '@/constants';
import { useFilterState } from '@/hooks';

export default function FeedContent() {
const { filterState } = useFilterState();
Expand Down
25 changes: 15 additions & 10 deletions src/app/(Main)/feed/FilterSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
import { useEffect, useState } from 'react';

import { FilterTagsResponse, useFilterTagQuery } from '@/apis';
import { BottomDiv, PrimaryButton } from '@/components/Button';
import { PrimaryButton } from '@/components/Button';
import BottomSheet from '@/components/Modal/BottomSheet';
import { SelectionBasic, SelectionTagList } from '@/components/Selection';
import { frameCountList, peopleCountList } from '@/constants/data';
import useBottomSheet from '@/hooks/useBottomSheet';
import useFilterState from '@/hooks/useFilterState';
import { FRAME_COUNT_LIST, PEOPLE_COUNT_LIST } from '@/constants';
import { useBottomSheet, useFilterState } from '@/hooks';

export default function FilterSheet() {
const { data: tagListData } = useFilterTagQuery();
Expand Down Expand Up @@ -52,13 +51,13 @@ export default function FilterSheet() {
<div id="subtitle-2" className="mb-8 text-secondary">
인원 수
</div>
<SelectionBasic data={peopleCountList} state={countState} setState={setCountState} />
<SelectionBasic data={PEOPLE_COUNT_LIST} state={countState} setState={setCountState} />
</section>
<section>
<div id="subtitle-2" className="mb-8 text-secondary">
프레임 수
</div>
<SelectionBasic data={frameCountList} state={frameState} setState={setFrameState} />
<SelectionBasic data={FRAME_COUNT_LIST} state={frameState} setState={setFrameState} />
</section>
<section>
<div id="subtitle-2" className="mb-8 text-secondary">
Expand All @@ -73,10 +72,16 @@ export default function FilterSheet() {
)}
</section>
</div>
<BottomDiv>
<PrimaryButton type="outline" icon="restart" text="필터 초기화" onClick={resetFilter} />
<PrimaryButton type="fill" text="포즈보기" onClick={decideFilter} />
</BottomDiv>
<div className="flex gap-8 px-20 pb-20">
<PrimaryButton
className="flex-1"
variant="outline"
icon="restart"
text="필터 초기화"
onClick={resetFilter}
/>
<PrimaryButton className="flex-1" variant="fill" text="포즈보기" onClick={decideFilter} />
</div>
</BottomSheet>
);
}
22 changes: 2 additions & 20 deletions src/app/(Main)/feed/page.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,5 @@
'use client';

import { QueryAsyncBoundary } from '@suspensive/react-query';

import FeedContent from './FeedContent';
import FilterSheet from './FilterSheet';
import { RejectedFallback } from '@/components/ErrorBoundary';
import { Loading } from '@/components/Loading';
import { PageAnimation } from '@/components/PageAnimation';
import FeedComponent from './FeedComponent';

export default function Feed() {
return (
<QueryAsyncBoundary
rejectedFallback={RejectedFallback}
pendingFallback={<Loading className="h-[calc(100dvh-178px)]" />}
>
<PageAnimation>
<FeedContent />
<FilterSheet />
</PageAnimation>
</QueryAsyncBoundary>
);
return <FeedComponent />;
}
4 changes: 2 additions & 2 deletions src/app/(Main)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import MainHeader from '@/components/Header/MainHeader';
import MainHeader from './MainHeader';
import { StrictPropsWithChildren } from '@/types';

export default function MainLayout({ children }: StrictPropsWithChildren) {
return (
<div className="flex h-full flex-col px-20">
<div className="flex flex-col h-full px-20">
<MainHeader />
{children}
</div>
Expand Down
23 changes: 23 additions & 0 deletions src/app/(Main)/mypose/MyPoseComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use client';

import { PrimaryButton } from '@/components/Button';
import EmptyCase from '@/components/Feed/EmptyCase';
import { PreparingPopup } from '@/components/Modal';
import { useOverlay } from '@/components/Overlay/useOverlay';

export default function MyPoseComponent() {
const { open } = useOverlay();

return (
<EmptyCase
title={'나만의 포즈를 추가해 보세요!'}
text={'포즈피드에 네컷사진을 업로드할 수 있어요'}
>
<PrimaryButton
onClick={() => open(({ exit }) => <PreparingPopup onClose={exit} />)}
text="포즈 등록하기"
variant="secondary"
/>
</EmptyCase>
);
}
2 changes: 1 addition & 1 deletion src/app/(Main)/mypose/bookmark/BookmarkEmpty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default function BookmarkEmpty() {
text={`북마크 버튼으로 포즈를 보관할 수 있어요.\n포즈피드에서 멋진 포즈를 찾아 보관해 보세요.`}
>
<Link href={'/feed'}>
<PrimaryButton text="포즈피드 바로가기" type="secondary" />
<PrimaryButton text="포즈피드 바로가기" variant="secondary" />
</Link>
</EmptyCase>
);
Expand Down
Loading

0 comments on commit 6b1ab23

Please sign in to comment.