diff --git a/apps/snutt-webclient/src/App.tsx b/apps/snutt-webclient/src/App.tsx index 5b47c201..d94f3120 100644 --- a/apps/snutt-webclient/src/App.tsx +++ b/apps/snutt-webclient/src/App.tsx @@ -10,16 +10,16 @@ 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 { 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'; @@ -70,6 +70,7 @@ export const App = () => { const [token, setToken] = useState(tokenService.getToken()); const tokenContextValue = { + token, saveToken: (newToken: string, permanent: boolean) => { setToken(newToken); tokenService.saveToken(newToken, permanent); @@ -104,7 +105,7 @@ export const App = () => { return ( - + {token ? ( { authService={unauthorizedServices.authService} /> )} - + ); @@ -190,16 +191,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] }); diff --git a/apps/snutt-webclient/src/contexts/TokenAuthContext.ts b/apps/snutt-webclient/src/contexts/TokenAuthContext.ts new file mode 100644 index 00000000..87a1f000 --- /dev/null +++ b/apps/snutt-webclient/src/contexts/TokenAuthContext.ts @@ -0,0 +1,11 @@ +import { createContext, useContext } from 'react'; + +type TokenAuthContext = { token: string }; + +export const TokenAuthContext = createContext(null); + +export const useTokenAuthContext = () => { + const value = useContext(TokenAuthContext); + if (value === null) throw new Error('TokenContextProvider not provided'); + return value; +}; diff --git a/apps/snutt-webclient/src/contexts/tokenContext.tsx b/apps/snutt-webclient/src/contexts/TokenManageContext.tsx similarity index 52% rename from apps/snutt-webclient/src/contexts/tokenContext.tsx rename to apps/snutt-webclient/src/contexts/TokenManageContext.tsx index 4272c162..3594cb71 100644 --- a/apps/snutt-webclient/src/contexts/tokenContext.tsx +++ b/apps/snutt-webclient/src/contexts/TokenManageContext.tsx @@ -1,14 +1,14 @@ import { createContext, useContext } from 'react'; -export type TokenContext = { +export type TokenManageContext = { saveToken: (token: string, permanent: boolean) => void; clearToken: () => void; }; -export const tokenContext = createContext(null); +export const TokenManageContext = createContext(null); -export const useTokenContext = () => { - const value = useContext(tokenContext); +export const useTokenManageContext = () => { + const value = useContext(TokenManageContext); if (value === null) throw new Error('TokenContextProvider not provided'); return value; }; diff --git a/apps/snutt-webclient/src/infrastructures/implColorSnuttApiRepository.ts b/apps/snutt-webclient/src/infrastructures/implColorSnuttApiRepository.ts new file mode 100644 index 00000000..ed76bade --- /dev/null +++ b/apps/snutt-webclient/src/infrastructures/implColorSnuttApiRepository.ts @@ -0,0 +1,17 @@ +import { type SnuttApi } from '@sf/snutt-api'; + +import { type getColorService } from '@/usecases/colorService'; + +export const implColorSnuttApiRepository = ({ + snuttApi, +}: { + snuttApi: SnuttApi; +}): Parameters[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; + }, + }; +}; diff --git a/apps/snutt-webclient/src/mocks/fixtures/color.ts b/apps/snutt-webclient/src/mocks/fixtures/color.ts index 112d63dc..b60ac554 100644 --- a/apps/snutt-webclient/src/mocks/fixtures/color.ts +++ b/apps/snutt-webclient/src/mocks/fixtures/color.ts @@ -1,4 +1,4 @@ -import type { ColorRepository } from '@/repositories/colorRepository'; +import type { ColorRepository } from '@/infrastructures/implColorSnuttApiRepository'; export const mockVividIos: Awaited> = { message: 'ok', diff --git a/apps/snutt-webclient/src/pages/landing/landing-login/index.tsx b/apps/snutt-webclient/src/pages/landing/landing-login/index.tsx index 301dcc88..f94fd6eb 100644 --- a/apps/snutt-webclient/src/pages/landing/landing-login/index.tsx +++ b/apps/snutt-webclient/src/pages/landing/landing-login/index.tsx @@ -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/TokenAuthContext'; 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'; @@ -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(''); diff --git a/apps/snutt-webclient/src/pages/landing/landing-signup/index.tsx b/apps/snutt-webclient/src/pages/landing/landing-signup/index.tsx index cc9feeed..9c71a5f1 100644 --- a/apps/snutt-webclient/src/pages/landing/landing-signup/index.tsx +++ b/apps/snutt-webclient/src/pages/landing/landing-signup/index.tsx @@ -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/TokenAuthContext'; import { useErrorDialog } from '@/hooks/useErrorDialog'; import { type AuthService } from '@/usecases/authService'; @@ -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 () => { diff --git a/apps/snutt-webclient/src/pages/main/main-lecture-edit-form/index.tsx b/apps/snutt-webclient/src/pages/main/main-lecture-edit-form/index.tsx index 54641c53..cce28455 100644 --- a/apps/snutt-webclient/src/pages/main/main-lecture-edit-form/index.tsx +++ b/apps/snutt-webclient/src/pages/main/main-lecture-edit-form/index.tsx @@ -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'; @@ -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``; diff --git a/apps/snutt-webclient/src/pages/main/main-timetable-section/main-timetable/index.tsx b/apps/snutt-webclient/src/pages/main/main-timetable-section/main-timetable/index.tsx index a459c4f4..220e3a4f 100644 --- a/apps/snutt-webclient/src/pages/main/main-timetable-section/main-timetable/index.tsx +++ b/apps/snutt-webclient/src/pages/main/main-timetable-section/main-timetable/index.tsx @@ -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'; @@ -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 }>` diff --git a/apps/snutt-webclient/src/pages/mypage/index.tsx b/apps/snutt-webclient/src/pages/mypage/index.tsx index c02b0410..ff896713 100644 --- a/apps/snutt-webclient/src/pages/mypage/index.tsx +++ b/apps/snutt-webclient/src/pages/mypage/index.tsx @@ -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'; @@ -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); @@ -122,7 +122,7 @@ const useMyInfo = () => { }; const useAttachFacebook = () => { - const { saveToken } = useTokenContext(); + const { saveToken } = useTokenManageContext(); const { errorService } = useGuardContext(serviceContext); const { userService } = useGuardContext(serviceContext); @@ -136,7 +136,7 @@ const useAttachFacebook = () => { }; const useDetachFacebook = () => { - const { saveToken } = useTokenContext(); + const { saveToken } = useTokenManageContext(); const { errorService } = useGuardContext(serviceContext); const { userService } = useGuardContext(serviceContext); diff --git a/apps/snutt-webclient/src/pages/mypage/mypage-change-password/index.tsx b/apps/snutt-webclient/src/pages/mypage/mypage-change-password/index.tsx index 14948eff..ceb3f665 100644 --- a/apps/snutt-webclient/src/pages/mypage/mypage-change-password/index.tsx +++ b/apps/snutt-webclient/src/pages/mypage/mypage-change-password/index.tsx @@ -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'; @@ -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(); diff --git a/apps/snutt-webclient/src/pages/mypage/mypage-close-account-dialog/index.tsx b/apps/snutt-webclient/src/pages/mypage/mypage-close-account-dialog/index.tsx index 6b214df2..076a90a7 100644 --- a/apps/snutt-webclient/src/pages/mypage/mypage-close-account-dialog/index.tsx +++ b/apps/snutt-webclient/src/pages/mypage/mypage-close-account-dialog/index.tsx @@ -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 = '탈퇴'; @@ -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(); diff --git a/apps/snutt-webclient/src/pages/mypage/mypage-register-id/index.tsx b/apps/snutt-webclient/src/pages/mypage/mypage-register-id/index.tsx index 44a735e8..2eaf0717 100644 --- a/apps/snutt-webclient/src/pages/mypage/mypage-register-id/index.tsx +++ b/apps/snutt-webclient/src/pages/mypage/mypage-register-id/index.tsx @@ -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'; @@ -67,7 +67,7 @@ export const MypageRegisterId = () => { }; const useAddIdPassword = () => { - const { saveToken } = useTokenContext(); + const { saveToken } = useTokenManageContext(); const queryClient = useQueryClient(); const { userService } = useGuardContext(serviceContext); diff --git a/apps/snutt-webclient/src/repositories/colorRepository.ts b/apps/snutt-webclient/src/repositories/colorRepository.ts deleted file mode 100644 index 17f3a609..00000000 --- a/apps/snutt-webclient/src/repositories/colorRepository.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { HttpClient } from '@/clients/HttpClient'; -import type { Color } from '@/entities/color'; - -export interface ColorRepository { - getColorPalette(): Promise<{ colors: Color[]; names: string[]; message: 'ok' }>; -} - -export const getColorRepository = ({ httpClient }: { httpClient: HttpClient }): ColorRepository => { - return { - getColorPalette: async () => - (await httpClient.get<{ colors: Color[]; names: string[]; message: 'ok' }>(`/v1/colors/vivid_ios`)).data, - }; -}; diff --git a/apps/snutt-webclient/src/usecases/colorService.ts b/apps/snutt-webclient/src/usecases/colorService.ts index a2da09d6..b8344ec0 100644 --- a/apps/snutt-webclient/src/usecases/colorService.ts +++ b/apps/snutt-webclient/src/usecases/colorService.ts @@ -1,13 +1,16 @@ import type { Color } from '@/entities/color'; -import type { ColorRepository } from '@/repositories/colorRepository'; export interface ColorService { - getColorList(): Promise; + getColorList(_: { token: string }): Promise; } -type Deps = { repositories: [ColorRepository] }; -export const getColorService = ({ repositories }: Deps): ColorService => { +type Deps = { + colorRepository: { + getColorPalette({ token }: { token: string }): Promise; + }; +}; +export const getColorService = ({ colorRepository }: Deps): ColorService => { return { - getColorList: () => repositories[0].getColorPalette().then((res) => res.colors), + getColorList: (req: { token: string }) => colorRepository.getColorPalette(req), }; }; diff --git a/packages/snutt-api/src/apis/index.ts b/packages/snutt-api/src/apis/index.ts index cf454765..9287b038 100644 --- a/packages/snutt-api/src/apis/index.ts +++ b/packages/snutt-api/src/apis/index.ts @@ -2,12 +2,12 @@ import { InternalClient } from '../httpClient'; import { ErrorResponse, SuccessResponse } from '../response'; import { LocalLoginRequest, LoginResponse } from './schemas'; -type Api = ({ body }: { body: never }) => Promise<{ status: number; data: unknown }>; +type Api = (_: { body: never; token: string }) => Promise<{ status: number; data: unknown }>; export const apis = (client: InternalClient) => { - // const callWithToken = ( - // p: Parameters[0] & { token: string }, - // ) => client.call>(p); + const callWithToken = ( + p: Parameters[0] & { token: string }, + ) => client.call>(p); const callWithoutToken = ( p: Omit[0], 'token'> & { token?: never }, @@ -62,5 +62,11 @@ export const apis = (client: InternalClient) => { path: `/v1/auth/password/reset`, body, }), + 'GET /v1/colors/vivid_ios': ({ token }: { token: string }) => + callWithToken>({ + method: 'get', + path: `/v1/colors/vivid_ios`, + token, + }), } satisfies Record; };