Skip to content

Commit

Permalink
Dev fe -> Dev (#374)
Browse files Browse the repository at this point in the history
  • Loading branch information
baegyeong authored Dec 5, 2024
2 parents e9d2e02 + db28e9f commit a9481ad
Show file tree
Hide file tree
Showing 106 changed files with 1,677 additions and 2,080 deletions.
3 changes: 3 additions & 0 deletions packages/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
"axios": "^1.7.7",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"dayjs": "^1.11.13",
"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 All @@ -36,6 +38,7 @@
"@storybook/react": "8.4.3",
"@storybook/react-vite": "8.4.3",
"@storybook/test": "8.4.3",
"@tanstack/react-query-devtools": "^5.62.0",
"@types/node": "^22.8.7",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
Expand Down
10 changes: 10 additions & 0 deletions packages/frontend/public/serviceWorker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
self.addEventListener('push', (event) => {
const data = event.data
? event.data.json()
: { title: '알림', body: '내용 없음' };

self.registration.showNotification(data.title, {
body: data.body,
// icon: 'icon.png',
});
});
29 changes: 25 additions & 4 deletions packages/frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,35 @@
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} />
{/* TODO:react query devtools 설치 */}
<ErrorBoundary fallback={<Error />}>
<Suspense
fallback={
<div className="bg-extra-light-gray flex h-screen items-center justify-center">
<Loader className="h-64 w-64 items-center" />
</div>
}
>
<RouterProvider router={router} />
<ReactQueryDevtools initialIsOpen={false} />
</Suspense>
</ErrorBoundary>
</QueryClientProvider>
);
};
Expand Down
6 changes: 4 additions & 2 deletions 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,13 +11,14 @@ 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) {
alert('로그인이 필요합니다.');
alert('로그인 후 이용 가능해요.');
location.href = '/login';
}
return Promise.reject(error);
Expand Down
5 changes: 5 additions & 0 deletions packages/frontend/src/apis/queries/alarm/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './schema';
export * from './useGetAlarm';
export * from './useGetStockAlarm';
export * from './usePostCreateAlarm';
export * from './usePostInitAlarm';
47 changes: 47 additions & 0 deletions packages/frontend/src/apis/queries/alarm/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { z } from 'zod';

const KeysSchema = z.object({
p256dh: z.string(),
auth: z.string(),
});

export const PostInitAlarmRequestSchema = z.object({
endpoint: z.string(),
keys: KeysSchema,
});

export type PostInitAlarmRequest = z.infer<typeof PostInitAlarmRequestSchema>;

export const PostInitAlarmResponseSchema = z.object({
message: z.string(),
});

export type PostInitAlarmResponse = z.infer<typeof PostInitAlarmResponseSchema>;

export const PostCreateAlarmRequestSchema = z.object({
stockId: z.string(),
targetPrice: z.number().optional(),
targetVolume: z.number().optional(),
alarmExpiredDate: z.string().datetime().nullish(),
});

export type PostCreateAlarmRequest = z.infer<
typeof PostCreateAlarmRequestSchema
>;

export const AlarmInfoSchema = z.object({
alarmId: z.number(),
stockId: z.string(),
targetPrice: z.number().nullable(),
targetVolume: z.number().nullable(),
alarmExpiredDate: z.string().datetime().nullable(),
});

export const AlarmResponseSchema = z.array(AlarmInfoSchema);
export type AlarmResponse = z.infer<typeof AlarmResponseSchema>;

export const StockAlarmRequestSchema = z.object({
stockId: z.string(),
});

export type StockAlarmRequest = z.infer<typeof StockAlarmRequestSchema>;
18 changes: 18 additions & 0 deletions packages/frontend/src/apis/queries/alarm/useGetAlarm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useQuery } from '@tanstack/react-query';
import { type AlarmResponse, AlarmResponseSchema } from './schema';
import { get } from '@/apis/utils/get';

const getAlarm = () =>
get<AlarmResponse>({
schema: AlarmResponseSchema,
url: '/api/alarm/user',
});

export const useGetAlarm = ({ isLoggedIn }: { isLoggedIn: boolean }) => {
return useQuery({
queryKey: ['getAlarm'],
queryFn: getAlarm,
enabled: isLoggedIn,
staleTime: 1000 * 60 * 5,
});
};
26 changes: 26 additions & 0 deletions packages/frontend/src/apis/queries/alarm/useGetStockAlarm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useQuery } from '@tanstack/react-query';
import {
type AlarmResponse,
StockAlarmRequest,
AlarmResponseSchema,
} from './schema';
import { get } from '@/apis/utils/get';

const getStockAlarm = ({ stockId }: StockAlarmRequest) =>
get<AlarmResponse>({
schema: AlarmResponseSchema,
url: `/api/alarm/stock/${stockId}`,
});

export const useGetStockAlarm = ({
stockId,
isLoggedIn,
}: StockAlarmRequest & { isLoggedIn: boolean }) => {
return useQuery({
queryKey: ['getStockAlarm', stockId],
queryFn: () => getStockAlarm({ stockId }),
enabled: isLoggedIn,
staleTime: 1000 * 60 * 5,
select: (data) => data.reverse(),
});
};
37 changes: 37 additions & 0 deletions packages/frontend/src/apis/queries/alarm/usePostCreateAlarm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import {
type PostCreateAlarmRequest,
type AlarmResponse,
AlarmInfoSchema,
} from './schema';
import { post } from '@/apis/utils/post';

const postCreateAlarm = ({
stockId,
targetPrice,
targetVolume,
alarmExpiredDate,
}: PostCreateAlarmRequest) =>
post<AlarmResponse>({
params: { stockId, targetPrice, targetVolume, alarmExpiredDate },
schema: AlarmInfoSchema,
url: '/api/alarm',
});

export const usePostCreateAlarm = () => {
const queryClient = useQueryClient();
return useMutation({
mutationKey: ['createAlarm'],
mutationFn: ({
stockId,
targetPrice,
targetVolume,
alarmExpiredDate,
}: PostCreateAlarmRequest) =>
postCreateAlarm({ stockId, targetPrice, targetVolume, alarmExpiredDate }),
onSuccess: () =>
queryClient.invalidateQueries({
queryKey: ['getStockAlarm', 'getAlarm'],
}),
});
};
20 changes: 20 additions & 0 deletions packages/frontend/src/apis/queries/alarm/usePostInitAlarm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useMutation } from '@tanstack/react-query';
import {
type PostInitAlarmResponse,
PostInitAlarmResponseSchema,
} from './schema';
import { post } from '@/apis/utils/post';

const postInitAlarm = (subscription: PushSubscription) =>
post<PostInitAlarmResponse>({
params: subscription,
schema: PostInitAlarmResponseSchema,
url: '/api/push/subscribe',
});

export const usePostInitAlarm = () => {
return useMutation({
mutationKey: ['initAlarm'],
mutationFn: (subscription: PushSubscription) => postInitAlarm(subscription),
});
};
35 changes: 1 addition & 34 deletions packages/frontend/src/apis/queries/auth/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { z } from 'zod';
export const GetLoginStatusSchema = z.object({
message: z.enum(['Authenticated', 'Not Authenticated']),
nickname: z.string().nullish(),
subName: z.string().nullish(),
});

export type GetLoginStatus = z.infer<typeof GetLoginStatusSchema>;
Expand All @@ -14,42 +15,8 @@ export const GetTestLoginSchema = z.object({

export type GetTestLogin = z.infer<typeof GetTestLoginSchema>;

export const GetUserInfoSchema = z.object({
nickname: z.string(),
subName: z.string(),
createdAt: z.string().datetime(),
email: z.string(),
type: z.string(),
});

export type GetUserInfo = z.infer<typeof GetUserInfoSchema>;

export const PostUserNicknameSchema = z.object({
message: z.string(),
date: z.string().datetime(),
});

export type PostUserNickname = z.infer<typeof PostUserNicknameSchema>;

export const PostLogoutSchema = z.object({
message: z.string(),
});

export type PostLogout = z.infer<typeof PostLogoutSchema>;

export const GetUserStockSchema = z.object({
id: z.number(),
stockId: z.string(),
name: z.string(),
isTrading: z.boolean(),
groupCode: z.string(),
createdAt: z.string().datetime(),
});

export type GetUserStock = z.infer<typeof GetUserStockSchema>;

export const GetUserStockResponseSchema = z.object({
userStocks: z.array(GetUserStockSchema),
});

export type GetUserStockResponse = z.infer<typeof GetUserStockResponseSchema>;
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ export const useGetLoginStatus = () => {
return useQuery({
queryKey: ['loginStatus'],
queryFn: getLoginStatus,
staleTime: 1000 * 60 * 3,
});
};
6 changes: 5 additions & 1 deletion packages/frontend/src/apis/queries/auth/usePostLogout.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 { PostLogout, PostLogoutSchema } from './schema';
import { post } from '@/apis/utils/post';

Expand All @@ -9,8 +9,12 @@ const postLogout = () =>
});

export const usePostLogout = () => {
const queryClient = useQueryClient();

return useMutation({
mutationKey: ['logout'],
mutationFn: postLogout,
onSuccess: () =>
queryClient.invalidateQueries({ queryKey: ['loginStatus'] }),
});
};
1 change: 1 addition & 0 deletions packages/frontend/src/apis/queries/chat/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './schema';
export * from './usePostChatLike';
export * from './useGetChatList';
9 changes: 9 additions & 0 deletions packages/frontend/src/apis/queries/chat/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,12 @@ export const GetChatLikeResponseSchema = z.object({
});

export type GetChatLikeResponse = z.infer<typeof GetChatLikeResponseSchema>;

export const GetChatListRequestSchema = z.object({
stockId: z.string(),
latestChatId: z.number().optional(),
pageSize: z.number().optional(),
order: z.enum(['latest', 'like']).optional(),
});

export type GetChatListRequest = z.infer<typeof GetChatListRequestSchema>;
51 changes: 51 additions & 0 deletions packages/frontend/src/apis/queries/chat/useGetChatList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useSuspenseInfiniteQuery } from '@tanstack/react-query';
import { GetChatListRequest } from './schema';
import { get } from '@/apis/utils/get';
import { ChatDataResponse, ChatDataResponseSchema } from '@/sockets/schema';

const getChatList = ({
stockId,
latestChatId,
pageSize,
order,
}: GetChatListRequest) =>
get<ChatDataResponse>({
schema: ChatDataResponseSchema,
url: '/api/chat',
params: {
stockId,
latestChatId,
pageSize,
order,
},
});

export const useGetChatList = ({
stockId,
latestChatId,
pageSize,
order,
}: GetChatListRequest) => {
return useSuspenseInfiniteQuery({
queryKey: ['chatList', stockId, order],
queryFn: ({ pageParam }) =>
getChatList({
stockId,
latestChatId: pageParam?.latestChatId,
pageSize,
order,
}),
getNextPageParam: (lastPage) =>
lastPage.hasMore
? {
latestChatId: lastPage.chats[lastPage.chats.length - 1].id,
}
: undefined,
initialPageParam: { latestChatId },
select: (data) => ({
pages: [...data.pages].flatMap((page) => page.chats),
pageParams: [...data.pageParams],
}),
staleTime: 1000 * 60 * 3,
});
};
Loading

0 comments on commit a9481ad

Please sign in to comment.