From 751b0e41a921cef0174281d801ecc7ecbcd3c520 Mon Sep 17 00:00:00 2001 From: yougyung Date: Sun, 15 Dec 2024 14:13:35 +0900 Subject: [PATCH 1/6] chore: update fetch-ax --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 36ca030..9d64e0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "express": "^4.18.2", - "fetch-ax": "^2.0.2", + "fetch-ax": "^2.0.3", "jotai": "^2.7.0", "lucide-react": "^0.336.0", "next": "^14.2.13", @@ -12454,9 +12454,9 @@ } }, "node_modules/fetch-ax": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fetch-ax/-/fetch-ax-2.0.2.tgz", - "integrity": "sha512-TzpshX5PllSXH/46YXpGprhmmxnKxCOHadC8HA2SmuLsUcXkbu85WTrdF89V0rcbFx/J6nG+Qc+af1lfzC5DoA==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fetch-ax/-/fetch-ax-2.0.3.tgz", + "integrity": "sha512-G7m6YJWup5rR0pIWnzySRvAH2um4ocgX98IbX3637OsSHKzaDUnRBVAfJ/dnay6OTQBYSGL9fuHc5lncTbuiYw==" }, "node_modules/figures": { "version": "3.2.0", diff --git a/package.json b/package.json index 3659c4f..fd68a56 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "express": "^4.18.2", - "fetch-ax": "^2.0.2", + "fetch-ax": "^2.0.3", "jotai": "^2.7.0", "lucide-react": "^0.336.0", "next": "^14.2.13", From 62da68427ee59b69b246dde3897ceeeb621ce83a Mon Sep 17 00:00:00 2001 From: yougyung Date: Sun, 15 Dec 2024 14:43:21 +0900 Subject: [PATCH 2/6] feat: connect error code --- .../services/lecture/taken-lecture.command.ts | 41 ++++++++----------- app/utils/api/constant.ts | 6 +-- app/utils/http/http-error.ts | 14 ++++++- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/app/business/services/lecture/taken-lecture.command.ts b/app/business/services/lecture/taken-lecture.command.ts index 1c31bdb..c64a583 100644 --- a/app/business/services/lecture/taken-lecture.command.ts +++ b/app/business/services/lecture/taken-lecture.command.ts @@ -1,45 +1,38 @@ 'use server'; import { FormState } from '@/app/ui/view/molecule/form/form-root'; import { API_PATH } from '../../api-path'; -import { BadRequestError } from '@/app/utils/http/http-error'; -import { cookies } from 'next/headers'; +import { BadRequestError, HttpError } from '@/app/utils/http/http-error'; import { redirect } from 'next/navigation'; import { instance } from '@/app/utils/api/instance'; import { revalidateTag } from 'next/cache'; import { TAG } from '@/app/utils/http/tag'; +import { ERROR_CODE } from '@/app/utils/api/constant'; export const registerUserGrade = async (prevState: FormState, formData: FormData) => { - const parsingText = await parsePDFtoText(formData); - - const res = await fetch(API_PATH.registerUserGrade, { - method: 'POST', - body: JSON.stringify({ parsingText }), - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${cookies().get('accessToken')?.value}`, - }, - }); - - if (!res.ok) { + try { + const parsingText = await parsePDFtoText(formData); + await instance.post(API_PATH.registerUserGrade, { parsingText }); + redirect('/result'); + } catch (error) { + if (error instanceof HttpError) { + return { + isSuccess: false, + isFailure: true, + validationError: {}, + message: error.getErrorMessage() ?? '', + }; + } return { isSuccess: false, isFailure: true, validationError: {}, - message: 'fail upload grade', + message: ERROR_CODE.INTERNAL_SEVER_ERROR, }; } - redirect('/result'); }; export const parsePDFtoText = async (formData: FormData) => { - const res = await fetch(API_PATH.parsePDFtoText, { method: 'POST', body: formData }); - if (!res.ok) { - return { - errors: {}, - message: 'fail parsing to text', - }; - } - return await res.text(); + return (await fetch(API_PATH.parsePDFtoText, { method: 'POST', body: formData })).text(); }; export const deleteTakenLecture = async (lectureId: number) => { diff --git a/app/utils/api/constant.ts b/app/utils/api/constant.ts index 6685462..da66713 100644 --- a/app/utils/api/constant.ts +++ b/app/utils/api/constant.ts @@ -20,7 +20,7 @@ export const ERROR_CODE = { UNFITTED_GRADUATION_CATEGORY: '', // LECTURE (아래 세개 모두 PDF Parsing에서 발생하는 에러) - INCORRECT_STUDENT_NUMBER: '', - NON_EXISTED_LECTURE: '', - UNSUPPORTED_STUDENT_CATEGORY: '', + INCORRECT_STUDENT_NUMBER: '학번과 일치하는 성적PDF를 입력해주세요.', + NON_EXISTED_LECTURE: '알수없는 수강과목이 존재해요. 채널톡으로 문의해주세요', + UNSUPPORTED_STUDENT_CATEGORY: '현재 지원하지않는 학번이에요.', } as const; diff --git a/app/utils/http/http-error.ts b/app/utils/http/http-error.ts index 31fec69..efc97e4 100644 --- a/app/utils/http/http-error.ts +++ b/app/utils/http/http-error.ts @@ -1,9 +1,15 @@ +import { ERROR_CODE } from '../api/constant'; + type ErrorConstrutor = { message?: string; statusCode?: number; response?: Partial; }; +interface HttpResponse extends Response { + data: { errorCode: keyof typeof ERROR_CODE | string }; +} + // Refactor: fetch가 NetworkError랑 TimeoutError 또 자동으로 에러로 던져서 처리가 더 애매하다. // export class NetworkError extends Error { // constructor(readonly message = 'Network Error') { @@ -23,10 +29,16 @@ export class HttpError extends Error { constructor( readonly statusCode?: number, message?: string, - readonly response?: Partial, + readonly response?: Partial, ) { super(message); } + + getErrorMessage(): string { + const errorCode = this.response?.data?.errorCode; + if (!errorCode) return ERROR_CODE.INTERNAL_SEVER_ERROR; + return errorCode in ERROR_CODE ? ERROR_CODE[errorCode as keyof typeof ERROR_CODE] : errorCode; + } } export class BadRequestError extends HttpError { From 4c306933d80c04b6d77cd7c81fb148792cad759b Mon Sep 17 00:00:00 2001 From: yougyung Date: Sun, 15 Dec 2024 14:56:35 +0900 Subject: [PATCH 3/6] refactor: execute redirect in browser --- app/business/services/lecture/taken-lecture.command.ts | 7 ++++++- .../upload-taken-lecture/upload-taken-lecture.tsx | 9 ++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/business/services/lecture/taken-lecture.command.ts b/app/business/services/lecture/taken-lecture.command.ts index c64a583..efd806c 100644 --- a/app/business/services/lecture/taken-lecture.command.ts +++ b/app/business/services/lecture/taken-lecture.command.ts @@ -12,7 +12,12 @@ export const registerUserGrade = async (prevState: FormState, formData: FormData try { const parsingText = await parsePDFtoText(formData); await instance.post(API_PATH.registerUserGrade, { parsingText }); - redirect('/result'); + return { + isSuccess: true, + isFailure: false, + validationError: {}, + message: '', + }; } catch (error) { if (error instanceof HttpError) { return { diff --git a/app/ui/lecture/upload-taken-lecture/upload-taken-lecture.tsx b/app/ui/lecture/upload-taken-lecture/upload-taken-lecture.tsx index 234b6a9..fe998bf 100644 --- a/app/ui/lecture/upload-taken-lecture/upload-taken-lecture.tsx +++ b/app/ui/lecture/upload-taken-lecture/upload-taken-lecture.tsx @@ -3,10 +3,17 @@ import { registerUserGrade } from '@/app/business/services/lecture/taken-lecture.command'; import UploadPdf from '@/app/ui/view/molecule/upload-pdf/upload-pdf'; import Form from '../../view/molecule/form'; +import { FormState } from '../../view/molecule/form/form-root'; +import { useRouter } from 'next/navigation'; function UploadTakenLecture() { + const router = useRouter(); + const handleSuccess = (formState?: FormState) => { + if (formState?.isSuccess) router.push('/my'); + }; + return ( -
+
From 56cfd0dd4e92fe28584b8c697763b81412c723b7 Mon Sep 17 00:00:00 2001 From: yougyung Date: Sun, 15 Dec 2024 19:01:50 +0900 Subject: [PATCH 4/6] fix: change parsing request to fetch-ax --- app/business/services/lecture/taken-lecture.command.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/business/services/lecture/taken-lecture.command.ts b/app/business/services/lecture/taken-lecture.command.ts index efd806c..9bc7082 100644 --- a/app/business/services/lecture/taken-lecture.command.ts +++ b/app/business/services/lecture/taken-lecture.command.ts @@ -7,6 +7,7 @@ import { instance } from '@/app/utils/api/instance'; import { revalidateTag } from 'next/cache'; import { TAG } from '@/app/utils/http/tag'; import { ERROR_CODE } from '@/app/utils/api/constant'; +import fetchAX from 'fetch-ax'; export const registerUserGrade = async (prevState: FormState, formData: FormData) => { try { @@ -37,7 +38,10 @@ export const registerUserGrade = async (prevState: FormState, formData: FormData }; export const parsePDFtoText = async (formData: FormData) => { - return (await fetch(API_PATH.parsePDFtoText, { method: 'POST', body: formData })).text(); + const response = await fetchAX.post(API_PATH.parsePDFtoText, formData, { + responseType: 'text', + }); + return response.data; }; export const deleteTakenLecture = async (lectureId: number) => { From eeebc9830076b06efeb30663f70aabfb39c2af56 Mon Sep 17 00:00:00 2001 From: yougyung Date: Sun, 15 Dec 2024 19:12:06 +0900 Subject: [PATCH 5/6] Revert "fix: change parsing request to fetch-ax" This reverts commit 56cfd0dd4e92fe28584b8c697763b81412c723b7. --- app/business/services/lecture/taken-lecture.command.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/business/services/lecture/taken-lecture.command.ts b/app/business/services/lecture/taken-lecture.command.ts index 9bc7082..0c8c4b5 100644 --- a/app/business/services/lecture/taken-lecture.command.ts +++ b/app/business/services/lecture/taken-lecture.command.ts @@ -2,12 +2,10 @@ import { FormState } from '@/app/ui/view/molecule/form/form-root'; import { API_PATH } from '../../api-path'; import { BadRequestError, HttpError } from '@/app/utils/http/http-error'; -import { redirect } from 'next/navigation'; import { instance } from '@/app/utils/api/instance'; import { revalidateTag } from 'next/cache'; import { TAG } from '@/app/utils/http/tag'; import { ERROR_CODE } from '@/app/utils/api/constant'; -import fetchAX from 'fetch-ax'; export const registerUserGrade = async (prevState: FormState, formData: FormData) => { try { @@ -38,10 +36,7 @@ export const registerUserGrade = async (prevState: FormState, formData: FormData }; export const parsePDFtoText = async (formData: FormData) => { - const response = await fetchAX.post(API_PATH.parsePDFtoText, formData, { - responseType: 'text', - }); - return response.data; + return (await fetch(API_PATH.parsePDFtoText, { method: 'POST', body: formData })).text(); }; export const deleteTakenLecture = async (lectureId: number) => { From 42445b79e327d383f2ef4cecf78c36dd2f81ba76 Mon Sep 17 00:00:00 2001 From: yougyung Date: Sun, 15 Dec 2024 21:41:27 +0900 Subject: [PATCH 6/6] chore: remove unused change --- app/business/services/lecture/taken-lecture.command.ts | 5 +---- app/business/services/lecture/taken-lecture.query.ts | 7 +------ 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/app/business/services/lecture/taken-lecture.command.ts b/app/business/services/lecture/taken-lecture.command.ts index 0c8c4b5..33b69e6 100644 --- a/app/business/services/lecture/taken-lecture.command.ts +++ b/app/business/services/lecture/taken-lecture.command.ts @@ -3,8 +3,6 @@ import { FormState } from '@/app/ui/view/molecule/form/form-root'; import { API_PATH } from '../../api-path'; import { BadRequestError, HttpError } from '@/app/utils/http/http-error'; import { instance } from '@/app/utils/api/instance'; -import { revalidateTag } from 'next/cache'; -import { TAG } from '@/app/utils/http/tag'; import { ERROR_CODE } from '@/app/utils/api/constant'; export const registerUserGrade = async (prevState: FormState, formData: FormData) => { @@ -44,7 +42,7 @@ export const deleteTakenLecture = async (lectureId: number) => { await instance.delete(`${API_PATH.takenLectures}/${lectureId}`, { responseType: 'text', }); - revalidateTag(TAG.GET_TAKEN_LECTURES); + return { isSuccess: true, }; @@ -68,7 +66,6 @@ export const addTakenLecture = async (lectureId: string) => { responseType: 'text', }, ); - revalidateTag(TAG.GET_TAKEN_LECTURES); return { isSuccess: true, isFailure: false, diff --git a/app/business/services/lecture/taken-lecture.query.ts b/app/business/services/lecture/taken-lecture.query.ts index 2885e07..ffc4a48 100644 --- a/app/business/services/lecture/taken-lecture.query.ts +++ b/app/business/services/lecture/taken-lecture.query.ts @@ -1,6 +1,5 @@ import { instance } from '@/app/utils/api/instance'; import { API_PATH } from '../../api-path'; -import { TAG } from '@/app/utils/http/tag'; export interface TakenLecturesResponse { totalCredit: number; @@ -18,10 +17,6 @@ export interface TakenLectureInfoResponse { } export const fetchTakenLectures = async () => { - const response = await instance.get(API_PATH.takenLectures, { - next: { - tags: [TAG.GET_TAKEN_LECTURES], - }, - }); + const response = await instance.get(API_PATH.takenLectures); return response.data; };