Skip to content

Commit

Permalink
Feature/#373 - suspense, error boundary, alarm로직 변경 (#375)
Browse files Browse the repository at this point in the history
  • Loading branch information
baegyeong authored Dec 5, 2024
2 parents 40c439e + e64a01d commit 329fc69
Show file tree
Hide file tree
Showing 38 changed files with 380 additions and 247 deletions.
1 change: 1 addition & 0 deletions packages/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"lightweight-charts": "^4.2.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-error-boundary": "^4.1.2",
"react-lottie-player": "^2.1.0",
"react-router-dom": "^6.28.0",
"socket.io-client": "^4.8.1",
Expand Down
22 changes: 18 additions & 4 deletions packages/frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { Suspense } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { RouterProvider } from 'react-router-dom';
import { Error } from './components/errors/error';
import { Loader } from './components/ui/loader';
import { router } from './routes';

const App = () => {
const queryClient = new QueryClient();
const queryClient = new QueryClient({
defaultOptions: {
queries: {
throwOnError: true,
},
},
});

const App = () => {
return (
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
<ReactQueryDevtools initialIsOpen={false} />
<ErrorBoundary fallback={<Error />}>
<Suspense fallback={<Loader className="h-64 w-64 items-center" />}>
<RouterProvider router={router} />
<ReactQueryDevtools initialIsOpen={false} />
</Suspense>
</ErrorBoundary>
</QueryClientProvider>
);
};
Expand Down
4 changes: 3 additions & 1 deletion packages/frontend/src/apis/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import axios, { AxiosError } from 'axios';
import { ErrorResponse } from '@/apis/queries/errorSchema';

export const instance = axios.create({
baseURL: import.meta.env.VITE_BASE_URL,
Expand All @@ -10,9 +11,10 @@ instance.interceptors.response.use(
(response) => response,
async (error: AxiosError) => {
const status = error.response?.status;
const { message } = error.response?.data as ErrorResponse;

if (status === 400) {
alert('잘못된 요청이에요.');
alert(message);
}

if (status === 403) {
Expand Down
6 changes: 3 additions & 3 deletions packages/frontend/src/apis/queries/alarm/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const PostCreateAlarmRequestSchema = z.object({
stockId: z.string(),
targetPrice: z.number().optional(),
targetVolume: z.number().optional(),
alarmDate: z.string().datetime(),
alarmExpiredDate: z.string().datetime().nullish(),
});

export type PostCreateAlarmRequest = z.infer<
Expand All @@ -33,8 +33,8 @@ export const AlarmInfoSchema = z.object({
alarmId: z.number(),
stockId: z.string(),
targetPrice: z.number().nullable(),
targetVolume: z.string().nullable(),
alarmDate: z.string().datetime(),
targetVolume: z.number().nullable(),
alarmExpiredDate: z.string().datetime().nullable(),
});

export const AlarmResponseSchema = z.array(AlarmInfoSchema);
Expand Down
2 changes: 2 additions & 0 deletions packages/frontend/src/apis/queries/alarm/useGetStockAlarm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@ export const useGetStockAlarm = ({
queryKey: ['getStockAlarm', stockId],
queryFn: () => getStockAlarm({ stockId }),
enabled: isLoggedIn,
staleTime: 1000 * 60 * 5,
select: (data) => data.reverse(),
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ const postCreateAlarm = ({
stockId,
targetPrice,
targetVolume,
alarmDate,
alarmExpiredDate,
}: PostCreateAlarmRequest) =>
post<AlarmResponse>({
params: { stockId, targetPrice, targetVolume, alarmDate },
params: { stockId, targetPrice, targetVolume, alarmExpiredDate },
schema: AlarmInfoSchema,
url: '/api/alarm',
});
Expand All @@ -26,9 +26,9 @@ export const usePostCreateAlarm = () => {
stockId,
targetPrice,
targetVolume,
alarmDate,
alarmExpiredDate,
}: PostCreateAlarmRequest) =>
postCreateAlarm({ stockId, targetPrice, targetVolume, alarmDate }),
postCreateAlarm({ stockId, targetPrice, targetVolume, alarmExpiredDate }),
onSuccess: () =>
queryClient.invalidateQueries({ queryKey: ['getStockAlarm'] }),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ export const useGetLoginStatus = () => {
return useQuery({
queryKey: ['loginStatus'],
queryFn: getLoginStatus,
staleTime: 1000 * 60 * 5,
staleTime: 1000 * 60 * 3,
});
};
4 changes: 2 additions & 2 deletions packages/frontend/src/apis/queries/chat/useGetChatList.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useInfiniteQuery } from '@tanstack/react-query';
import { useSuspenseInfiniteQuery } from '@tanstack/react-query';
import { GetChatListRequest } from './schema';
import { get } from '@/apis/utils/get';
import { ChatDataResponse, ChatDataResponseSchema } from '@/sockets/schema';
Expand Down Expand Up @@ -26,7 +26,7 @@ export const useGetChatList = ({
pageSize,
order,
}: GetChatListRequest) => {
return useInfiniteQuery({
return useSuspenseInfiniteQuery({
queryKey: ['chatList', stockId, order],
queryFn: ({ pageParam }) =>
getChatList({
Expand Down
4 changes: 3 additions & 1 deletion packages/frontend/src/apis/queries/chat/usePostChatLike.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMutation } from '@tanstack/react-query';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import {
GetChatLikeResponseSchema,
type GetChatLikeRequest,
Expand All @@ -14,8 +14,10 @@ const postChatLike = ({ chatId }: GetChatLikeRequest) =>
});

export const usePostChatLike = () => {
const queryClient = useQueryClient();
return useMutation({
mutationKey: ['chatLike'],
mutationFn: ({ chatId }: GetChatLikeRequest) => postChatLike({ chatId }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['chatList'] }),
});
};
20 changes: 20 additions & 0 deletions packages/frontend/src/apis/queries/errorSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { z } from 'zod';

export const ErrorResponseSchema = z.object({
message: z.string(),
error: z.string(),
statusCode: z.number(),
});

export const AxiosErrorSchema = z.object({
response: z.object({
data: ErrorResponseSchema,
status: z.number(),
statusText: z.string(),
}),
request: z.any().optional(),
message: z.string(),
});

export type ErrorResponse = z.infer<typeof ErrorResponseSchema>;
export type AxiosError = z.infer<typeof AxiosErrorSchema>;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useQuery } from '@tanstack/react-query';
import { useSuspenseQuery } from '@tanstack/react-query';
import {
GetStockResponseSchema,
type GetStockRequest,
Expand All @@ -13,9 +13,8 @@ const getStockDetail = ({ stockId }: GetStockRequest) =>
});

export const useGetStockDetail = ({ stockId }: GetStockRequest) => {
return useQuery({
return useSuspenseQuery({
queryKey: ['stockDetail', stockId],
queryFn: () => getStockDetail({ stockId }),
enabled: !!stockId,
});
};
2 changes: 1 addition & 1 deletion packages/frontend/src/apis/queries/stocks/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from './schema';
export * from './useGetTopViews';
export * from './useGetStocksByPrice';
export * from './useGetSearchStocks';
export * from './useGetStocksPriceSeries';
export * from './useStockQueries';
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const useGetSearchStocks = (name: string) => {
await new Promise((resolve) => setTimeout(resolve, 500));
return getSearchStocks(name);
},
retry: 0,
enabled: false,
});
};
17 changes: 0 additions & 17 deletions packages/frontend/src/apis/queries/stocks/useGetStockIndex.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useQuery } from '@tanstack/react-query';
import { useSuspenseQuery } from '@tanstack/react-query';
import {
GetStockListResponseSchema,
type GetStockListRequest,
Expand All @@ -14,7 +14,7 @@ const getStockByPrice = ({ limit, type }: GetStockListRequest) =>
});

export const useGetStocksByPrice = ({ limit, type }: GetStockListRequest) => {
return useQuery({
return useSuspenseQuery({
queryKey: ['stocks', limit, type],
queryFn: () => getStockByPrice({ limit, type }),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,12 @@ export const useGetStocksPriceSeries = ({
: undefined,
initialPageParam: { lastStartTime },
select: (data) => ({
pages: [...data.pages].reverse(),
pageParams: [...data.pageParams].reverse(),
priceDtoList: [...data.pages]
.reverse()
.flatMap((page) => page.priceDtoList),
volumeDtoList: [...data.pages]
.reverse()
.flatMap((page) => page.volumeDtoList),
}),
refetchOnWindowFocus: false,
staleTime: 5 * 60 * 1000,
Expand Down
22 changes: 0 additions & 22 deletions packages/frontend/src/apis/queries/stocks/useGetTopViews.ts

This file was deleted.

42 changes: 42 additions & 0 deletions packages/frontend/src/apis/queries/stocks/useStockQueries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useSuspenseQueries } from '@tanstack/react-query';
import { z } from 'zod';
import {
GetStockListRequest,
GetStockListResponseSchema,
GetStockTopViewsResponse,
StockIndexResponse,
StockIndexSchema,
} from './schema';
import { get } from '@/apis/utils/get';

interface StockQueriesProps {
viewsLimit: GetStockListRequest['limit'];
}

const getStockIndex = () =>
get<StockIndexResponse[]>({
schema: z.array(StockIndexSchema),
url: `/api/stock/index`,
});

const getTopViews = ({ limit }: Partial<GetStockListRequest>) =>
get<Partial<GetStockTopViewsResponse>[]>({
schema: z.array(GetStockListResponseSchema.partial()),
url: `/api/stock/topViews`,
params: { limit },
});

export const useStockQueries = ({ viewsLimit }: StockQueriesProps) => {
return useSuspenseQueries({
queries: [
{
queryKey: ['stockIndex'],
queryFn: getStockIndex,
},
{
queryKey: ['topViews'],
queryFn: () => getTopViews({ limit: viewsLimit }),
},
],
});
};
4 changes: 2 additions & 2 deletions packages/frontend/src/apis/queries/user/useGetUserInfo.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useQuery } from '@tanstack/react-query';
import { useSuspenseQuery } from '@tanstack/react-query';
import { GetUserInfoSchema, type GetUserInfo } from './schema';
import { get } from '@/apis/utils/get';

Expand All @@ -9,7 +9,7 @@ const getUserInfo = () =>
});

export const useGetUserInfo = () => {
return useQuery({
return useSuspenseQuery({
queryKey: ['userInfo'],
queryFn: getUserInfo,
});
Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/src/apis/queries/user/useGetUserStock.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useQuery } from '@tanstack/react-query';
import { useSuspenseQuery } from '@tanstack/react-query';
import {
GetUserStockResponseSchema,
type GetUserStockResponse,
Expand All @@ -12,7 +12,7 @@ const getUserStock = () =>
});

export const useGetUserStock = () => {
return useQuery({
return useSuspenseQuery({
queryKey: ['userStock'],
queryFn: getUserStock,
});
Expand Down
30 changes: 30 additions & 0 deletions packages/frontend/src/components/errors/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Lottie from 'react-lottie-player';
import { useNavigate } from 'react-router-dom';
import { Button } from '../ui/button';
import error from '@/components/lottie/error-loading.json';
import { cn } from '@/utils/cn';

interface ErrorProps {
className?: string;
}

export const Error = ({ className }: ErrorProps) => {
const navigate = useNavigate();

return (
<div className="bg-extra-light-gray flex justify-center">
<section className="flex flex-col items-center gap-5">
<Lottie
className={cn('h-36 w-36', className)}
animationData={error}
play
/>
<p>에러가 발생했어요. 주춤주춤 팀을 찾아주세요.</p>
<div className="flex gap-5">
<Button onClick={() => navigate(-1)}>뒤로가기</Button>
<Button onClick={() => navigate('/')}></Button>
</div>
</section>
</div>
);
};
4 changes: 2 additions & 2 deletions packages/frontend/src/components/layouts/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useContext, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import logoCharacter from '/logoCharacter.png';
import logoTitle from '/logoTitle.png';
import { Alarm } from './alarm';
// import { Alarm } from './alarm';
import { MenuList } from './MenuList';
import { Search } from './search';
import { BOTTOM_MENU_ITEMS, TOP_MENU_ITEMS } from '@/constants/menuItems';
Expand Down Expand Up @@ -101,7 +101,7 @@ export const Sidebar = () => {
)}
>
{showTabs.search && <Search className="h-screen" />}
{showTabs.alarm && <Alarm className="h-screen" />}
{/* {showTabs.alarm && <Alarm className="h-screen" />} */}
</div>
</div>
);
Expand Down
Loading

0 comments on commit 329fc69

Please sign in to comment.