Skip to content

Commit

Permalink
Merge pull request #71 from dnd-side-project/develop
Browse files Browse the repository at this point in the history
✨ Update v0.3.0 - 소셜로그인 & 북마크
  • Loading branch information
seondal committed Apr 17, 2024
2 parents e7a3633 + e42954d commit 63bc5ae
Show file tree
Hide file tree
Showing 88 changed files with 1,118 additions and 775 deletions.
2 changes: 1 addition & 1 deletion next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const withPWA = require('next-pwa')({
});

const nextConfig = withPWA({
reactStrictMode: true,
reactStrictMode: false,
images: {
remotePatterns: [
{
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"react-lottie-player": "^1.5.4",
"react-tooltip": "^5.20.0",
"recoil": "^0.7.7",
"recoil-persist": "^5.1.0",
"svgstore": "^3.0.1",
"svgstore-cli": "^2.0.1",
"tailwind-merge": "^1.14.0",
Expand Down
Binary file removed public/fonts/Pretendard-Bold.woff2
Binary file not shown.
Binary file removed public/fonts/Pretendard-Medium.woff2
Binary file not shown.
Binary file removed public/fonts/Pretendard-Regular.woff2
Binary file not shown.
Binary file removed public/fonts/test.woff2
Binary file not shown.
8 changes: 0 additions & 8 deletions public/icons/bookmark_black_fill.svg

This file was deleted.

3 changes: 0 additions & 3 deletions public/icons/github.svg

This file was deleted.

5 changes: 0 additions & 5 deletions public/icons/instagram.svg

This file was deleted.

19 changes: 5 additions & 14 deletions public/icons/profile_default.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 39 additions & 2 deletions src/apis/apis.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import {
FilterTagsResponse,
PoseDetailResponse,
PoseFeedContents,
PoseFeedResponse,
PosePickResponse,
PoseTalkResponse,
RegisterResponse,
} from '.';
import privateApi from './config/privateApi';
import publicApi from './config/publicApi';
import { KAKAO_REDIRECT_URI } from '@/constants/env';

export const getPosePick = (peopleCount: number) =>
publicApi.get<PosePickResponse>(`/pose/pick/${peopleCount}`);
Expand All @@ -22,7 +25,7 @@ export const getPoseFeed = async (
tags: string,
pageNumber: number
) =>
await publicApi.get<PoseFeedResponse>(`/pose`, {
await privateApi.get<PoseFeedResponse>(`/pose`, {
params: {
frameCount,
pageNumber,
Expand All @@ -34,4 +37,38 @@ export const getPoseFeed = async (
export const getFilterTag = () => publicApi.get<FilterTagsResponse>('/pose/tags');

export const getRegister = (code: string) =>
publicApi.get<RegisterResponse>(`/users/login/oauth/kakao?code=${code}`);
publicApi.get<RegisterResponse>(
`/users/login/oauth/kakao?code=${code}&redirectURI=${KAKAO_REDIRECT_URI}`
);

export const patchLogout = (accessToken: string, refreshToken: string) =>
publicApi.patch('/users/logout', {
accessToken: `Bearer ${accessToken}`,
refreshToken: `Bearer ${refreshToken}`,
});

export const patchDeleteAccount = (
accessToken: string,
refreshToken: string,
withdrawalReason: string
) =>
publicApi.patch('/users/deleteAccount', {
accessToken: `Bearer ${accessToken}`,
refreshToken: `Bearer ${refreshToken}`,
withdrawalReason,
});

export const postBookmark = (poseId: number) =>
privateApi.post(`/bookmark`, null, {
params: { poseId },
});

export const deleteBookmark = (poseId: number) =>
privateApi.delete(`/bookmark`, {
params: { poseId },
});

export const getBookmarkFeed = (pageNumber: number) =>
privateApi.get<PoseFeedContents>('/bookmark/feed', {
params: { pageNumber, pageSize: 10 },
});
42 changes: 29 additions & 13 deletions src/apis/config/privateApi.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,46 @@
import axios, { AxiosError, InternalAxiosRequestConfig } from 'axios';
import axios from 'axios';

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

import type { CustomInstance } from './type';
function getAccesstoken() {
if (typeof window !== 'undefined') {
const item = localStorage.getItem('accesstoken');
return item;
}
}

const privateApi: CustomInstance = axios.create({
baseURL: `${BASE_API_URL}/api`,
withCredentials: true,
});

privateApi.interceptors.response.use(
(response) => response.data,
(error) => {
if (error.response.status === 415) {
alert('세션이 만료되었어요. 다시 로그인이 필요해요!');
} else {
alert('오류가 발생했어요. 다시 시도해주세요');
}
location.href = '/auth/logout';
return Promise.reject(error);
}
);

privateApi.interceptors.request.use(
async (config: InternalAxiosRequestConfig) => {
try {
const accessToken = getCookie('accessToken');
(config) => {
const accessToken = getAccesstoken();

if (accessToken) {
config.headers.Authorization = `Bearer ${accessToken}`;
return config;
} catch (error) {
return Promise.reject(error);
}

return config;
},
(error: AxiosError) => {
Promise.reject(error);
(error) => {
console.log('request : ' + error.response);
}
);

privateApi.interceptors.response.use((response) => response.data);

export default privateApi;
2 changes: 1 addition & 1 deletion src/apis/config/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ export interface CustomInstance extends AxiosInstance {
patch<T>(...params: Parameters<AxiosInstance['patch']>): Promise<T>;
}

export type ErrorStatus = 400 | 401 | 403 | 412 | 500;
export type ErrorStatus = 400 | 401 | 403 | 412 | 500 | 415;
27 changes: 20 additions & 7 deletions src/apis/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import {

import {
FilterTagsResponse,
PoseFeedContents,
PoseFeedResponse,
PosePickResponse,
PoseTalkResponse,
RegisterResponse,
getBookmarkFeed,
getFilterTag,
getPoseDetail,
getPoseFeed,
getPosePick,
getPoseTalk,
getRegister,
} from '.';
import { FilterState } from '@/hooks/useFilterState';

Expand All @@ -38,8 +38,8 @@ export const usePoseTalkQuery = (options?: UseQueryOptions<PoseTalkResponse>) =>
export const usePoseFeedQuery = (
{ peopleCount, frameCount, tags }: FilterState,
options?: UseInfiniteQueryOptions<PoseFeedResponse>
) =>
useSuspenseInfiniteQuery<PoseFeedResponse>(
) => {
return useSuspenseInfiniteQuery<PoseFeedResponse>(
['poseFeed', peopleCount, frameCount, tags],
({ pageParam = 0 }) => getPoseFeed(peopleCount, frameCount, tags.join(','), pageParam),
{
Expand All @@ -52,9 +52,22 @@ export const usePoseFeedQuery = (
...options,
}
);
};

export const useBookmarkFeedQuery = (
accesstoken: string,
options?: UseInfiniteQueryOptions<PoseFeedContents>
) =>
useSuspenseInfiniteQuery<PoseFeedContents>(
['bookmarkFeed'],
({ pageParam = 0 }) => getBookmarkFeed(pageParam),
{
getNextPageParam: (lastPage) => {
return lastPage.last ? undefined : lastPage.number + 1;
},
...options,
}
);

export const useFilterTagQuery = (options?: UseQueryOptions<FilterTagsResponse>) =>
useSuspenseQuery<FilterTagsResponse>(['filterTag'], getFilterTag, { ...options });

export const useRegisterQuery = (code: string) =>
useSuspenseQuery<RegisterResponse>(['register'], () => getRegister(code), {});
3 changes: 2 additions & 1 deletion src/apis/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface PoseInfo {
sourceUrl: string;
tagAttributes: string;
updatedAt: string;
bookmarkCheck: boolean;
}

// 포즈피드
Expand All @@ -16,7 +17,7 @@ interface PoseFeedContentsSort {
sorted: boolean;
unsorted: boolean;
}
interface PoseFeedContents {
export interface PoseFeedContents {
content: Array<{ poseInfo: PoseInfo }>;
pageable: {
sort: PoseFeedContentsSort;
Expand Down
26 changes: 26 additions & 0 deletions src/app/(Main)/feed/FeedContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Link from 'next/link';

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';

export default function FeedContent() {
const { filterState } = useFilterState();
const query = usePoseFeedQuery(filterState);

return (
<FeedSection query={query}>
<EmptyCase
title={'신비한 포즈를 찾으시는군요!'}
text={'찾고 싶은 포즈를 저희에게 알려주세요.'}
>
<Link href={URL.inquiry}>
<PrimaryButton text={'문의사항 남기기'} />
</Link>
</EmptyCase>
</FeedSection>
);
}
65 changes: 0 additions & 65 deletions src/app/(Main)/feed/FeedSection.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
'use client';

import { useEffect, useState } from 'react';

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

Expand Down
8 changes: 6 additions & 2 deletions src/app/(Main)/feed/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
'use client';

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

import FeedSection from './FeedSection';
import FeedContent from './FeedContent';
import FilterSheet from './FilterSheet';
import { RejectedFallback } from '@/components/ErrorBoundary';
import { Loading } from '@/components/Loading';
import { PageAnimation } from '@/components/PageAnimation';
Expand All @@ -12,7 +15,8 @@ export default function Feed() {
pendingFallback={<Loading className="h-[calc(100dvh-178px)]" />}
>
<PageAnimation>
<FeedSection />
<FeedContent />
<FilterSheet />
</PageAnimation>
</QueryAsyncBoundary>
);
Expand Down
Loading

0 comments on commit 63bc5ae

Please sign in to comment.