-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[feat] 기업 자동응답 목록 추가 페이지 구현 및 테스트 코드 작성
- Loading branch information
Showing
13 changed files
with
310 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { useEffect, useRef } from 'react'; | ||
|
||
import { useNavigate } from 'react-router-dom'; | ||
|
||
import { Controller, useForm } from 'react-hook-form'; | ||
|
||
import useAutoReplyFormStore from '../../hooks/useAutoReplyFormStore'; | ||
|
||
import { STATIC_ROUTES } from '../../constants/routes'; | ||
|
||
import TextArea from '../ui/TextArea'; | ||
import OperationButtons from '../ui/OperationButtons'; | ||
import ErrorMessage from '../ui/ErrorMessage'; | ||
|
||
const MAX_LENGTH = { | ||
question: 60, | ||
answer: 150, | ||
}; | ||
|
||
export default function AutoReplyAddForm() { | ||
const navigate = useNavigate(); | ||
|
||
const [{ done, errorMessage }, store] = useAutoReplyFormStore(); | ||
|
||
const questionRef = useRef<HTMLTextAreaElement | null>(null); | ||
|
||
interface FormValues { | ||
question: string, | ||
answer: string, | ||
} | ||
|
||
const { control, handleSubmit } = useForm<FormValues>(); | ||
|
||
useEffect(() => { | ||
if (done) { | ||
store.reset(); | ||
|
||
navigate(STATIC_ROUTES.AUTO_REPLIES); | ||
} | ||
}, [done]); | ||
|
||
const onSubmit = (data: FormValues) => { | ||
store.addAutoReply(data.question, data.answer.trim()); | ||
}; | ||
|
||
return ( | ||
<div> | ||
<form | ||
onSubmit={handleSubmit(onSubmit)} | ||
data-testid="auto-reply-form" | ||
> | ||
<Controller | ||
control={control} | ||
name="question" | ||
render={({ field: { value, onChange } }) => ( | ||
<TextArea | ||
label="질문" | ||
value={value} | ||
onChange={onChange} | ||
maxLength={MAX_LENGTH.question} | ||
showLength | ||
ref={questionRef} | ||
/> | ||
)} | ||
/> | ||
|
||
<Controller | ||
control={control} | ||
name="answer" | ||
render={({ field: { value, onChange } }) => ( | ||
<TextArea | ||
label="답변" | ||
value={value} | ||
onChange={onChange} | ||
maxLength={MAX_LENGTH.answer} | ||
showLength | ||
fixHeight | ||
/> | ||
)} | ||
/> | ||
|
||
<OperationButtons | ||
primaryType="submit" | ||
primaryName="저장하기" | ||
/> | ||
|
||
{errorMessage && ( | ||
<ErrorMessage>{errorMessage}</ErrorMessage> | ||
)} | ||
</form> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { container } from 'tsyringe'; | ||
|
||
import { useStore } from 'usestore-ts'; | ||
|
||
import AutoReplyFormStore from '../stores/AutoReplyFormStore'; | ||
|
||
const useAutoReplyFormStore = () => { | ||
const store = container.resolve(AutoReplyFormStore); | ||
|
||
return useStore(store); | ||
}; | ||
|
||
export default useAutoReplyFormStore; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import AutoReplyAddForm from '../components/auto-reply-company/AutoReplyAddForm'; | ||
import ContentLayout from '../components/layout/ContentLayout'; | ||
|
||
export default function AutoReplyNewPage() { | ||
return ( | ||
<ContentLayout | ||
pageHeader="자동응답 추가" | ||
testId="auto-reply-new" | ||
enableBack | ||
> | ||
<AutoReplyAddForm /> | ||
</ContentLayout> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import AutoReplyFormStore from './AutoReplyFormStore'; | ||
|
||
const context = describe; | ||
|
||
const createAutoReply = jest.fn(); | ||
|
||
jest.mock('../services/ApiService', () => ({ | ||
get apiService() { | ||
return { | ||
createAutoReply, | ||
}; | ||
}, | ||
})); | ||
|
||
describe('ChatRoomStore', () => { | ||
let store: AutoReplyFormStore; | ||
|
||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
|
||
store = new AutoReplyFormStore(); | ||
}); | ||
|
||
describe('add data', () => { | ||
const params = { | ||
question: '', | ||
answer: '', | ||
}; | ||
|
||
context('empty question', () => { | ||
const errorMessage = '질문을 작성해주세요'; | ||
|
||
it(`errorMessage set to ${errorMessage}`, async () => { | ||
await store.addAutoReply(params.question, params.answer); | ||
|
||
expect(store.errorMessage).toBe(errorMessage); | ||
}); | ||
}); | ||
|
||
context('empty answer', () => { | ||
const errorMessage = '답변을 작성해주세요'; | ||
|
||
beforeEach(() => { | ||
params.question = 'question'; | ||
}); | ||
|
||
it(`errorMessage set to ${errorMessage}`, async () => { | ||
await store.addAutoReply(params.question, params.answer); | ||
|
||
expect(store.errorMessage).toBe(errorMessage); | ||
}); | ||
}); | ||
|
||
context('when API responds with success', () => { | ||
beforeEach(() => { | ||
params.answer = 'answer'; | ||
}); | ||
|
||
it('done set to true', async () => { | ||
await store.addAutoReply(params.question, params.answer); | ||
|
||
expect(createAutoReply).toBeCalledWith(params); | ||
|
||
expect(store.done).toBe(true); | ||
expect(store.errorMessage).toBe(''); | ||
}); | ||
}); | ||
|
||
context('when API responds with error', () => { | ||
const errorMessage = 'Error Message'; | ||
|
||
beforeEach(() => { | ||
createAutoReply.mockRejectedValue(Error(errorMessage)); | ||
}); | ||
|
||
it('errorMessage set to error message', async () => { | ||
await store.addAutoReply(params.question, params.answer); | ||
|
||
expect(createAutoReply).toBeCalledWith(params); | ||
|
||
expect(store.done).toBe(false); | ||
expect(store.errorMessage).toBe(errorMessage); | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { AxiosError } from 'axios'; | ||
|
||
import { singleton } from 'tsyringe'; | ||
|
||
import { Action, Store } from 'usestore-ts'; | ||
|
||
import { apiService } from '../services/ApiService'; | ||
|
||
@singleton() | ||
@Store() | ||
export default class AutoReplyFormStore { | ||
errorMessage = ''; | ||
|
||
done = false; | ||
|
||
@Action() | ||
reset() { | ||
this.errorMessage = ''; | ||
|
||
this.done = false; | ||
} | ||
|
||
@Action() | ||
setDone() { | ||
this.done = true; | ||
|
||
this.errorMessage = ''; | ||
} | ||
|
||
@Action() | ||
setErrorMessage(message: string) { | ||
this.errorMessage = message; | ||
|
||
this.done = false; | ||
} | ||
|
||
@Action() | ||
async addAutoReply( | ||
question: string, | ||
answer: string, | ||
) { | ||
try { | ||
if (!question) { | ||
throw Error('질문을 작성해주세요'); | ||
} | ||
|
||
if (!answer) { | ||
throw Error('답변을 작성해주세요'); | ||
} | ||
|
||
await apiService.createAutoReply({ question, answer }); | ||
|
||
this.setDone(); | ||
} catch (e) { | ||
if (e instanceof AxiosError) { | ||
if (e.response?.status === 440) { | ||
this.setErrorMessage(e.response?.data); | ||
|
||
return; | ||
} | ||
} | ||
|
||
if (e instanceof Error) { | ||
this.setErrorMessage(e.message); | ||
} | ||
} | ||
} | ||
} |