Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/features/interview-page/interview/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@ export {
parseInterviewSocketMessage,
} from "./interview-socket";
export { prepareInterview } from "./prepare-interview";
export { prepareInterviewRecord } from "./prepare-interview-record";
export {
getInterviewPreparation,
prepareInterviewRecord,
} from "./prepare-interview-record";
export type {
InterviewPreparationData,
InterviewPreparationStatus,
} from "./prepare-interview-record";
export { quitInterview } from "./quit-interview";
export { savePersona } from "./save-persona";
export { submitInterviewAnswer } from "./submit-answer";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,33 @@ import { apiInstance } from "@/shared/api/axiosInstance";

import {
getErrorMessage,
getInterviewQuestion,
getNumericValue,
getRecord,
getTrimmedString,
} from "../shared";
import type { CurrentInterviewQuestion } from "../type";


const PREPARE_INTERVIEW_RECORD_URL = "/api/interviews";
const PREPARE_INTERVIEW_RECORD_BODY = 0;
const PREPARATION_STATUS_VALUES = [
"NOT_REQUESTED",
"PENDING",
"SUCCEEDED",
"FAILED",
] as const;

export type InterviewPreparationStatus =
(typeof PREPARATION_STATUS_VALUES)[number];

export interface InterviewPreparationData {
chatDelivered: boolean;
errorMessage: string | null;
interviewId: number;
questions: CurrentInterviewQuestion[];
status: InterviewPreparationStatus;
}

const getInterviewId = (payload: unknown) => {
const responseRecord = getRecord(payload);
Expand Down Expand Up @@ -81,3 +101,66 @@ export const prepareInterviewRecord = async (interviewId: number) => {
};
}
};

const isInterviewPreparationStatus = (
value: string | null,
): value is InterviewPreparationStatus =>
value !== null &&
PREPARATION_STATUS_VALUES.includes(value as InterviewPreparationStatus);

export const getInterviewPreparation = async (interviewId: number) => {
if (!Number.isInteger(interviewId) || interviewId <= 0) {
return {
data: null,
errorMessage: "유효한 인터뷰 ID가 없습니다.",
};
}

try {
const response = await apiInstance.get("/api/questions/tailor", {
params: { interviewId },
});
const responseRecord = getRecord(response.data);
const sourceRecord = getRecord(responseRecord?.data) ?? responseRecord;
const status = getTrimmedString(sourceRecord?.status)?.toUpperCase() ?? null;

if (!isInterviewPreparationStatus(status)) {
return {
data: null,
errorMessage: "면접 준비 상태를 확인하지 못했습니다.",
};
}

const questions = Array.isArray(sourceRecord?.questions)
? sourceRecord.questions.reduce<CurrentInterviewQuestion[]>(
(items, question) => {
const normalizedQuestion = getInterviewQuestion(question);

if (normalizedQuestion) {
items.push(normalizedQuestion);
}

return items;
},
[],
)
: [];

return {
data: {
chatDelivered: sourceRecord?.chatDelivered === true,
errorMessage: getTrimmedString(sourceRecord?.errorMessage),
interviewId:
getNumericValue(sourceRecord?.interviewId) ?? interviewId,
questions,
status,
} satisfies InterviewPreparationData,
errorMessage: null,
};
} catch (error) {
return {
data: null,
errorMessage: getErrorMessage(error, "면접 준비 상태를 확인하지 못했습니다."),
};
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ const buildPrepareInterviewRequest = (
status: "IN_PROGRESS",
currentQuestionIndex: 0,
questions: normalizedQuestions,
mode: "SOLO",
};
};

Expand Down Expand Up @@ -286,6 +287,14 @@ const normalizePreparedInterview = (
: fallbackData.status,
currentQuestionIndex,
questions: normalizedQuestions,
mode: "SOLO",
interviewers: [
{
personaId: getNumericValue(sourceRecord?.personaId) ?? fallbackData.personaId,
name: getTrimmedString(sourceRecord?.personaName) ?? fallbackData.personaName,
roleLabel: "기술 면접관",
},
],
};
};

Expand Down
7 changes: 4 additions & 3 deletions src/features/interview-page/interview/api/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,11 @@ export const getInterviewQuestion = (
questionId,
parentId: getNumericValue(questionRecord?.parentId) ?? 0,
type: getTrimmedString(questionRecord?.type) ?? "ORIGINAL",
intention:
getTrimmedString(questionRecord?.intention ?? questionRecord?.purpose) ??
"",
intention: getTrimmedString(
questionRecord?.intention ?? questionRecord?.purpose ?? questionRecord?.category,
) ?? "",
content,
personaId: getNumericValue(questionRecord?.personaId) ?? undefined,
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export interface CurrentInterviewQuestion {
type: string;
intention: string;
content: string;
personaId?: number;
}
2 changes: 2 additions & 0 deletions src/features/interview-page/interview/api/type/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export type { CurrentInterviewQuestion } from "./current-question";
export type {
InterviewLevel,
InterviewProgressStatus,
PreparedInterviewer,
PreparedInterviewMode,
PersonaType,
PrepareInterviewParams,
PrepareInterviewQuestion,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ export type InterviewProgressStatus =
| "READY"
| "ABANDONED";

export type PreparedInterviewMode = "SOLO" | "MULTI";

export interface PreparedInterviewer {
personaId: number;
name: string;
roleLabel: string;
image?: string;
}

export interface PrepareInterviewQuestion {
questionId: number;
intention: string;
Expand Down Expand Up @@ -56,4 +65,6 @@ export interface PreparedInterviewData {
status: InterviewProgressStatus;
currentQuestionIndex: number;
questions: PrepareInterviewQuestion[];
mode: PreparedInterviewMode;
interviewers?: PreparedInterviewer[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface SubmitInterviewAnswerQuestion {
type: string;
intention: string;
content: string;
personaId?: number;
}

export interface SubmitInterviewAnswerResponse {
Expand Down
Loading