Skip to content

Commit

Permalink
♻️ colorRepository 마이그레이션 (#130)
Browse files Browse the repository at this point in the history
  • Loading branch information
woohm402 authored May 17, 2024
1 parent 3f4da07 commit 05db1c7
Show file tree
Hide file tree
Showing 17 changed files with 132 additions and 91 deletions.
79 changes: 42 additions & 37 deletions apps/snutt-webclient/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ import { Button } from '@/components/button';
import { Dialog } from '@/components/dialog';
import { envContext } from '@/contexts/EnvContext';
import { serviceContext } from '@/contexts/ServiceContext';
import { tokenContext } from '@/contexts/tokenContext';
import { TokenAuthContext } from '@/contexts/TokenAuthContext';
import { TokenManageContext } from '@/contexts/TokenManageContext';
import { useGuardContext } from '@/hooks/useGuardContext';
import { createFetchClient } from '@/infrastructures/createFetchClient';
import { createLocalStorageClient } from '@/infrastructures/createLocalStorageClient';
import { createSessionStorageClient } from '@/infrastructures/createSessionStorageClient';
import { implAuthSnuttApiRepository } from '@/infrastructures/implAuthSnuttApiRepository';
import { implColorSnuttApiRepository } from '@/infrastructures/implColorSnuttApiRepository';
import { ErrorPage } from '@/pages/error';
import { Main } from '@/pages/main';
import { MyPage } from '@/pages/mypage';
import { getColorRepository } from '@/repositories/colorRepository';
import { getErrorRepository } from '@/repositories/errorRepository';
import { getFeedbackRepository } from '@/repositories/feedbackRepository';
import { getNotificationRepository } from '@/repositories/notificationRepository';
Expand Down Expand Up @@ -104,45 +105,47 @@ export const App = () => {
return (
<QueryClientProvider key={token} client={queryClient}>
<GlobalStyles />
<tokenContext.Provider value={tokenContextValue}>
<TokenManageContext.Provider value={tokenContextValue}>
{token ? (
<serviceContext.Provider
value={{
...getAuthorizedServices(token, ENV),
errorService,
timetableViewService,
feedbackService: unauthorizedServices.feedbackService,
}}
>
<RouterProvider
router={createBrowserRouter([
{
children: [
{ path: '/', element: <Main /> },
{ path: '/mypage', element: <MyPage /> },
{ path: '/*', element: <NotFoundPage /> },
],
errorElement: <ErrorPage errorService={errorService} />,
},
])}
/>
<Dialog open={isWrongTokenDialogOpen}>
<Dialog.Title>인증정보가 올바르지 않아요</Dialog.Title>
<Dialog.Content>다시 로그인해 주세요</Dialog.Content>
<Dialog.Actions>
<Button data-testid="wrong-token-dialog-logout" onClick={onClickLogout}>
로그아웃하기
</Button>
</Dialog.Actions>
</Dialog>
</serviceContext.Provider>
<TokenAuthContext.Provider value={{ token }}>
<serviceContext.Provider
value={{
...getAuthorizedServices(token, ENV),
errorService,
timetableViewService,
feedbackService: unauthorizedServices.feedbackService,
}}
>
<RouterProvider
router={createBrowserRouter([
{
children: [
{ path: '/', element: <Main /> },
{ path: '/mypage', element: <MyPage /> },
{ path: '/*', element: <NotFoundPage /> },
],
errorElement: <ErrorPage errorService={errorService} />,
},
])}
/>
<Dialog open={isWrongTokenDialogOpen}>
<Dialog.Title>인증정보가 올바르지 않아요</Dialog.Title>
<Dialog.Content>다시 로그인해 주세요</Dialog.Content>
<Dialog.Actions>
<Button data-testid="wrong-token-dialog-logout" onClick={onClickLogout}>
로그아웃하기
</Button>
</Dialog.Actions>
</Dialog>
</serviceContext.Provider>
</TokenAuthContext.Provider>
) : (
<Landing
feedbackService={unauthorizedServices.feedbackService}
authService={unauthorizedServices.authService}
/>
)}
</tokenContext.Provider>
</TokenManageContext.Provider>
<ReactQueryDevtools />
</QueryClientProvider>
);
Expand Down Expand Up @@ -190,16 +193,18 @@ const getAuthorizedServices = (
headers: { 'x-access-apikey': ENV.API_KEY, 'x-access-token': token },
});

const snuttApi = getSnuttApi(ENV);

const userRepository = getUserRepository({ httpClient });
const authRepository = implAuthSnuttApiRepository({ snuttApi: getSnuttApi(ENV) });
const authRepository = implAuthSnuttApiRepository({ snuttApi });
const timetableRepository = getTimetableRepository({ httpClient });
const semesterRepository = getSemesterRepository({ httpClient });
const searchRepository = getSearchRepository({ httpClient });
const notificationRepository = getNotificationRepository({ httpClient });
const colorRepository = getColorRepository({ httpClient });
const colorRepository = implColorSnuttApiRepository({ snuttApi });

const userService = getUserService({ repositories: [userRepository] });
const colorService = getColorService({ repositories: [colorRepository] });
const colorService = getColorService({ colorRepository });
const notificationService = getNotificationService({ repositories: [notificationRepository] });
const searchService = getSearchService({ repositories: [searchRepository] });
const timetableService = getTimetableService({ repositories: [timetableRepository] });
Expand Down
11 changes: 11 additions & 0 deletions apps/snutt-webclient/src/contexts/TokenAuthContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createContext, useContext } from 'react';

type TokenAuthContext = { token: string };

export const TokenAuthContext = createContext<TokenAuthContext | null>(null);

export const useTokenAuthContext = () => {
const value = useContext(TokenAuthContext);
if (value === null) throw new Error('TokenAuthContext not provided');
return value;
};
14 changes: 14 additions & 0 deletions apps/snutt-webclient/src/contexts/TokenManageContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { createContext, useContext } from 'react';

export type TokenManageContext = {
saveToken: (token: string, permanent: boolean) => void;
clearToken: () => void;
};

export const TokenManageContext = createContext<TokenManageContext | null>(null);

export const useTokenManageContext = () => {
const value = useContext(TokenManageContext);
if (value === null) throw new Error('TokenManageContext not provided');
return value;
};
14 changes: 0 additions & 14 deletions apps/snutt-webclient/src/contexts/tokenContext.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { type SnuttApi } from '@sf/snutt-api';

import { type getColorService } from '@/usecases/colorService';

export const implColorSnuttApiRepository = ({
snuttApi,
}: {
snuttApi: SnuttApi;
}): Parameters<typeof getColorService>[0]['colorRepository'] => {
return {
getColorPalette: async ({ token }) => {
const { status, data } = await snuttApi['GET /v1/colors/vivid_ios']({ token });
if (status === 200) return data.colors;
else throw data;
},
};
};
4 changes: 2 additions & 2 deletions apps/snutt-webclient/src/mocks/fixtures/color.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ColorRepository } from '@/repositories/colorRepository';
import { type SnuttApi } from '@sf/snutt-api';

export const mockVividIos: Awaited<ReturnType<ColorRepository['getColorPalette']>> = {
export const mockVividIos: (Awaited<ReturnType<SnuttApi['GET /v1/colors/vivid_ios']>> & { status: 200 })['data'] = {
message: 'ok',
colors: [
{ fg: '#ffffff', bg: '#e54459' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import styled from 'styled-components';

import { Button } from '@/components/button';
import { envContext } from '@/contexts/EnvContext';
import { useTokenContext } from '@/contexts/tokenContext';
import { useTokenManageContext } from '@/contexts/TokenManageContext';
import { useGuardContext } from '@/hooks/useGuardContext';
import { LoginFindIdDialog } from '@/pages/landing/landing-login/find-id-dialog';
import { LoginResetPasswordDialog } from '@/pages/landing/landing-login/reset-password-dialog';
Expand All @@ -14,7 +14,7 @@ import { type AuthService } from '@/usecases/authService';
type Props = { className?: string; authService: AuthService; onSignUp: () => void };

export const LandingLogin = ({ className, authService, onSignUp }: Props) => {
const { saveToken } = useTokenContext();
const { saveToken } = useTokenManageContext();
const { FACEBOOK_APP_ID } = useGuardContext(envContext);
const [id, setId] = useState('');
const [password, setPassword] = useState('');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import styled from 'styled-components';

import { Button } from '@/components/button';
import { ErrorDialog } from '@/components/error-dialog';
import { useTokenContext } from '@/contexts/tokenContext';
import { useTokenManageContext } from '@/contexts/TokenManageContext';
import { useErrorDialog } from '@/hooks/useErrorDialog';
import { type AuthService } from '@/usecases/authService';

Expand All @@ -14,7 +14,7 @@ export const LandingSignUp = ({ authService, className }: { className?: string;
const [passwordConfirm, setPasswordConfirm] = useState('');

const { isOpen, message, onClose, open } = useErrorDialog();
const { saveToken } = useTokenContext();
const { saveToken } = useTokenManageContext();
const { mutate } = useSignUp(authService);

const onSubmit = async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useQuery } from '@tanstack/react-query';
import styled from 'styled-components';

import { serviceContext } from '@/contexts/ServiceContext';
import { useTokenAuthContext } from '@/contexts/TokenAuthContext';
import type { Color } from '@/entities/color';
import type { WithInternalId } from '@/entities/id';
import type { ClassTime, Lecture } from '@/entities/lecture';
Expand Down Expand Up @@ -95,7 +96,12 @@ export const MainLectureEditForm = ({ draft, defaultState = {}, setDraft }: Prop

const useColorList = () => {
const { colorService } = useGuardContext(serviceContext);
return useQuery({ queryKey: ['colors'], queryFn: () => colorService.getColorList(), staleTime: Infinity });
const { token } = useTokenAuthContext();
return useQuery({
queryKey: ['ColorService', 'getColorList', { token }] as const,
queryFn: ({ queryKey: [, , req] }) => colorService.getColorList(req),
staleTime: Infinity,
});
};

const Wrapper = styled.div``;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import styled, { css, keyframes } from 'styled-components';

import { Button } from '@/components/button';
import { serviceContext } from '@/contexts/ServiceContext';
import { useTokenAuthContext } from '@/contexts/TokenAuthContext';
import type { BaseLecture } from '@/entities/lecture';
import { DAY_LABEL_MAP } from '@/entities/time';
import type { FullTimetable } from '@/entities/timetable';
Expand Down Expand Up @@ -135,7 +136,12 @@ export const MainTimeTable = ({

const useColorList = () => {
const { colorService } = useGuardContext(serviceContext);
return useQuery({ queryKey: ['colors'], queryFn: () => colorService.getColorList(), staleTime: Infinity });
const { token } = useTokenAuthContext();
return useQuery({
queryKey: ['ColorService', 'getColorList', { token }] as const,
queryFn: ({ queryKey: [, , req] }) => colorService.getColorList(req),
staleTime: Infinity,
});
};

const Wrapper = styled.div<{ $columnCount: number; $rowCount: number }>`
Expand Down
8 changes: 4 additions & 4 deletions apps/snutt-webclient/src/pages/mypage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Button } from '@/components/button';
import { Layout } from '@/components/layout';
import { envContext } from '@/contexts/EnvContext';
import { serviceContext } from '@/contexts/ServiceContext';
import { useTokenContext } from '@/contexts/tokenContext';
import { useTokenManageContext } from '@/contexts/TokenManageContext';
import type { CoreServerError } from '@/entities/error';
import { useGuardContext } from '@/hooks/useGuardContext';
import { queryKey } from '@/utils/query-key-factory';
Expand All @@ -20,7 +20,7 @@ import { MypageRegisterId } from './mypage-register-id';

export const MyPage = () => {
const [isCloseOpen, setCloseOpen] = useState(false);
const { clearToken } = useTokenContext();
const { clearToken } = useTokenManageContext();
const { data: myInfo } = useMyInfo();
const navigate = useNavigate();
const { timetableViewService, userService } = useGuardContext(serviceContext);
Expand Down Expand Up @@ -122,7 +122,7 @@ const useMyInfo = () => {
};

const useAttachFacebook = () => {
const { saveToken } = useTokenContext();
const { saveToken } = useTokenManageContext();
const { errorService } = useGuardContext(serviceContext);
const { userService } = useGuardContext(serviceContext);

Expand All @@ -136,7 +136,7 @@ const useAttachFacebook = () => {
};

const useDetachFacebook = () => {
const { saveToken } = useTokenContext();
const { saveToken } = useTokenManageContext();
const { errorService } = useGuardContext(serviceContext);
const { userService } = useGuardContext(serviceContext);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import styled from 'styled-components';
import { Button } from '@/components/button';
import { ErrorDialog } from '@/components/error-dialog';
import { serviceContext } from '@/contexts/ServiceContext';
import { useTokenContext } from '@/contexts/tokenContext';
import { useTokenManageContext } from '@/contexts/TokenManageContext';
import { useErrorDialog } from '@/hooks/useErrorDialog';
import { useGuardContext } from '@/hooks/useGuardContext';
import { get } from '@/utils/object/get';
Expand All @@ -14,7 +14,7 @@ export const MypageChangePassword = () => {
const [currentPassword, setCurrentPassword] = useState('');
const [newPassword, setNewPassword] = useState('');
const [newPasswordConfirm, setNewPasswordConfirm] = useState('');
const { saveToken } = useTokenContext();
const { saveToken } = useTokenManageContext();
const { authService, errorService } = useGuardContext(serviceContext);

const { isOpen, message, onClose, open } = useErrorDialog();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import styled from 'styled-components';
import { Button } from '@/components/button';
import { Dialog } from '@/components/dialog';
import { serviceContext } from '@/contexts/ServiceContext';
import { useTokenContext } from '@/contexts/tokenContext';
import { useTokenManageContext } from '@/contexts/TokenManageContext';
import { useGuardContext } from '@/hooks/useGuardContext';

const CONFIRM_TEXT = '탈퇴';
Expand All @@ -15,7 +15,7 @@ type Props = { isOpen: boolean; onClose: () => void };

export const MypageCloseAccountDialog = ({ onClose, isOpen }: Props) => {
const [confirmText, setConfirmText] = useState('');
const { clearToken } = useTokenContext();
const { clearToken } = useTokenManageContext();
const { mutate } = useCloseAccount();
const navigate = useNavigate();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import styled from 'styled-components';
import { Button } from '@/components/button';
import { ErrorDialog } from '@/components/error-dialog';
import { serviceContext } from '@/contexts/ServiceContext';
import { useTokenContext } from '@/contexts/tokenContext';
import { useTokenManageContext } from '@/contexts/TokenManageContext';
import { useErrorDialog } from '@/hooks/useErrorDialog';
import { useGuardContext } from '@/hooks/useGuardContext';
import { get } from '@/utils/object/get';
Expand Down Expand Up @@ -67,7 +67,7 @@ export const MypageRegisterId = () => {
};

const useAddIdPassword = () => {
const { saveToken } = useTokenContext();
const { saveToken } = useTokenManageContext();
const queryClient = useQueryClient();
const { userService } = useGuardContext(serviceContext);

Expand Down
13 changes: 0 additions & 13 deletions apps/snutt-webclient/src/repositories/colorRepository.ts

This file was deleted.

13 changes: 8 additions & 5 deletions apps/snutt-webclient/src/usecases/colorService.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import type { Color } from '@/entities/color';
import type { ColorRepository } from '@/repositories/colorRepository';

export interface ColorService {
getColorList(): Promise<Color[]>;
getColorList(_: { token: string }): Promise<Color[]>;
}

type Deps = { repositories: [ColorRepository] };
export const getColorService = ({ repositories }: Deps): ColorService => {
type Deps = {
colorRepository: {
getColorPalette({ token }: { token: string }): Promise<Color[]>;
};
};
export const getColorService = ({ colorRepository }: Deps): ColorService => {
return {
getColorList: () => repositories[0].getColorPalette().then((res) => res.colors),
getColorList: (req: { token: string }) => colorRepository.getColorPalette(req),
};
};
Loading

0 comments on commit 05db1c7

Please sign in to comment.