-
Notifications
You must be signed in to change notification settings - Fork 1
RELEASE-20251223 #199
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
RELEASE-20251223 #199
Changes from all commits
de9cc42
d1c9306
daafdb5
ff3d5a8
3bc3c4d
c2508df
ef7414d
66dc63a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,4 +15,6 @@ node_modules/ | |
| .tanstack | ||
| *.pem | ||
| *.key | ||
| *.crt | ||
| *.crt | ||
| robots.txt | ||
| sitemap.xml | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,113 +1,22 @@ | ||||||||||||||||||
| /* eslint-disable no-unused-vars */ | ||||||||||||||||||
| import { EventEmitter } from "events"; | ||||||||||||||||||
| import { DependencyList, useEffect } from "react"; | ||||||||||||||||||
|
|
||||||||||||||||||
| export type InterviewEventType = | ||||||||||||||||||
| | "startVoiceRecognition" | ||||||||||||||||||
| | "stopVoiceRecognition" | ||||||||||||||||||
| | "voiceRecognitionStarted" | ||||||||||||||||||
| | "voiceRecognitionStopped" | ||||||||||||||||||
| | "voiceRecognitionError" | ||||||||||||||||||
| | "voiceRecognitionResult"; | ||||||||||||||||||
|
|
||||||||||||||||||
| interface InterviewEventPayloads { | ||||||||||||||||||
| startVoiceRecognition: undefined; | ||||||||||||||||||
| stopVoiceRecognition: undefined; | ||||||||||||||||||
| voiceRecognitionStarted: undefined; | ||||||||||||||||||
| voiceRecognitionStopped: undefined; | ||||||||||||||||||
| voiceRecognitionError: { error: string }; | ||||||||||||||||||
| voiceRecognitionResult: { text: string }; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| class TypedEventEmitter extends EventEmitter { | ||||||||||||||||||
| public emit<K extends InterviewEventType>( | ||||||||||||||||||
| event: K, | ||||||||||||||||||
| ...args: InterviewEventPayloads[K] extends undefined | ||||||||||||||||||
| ? [] | ||||||||||||||||||
| : [InterviewEventPayloads[K]] | ||||||||||||||||||
| ): boolean { | ||||||||||||||||||
| return super.emit(event, ...args); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| public on<K extends InterviewEventType>( | ||||||||||||||||||
| event: K, | ||||||||||||||||||
| listener: InterviewEventPayloads[K] extends undefined | ||||||||||||||||||
| ? () => void | ||||||||||||||||||
| : (payload: InterviewEventPayloads[K]) => void | ||||||||||||||||||
| ): this { | ||||||||||||||||||
| return super.on(event, listener); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| public off<K extends InterviewEventType>( | ||||||||||||||||||
| event: K, | ||||||||||||||||||
| listener: InterviewEventPayloads[K] extends undefined | ||||||||||||||||||
| ? () => void | ||||||||||||||||||
| : (payload: InterviewEventPayloads[K]) => void | ||||||||||||||||||
| ): this { | ||||||||||||||||||
| return super.off(event, listener); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| public once<K extends InterviewEventType>( | ||||||||||||||||||
| event: K, | ||||||||||||||||||
| listener: InterviewEventPayloads[K] extends undefined | ||||||||||||||||||
| ? () => void | ||||||||||||||||||
| : (payload: InterviewEventPayloads[K]) => void | ||||||||||||||||||
| ): this { | ||||||||||||||||||
| return super.once(event, listener); | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // 싱글톤 인스턴스 | ||||||||||||||||||
| export const interviewEvents: TypedEventEmitter = new TypedEventEmitter(); | ||||||||||||||||||
|
|
||||||||||||||||||
| // React Hook for subscribing to events | ||||||||||||||||||
| import { publishEvent, useSubscribeEvents } from "@/utils/eventEmitter"; | ||||||||||||||||||
| import { InterviewEventPayloads, InterviewEventType } from "@kokomen/types"; | ||||||||||||||||||
| import { DependencyList } from "react"; | ||||||||||||||||||
| // 이벤트에 대서 콜백 함수 구독하는 훅 | ||||||||||||||||||
| export function useInterviewEvent<K extends InterviewEventType>( | ||||||||||||||||||
| event: K, | ||||||||||||||||||
| handler: InterviewEventPayloads[K] extends undefined | ||||||||||||||||||
| ? () => void | ||||||||||||||||||
| : (payload: InterviewEventPayloads[K]) => void, | ||||||||||||||||||
| deps: DependencyList = [] | ||||||||||||||||||
| ): void { | ||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||||||||||||||||||
| interviewEvents.on(event, handler as any); | ||||||||||||||||||
| return () => { | ||||||||||||||||||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||||||||||||||||||
| interviewEvents.off(event, handler as any); | ||||||||||||||||||
| }; | ||||||||||||||||||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||||||||||||||||||
| }, [event, ...deps]); | ||||||||||||||||||
| const eventEmitter = useSubscribeEvents<InterviewEventType>( | ||||||||||||||||||
| [{ event, handler }], | ||||||||||||||||||
| [] | ||||||||||||||||||
| ); | ||||||||||||||||||
|
Comment on lines
+13
to
+16
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // 이벤트 발행 헬퍼 함수들 | ||||||||||||||||||
| export const interviewEventHelpers: { | ||||||||||||||||||
| startVoiceRecognition: () => void; | ||||||||||||||||||
| stopVoiceRecognition: () => void; | ||||||||||||||||||
| notifyVoiceStarted: () => void; | ||||||||||||||||||
| notifyVoiceStopped: () => void; | ||||||||||||||||||
| notifyVoiceError: (error: string) => void; | ||||||||||||||||||
| sendVoiceResult: (text: string) => void; | ||||||||||||||||||
| } = { | ||||||||||||||||||
| startVoiceRecognition: (): void => { | ||||||||||||||||||
| interviewEvents.emit("startVoiceRecognition"); | ||||||||||||||||||
| }, | ||||||||||||||||||
| stopVoiceRecognition: (): void => { | ||||||||||||||||||
| interviewEvents.emit("stopVoiceRecognition"); | ||||||||||||||||||
| }, | ||||||||||||||||||
|
|
||||||||||||||||||
| notifyVoiceStarted: (): void => { | ||||||||||||||||||
| interviewEvents.emit("voiceRecognitionStarted"); | ||||||||||||||||||
| }, | ||||||||||||||||||
|
|
||||||||||||||||||
| notifyVoiceStopped: (): void => { | ||||||||||||||||||
| interviewEvents.emit("voiceRecognitionStopped"); | ||||||||||||||||||
| }, | ||||||||||||||||||
|
|
||||||||||||||||||
| notifyVoiceError: (error: string): void => { | ||||||||||||||||||
| interviewEvents.emit("voiceRecognitionError", { error }); | ||||||||||||||||||
| }, | ||||||||||||||||||
|
|
||||||||||||||||||
| sendVoiceResult: (text: string): void => { | ||||||||||||||||||
| interviewEvents.emit("voiceRecognitionResult", { text }); | ||||||||||||||||||
| } | ||||||||||||||||||
| }; | ||||||||||||||||||
| export const publishInterviewEvent = publishEvent< | ||||||||||||||||||
| InterviewEventType, | ||||||||||||||||||
| InterviewEventPayloads | ||||||||||||||||||
| >(); | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import { mapToCamelCase } from "@/utils/convertConvention"; | ||
| import { ArchivedResumeAndPortfolio } from "@kokomen/types"; | ||
| import axios from "axios"; | ||
|
|
||
| const archiveServerInstance = axios.create({ | ||
| baseURL: process.env.NEXT_PUBLIC_API_BASE_URL + "/resumes", | ||
| withCredentials: true | ||
| }); | ||
|
|
||
| export const getArchivedResumes = (type?: "ALL" | "RESUME" | "PORTFOLIO") => { | ||
| return archiveServerInstance | ||
| .get<{ | ||
| resumes: ArchivedResumeAndPortfolio[]; | ||
| portfolios: ArchivedResumeAndPortfolio[]; | ||
| }>("", { | ||
| params: { | ||
| type: type ?? "ALL" | ||
| } | ||
| }) | ||
| .then((res) => mapToCamelCase(res.data)); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
robots.txtandsitemap.xmlare generally not included in.gitignoreas they are crucial for search engine optimization (SEO). If these files are generated during the build process and are meant to be publicly accessible, they should be committed or be part of the build output that gets deployed. Ignoring them might prevent search engine crawlers from finding and indexing your site correctly. Please verify if ignoring these files is the intended behavior.