Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

user fetch refactoring /#98 #100

Merged
merged 13 commits into from
May 11, 2024
1 change: 0 additions & 1 deletion app/business/api-path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export const API_PATH = {
takenLectures: `${BASE_URL}/taken-lectures`,
resultCategoryDetailInfo: `${BASE_URL}/result-category-detail-info`,
user: `${BASE_URL}/users`,
resultUserInfo: `${BASE_URL}/resultUserInfo`,
credits: `${BASE_URL}/credits`,
auth: `${BASE_URL}/auth`,
lectures: `${BASE_URL}/lectures`,
Expand Down
39 changes: 1 addition & 38 deletions app/business/result/result.query.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,8 @@
import { LectureInfo } from '@/app/type/lecture';
import { API_PATH } from '../api-path';
import { cookies } from 'next/headers';
import { httpErrorHandler } from '@/app/utils/http/http-error-handler';
import { RESULT_CATEGORY } from '@/app/utils/key/result-category.key';
import { CreditResponse, ResultCategoryDetailResponse } from './result.type';

export interface ResultCategoryDetailLectures {
categoryName: string;
totalCredits: number;
takenCredits: number;
takenLectures: LectureInfo[];
haveToLectures: LectureInfo[];
completed: boolean;
}

export interface ResultCategoryDetailResponse {
totalCredit: number;
takenCredit: number;
detailCategory: ResultCategoryDetailLectures[];
completed: boolean;
}

export interface Major {
majorType: 'PRIMARY' | 'DUAL' | 'SUB';
major: string;
}

export interface ResultUserInfo {
studentNumber: string;
studentName: string;
completionDivision: Major[];
totalCredit: number;
takenCredit: number;
graduated: boolean;
}

export interface CreditResponse {
category: keyof typeof RESULT_CATEGORY;
totalCredit: number;
takenCredit: number;
completed: boolean;
}
export const fetchResultCategoryDetailInfo = async (category: string): Promise<ResultCategoryDetailResponse> => {
//FIX : category를 querystring으로 호출하는 건은 mock단계에서는 불필요할 것으로 예상, 실제 api 연결시 변경 예정
try {
Expand Down
30 changes: 30 additions & 0 deletions app/business/result/result.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { LectureInfo } from '@/app/type/lecture';
import { RESULT_CATEGORY } from '@/app/utils/key/result-category.key';

export interface ResultCategoryDetailLectures {
categoryName: string;
totalCredits: number;
takenCredits: number;
takenLectures: LectureInfo[];
haveToLectures: LectureInfo[];
completed: boolean;
}

export interface ResultCategoryDetailResponse {
totalCredit: number;
takenCredit: number;
detailCategory: ResultCategoryDetailLectures[];
completed: boolean;
}

export interface Major {
majorType: 'PRIMARY' | 'DUAL' | 'SUB';
major: string;
}

export interface CreditResponse {
category: keyof typeof RESULT_CATEGORY;
totalCredit: number;
takenCredit: number;
completed: boolean;
}
27 changes: 5 additions & 22 deletions app/business/user/user.query.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { httpErrorHandler } from '@/app/utils/http/http-error-handler';
import { API_PATH } from '../api-path';
import { UserInfoResponse } from './user.type';

import { cookies } from 'next/headers';
import { isValidation } from '@/app/utils/zod/validation.util';
import { UserInfoResponseSchema } from './user.validation';
import { ResultUserInfo } from '../result/result.query';
import { InitUserInfoResponse, UserInfoResponse } from './user.type';
import { UserInfoResponseSchema, InitUserInfoResponseSchema } from './user.validation';

export async function getUserInfo(): Promise<UserInfoResponse> {
export async function fetchUserInfo(): Promise<InitUserInfoResponse | UserInfoResponse> {
try {
const response = await fetch(`${API_PATH.user}`, {
headers: {
Expand All @@ -18,7 +18,7 @@ export async function getUserInfo(): Promise<UserInfoResponse> {

httpErrorHandler(response, result);

if (isValidation(result, UserInfoResponseSchema)) {
if (isValidation(result, UserInfoResponseSchema || InitUserInfoResponseSchema)) {
return result;
} else {
throw 'Invalid user info response schema.';
Expand All @@ -27,20 +27,3 @@ export async function getUserInfo(): Promise<UserInfoResponse> {
throw error;
}
}

export async function fetchResultUserInfo(): Promise<ResultUserInfo> {
try {
const response = await fetch(API_PATH.resultUserInfo, {
headers: {
Authorization: `Bearer ${cookies().get('accessToken')?.value}`,
},
});

const result = await response.json();

httpErrorHandler(response, result);
return result;
} catch (error) {
throw error;
}
}
16 changes: 11 additions & 5 deletions app/business/user/user.type.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
// https://stackoverflow.com/questions/76957592/error-only-async-functions-are-allowed-to-be-exported-in-a-use-server-file
// server action 파일에서는 async function만 export 가능

import { SignInResponseSchema, UserInfoResponseSchema, ValidateTokenResponseSchema } from './user.validation';
import {
InitUserInfoResponseSchema,
SignInResponseSchema,
UserInfoResponseSchema,
ValidateTokenResponseSchema,
} from './user.validation';
import z from 'zod';

export interface SignUpRequestBody {
export interface SignInRequestBody {
authId: string;
password: string;
studentNumber: string;
engLv: string;
}

export interface SignInRequestBody {
export interface SignUpRequestBody {
authId: string;
password: string;
studentNumber: string;
engLv: string;
}

export type SignInResponse = z.infer<typeof SignInResponseSchema>;

export type UserInfoResponse = z.infer<typeof UserInfoResponseSchema>;
export type InitUserInfoResponse = z.infer<typeof InitUserInfoResponseSchema>;

export type ValidateTokenResponse = z.infer<typeof ValidateTokenResponseSchema>;
13 changes: 10 additions & 3 deletions app/business/user/user.validation.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { z } from 'zod';

// api 변경 예정

export const UserInfoResponseSchema = z.object({
studentNumber: z.string(),
studentName: z.string(),
completionDivision: z.array(
z.object({
majorType: z.string(),
majorType: z.enum(['PRIMARY', 'DUAL', 'SUB']),
major: z.string(),
}),
),
Expand All @@ -16,6 +14,15 @@ export const UserInfoResponseSchema = z.object({
graduated: z.boolean(),
});

export const InitUserInfoResponseSchema = z.object({
studentNumber: z.string(),
studentName: z.null(),
completionDivision: z.null(),
totalCredit: z.null(),
takenCredit: z.null(),
graduated: z.null(),
});

export const ValidateTokenResponseSchema = z.object({
accessToken: z.string(),
});
Expand Down
12 changes: 11 additions & 1 deletion app/mocks/data.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const takenLectures = JSON.parse(`{
]
}`);

export const resultUserInfo = JSON.parse(`{
export const userInfo = JSON.parse(`{
"studentNumber": "60181666",
"studentName": "장진욱",
"completionDivision" : [
Expand Down Expand Up @@ -195,6 +195,15 @@ export const resultCategoryDetailInfo = JSON.parse(`{
"completed": false
}`);

export const users = JSON.parse(`[
{
"authId": "admin",
"password": "admin",
"studentNumber": "60000000",
"engLv": "ENG12"
}
]`);

export const credits = JSON.parse(`[
{
"category": "COMMON_CULTURE",
Expand Down Expand Up @@ -269,6 +278,7 @@ export const credits = JSON.parse(`[
"completed": false
}
]`);

export const searchLectures = JSON.parse(`{
"lectures": [
{
Expand Down
90 changes: 23 additions & 67 deletions app/mocks/db.mock.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,39 @@
import { SearchLectures } from '../business/lecture/search-lecture.query';
import { TakenLectures } from '../business/lecture/taken-lecture.query';
import { CreditResponse, ResultCategoryDetailResponse, ResultUserInfo } from '../business/result/result.query';
import { SignUpRequestBody, SignInRequestBody, UserInfoResponse } from '../business/user/user.type';
import { takenLectures, resultCategoryDetailInfo, resultUserInfo, credits, searchLectures } from './data.mock';

interface MockUser {
authId: string;
password: string;
studentNumber: string;
engLv: string;
major: string;
isSumbitted: boolean;
name: string;
}
import { CreditResponse, ResultCategoryDetailResponse } from '../business/result/result.type';
import {
SignUpRequestBody,
SignInRequestBody,
UserInfoResponse,
InitUserInfoResponse,
} from '../business/user/user.type';
import { takenLectures, credits, searchLectures, userInfo, users, resultCategoryDetailInfo } from './data.mock';

interface MockDatabaseState {
takenLectures: TakenLectures;
resultCategoryDetailInfo: ResultCategoryDetailResponse;
resultUserInfo: ResultUserInfo;
credits: CreditResponse[];
users: MockUser[];
users: SignUpRequestBody[];
searchLectures: SearchLectures;
userInfo: UserInfoResponse;
}

type MockDatabaseAction = {
getTakenLectures: () => TakenLectures;
getSearchLectures: () => SearchLectures;
getResultCategoryDetailInfo: () => ResultCategoryDetailResponse;
addTakenLecture: (lectureId: number) => boolean;
deleteTakenLecture: (lectureId: number) => boolean;
getUser: (authId: string) => MockUser | undefined;
createUser: (user: SignUpRequestBody) => boolean;
signIn: (userData: SignInRequestBody) => boolean;
getCredits: () => CreditResponse[];
getUserInfo: (authId: string) => UserInfoResponse;
getResultUserInfo: () => ResultUserInfo;
getUserInfo: (authId: string) => UserInfoResponse | InitUserInfoResponse;
getResultCategoryDetailInfo: () => ResultCategoryDetailResponse;
};

export const mockDatabase: MockDatabaseAction = {
getTakenLectures: () => mockDatabaseStore.takenLectures,
getResultUserInfo: () => mockDatabaseStore.resultUserInfo,
getSearchLectures: () => mockDatabaseStore.searchLectures,
getResultCategoryDetailInfo: () => mockDatabaseStore.resultCategoryDetailInfo,
deleteTakenLecture: (lectureId) => {
if (mockDatabaseStore.takenLectures.takenLectures.find((lecture) => lecture.id === lectureId)) {
mockDatabaseStore.takenLectures.takenLectures = mockDatabaseStore.takenLectures.takenLectures.filter(
Expand All @@ -64,22 +57,13 @@ export const mockDatabase: MockDatabaseAction = {
];
return true;
},
getResultCategoryDetailInfo: () => mockDatabaseStore.resultCategoryDetailInfo,
getUser: (authId: string) => mockDatabaseStore.users.find((user) => user.authId === authId),

getCredits: () => mockDatabaseStore.credits,
createUser: (user: SignUpRequestBody) => {
if (mockDatabaseStore.users.find((u) => u.authId === user.authId || u.studentNumber === user.studentNumber)) {
return false;
}
mockDatabaseStore.users = [
...mockDatabaseStore.users,
{
...user,
isSumbitted: false,
major: '융소입니다',
name: '모킹이2',
},
];
mockDatabaseStore.users = [...mockDatabaseStore.users, user];
return true;
},
signIn: (userData: SignInRequestBody) => {
Expand All @@ -91,52 +75,24 @@ export const mockDatabase: MockDatabaseAction = {
if (!user) {
return {
studentNumber: '',
studentName: '',
completionDivision: [
{
majorType: '',
major: '',
},
],
totalCredit: 0,
takenCredit: 0,
graduated: false,
studentName: null,
completionDivision: null,
totalCredit: null,
takenCredit: null,
graduated: null,
};
}
return {
studentNumber: user.studentNumber,
studentName: user.name,
completionDivision: [
{
majorType: 'primary',
major: '디지털컨텐츠디자인학과',
},
],

totalCredit: 132,
takenCredit: 50,
graduated: false,
};
return mockDatabaseStore.userInfo;
},
};

const initialState: MockDatabaseState = {
takenLectures: takenLectures,
resultCategoryDetailInfo: resultCategoryDetailInfo,
credits: credits,
resultUserInfo: resultUserInfo,
users: [
{
authId: 'admin',
password: 'admin',
studentNumber: '60000000',
engLv: 'ENG12',
isSumbitted: false,
major: '융소입니다',
name: '모킹이',
},
],
users: users,
searchLectures: searchLectures,
userInfo: userInfo,
};

function initStore(): MockDatabaseState {
Expand Down
2 changes: 1 addition & 1 deletion app/mocks/handlers/result-handler.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { HttpResponse, http, delay } from 'msw';
import { API_PATH } from '../../business/api-path';
import { mockDatabase } from '../db.mock';
import { ErrorResponseData } from '@/app/utils/http/http-error-handler';
import { CreditResponse, ResultCategoryDetailResponse } from '@/app/business/result/result.query';
import { CreditResponse, ResultCategoryDetailResponse } from '@/app/business/result/result.type';

export const resultHandlers = [
http.get<never, never, ResultCategoryDetailResponse | ErrorResponseData>(
Expand Down
1 change: 0 additions & 1 deletion app/mocks/handlers/taken-lecture-handler.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export const takenLectureHandlers = [
}),
http.post(API_PATH.parsePDFtoText, async () => {
await delay(1000);
console.log(parsePDF);
return HttpResponse.json(parsePDF);
}),

Expand Down
Loading
Loading