From 06f82499f679da98cda420357cc012d8bb75c18a Mon Sep 17 00:00:00 2001 From: Yeonu-Kim Date: Tue, 16 Jun 2026 10:50:49 +0900 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20presigned=20url=20=EB=B0=9C?= =?UTF-8?q?=EA=B8=89=20=EC=8B=9C=20=ED=86=A0=ED=81=B0=EC=9D=84=20=EB=B0=98?= =?UTF-8?q?=EB=93=9C=EC=8B=9C=20=ED=8F=AC=ED=95=A8=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/application/application-query.ts | 3 +++ .../application/usecase/application-usecase.ts | 5 ++++- src/feature/file/usecase/file-usecase.ts | 5 +++-- src/infrastructure/api/apis/local-server/apis.ts | 11 +++++++++-- src/infrastructure/api/apis/local-server/schemas.ts | 1 + src/mocks/s3/schemas.ts | 1 + src/widgets/application/ui/submit-form.tsx | 8 ++++++++ 7 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/feature/application/application/application-query.ts b/src/feature/application/application/application-query.ts index ea7fdac..8af7faa 100644 --- a/src/feature/application/application/application-query.ts +++ b/src/feature/application/application/application-query.ts @@ -54,15 +54,18 @@ export const useApplicationQuery = ({ eventId, walletAddress, imageFile, + token, }: { eventId: string; walletAddress: string; imageFile: File; + token: string; }) => { return await applicationUsecase.submitApplication({ eventId, walletAddress, imageFile, + token, }); }, onSuccess: (response) => { diff --git a/src/feature/application/usecase/application-usecase.ts b/src/feature/application/usecase/application-usecase.ts index 009f6e0..b784c98 100644 --- a/src/feature/application/usecase/application-usecase.ts +++ b/src/feature/application/usecase/application-usecase.ts @@ -13,6 +13,7 @@ export type ApplicationUsecase = { eventId: string; walletAddress: string; imageFile: File; + token: string; }): UsecaseResponse; }; @@ -45,10 +46,11 @@ export const implApplicationUsecase = ({ return { type: 'error', code: err.code, message: err.message }; }, - submitApplication: async ({ eventId, walletAddress, imageFile }) => { + submitApplication: async ({ eventId, walletAddress, imageFile, token }) => { const presignedResp = await fileUsecase.getUploadPresignedUrl({ fileName: imageFile.name, fileType: 'REVIEW', + contentType: imageFile.type, }); if (presignedResp.type === 'error') { return presignedResp; @@ -64,6 +66,7 @@ export const implApplicationUsecase = ({ const { status, data } = await api['POST /api/applications']({ body: { eventId, walletAddress, imageKey: presignedResp.data.s3Key }, + token, }); if (status === 200) { return { type: 'success', data: null }; diff --git a/src/feature/file/usecase/file-usecase.ts b/src/feature/file/usecase/file-usecase.ts index 0e28103..d127333 100644 --- a/src/feature/file/usecase/file-usecase.ts +++ b/src/feature/file/usecase/file-usecase.ts @@ -8,6 +8,7 @@ export type FileUsecase = { getUploadPresignedUrl(params: { fileName: string; fileType: FileType; + contentType: string; }): UsecaseResponse; uploadFile(params: { presignedUrl: string; @@ -22,9 +23,9 @@ export const implFileUsecase = ({ api: Apis; storageApi: StorageApis; }): FileUsecase => ({ - getUploadPresignedUrl: async ({ fileName, fileType }) => { + getUploadPresignedUrl: async ({ fileName, fileType, contentType }) => { const { status, data } = await api['POST /api/s3']({ - body: { fileName, fileType }, + body: { fileName, fileType, contentType }, }); if (status === 200) { return { type: 'success', data: data as S3UploadResponse }; diff --git a/src/infrastructure/api/apis/local-server/apis.ts b/src/infrastructure/api/apis/local-server/apis.ts index 28e9cc2..e165142 100644 --- a/src/infrastructure/api/apis/local-server/apis.ts +++ b/src/infrastructure/api/apis/local-server/apis.ts @@ -138,11 +138,18 @@ export const getLocalServerApis = ({ path: 'api/s3', body, }), - 'POST /api/applications': ({ body }: { body: ApplicationCreateRequest }) => - callWithoutToken>({ + 'POST /api/applications': ({ + body, + token, + }: { + body: ApplicationCreateRequest; + token: string; + }) => + callWithToken>({ method: 'POST', path: 'api/applications', body, + token, }), // Event diff --git a/src/infrastructure/api/apis/local-server/schemas.ts b/src/infrastructure/api/apis/local-server/schemas.ts index 19db198..267f95d 100644 --- a/src/infrastructure/api/apis/local-server/schemas.ts +++ b/src/infrastructure/api/apis/local-server/schemas.ts @@ -90,6 +90,7 @@ export type S3FileType = 'REVIEW' | 'STORE'; export type S3UploadRequest = { fileName: string; fileType: S3FileType; + contentType: string; }; export type S3UploadResponse = { diff --git a/src/mocks/s3/schemas.ts b/src/mocks/s3/schemas.ts index c2248fa..09aa576 100644 --- a/src/mocks/s3/schemas.ts +++ b/src/mocks/s3/schemas.ts @@ -3,6 +3,7 @@ export type S3FileType = 'REVIEW' | 'STORE'; export type S3UploadRequest = { fileName: string; fileType: S3FileType; + contentType: string; }; export type S3UploadResponse = { diff --git a/src/widgets/application/ui/submit-form.tsx b/src/widgets/application/ui/submit-form.tsx index 0f82ee7..d029608 100644 --- a/src/widgets/application/ui/submit-form.tsx +++ b/src/widgets/application/ui/submit-form.tsx @@ -4,6 +4,7 @@ import { useParams } from 'react-router'; import { applicationFormPresenter } from '@/feature/application/presenter/application-form-presenter'; import { applicationInputPresenter } from '@/feature/application/presenter/application-input-presenter'; import { QueryContext } from '@/feature/shared/context/query-context'; +import { TokenContext } from '@/feature/shared/context/token-context'; import { useGuardContext } from '@/feature/shared/context/use-gaurd-context'; import { Button } from '@/widgets/common/ui/button'; import { @@ -32,6 +33,7 @@ export const SubmitForm = () => { }>(); const { applicationQuery } = useGuardContext(QueryContext); + const { token } = useGuardContext(TokenContext); const { store } = applicationQuery.useGetStore({ storeId: storeId ?? '' }); const { event } = applicationQuery.useGetEvent({ eventId: eventId ?? '' }); @@ -133,10 +135,16 @@ export const SubmitForm = () => { return; } + if (token === null) { + setResponseMessage('로그인이 필요합니다.'); + return; + } + submitApplication({ eventId, walletAddress: inputStates.walletAddress.value, imageFile: inputStates.imageFile.value, + token, }); };